diff --git a/src/Balea.Api.Store/ApiRuntimeAuthorizationServerStore.cs b/src/Balea.Api.Store/ApiRuntimeAuthorizationServerStore.cs index 2de0051..9e04faa 100644 --- a/src/Balea.Api.Store/ApiRuntimeAuthorizationServerStore.cs +++ b/src/Balea.Api.Store/ApiRuntimeAuthorizationServerStore.cs @@ -43,21 +43,22 @@ public async Task FindAuthorizationAsync(ClaimsPrincipal u { if (_storeOptions.CacheEnabled) { - var key = $"balea:1.0:user:{user.GetSubjectId(_baleaOptions)}:application:{_baleaOptions.ApplicationName}"; - + var key = $"balea:1.1:user:{user.GetSubjectId(_baleaOptions)}:application:{_baleaOptions.ApplicationName}"; + var cachedResponse = await _cache.GetOrSet( key, - miss: () => - { - Log.CacheMiss(_logger, key); - return GetAuthorizationContext(user); + miss: async () => + { + Log.CacheMiss(_logger, key); + var response = await GetAuthorizationContext(user); + return response.To(); }, hit: _ => Log.CacheHit(_logger, key), _storeOptions.AbsoluteExpirationRelativeToNow, _storeOptions.SlidingExpiration, cancellationToken); - return cachedResponse.To(); + return cachedResponse; } var response = await GetAuthorizationContext(user); @@ -69,21 +70,22 @@ public async Task GetPolicyAsync(string name, CancellationToken cancella { if (_storeOptions.CacheEnabled) { - var key = $"balea:1.0:application:{_baleaOptions.ApplicationName}:policy:{name}"; + var key = $"balea:1.1:application:{_baleaOptions.ApplicationName}:policy:{name}"; var cachedResponse = await _cache.GetOrSet( key, - miss: () => + miss: async () => { Log.CacheMiss(_logger, key); - return GetPolicy(name); + var response = await GetPolicy(name); + return response.To(); }, hit: _ => Log.CacheHit(_logger, key), _storeOptions.AbsoluteExpirationRelativeToNow, _storeOptions.SlidingExpiration, cancellationToken); - return cachedResponse.To(); + return cachedResponse; } var response = await GetPolicy(name); diff --git a/src/Balea.Api.Store/Model/HttpClientStoreAuthorizationResponse.cs b/src/Balea.Api.Store/Model/HttpClientStoreAuthorizationResponse.cs index 812a1d6..18ac5f4 100644 --- a/src/Balea.Api.Store/Model/HttpClientStoreAuthorizationResponse.cs +++ b/src/Balea.Api.Store/Model/HttpClientStoreAuthorizationResponse.cs @@ -20,12 +20,9 @@ public AuthorizationContext To() Roles.Select(role => new Role( role.Name, role.Description, - role.Subjects, - role.Mappings, - role.Permissions, - role.Enabled)), - Delegation is null - ? null + role.Permissions)), + Delegation is null + ? null : new Delegation( Delegation.Who, Delegation.Whom, diff --git a/src/Balea.Configuration.Store/ConfigurationRuntimeAuthorizationServerStore.cs b/src/Balea.Configuration.Store/ConfigurationRuntimeAuthorizationServerStore.cs index 4498707..0dd6509 100644 --- a/src/Balea.Configuration.Store/ConfigurationRuntimeAuthorizationServerStore.cs +++ b/src/Balea.Configuration.Store/ConfigurationRuntimeAuthorizationServerStore.cs @@ -27,7 +27,7 @@ public Task FindAuthorizationAsync(ClaimsPrincipal user, C if (application is null) { - return Task.FromResult(new AuthorizationContext(new Role[0], null)); + return Task.FromResult(new AuthorizationContext(Array.Empty(), null)); } var delegation = application.Delegations.GetCurrentDelegation(user.GetSubjectId(_options)); diff --git a/src/Balea.Configuration.Store/Extensions/ModelExtensions.cs b/src/Balea.Configuration.Store/Extensions/ModelExtensions.cs index 81813e6..0a130a5 100644 --- a/src/Balea.Configuration.Store/Extensions/ModelExtensions.cs +++ b/src/Balea.Configuration.Store/Extensions/ModelExtensions.cs @@ -16,10 +16,7 @@ public static Role To(this RoleConfiguration role) return new Role( role.Name, role.Description, - role.Subjects, - role.Mappings, - role.Permissions.Distinct(), - role.Enabled + role.Permissions.Distinct() ); } diff --git a/src/Balea.EntityFrameworkCore.Store/EntityFrameworkCoreRuntimeAuthorizationServerStore.cs b/src/Balea.EntityFrameworkCore.Store/EntityFrameworkCoreRuntimeAuthorizationServerStore.cs index b3d5efc..ef29d2b 100644 --- a/src/Balea.EntityFrameworkCore.Store/EntityFrameworkCoreRuntimeAuthorizationServerStore.cs +++ b/src/Balea.EntityFrameworkCore.Store/EntityFrameworkCoreRuntimeAuthorizationServerStore.cs @@ -26,44 +26,46 @@ public EntityFrameworkCoreRuntimeAuthorizationServerStore(TContext context, Bale public async Task FindAuthorizationAsync(ClaimsPrincipal user, CancellationToken cancellationToken = default) { + var userSubjectId = user.GetSubjectId(_options); var sourceRoleClaims = user.GetClaimValues(_options.DefaultClaimTypeMap.RoleClaimType); - var delegation = await _context.Delegations.GetCurrentDelegation( - user.GetSubjectId(_options), + + var delegation = await _context.Delegations.GetDelegation( + userSubjectId, _options.ApplicationName, cancellationToken); - var subject = GetSubject(user, delegation); + + var subject = delegation?.Who ?? userSubjectId; + var roles = await _context.Roles - .AsNoTracking() - .Include(r => r.Application) - .Include(r => r.Mappings) - .ThenInclude(rm => rm.Mapping) - .Include(r => r.Subjects) - .ThenInclude(rs => rs.Subject) - .Include(r => r.Permissions) - .ThenInclude(rp => rp.Permission) - .Where(role => - role.Application.Name == _options.ApplicationName && - role.Enabled && - (role.Subjects.Any(rs => rs.Subject.Sub == subject) || role.Mappings.Any(rm => sourceRoleClaims.Contains(rm.Mapping.Name))) + .AsNoTracking() + .Where(role => + role.Application.Name == _options.ApplicationName && + role.Enabled && + ( + role.Subjects.Any(rs => rs.Subject.Sub == subject) || + role.Mappings.Any(rm => sourceRoleClaims.Contains(rm.Mapping.Name)) ) - .ToListAsync(cancellationToken); + ) + .Select(role => new Role( + role.Name, + role.Description, + role.Permissions.Select(rp => rp.Permission.Name) + )) + .ToListAsync(cancellationToken); - return new AuthorizationContext(roles.Select(r => r.To()), delegation.To()); + return new AuthorizationContext(roles, delegation); } public async Task GetPolicyAsync(string name, CancellationToken cancellationToken = default) { var policy = await _context .Policies - .Include(p => p.Application) - .SingleOrDefaultAsync(p => p.Application.Name == _options.ApplicationName && p.Name == name); + .AsNoTracking() + .Where(p => p.Application.Name == _options.ApplicationName && p.Name == name) + .Select(p => new Policy(p.Name, p.Content)) + .FirstOrDefaultAsync(cancellationToken); - return policy.To(); - } - - private string GetSubject(ClaimsPrincipal user, DelegationEntity delegation) - { - return delegation?.Who?.Sub ?? user.GetSubjectId(_options); + return policy; } } } diff --git a/src/Balea.EntityFrameworkCore.Store/Extensions/EntitiesExtensions.cs b/src/Balea.EntityFrameworkCore.Store/Extensions/EntitiesExtensions.cs index a6ac3b9..b0b6ab5 100644 --- a/src/Balea.EntityFrameworkCore.Store/Extensions/EntitiesExtensions.cs +++ b/src/Balea.EntityFrameworkCore.Store/Extensions/EntitiesExtensions.cs @@ -19,10 +19,7 @@ public static Role To(this RoleEntity role) return new Role( role.Name, role.Description, - role.Subjects.Select(rs => rs.Subject.Sub), - role.Mappings.Select(rm => rm.Mapping.Name), - role.Permissions.Select(rp => rp.Permission.Name), - role.Enabled + role.Permissions.Select(rp => rp.Permission.Name) ); } @@ -57,8 +54,32 @@ public static Task GetCurrentDelegation( d.Selected && d.From <= now && d.To >= now && d.Whom.Sub == subjectId && - d.Application.Name == applicationName, + d.Application.Name == applicationName, cancellationToken); + } + + public static Task GetDelegation( + this DbSet delegations, + string subjectId, + string applicationName, + CancellationToken cancellationToken = default) + { + var now = DateTime.UtcNow; + return delegations + .AsNoTracking() + .Where( + d => + d.Selected && + d.From <= now && d.To >= now && + d.Whom.Sub == subjectId && + d.Application.Name == applicationName) + .Select( + d => new Delegation( + d.Who.Sub, + d.Whom.Sub, + d.From, + d.To)) + .FirstOrDefaultAsync(cancellationToken); } public static Policy To(this PolicyEntity policy) diff --git a/src/Balea/Authorization/BaleaPolicyEvaluator.cs b/src/Balea/Authorization/BaleaPolicyEvaluator.cs index 8e6d1ea..5b85c4a 100644 --- a/src/Balea/Authorization/BaleaPolicyEvaluator.cs +++ b/src/Balea/Authorization/BaleaPolicyEvaluator.cs @@ -150,7 +150,6 @@ private async Task AddBaleaIdentity(ClaimsPrincipal user, HttpContext context) } var roleClaims = authorization.Roles - .Where(role => role.Enabled) .Select(role => new Claim(_options.DefaultClaimTypeMap.RoleClaimType, role.Name)); var permissionClaims = authorization.Roles diff --git a/src/Balea/Model/Role.cs b/src/Balea/Model/Role.cs index 9a48486..02ed5a3 100644 --- a/src/Balea/Model/Role.cs +++ b/src/Balea/Model/Role.cs @@ -4,39 +4,20 @@ namespace Balea.Model { public class Role { - private readonly List _subjects = new List(); - private readonly List _mappings = new List(); private readonly List _permissions = new List(); public Role( string name, string description, - IEnumerable subjects, - IEnumerable mappings, - IEnumerable permissions, - bool enabled = true) + IEnumerable permissions) { Name = name; Description = description; - Enabled = enabled; - _subjects.AddRange(subjects); - _mappings.AddRange(mappings); _permissions.AddRange(permissions); } public string Name { get; private set; } public string Description { get; private set; } - public bool Enabled { get; private set; } - - public void AddSubjects(IEnumerable subjects) - { - _subjects.AddRange(subjects); - } - - public void AddMappings(IEnumerable mappings) - { - _mappings.AddRange(mappings); - } public void AddPermissions(IEnumerable permissions) { @@ -47,15 +28,5 @@ public IEnumerable GetPermissions() { return _permissions; } - - public IEnumerable GetMappings() - { - return _mappings; - } - - public IEnumerable GetSubjects() - { - return _subjects; - } } }