Files
jinko.yikatong/Src/Dlhis.Basic/Device/Services/Implements/BasePermissionAnalyzeService.cs
2024-12-13 16:32:26 +08:00

302 lines
12 KiB
C#

using Dlhis.Basic.DataPermissions;
using Dlhis.Basic.Device.Dtos;
using Dlhis.Basic.Device.Request;
using Dlhis.Basic.Device.Response;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Dlhis.Entity.Sys.Entities;
using Dlhis.Entity.Sys.Enums;
using Kurisu.AspNetCore.Authentication.Abstractions;
using Kurisu.AspNetCore.DataAccess.Entity;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Scope;
using Kurisu.AspNetCore.Utils.Extensions;
using SqlSugar;
namespace Dlhis.Basic.Device.Services.Implements;
/// <summary>
/// 权限分析基类
/// </summary>
public abstract class BasePermissionAnalyzeService : IPermissionAnalyzeService
{
private readonly ICurrentUser _currentUser;
private readonly IMyDataPermissionService _myDataPermissionService;
private readonly IDevicePermissionAnalyzeService _devicePermissionAnalyzeService;
protected IDbContext DbContext { get; }
protected BasePermissionAnalyzeService(IServiceProvider serviceProvider)
{
_currentUser = serviceProvider.GetService<ICurrentUser>();
_myDataPermissionService = serviceProvider.GetService<IMyDataPermissionService>();
DbContext = serviceProvider.GetService<IDbContext>();
CurrentTenantId = _currentUser.GetStringTenantId();
_devicePermissionAnalyzeService = serviceProvider.GetService<IDevicePermissionAnalyzeService>();
}
private string CurrentTenantId { get; }
protected ISugarQueryable<DevicePermissionEntity> DevicePermission => DbContext.Queryable<DevicePermissionEntity>();
public async Task<DevicePermissionAssignResponse> AnalyzeAsync(DevicePermissionSaveRequest request)
{
await CheckWhetherAssignToTopDeviceGroupAsync(request);
await CheckAssignedToTenantAsync(request);
var dps = await GetAssignedDevicePermissionsAsync(request);
(List<Guid> codesToAdd, List<Guid> codesToDelete) = await GetDiffAsync(request.UniqueType, dps, request.Codes);
if (codesToAdd.IsEmpty() && codesToDelete.IsEmpty())
{
return new DevicePermissionAssignResponse(0, 0);
}
var devicesToAdd = await DbContext.Queryable<DeviceEntity>().Where(x => codesToAdd.Contains(x.Code)).Distinct().ToListAsync();
var devicesToDelete = await DbContext.Queryable<DeviceEntity>().Where(x => codesToDelete.Contains(x.Code)).Distinct().ToListAsync();
var gainfoNos = await GetGainfoNosAsync(request.GetActualAssignValue());
var userTenantDeviceCodes =
devicesToDelete.IsPresent() && request.AssignType != AssignTypeEnumType.Tenant
? await _devicePermissionAnalyzeService.GetUserAssignDeviceCodesWithTypeInTenantAsync(gainfoNos, request.AssignType)
: new Dictionary<string, IEnumerable<TenantAssignTypeDeviceCode>>();
var tasks = new List<DeviceTaskEntity>();
foreach (var gainfoNo in gainfoNos)
{
tasks.AddRange(devicesToAdd.Select(x => new DeviceTaskEntity
{
Type = DeviceTaskEnumType.Add,
DeviceType = x.Type,
UserId = null,
UserNo = gainfoNo,
DeviceUniqueNo = x.UniqueNo,
Status = DeviceTaskStatusEnumType.Wait,
Version = 0,
ResultMessage = null,
CancellationId = 0,
Source = DeviceTaskSourceEnumType.Manually,
Priority = 0,
TenantId = x.TenantId,
}).ToList());
if (userTenantDeviceCodes.Any())
{
var myDeviceCodes = userTenantDeviceCodes[gainfoNo].SelectMany(x => x.AssignTypes).SelectMany(x => x.Codes);
devicesToDelete = devicesToDelete.Where(p => devicesToDelete.Select(x => x.Code).Except(myDeviceCodes).Contains(p.Code)).ToList();
}
tasks.AddRange(devicesToDelete.Select(x => new DeviceTaskEntity
{
Type = DeviceTaskEnumType.Delete,
DeviceType = x.Type,
UserId = null,
UserNo = gainfoNo,
DeviceUniqueNo = x.UniqueNo,
Status = DeviceTaskStatusEnumType.Wait,
Version = 0,
ResultMessage = null,
CancellationId = 0,
Source = DeviceTaskSourceEnumType.Manually,
Priority = 0,
TenantId = x.TenantId,
}).ToList());
}
await ChunkInsertAsync(tasks);
await PersistDataAsync(dps, request);
return new DevicePermissionAssignResponse(devicesToAdd.Count, devicesToDelete.Count);
}
public async Task CheckAssignedToTenantAsync(DevicePermissionSaveRequest request)
{
if (request.AssignType != AssignTypeEnumType.Tenant)
{
(request.Type == DeviceTypeEnumType.Meal).ThrowIfTrue("餐饮设备需分配到厂区级别");
if (request.UniqueType == DeviceAssignmentTypeEnumType.Device)
{
if (await DbContext.Queryable<DevicePermissionEntity>()
.Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Device)
.Where(x => x.AssignType == AssignTypeEnumType.Tenant)
.Where(x => request.Codes.Contains(x.UniqueValue))
.AnyAsync())
{
true.ThrowIfTrue("存在设备分配到厂区中");
}
}
if (request.UniqueType == DeviceAssignmentTypeEnumType.Group)
{
var result = new List<Guid>();
var deviceGroups = await DbContext.Queryable<DeviceGroupEntity>().ToListAsync();
request.Codes.ForEach(groupCode => result.AddRange(RecursionHelper.HandlerDeviceGroupNextCodes(groupCode, deviceGroups)));
if (await DbContext.Queryable<DevicePermissionEntity>()
.Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Group)
.Where(x => x.AssignType == AssignTypeEnumType.Tenant)
.Where(x => result.Contains(x.UniqueValue))
.AnyAsync())
{
true.ThrowIfTrue("存在设备组分配到厂区中");
}
var deviceCodes = await DbContext.Queryable<DeviceGroupRelationshipEntity>()
.Where(x => result.Contains(x.GroupCode))
.Select(x => x.DeviceCode).Distinct()
.ToListAsync();
if (await DbContext.Queryable<DevicePermissionEntity>()
.Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Device)
.Where(x => x.AssignType == AssignTypeEnumType.Tenant)
.Where(x => deviceCodes.Contains(x.UniqueValue))
.AnyAsync())
{
true.ThrowIfTrue("设备组存在关联设备已分配到厂区中");
}
}
}
}
/// <summary>
/// 获取分配当前类型关联的用户
/// </summary>
/// <param name="assignValue"></param>
/// <returns></returns>
protected abstract Task<List<string>> GetGainfoNosAsync(string assignValue);
// --------------------------------------------------------------------------------------------------------------------- //
private async Task ChunkInsertAsync<T>(List<T> batch) where T : class, new()
{
foreach (var tasks in batch.Chunk(500))
{
await DbContext.InsertAsync(tasks);
}
}
/// <summary>
/// 检查是否分配顶级的设备分组
/// </summary>
/// <param name="request"></param>
private static async Task CheckWhetherAssignToTopDeviceGroupAsync(DevicePermissionSaveRequest request)
{
if (request.UniqueType == DeviceAssignmentTypeEnumType.Group)
{
await Scoped.Temp.Value.CreateAsync(async sp =>
{
var currentDb = sp.GetService<IDbContext>();
await currentDb.IgnoreAsync<ITenantId>(async () =>
{
var dgs = await currentDb.Queryable<DeviceGroupEntity>().Where(x => request.Codes.Contains(x.Code)).ToListAsync();
dgs.Any(x => x.TenantId.IsEmpty()).ThrowIfTrue("不可分配顶级分组节点");
});
});
}
}
/// <summary>
/// 持久化数据
/// </summary>
/// <param name="dps"></param>
/// <param name="request"></param>
private async Task PersistDataAsync(List<DevicePermissionEntity> dps, DevicePermissionSaveRequest request)
{
await DbContext.DeleteAsync(dps);
//保存配置的权限
if (request.Codes.IsPresent())
{
var devicePermissions = request.Codes.Select(code => new DevicePermissionEntity
{
AssignType = request.AssignType,
AssignValue = request.GetActualAssignValue(),
UniqueType = request.UniqueType,
UniqueValue = code,
Type = request.Type,
TenantId = CurrentTenantId
}).ToList();
await DbContext.InsertAsync(devicePermissions);
}
}
private List<Guid> GetMyUniqueValues(DeviceAssignmentTypeEnumType uniqueType)
{
var searchAll = _currentUser.GetRole() is "admin" or "tenant-admin";
if (!searchAll && uniqueType == DeviceAssignmentTypeEnumType.Device)
{
return _myDataPermissionService.GetMyDeviceCodes();
}
return new List<Guid>();
}
/// <summary>
/// 获取当前分配对应的现有权限
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private async Task<List<DevicePermissionEntity>> GetAssignedDevicePermissionsAsync(DevicePermissionSaveRequest request)
{
var myData = GetMyUniqueValues(request.UniqueType);
return await DevicePermission.Where(x => x.AssignType == request.AssignType
&& x.AssignValue == request.GetActualAssignValue()
&& x.UniqueType == request.UniqueType
&& x.Type == request.Type
&& x.TenantId == CurrentTenantId)
.WhereIF(myData.Any(), x => myData.Contains(x.UniqueValue))
.ToListAsync();
}
/// <summary>
/// 获取现在权限与当前的分配之间的deviceCode差异
/// </summary>
/// <param name="type"></param>
/// <param name="dps"></param>
/// <param name="uniqueValues"></param>
/// <returns></returns>
private async Task<(List<Guid>, List<Guid>)> GetDiffAsync(DeviceAssignmentTypeEnumType type, List<DevicePermissionEntity> dps, List<Guid> uniqueValues)
{
var beforeCodes = dps.Select(x => x.UniqueValue).ToList();
var presentCodes = uniqueValues.IsPresent() ? uniqueValues : new List<Guid>();
if (type == DeviceAssignmentTypeEnumType.Group)
{
var deviceGroups = await DbContext.Queryable<DeviceGroupEntity>().ToListAsync();
beforeCodes = await GetDeviceCodeByGroupAsync(beforeCodes, deviceGroups);
presentCodes = await GetDeviceCodeByGroupAsync(presentCodes, deviceGroups);
}
var codesToAdd = presentCodes.Except(beforeCodes).ToList();
var codesToDelete = beforeCodes.Except(presentCodes).ToList();
return (codesToAdd, codesToDelete);
}
/// <summary>
/// 获取分组下的deviceCode
/// </summary>
/// <param name="codes"></param>
/// <param name="deviceGroups"></param>
/// <returns></returns>
private async Task<List<Guid>> GetDeviceCodeByGroupAsync(List<Guid> codes, List<DeviceGroupEntity> deviceGroups)
{
var result = new List<Guid>();
codes.ForEach(groupCode => result.AddRange(RecursionHelper.HandlerDeviceGroupNextCodes(groupCode, deviceGroups)));
result = result.Distinct().ToList();
return await DbContext.Queryable<DeviceGroupRelationshipEntity>()
.Where(x => result.Contains(x.GroupCode))
.Select(x => x.DeviceCode)
.Distinct()
.ToListAsync();
}
}