DD.WellWorkover.Cloud/AsbCloudInfrastructure/Repository/UserRoleRepository.cs

294 lines
11 KiB
C#
Raw Normal View History

using AsbCloudApp.Comparators;
using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudDb;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.EfCache;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository
{
#nullable enable
public class UserRoleRepository : IUserRoleRepository
{
private readonly IAsbCloudDbContext dbContext;
private const string userRoleCacheTag = "UserRole";
private const string relationUserRoleUserRoleCacheTag = "RelationUserRoleUserRole";
private const string relationUserRolePermissionsCacheTag = "RelationUserRolePermissions";
private static readonly TimeSpan relationCacheObsolence = TimeSpan.FromMinutes(15);
public UserRoleRepository(IAsbCloudDbContext dbContext)
{
this.dbContext = dbContext;
}
public async Task<int> InsertAsync(UserRoleDto dto, CancellationToken token)
{
var entity = dto.Adapt<UserRole>();
var updatedEntity = await dbContext.UserRoles.AddAsync(entity, token)
.ConfigureAwait(false);
dto.Id = updatedEntity.Entity.Id;
await UpdatePermissionsAsync(dto, token);
await UpdateIncludedRolesAsync(dto, token);
await dbContext.SaveChangesAsync(token);
DropCacheUserRole();
2022-11-08 12:04:09 +05:00
return updatedEntity.Entity.Id;
}
public Task<int> InsertRangeAsync(IEnumerable<UserRoleDto> newItems, CancellationToken token)
{
throw new NotImplementedException();
}
public async Task<IEnumerable<UserRoleDto>> GetAllAsync(CancellationToken token)
{
2022-11-08 11:55:47 +05:00
var entities = await GetCacheUserRoleAsync(token)
.ConfigureAwait(false);
2022-11-08 11:55:47 +05:00
return entities.Select(Convert);
2022-10-27 14:18:59 +05:00
}
public UserRoleDto? GetOrDefault(int id)
{
2022-11-08 11:55:47 +05:00
var entity = GetCacheUserRole().FirstOrDefault(x => x.Id == id);
if (entity is null)
return null;
2022-11-08 11:55:47 +05:00
return Convert(entity);
}
public async Task<UserRoleDto?> GetOrDefaultAsync(int id, CancellationToken token)
{
2022-11-08 11:55:47 +05:00
var entity = (await GetCacheUserRoleAsync(token)
.ConfigureAwait(false)).FirstOrDefault(r => r.Id == id);
2022-11-08 11:55:47 +05:00
if (entity is null)
return null;
2022-11-08 11:55:47 +05:00
return Convert(entity);
}
2022-10-27 14:18:59 +05:00
public async Task<IEnumerable<UserRoleDto>> GetByNamesAsync(IEnumerable<string> names, CancellationToken token)
{
if (names?.Any() != true)
2022-10-27 14:18:59 +05:00
return Enumerable.Empty<UserRoleDto>();
2022-11-08 11:55:47 +05:00
var entities = (await GetCacheUserRoleAsync(token))
2022-10-27 14:18:59 +05:00
.Where(r => names.Contains(r.Caption));
2022-11-08 11:55:47 +05:00
if (entities?.Count() != names.Count())
throw new ArgumentInvalidException("Invalid role names", nameof(names));
2022-10-27 14:18:59 +05:00
2022-11-08 11:55:47 +05:00
return entities.Select(Convert);
}
public async Task<int> UpdateAsync(UserRoleDto dto, CancellationToken token)
{
var entity = Convert(dto);
await UpdatePermissionsAsync(dto, token);
await UpdateIncludedRolesAsync(dto, token);
var result = dbContext.UserRoles.Upsert(entity);
await dbContext.SaveChangesAsync(token);
DropCacheUserRole();
2022-11-08 12:04:09 +05:00
return result.Entity.Id;
}
2022-10-27 14:18:59 +05:00
public IEnumerable<UserRoleDto> GetNestedById(int id, int recursionLevel = 7)
{
var role = GetCacheUserRole()
.FirstOrDefault(r => r.Id == id);
if (role is null)
2022-10-27 14:18:59 +05:00
return Enumerable.Empty<UserRoleDto>();
var roles = new SortedSet<UserRoleDto>(ComparerIId.GetInstance()) { Convert(role) };
if (recursionLevel <= 0 || role.RelationUserRoleUserRoles?.Any() != true)
return roles;
foreach (var relation in role.RelationUserRoleUserRoles)
{
var nestedRoles = GetNestedById(relation.IdInclude, --recursionLevel);
if (nestedRoles?.Any() != true)
continue;
foreach (var nestedRole in nestedRoles)
roles.Add(nestedRole);
}
return roles;
}
public async Task<int> DeleteAsync(int id, CancellationToken token)
{
2022-11-08 11:55:47 +05:00
var entity = (await GetCacheUserRoleAsync(token)).FirstOrDefault(r => r.Id == id);
2022-11-08 11:55:47 +05:00
if (entity is not null)
{
2022-11-08 11:55:47 +05:00
var removeEntity = dbContext.UserRoles.Remove(entity);
await dbContext.SaveChangesAsync(token);
DropCacheUserRole();
2022-11-08 12:04:09 +05:00
return removeEntity.Entity.Id;
}
else return 0;
}
public bool HasPermission(IEnumerable<int> rolesIds, string permissionName)
{
var permissionInfo = GetCacheRelationUserRolePermissions()
.FirstOrDefault(p => p. Permission?.Name.ToLower() == permissionName.ToLower())
?.Permission;
if (permissionInfo is null)
return false;
if (rolesIds.Contains(1))
return true;
var idPermissionInfo = permissionInfo.Id;
2022-11-08 11:55:47 +05:00
var entities = GetCacheUserRole()
.Where(r => rolesIds.Contains(r.Id));
2022-10-27 15:44:04 +05:00
2022-11-08 11:55:47 +05:00
foreach (var role in entities)
if (HasPermission(role, idPermissionInfo))
return true;
return false;
}
private bool HasPermission(UserRole userRole, int idPermission, int recursionLevel = 7)
{
if (userRole.RelationUserRolePermissions.Any(p => p.IdPermission == idPermission))
return true;
if (recursionLevel <= 0 || userRole.RelationUserRoleUserRoles?.Any() != true)
return false;
foreach (var relation in userRole.RelationUserRoleUserRoles)
{
2022-11-08 11:55:47 +05:00
var entity = GetCacheUserRole()
.First(p => p.Id == relation.IdInclude);
2022-11-08 11:55:47 +05:00
if (HasPermission(entity, idPermission, --recursionLevel))
return true;
}
return false;
}
private async Task UpdateIncludedRolesAsync(UserRoleDto dto, CancellationToken token)
{
if (dto?.Roles is null)
return;
var relations = (await GetCacheRelationUserRoleUserRoleAsync(token).ConfigureAwait(false))
.Where(r => r.Id == dto.Id);
dbContext.RelationUserRoleUserRoles.RemoveRange(relations);
if (dto.Roles.Any())
{
var newRelations = dto.Roles.Select(r => new RelationUserRoleUserRole { Id = dto.Id, IdInclude = r.Id });
await dbContext.RelationUserRoleUserRoles.AddRangeAsync(newRelations, token);
await dbContext.SaveChangesAsync(token);
}
2022-11-08 12:12:46 +05:00
DropCacheRelationUserRoleUserRole();
}
private async Task UpdatePermissionsAsync(UserRoleDto dto, CancellationToken token)
{
if (dto?.Permissions is null)
return;
var relations = (await GetCacheRelationUserRolePermissionsAsync(token).ConfigureAwait(false))
.Where(r => r.IdUserRole == dto.Id);
dbContext.RelationUserRolePermissions.RemoveRange(relations);
if (dto.Permissions.Any())
{
var newRelations = dto.Permissions.Select(p => new RelationUserRolePermission
{
IdPermission = p.Id,
IdUserRole = dto.Id,
});
await dbContext.RelationUserRolePermissions.AddRangeAsync(newRelations, token);
await dbContext.SaveChangesAsync(token);
}
2022-11-08 12:12:46 +05:00
DropCacheRelationUserRolePermissions();
}
private Task<IEnumerable<UserRole>> GetCacheUserRoleAsync(CancellationToken token)
=> dbContext.UserRoles
.Include(r => r.RelationUserRolePermissions)
.Include(r => r.RelationUserRoleUserRoles)
.Include(r => r.RelationUsersUserRoles)
.FromCacheAsync(userRoleCacheTag, relationCacheObsolence, token);
private IEnumerable<UserRole> GetCacheUserRole()
=> dbContext.UserRoles
.Include(r => r.RelationUserRolePermissions)
.Include(r => r.RelationUserRoleUserRoles)
.Include(r => r.RelationUsersUserRoles)
.FromCache(userRoleCacheTag, relationCacheObsolence);
private void DropCacheUserRole()
=> dbContext.RelationUserUserRoles.DropCache(userRoleCacheTag);
private Task<IEnumerable<RelationUserRoleUserRole>> GetCacheRelationUserRoleUserRoleAsync(CancellationToken token)
=> dbContext.RelationUserRoleUserRoles
.Include(r => r.IncludeRole)
.Include(r => r.Role)
.FromCacheAsync(relationUserRoleUserRoleCacheTag, relationCacheObsolence, token);
private void DropCacheRelationUserRoleUserRole()
=> dbContext.RelationUserUserRoles.DropCache(relationUserRoleUserRoleCacheTag);
private Task<IEnumerable<RelationUserRolePermission>> GetCacheRelationUserRolePermissionsAsync(CancellationToken token)
=> dbContext.RelationUserRolePermissions
.Include(r => r.UserRole)
.Include(r => r.Permission)
.FromCacheAsync(relationUserRolePermissionsCacheTag, relationCacheObsolence, token);
private IEnumerable<RelationUserRolePermission> GetCacheRelationUserRolePermissions()
=> dbContext.RelationUserRolePermissions
.Include(r => r.UserRole)
.Include(r => r.Permission)
.FromCache(relationUserRolePermissionsCacheTag, relationCacheObsolence);
2022-11-08 11:33:35 +05:00
private void DropCacheRelationUserRolePermissions()
=> dbContext.RelationUserRolePermissions.DropCache(relationUserRolePermissionsCacheTag);
private UserRoleDto Convert(UserRole entity)
{
var dto = entity.Adapt<UserRoleDto>();
if (entity.RelationUserRolePermissions?.Any() == true)
{
dto.Permissions = GetCacheRelationUserRolePermissions()
.Where(r => entity.Id == r.IdUserRole)
.Select(r => Convert(r.Permission));
}
if (entity.RelationUserRoleUserRoles?.Any() == true)
{
2022-10-28 09:05:33 +05:00
var rolesCache = GetCacheUserRole();
dto.Roles = entity.RelationUserRoleUserRoles
.Select(rel => Convert(rolesCache
.First(r => r.Id == rel.IdInclude)))
.ToArray();
}
return dto;
}
private static PermissionDto Convert(Permission entity)
{
var dto = entity.Adapt<PermissionDto>();
return dto;
}
private static UserRole Convert(UserRoleDto dto)
{
var entity = dto.Adapt<UserRole>();
return entity;
}
}
#nullable disable
}