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 UserService : IUserService { private readonly CacheTable cacheUsers; private readonly CacheTable cacheRelationUserToRoles; public List Includes { get; } public IUserRoleService RoleService { get; } public UserService(IAsbCloudDbContext context, CacheDb cacheDb, IUserRoleService roleService) { var db = (AsbCloudDbContext)context; cacheUsers = cacheDb.GetCachedTable( db, new[] { nameof(User.RelationUsersUserRoles), nameof(User.Company), }); cacheRelationUserToRoles = cacheDb.GetCachedTable( db, new[] { nameof(RelationUserUserRole.User), nameof(RelationUserUserRole.UserRole), }); RoleService = roleService; } public async Task InsertAsync(UserExtendedDto dto, CancellationToken token = default) { var entity = dto.Adapt(); var updatedEntity = await cacheUsers.InsertAsync(entity, token).ConfigureAwait(false); await UpdateRolesCacheForUserAsync((int)updatedEntity.Id, dto.RoleNames, token); return updatedEntity?.Id ?? 0; } public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token = default) { throw new NotImplementedException(); } public async Task> GetAllAsync(CancellationToken token = default) { var entities = (await cacheUsers.WhereAsync(token).ConfigureAwait(false)) .ToList(); if (entities.Count == 0) return null; var dtos = entities.Adapt().ToList(); for (var i = 0; i < dtos.Count; i++) dtos[i].RoleNames = GetRolesNamesByIdUser(dtos[i].Id); return dtos; } public async Task GetAsync(int id, CancellationToken token = default) { var entity = await cacheUsers.FirstOrDefaultAsync(u=>u.Id == id, token).ConfigureAwait(false); var dto = entity.Adapt(); dto.RoleNames = GetRolesNamesByIdUser(dto.Id); return dto; } public async Task UpdateAsync(int id, UserExtendedDto dto, CancellationToken token = default) { var entity = dto.Adapt(); await UpdateRolesCacheForUserAsync(id, dto.RoleNames, token); var result = await cacheUsers.UpsertAsync(entity, token) .ConfigureAwait(false); return result; } public Task DeleteAsync(int id, CancellationToken token = default) => cacheUsers.RemoveAsync(r => r.Id == id, token); public Task DeleteAsync(IEnumerable ids, CancellationToken token = default) => cacheUsers.RemoveAsync(r => ids.Contains(r.Id), token); private IEnumerable GetRolesNamesByIdUser(int idUser) => GetRolesByIdUser(idUser) ?.Select(r => r.Caption) .Distinct(); public IEnumerable GetRolesByIdUser(int idUser) { var roles = cacheRelationUserToRoles.Where(r => r.IdUser == idUser); if (roles?.Any() != true) return null; return roles.SelectMany(r => RoleService.GetNestedById(r.IdUserRole)); } public IEnumerable GetNestedPermissions(int idUser) { var roles = GetRolesByIdUser(idUser); if(roles?.Any() != true) return null; var permissions = roles .Where(r => r.Permissions is not null) .SelectMany(r => r.Permissions); return permissions; } private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable newRoleNames, CancellationToken token) { if (newRoleNames?.Any() != true) return; var relatrions = new List(newRoleNames.Count()); foreach (var roleName in newRoleNames) { var role = await RoleService.GetByNameAsync(roleName, token) .ConfigureAwait(false); if (role != null) relatrions.Add(new() { IdUser = idUser, IdUserRole = role.Id, }); } await cacheRelationUserToRoles.RemoveAsync(r => r.IdUser == idUser, token) .ConfigureAwait(false); await cacheRelationUserToRoles.InsertAsync(relatrions, token) .ConfigureAwait(false); } public bool HasAnyRoleOf(int idUser, IEnumerable roleNames) { if(!roleNames.Any()) return true; var userRoleNames = GetRolesNamesByIdUser(idUser); foreach (var roleName in userRoleNames) if (roleNames.Contains(roleName)) return true; return false; } public bool HasAnyRoleOf(int idUser, IEnumerable roleIds) { if (!roleIds.Any()) return true; var userRoles = GetRolesByIdUser(idUser); foreach (var role in userRoles) if (roleIds.Contains(role.Id)) return true; return false; } public bool HasPermission(int idUser, string permissionName) { var relationsToRoles = cacheRelationUserToRoles.Where(r=>r.IdUser == idUser); if (relationsToRoles is null) return false; return RoleService.HasPermission(relationsToRoles.Select(r => r.IdUserRole), permissionName); } } }