using System.Diagnostics; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.Cache; using Mapster; using AsbCloudApp.Services; namespace AsbCloudInfrastructure.Services { public class UserRoleService : IUserRoleService { private readonly CacheTable cacheUserRoles; private readonly IPermissionService permissionService; public List Includes { get; } = new(); public UserRoleService(IAsbCloudDbContext context, CacheDb cacheDb, IPermissionService permissionService) { cacheUserRoles = cacheDb.GetCachedTable((AsbCloudDbContext)context, new [] { nameof(UserRole.Permissions) }); this.permissionService = permissionService; } public async Task> GetAllAsync(CancellationToken token = default) { var entities = await cacheUserRoles.WhereAsync(token) .ConfigureAwait(false); var dtos = entities.Adapt(); return dtos; } public async Task GetAsync(int id, CancellationToken token = default) { var entity = await cacheUserRoles.FirstOrDefaultAsync(r=>r.Id == id, token) .ConfigureAwait(false); var dto = entity?.Adapt(); return dto; } public async Task InsertAsync(UserRoleDto dto, CancellationToken token = default) { var entity = dto.Adapt(); var updatedEntity = await cacheUserRoles.InsertAsync(entity, token).ConfigureAwait(false); if (dto.Permissions?.Any() != true) return updatedEntity?.Id ?? 0; foreach (var permission in dto.Permissions) permission.IdUserRole = updatedEntity.Id; await permissionService.InsertRangeAsync(dto.Permissions, token).ConfigureAwait(false); await cacheUserRoles.RefreshAsync(true, token) .ConfigureAwait(false); return updatedEntity?.Id ?? 0; } public async Task InsertRangeAsync(IEnumerable dtos, CancellationToken token = default) { var entities = dtos.Adapt(); return await cacheUserRoles.InsertAsync(entities, token).ConfigureAwait(false); } public async Task UpdateAsync(int id, UserRoleDto dto, CancellationToken token = default) { var entity = dto.Adapt(); entity.Id = id; await cacheUserRoles.UpsertAsync(entity, token) .ConfigureAwait(false); if(dto.Permissions is not null) { await permissionService.DeleteAllByRoleAsync(id, token) .ConfigureAwait(false); if (dto.Permissions.Any()) { foreach (var permission in dto.Permissions) permission.IdUserRole = id; await permissionService.InsertRangeAsync(dto.Permissions, token) .ConfigureAwait(false); } await cacheUserRoles.RefreshAsync(true, token) .ConfigureAwait(false); } return id; } private IEnumerable GetNestedPermissions(UserRole role, int counter = 10) { var permissions = role.Permissions.ToList(); if (role.IdParent is null) return permissions; if (counter == 0) { Trace.WriteLine($"User role with id: {role.Id} has more than 10 nested childs"); return permissions; } var parentRole = cacheUserRoles.FirstOrDefault(r => r.Id == role.IdParent); if (parentRole is null) return permissions; var parentPermissions = GetNestedPermissions(parentRole, --counter); Merge(ref permissions, parentPermissions); return permissions; } private static void Merge(ref List permissions, IEnumerable newPermissions) { foreach (var newPermission in newPermissions) { var permissionIndex = permissions.FindIndex(p => p.IdPermission == newPermission.IdPermission); if (permissionIndex == -1) permissions.Add(newPermission); else { var permission = permissions[permissionIndex]; permissions[permissionIndex] = new Permission { IdPermission = permission.IdPermission, IdUserRole = permission.IdUserRole, PermissionValue = permission.PermissionValue | newPermission.PermissionValue, }; } } } public Task DeleteAsync(int id, CancellationToken token = default) => cacheUserRoles.RemoveAsync(r => r.Id == id, token); public Task DeleteAsync(IEnumerable ids, CancellationToken token = default) => cacheUserRoles.RemoveAsync(r => ids.Contains(r.Id), token); } }