diff --git a/AsbCloudApp/Data/PermissionBaseDto.cs b/AsbCloudApp/Data/PermissionBaseDto.cs deleted file mode 100644 index 48965c19..00000000 --- a/AsbCloudApp/Data/PermissionBaseDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace AsbCloudApp.Data -{ - public class PermissionBaseDto - { - public int Id { get; set; } - public string Name { get; set; } - public string Description { get; set; } - } -} \ No newline at end of file diff --git a/AsbCloudApp/Data/PermissionDto.cs b/AsbCloudApp/Data/PermissionDto.cs index 9e13e54b..944c1fc2 100644 --- a/AsbCloudApp/Data/PermissionDto.cs +++ b/AsbCloudApp/Data/PermissionDto.cs @@ -1,7 +1,9 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data { - public class PermissionDto : PermissionBaseDto + public class PermissionDto: IId { - public int IdUserRole { get; set; } + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } } } \ No newline at end of file diff --git a/AsbCloudApp/Data/UserRoleDto.cs b/AsbCloudApp/Data/UserRoleDto.cs index d4506cf2..a16a4959 100644 --- a/AsbCloudApp/Data/UserRoleDto.cs +++ b/AsbCloudApp/Data/UserRoleDto.cs @@ -9,7 +9,7 @@ namespace AsbCloudApp.Data public string Caption { get; set; } public int? IdParent { get; set; } public int IdType { get; set; } - public IEnumerable Permissions { get; set; } + public IEnumerable Permissions { get; set; } [JsonIgnore] public virtual ICollection Users { get; set; } } diff --git a/AsbCloudApp/Data/UserTokenDto.cs b/AsbCloudApp/Data/UserTokenDto.cs index cf225a6a..24defd9a 100644 --- a/AsbCloudApp/Data/UserTokenDto.cs +++ b/AsbCloudApp/Data/UserTokenDto.cs @@ -4,7 +4,7 @@ namespace AsbCloudApp.Data { public class UserTokenDto : UserExtendedDto { - public IEnumerable Permissions { get; set; } + public IEnumerable Permissions { get; set; } public string Token { get; set; } } } diff --git a/AsbCloudApp/Services/IPermissionService.cs b/AsbCloudApp/Services/IPermissionService.cs deleted file mode 100644 index a4c6cb66..00000000 --- a/AsbCloudApp/Services/IPermissionService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using AsbCloudApp.Data; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudApp.Services -{ - public interface IPermissionService - { - Task> GetByIdRoleAsync(int idRole, CancellationToken token); - Task InsertRangeAsync(IEnumerable dtos, CancellationToken token); - Task UpdateAsync(PermissionDto dto, CancellationToken token); - Task DeleteAsync(int idUserRole, int idPermission, CancellationToken token); - Task DeleteAllByRoleAsync(int idUserRole, CancellationToken token); - } -} \ No newline at end of file diff --git a/AsbCloudApp/Services/IUserRoleService.cs b/AsbCloudApp/Services/IUserRoleService.cs index 5a6ba64a..85780812 100644 --- a/AsbCloudApp/Services/IUserRoleService.cs +++ b/AsbCloudApp/Services/IUserRoleService.cs @@ -9,7 +9,6 @@ namespace AsbCloudApp.Services { Task GetByNameAsync(string name, CancellationToken token = default); List GetNestedById(int id, int counter = 10); - IEnumerable GetNestedPermissions(IEnumerable roles); bool HasPermission(IEnumerable rolesIds, string permissionName); } } \ No newline at end of file diff --git a/AsbCloudApp/Services/IUserService.cs b/AsbCloudApp/Services/IUserService.cs index 0abc8606..beb6e3d1 100644 --- a/AsbCloudApp/Services/IUserService.cs +++ b/AsbCloudApp/Services/IUserService.cs @@ -5,8 +5,8 @@ namespace AsbCloudApp.Services { public interface IUserService : ICrudService { - IUserRoleService RoleService { get; } - IEnumerable GetNestedPermissions(int idUser); + IUserRoleService RoleService { get; } + IEnumerable GetNestedPermissions(int idUser); IEnumerable GetRolesByIdUser(int idUser); bool HasAnyRoleOf(int idUser, IEnumerable roleNames); bool HasAnyRoleOf(int idUser, IEnumerable roleIds); diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 8aa4ab02..f16b4a7d 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -48,8 +48,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -70,6 +69,7 @@ namespace AsbCloudInfrastructure services.AddTransient, CrudServiceBase>(); services.AddTransient, CrudServiceBase>(); services.AddTransient, CrudServiceBase>(); + services.AddTransient, CrudCacheServiceBase>(); // TelemetryData services services.AddTransient, TelemetryDataSaubService>(); diff --git a/AsbCloudInfrastructure/Services/AuthService.cs b/AsbCloudInfrastructure/Services/AuthService.cs index 10fbb79b..e483f015 100644 --- a/AsbCloudInfrastructure/Services/AuthService.cs +++ b/AsbCloudInfrastructure/Services/AuthService.cs @@ -35,7 +35,7 @@ namespace AsbCloudInfrastructure.Services private readonly HashAlgorithm hashAlgorithm; private readonly Random rnd; - public AuthService(IAsbCloudDbContext db, CacheDb cacheDb, IUserService userService) + public AuthService(IAsbCloudDbContext db, IUserService userService) { this.db = db; this.userService = userService; diff --git a/AsbCloudInfrastructure/Services/PermissionService.cs b/AsbCloudInfrastructure/Services/PermissionService.cs deleted file mode 100644 index eaa2fe90..00000000 --- a/AsbCloudInfrastructure/Services/PermissionService.cs +++ /dev/null @@ -1,90 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Services; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.Cache; -using Mapster; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudInfrastructure.Services -{ - public class PermissionService : IPermissionService - { - private readonly CacheTable cacheUserRolePermission; - private readonly CacheTable cachePermission; - - public PermissionService(IAsbCloudDbContext db, CacheDb cacheDb) - { - cacheUserRolePermission = cacheDb.GetCachedTable( - (AsbCloudDbContext)db, - new string[] { nameof(RelationUserRolePermission.Permission) }); - cachePermission = cacheDb.GetCachedTable( - (AsbCloudDbContext)db); - } - - public async Task> GetByIdRoleAsync(int idRole, CancellationToken token) - { - var entities = await cacheUserRolePermission - .WhereAsync(p => p.IdUserRole == idRole, token) - .ConfigureAwait(false); - var dto = entities.Select(e => e.Permission).Adapt(); - return dto; - } - - public async Task InsertRangeAsync(IEnumerable dtos, CancellationToken token) - { - foreach (var dto in dtos) - { - var entity = Convert(dto); - var insertedEntity = cachePermission.Insert(entity); - cacheUserRolePermission.Insert(new RelationUserRolePermission() - { - IdPermission = insertedEntity.Id, - IdUserRole = dto.IdUserRole - }); - } - - return 1; - } - - public async Task UpdateAsync(PermissionDto dto, CancellationToken token) - { - var entity = Convert(dto); - await cachePermission.UpsertAsync(entity, token) - .ConfigureAwait(false); - return 1; - } - - public async Task DeleteAsync(int idUserRole, int idPermission, CancellationToken token) - { - bool predicate(RelationUserRolePermission p) => p.IdUserRole == idUserRole && p.IdPermission == idPermission; - await DeleteAsync(predicate, token); - cachePermission.Remove(p => p.Id == idPermission); - return 1; - } - - public Task DeleteAllByRoleAsync(int idUserRole, CancellationToken token) - { - bool predicate(RelationUserRolePermission p) => p.IdUserRole == idUserRole; - return DeleteAsync(predicate, token); - } - - private async Task DeleteAsync(Func predicate, CancellationToken token) - { - var count = (await cacheUserRolePermission.WhereAsync(predicate, token).ConfigureAwait(false)).Count(); - if (count > 0) - await cacheUserRolePermission.RemoveAsync(predicate, token) - .ConfigureAwait(false); - return count; - } - - public Permission Convert(PermissionDto src) - { - var entity = src.Adapt(); - return entity; - } - } -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/UserRoleService.cs b/AsbCloudInfrastructure/Services/UserRoleService.cs index 11640264..6675757e 100644 --- a/AsbCloudInfrastructure/Services/UserRoleService.cs +++ b/AsbCloudInfrastructure/Services/UserRoleService.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -15,15 +14,14 @@ namespace AsbCloudInfrastructure.Services public class UserRoleService : IUserRoleService { private readonly CacheTable cacheUserRoles; - private readonly CacheTable cachePermission; - private readonly IPermissionService permissionService; - public List Includes { get; } = new(); + private readonly CacheTable cacheUserRolePermissions; + + public List Includes { get; } - public UserRoleService(IAsbCloudDbContext context, CacheDb cacheDb, IPermissionService permissionService) + public UserRoleService(IAsbCloudDbContext context, CacheDb cacheDb) { cacheUserRoles = cacheDb.GetCachedTable((AsbCloudDbContext)context, new [] { nameof(UserRole.RelationUserRolePermissions) }); - cachePermission = cacheDb.GetCachedTable((AsbCloudDbContext)context); - this.permissionService = permissionService; + cacheUserRolePermissions = cacheDb.GetCachedTable((AsbCloudDbContext)context, new[] { nameof(RelationUserRolePermission.Permission) }); } public async Task InsertAsync(UserRoleDto dto, CancellationToken token = default) @@ -31,6 +29,7 @@ namespace AsbCloudInfrastructure.Services var entity = dto.Adapt(); var updatedEntity = await cacheUserRoles.InsertAsync(entity, token) .ConfigureAwait(false); + dto.Id = updatedEntity.Id; await UpdatePermissionsAsync(dto, token); await cacheUserRoles.RefreshAsync(true, token) .ConfigureAwait(false); @@ -48,7 +47,7 @@ namespace AsbCloudInfrastructure.Services { var entities = await cacheUserRoles.WhereAsync(token) .ConfigureAwait(false); - var dtos = entities.Adapt(); + var dtos = entities?.Select(Convert); return dtos; } @@ -56,7 +55,9 @@ namespace AsbCloudInfrastructure.Services { var entity = await cacheUserRoles.FirstOrDefaultAsync(r=>r.Id == id, token) .ConfigureAwait(false); - var dto = entity?.Adapt(); + if (entity is null) + return null; + var dto = Convert(entity); return dto; } @@ -64,20 +65,33 @@ namespace AsbCloudInfrastructure.Services { var entity = await cacheUserRoles.FirstOrDefaultAsync(r => r.Caption == name, token) .ConfigureAwait(false); - var dto = entity?.Adapt(); + if (entity is null) + return null; + var dto = Convert(entity); return dto; } public async Task UpdateAsync(int id, UserRoleDto dto, CancellationToken token = default) { - dto.Id = id; - var entity = dto.Adapt(); + if (dto.Id != id) + { + var exist = await cacheUserRoles.ContainsAsync(i => i.Id == dto.Id, token) + .ConfigureAwait(false); + + if (exist) + return -1; + + await cacheUserRoles.RemoveAsync(i => i.Id == id, token) + .ConfigureAwait(false); + } + + var entity = Convert(dto); await UpdatePermissionsAsync(dto, token); await cacheUserRoles.UpsertAsync(entity, token) .ConfigureAwait(false); - return id; + return dto.Id; } public List GetNestedById(int id, int recursionLevel = 7) @@ -85,7 +99,7 @@ namespace AsbCloudInfrastructure.Services var role = cacheUserRoles.FirstOrDefault(r => r.Id == id); if (role is null) return null; - var dto = role.Adapt(); + var dto = Convert(role); if (role.IdParent is null || recursionLevel == 0) return new List { dto }; var parentRoles = GetNestedById((int)role.IdParent, --recursionLevel) ?? @@ -94,76 +108,28 @@ namespace AsbCloudInfrastructure.Services return parentRoles; } - public IEnumerable GetNestedPermissions(IEnumerable roles) - { - var permissions = new Dictionary(16); - foreach (var roleDto in roles) - { - var role = cacheUserRoles.FirstOrDefault(r => r.Id == roleDto.Id); - var rolePermissions = GetNestedPermissions(role, 10); - if ((rolePermissions?.Any()) != true) - continue; - - foreach (var newPermission in rolePermissions) - { - if (permissions.ContainsKey(newPermission.Id)) - { - permissions[newPermission.Id] = newPermission.Adapt(); - } - else - { - permissions.Add(newPermission.Id, - new PermissionBaseDto - { - Id = newPermission.Id, - Name = newPermission.Name ?? - cachePermission.FirstOrDefault(p => p.Id == newPermission.Id).Name - }); - } - } - } - - return permissions.Values; - } - private async Task UpdatePermissionsAsync(UserRoleDto roleDto, CancellationToken token) { - await permissionService.DeleteAllByRoleAsync(roleDto.Id, token) - .ConfigureAwait(false); - if (!roleDto.Permissions.Any()) + if (roleDto?.Permissions is null) return; - - var newPermissions = roleDto.Permissions.Select(p => new PermissionDto + + await cacheUserRolePermissions.RemoveAsync(r => r.IdUserRole == roleDto.Id, token) + .ConfigureAwait(false); + + if (!roleDto.Permissions.Any()) + return; + + var newRelationRoleToPermission = roleDto.Permissions.Select(p => new RelationUserRolePermission { - Id = p.Id, + IdPermission = p.Id, IdUserRole = roleDto.Id, - Name = p.Name }); - await permissionService.InsertRangeAsync(newPermissions, token) + await cacheUserRolePermissions.InsertAsync(newRelationRoleToPermission, token) .ConfigureAwait(false); } - private IEnumerable GetNestedPermissions(UserRole role, int recursionLevel = 7) - { - var permissionRelations = role.RelationUserRolePermissions.ToList(); - var permissionIds = permissionRelations.Select(p => p.IdPermission); - if (role.IdParent is null) - return cachePermission.Where(c => permissionIds.Contains(c.Id)); - if (recursionLevel == 0) - { - Trace.WriteLine($"User role with id: {role.Id} has more than 10 nested children"); - cachePermission.Where(c => permissionIds.Contains(c.Id)); - } - var parentRole = cacheUserRoles.FirstOrDefault(r => r.Id == role.IdParent); - if (parentRole is null) - return cachePermission.Where(c => permissionIds.Contains(c.Id)); - - var parentPermissions = GetNestedPermissions(parentRole, --recursionLevel); - - return cachePermission.Where(c => permissionIds.Contains(c.Id)).Union(parentPermissions); - } public Task DeleteAsync(int id, CancellationToken token = default) => cacheUserRoles.RemoveAsync(r => r.Id == id, token); @@ -173,7 +139,9 @@ namespace AsbCloudInfrastructure.Services public bool HasPermission(IEnumerable rolesIds, string permissionName) { - var permissionInfo = cachePermission.FirstOrDefault(p => p.Name.ToLower() == permissionName.ToLower()); + var permissionInfo = cacheUserRolePermissions + .FirstOrDefault(p => p.Permission?.Name.ToLower() == permissionName.ToLower()) + ?.Permission; if (permissionInfo is null) return false; @@ -197,5 +165,30 @@ namespace AsbCloudInfrastructure.Services } return false; } + + private static UserRole Convert(UserRoleDto dto) + { + var entity = dto.Adapt(); + return entity; + } + + private UserRoleDto Convert(UserRole entity) + { + var dto = entity.Adapt(); + if(entity.RelationUserRolePermissions?.Any() == true) + { + var permissionsIds = entity.RelationUserRolePermissions.Select(r => r.IdPermission); + dto.Permissions = cacheUserRolePermissions + .Where(r => permissionsIds.Contains(r.IdPermission)) + .Select(r => Convert(r.Permission)); + } + return dto; + } + + private static PermissionDto Convert(Permission entity) + { + var dto = entity.Adapt(); + return dto; + } } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/UserService.cs b/AsbCloudInfrastructure/Services/UserService.cs index d39aaf03..d4438fdd 100644 --- a/AsbCloudInfrastructure/Services/UserService.cs +++ b/AsbCloudInfrastructure/Services/UserService.cs @@ -101,10 +101,10 @@ namespace AsbCloudInfrastructure.Services return roles.SelectMany(r => RoleService.GetNestedById(r.IdUserRole)); } - public IEnumerable GetNestedPermissions(int idUser) + public IEnumerable GetNestedPermissions(int idUser) { var roles = GetRolesByIdUser(idUser); - return RoleService.GetNestedPermissions(roles); + return roles.SelectMany(r => r.Permissions); } private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoleNames, CancellationToken token) diff --git a/AsbCloudWebApi/Controllers/AdminPermissionController.cs b/AsbCloudWebApi/Controllers/AdminPermissionController.cs index 9fd28920..a7633f58 100644 --- a/AsbCloudWebApi/Controllers/AdminPermissionController.cs +++ b/AsbCloudWebApi/Controllers/AdminPermissionController.cs @@ -11,74 +11,10 @@ namespace AsbCloudWebApi.Controllers [Route("api/admin/permission")] [ApiController] [Authorize] - public class AdminPermissionController : ControllerBase - { - private readonly IPermissionService permissionService; - - public AdminPermissionController(IPermissionService permissionService) - { - this.permissionService = permissionService; - } - - /// - /// Получает список всех разрешений для роли - /// - /// id роли - /// Токен отмены задачи - /// - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - [Permission] - public async Task GetByIdRoleAsync(int idRole, CancellationToken token = default) - { - var result = await permissionService.GetByIdRoleAsync(idRole, token); - return Ok(result); - } - - /// - /// Добавляет разрешения для роли - /// - /// Объекты новых разрешений для справочника - /// Токен отмены задачи - /// - [HttpPost] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task InsertRangeAsync(IEnumerable dtos, - CancellationToken token = default) - { - var result =await permissionService.InsertRangeAsync(dtos, token); - return Ok(result); - } - - /// - /// Обновляет разрешение для роли - /// - /// Объект разрешения - /// Токен отмены задачи - /// - [HttpPut] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateAsync(PermissionDto dto, - CancellationToken token = default) - { - var result = await permissionService.UpdateAsync(dto, token); - return Ok(result); - } - - /// - /// Удаляет разрешение для роли - /// - /// id разрешения - /// id роли для удаления разрешения - /// Токен отмены задачи - /// - [HttpDelete("{idPermission}/{idUserRole}")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task DeleteAsync(int idUserRole, int idPermission, - CancellationToken token = default) - { - var result = await permissionService.DeleteAsync(idUserRole, idPermission, token); - return Ok(result); - } + public class AdminPermissionController : CrudController> + { + public AdminPermissionController(ICrudService permissionService) + :base(permissionService) + {} } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/AdminUserController.cs b/AsbCloudWebApi/Controllers/AdminUserController.cs index e43cb253..a14afab3 100644 --- a/AsbCloudWebApi/Controllers/AdminUserController.cs +++ b/AsbCloudWebApi/Controllers/AdminUserController.cs @@ -2,6 +2,8 @@ using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using System.Threading; +using System.Threading.Tasks; namespace AsbCloudWebApi.Controllers { @@ -14,6 +16,5 @@ namespace AsbCloudWebApi.Controllers :base(service) {} - } }