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; namespace AsbCloudInfrastructure.Services { public class UserRoleService : CrudServiceBase { private readonly CacheTable cacheUserRoles; private readonly CacheTable cachePermissionsInfo; private readonly CacheTable cachePermissions; private int counter = 0; public UserRoleService(IAsbCloudDbContext context, CacheDb cacheDb) : base(context) { cacheUserRoles = cacheDb.GetCachedTable((AsbCloudDbContext)context); cachePermissionsInfo = cacheDb.GetCachedTable((AsbCloudDbContext)context); cachePermissions = cacheDb.GetCachedTable((AsbCloudDbContext)context); } public override async Task> GetPageAsync(int skip = 0, int take = 32, CancellationToken token = default) { var rolesDtos = await base.GetPageAsync(skip, take,token); rolesDtos.Items = rolesDtos.Items.Select(FillUserRoleWithPermissions).ToList(); return rolesDtos; } public override async Task GetAsync(int id, CancellationToken token = default) { var roleDto = await base.GetAsync(id,token); return roleDto is null ? null : FillUserRoleWithPermissions(roleDto); } public override async Task InsertAsync(UserRoleDto dto, CancellationToken token = default) { var newRoleId = await base.InsertAsync(dto, token); var newRolePermissions = GetAncestorsPermissions(newRoleId, dto.Permissions.Adapt(), dto.IdParent, ref counter); return await cachePermissions.InsertAsync(newRolePermissions, token); } public override async Task UpdateAsync(int id, UserRoleDto item, CancellationToken token = default) { foreach (var p in item.Permissions) p.IdUserRole = item.Id; var result = await base.UpdateAsync(id, item, token); await cachePermissions.RemoveAsync(r => r.IdUserRole == item.Id, token) .ConfigureAwait(false); var newPermissions = item.Permissions.Adapt(); await cachePermissions.InsertAsync(newPermissions, token); return result; } private UserRoleDto FillUserRoleWithPermissions(UserRoleDto roleDto) { roleDto.Permissions = cachePermissions.Where(c => c.IdUserRole == roleDto.Id).Adapt(); return roleDto; } private IEnumerable GetAncestorsPermissions(int idRole, IEnumerable currentPermissions, int? idParent, ref int counter) { if (idParent == null) return currentPermissions; if (counter > 10) { Trace.WriteLine($"User role with id: {idRole} has more than 10 nested parents"); return currentPermissions; } var parentRole = cacheUserRoles.FirstOrDefault(r => r.Id == idParent); var parentRolePermissions = cachePermissions.Where(p => p.IdUserRole == parentRole.Id); var resultPermissions = currentPermissions.Union(parentRolePermissions); counter++; return GetAncestorsPermissions(parentRole.Id, resultPermissions, parentRole.IdParent, ref counter); } } }