DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/UserRoleService.cs

205 lines
8.2 KiB
C#
Raw Normal View History

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;
2021-12-03 09:44:10 +05:00
using AsbCloudApp.Services;
using System;
namespace AsbCloudInfrastructure.Services
{
public class UserRoleService : IUserRoleService
{
private readonly CacheTable<UserRole> cacheUserRoles;
private readonly CacheTable<PermissionInfo> cachePermissionInfo;
2021-12-03 09:44:10 +05:00
private readonly IPermissionService permissionService;
public List<string> Includes { get; } = new();
public UserRoleService(IAsbCloudDbContext context, CacheDb cacheDb, IPermissionService permissionService)
{
cacheUserRoles = cacheDb.GetCachedTable<UserRole>((AsbCloudDbContext)context, new [] { nameof(UserRole.Permissions) });
cachePermissionInfo = cacheDb.GetCachedTable<PermissionInfo>((AsbCloudDbContext)context);
2021-12-03 09:44:10 +05:00
this.permissionService = permissionService;
}
public async Task<int> InsertAsync(UserRoleDto dto, CancellationToken token = default)
{
var entity = dto.Adapt<UserRole>();
var updatedEntity = await cacheUserRoles.InsertAsync(entity, token)
.ConfigureAwait(false);
await UpdatePermissionsAsync(dto, token);
await cacheUserRoles.RefreshAsync(true, token)
.ConfigureAwait(false);
return updatedEntity?.Id ?? 0;
}
public Task<int> InsertRangeAsync(IEnumerable<UserRoleDto> dtos, CancellationToken token = default)
{
throw new NotImplementedException();
//var entities = dtos.Adapt<UserRole>();
//return await cacheUserRoles.InsertAsync(entities, token).ConfigureAwait(false);
}
public async Task<IEnumerable<UserRoleDto>> GetAllAsync(CancellationToken token = default)
{
var entities = await cacheUserRoles.WhereAsync(token)
.ConfigureAwait(false);
var dtos = entities.Adapt<UserRoleDto>();
return dtos;
}
public async Task<UserRoleDto> GetAsync(int id, CancellationToken token = default)
{
var entity = await cacheUserRoles.FirstOrDefaultAsync(r=>r.Id == id, token)
.ConfigureAwait(false);
var dto = entity?.Adapt<UserRoleDto>();
return dto;
}
public async Task<UserRoleDto> GetByNameAsync(string name, CancellationToken token = default)
{
var entity = await cacheUserRoles.FirstOrDefaultAsync(r => r.Caption == name, token)
.ConfigureAwait(false);
var dto = entity?.Adapt<UserRoleDto>();
return dto;
}
public async Task<int> UpdateAsync(int id, UserRoleDto dto, CancellationToken token = default)
{
dto.Id = id;
var entity = dto.Adapt<UserRole>();
await UpdatePermissionsAsync(dto, token);
await cacheUserRoles.UpsertAsync(entity, token)
.ConfigureAwait(false);
return id;
}
public List<UserRoleDto> GetNestedById(int id, int recursionLevel = 7)
{
var role = cacheUserRoles.FirstOrDefault(r => r.Id == id);
if (role is null)
return null;
var dto = role.Adapt<UserRoleDto>();
if (role.IdParent is null || recursionLevel == 0)
return new List<UserRoleDto> { dto };
var parentRoles = GetNestedById((int)role.IdParent, --recursionLevel) ??
new List<UserRoleDto>();
parentRoles.Add(dto);
return parentRoles;
}
public IEnumerable<PermissionBaseDto> GetNestedPermissions(IEnumerable<UserRoleDto> roles)
{
var permissions = new Dictionary<int, PermissionBaseDto>(16);
foreach (var roleDto in roles)
{
var role = cacheUserRoles.FirstOrDefault(r => r.Id == roleDto.Id);
var rolePermissions = GetNestedPermissions(role, 10);
if ((rolePermissions?.Any()) != true)
continue;
foreach (var newPermission in rolePermissions)
{
if (permissions.ContainsKey(newPermission.IdPermissionInfo))
{
permissions[newPermission.IdPermissionInfo].Value |= newPermission.Value;
}
else
{
permissions.Add(newPermission.IdPermissionInfo,
new PermissionBaseDto
{
IdPermissionInfo = newPermission.IdPermissionInfo,
PermissionName = newPermission.PermissionInfo?.Name ??
cachePermissionInfo.FirstOrDefault(p => p.Id == newPermission.IdPermissionInfo).Name,
Value = newPermission.Value,
});
}
}
}
return permissions.Values;
}
private async Task UpdatePermissionsAsync(UserRoleDto roleDto, CancellationToken token)
{
await permissionService.DeleteAllByRoleAsync(roleDto.Id, token)
.ConfigureAwait(false);
if (!roleDto.Permissions.Any())
return;
var newPermissions = roleDto.Permissions.Select(p => new PermissionDto
{
IdPermissionInfo = p.IdPermissionInfo,
IdUserRole = roleDto.Id,
PermissionName = p.PermissionName,
Value = p.Value,
});
await permissionService.InsertRangeAsync(newPermissions, token)
.ConfigureAwait(false);
}
private IEnumerable<Permission> GetNestedPermissions(UserRole role, int recursionLevel = 7)
{
var permissions = role.Permissions.ToList();
if (role.IdParent is null)
return permissions;
if (recursionLevel == 0)
2021-12-03 09:44:10 +05:00
{
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;
2021-12-03 09:44:10 +05:00
var parentPermissions = GetNestedPermissions(parentRole, --recursionLevel);
return permissions.Union(parentPermissions);
}
public Task<int> DeleteAsync(int id, CancellationToken token = default)
=> cacheUserRoles.RemoveAsync(r => r.Id == id, token);
public Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token = default)
=> cacheUserRoles.RemoveAsync(r => ids.Contains(r.Id), token);
public bool HasPermission(IEnumerable<int> rolesIds, string permissionName, int permissionMask = 0)
{
var permissionInfo = cachePermissionInfo.FirstOrDefault(p => p.Name.ToLower() == permissionName.ToLower());
if (permissionInfo is null)
return false;
if (permissionMask == 0)
permissionMask = -1;
var idPermissionInfo = permissionInfo.Id;
var roles = cacheUserRoles.Where(r => rolesIds.Contains(r.Id));
foreach (var role in roles)
if (HasPermission(role, idPermissionInfo, permissionMask))
return true;
return false;
}
private bool HasPermission(UserRole userRole, int idPermissionInfo, int permissionMask, int recursionLevel = 7)
{
if (userRole.Permissions.Any(p => p.IdPermissionInfo == idPermissionInfo && (p.Value & permissionMask) > 0))
return true;
if (userRole.IdParent is not null && recursionLevel > 0)
{
var parentRole = cacheUserRoles.FirstOrDefault(p => p.Id == userRole.IdParent);
return HasPermission(parentRole, idPermissionInfo, permissionMask, --recursionLevel);
}
return false;
}
}
}