using System.Collections.Generic; using System.Diagnostics; 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 cachePermissions; private readonly CacheTable cacheUserRolesPermissions; private int counter = 0; public UserRoleService(IAsbCloudDbContext context, CacheDb cacheDb) : base(context) { cacheUserRoles = cacheDb.GetCachedTable((AsbCloudDbContext)context); cachePermissions = cacheDb.GetCachedTable((AsbCloudDbContext)context); cacheUserRolesPermissions = 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) { dto.PermissionIds = GetAncestorsPermissionIds(dto, ref counter); var newRoleId = await base.InsertAsync(dto, token); if (dto.PermissionIds == default) return newRoleId; foreach (var pId in dto.PermissionIds) { var relation = new RelationUserRolePermission() { IdUserRole = newRoleId, IdPermission = pId }; context.RelationUserRolesPermissions.Add(relation); } return await context.SaveChangesAsync(token); } public override async Task UpdateAsync(int id, UserRoleDto item, CancellationToken token = default) { var result = await base.UpdateAsync(id, item, token); if (item.PermissionIds == default) return result; await cacheUserRolesPermissions.RemoveAsync(r => r.IdUserRole == item.Id, token) .ConfigureAwait(false); var newRelations = item.PermissionIds.Select(p => new RelationUserRolePermission() { IdUserRole = item.Id, IdPermission = p }); await cacheUserRolesPermissions.InsertAsync(newRelations, token); return result; } private UserRoleDto FillUserRoleWithPermissions(UserRoleDto roleDto) { var rolePermissionIds = cacheUserRolesPermissions.Where(c => c.IdUserRole == roleDto.Id).Select(p => p.IdPermission); roleDto.Permissions = cachePermissions.Where(permission => rolePermissionIds.Contains(permission.Id)) .Adapt(); return roleDto; } private IEnumerable GetAncestorsPermissionIds(UserRoleDto userRoleDto, ref int counter) { var idParent = userRoleDto.IdParent; var resultPermissionsIds = userRoleDto.PermissionIds ?? new List(); if (idParent == default) return resultPermissionsIds; if (counter > 10) { Trace.WriteLine($"User role with id: {userRoleDto.Id} has more than 10 nested parents"); return resultPermissionsIds; } var parentRole = cacheUserRoles.FirstOrDefault(r => r.Id == idParent) .Adapt(); var parentRolePermissionsIds = cacheUserRolesPermissions.Where(p => p.IdUserRole == parentRole.Id).Select(perm => perm.IdPermission); parentRole.PermissionIds = resultPermissionsIds.Union(parentRolePermissionsIds); counter++; return GetAncestorsPermissionIds(parentRole, ref counter); } } }