294 lines
12 KiB
C#
294 lines
12 KiB
C#
using Dlhis.Basic.Device.Dtos;
|
|
using Dlhis.Basic.Device.Request;
|
|
using Dlhis.Basic.Device.Response;
|
|
using Dlhis.Basic.Utils;
|
|
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;
|
|
|
|
namespace Dlhis.Basic.Device.Services.Implements;
|
|
|
|
/// <summary>
|
|
/// 权限分析基类
|
|
/// </summary>
|
|
public abstract class BasePermissionAnalyzeService : IPermissionAnalyzeService
|
|
{
|
|
private readonly IDevicePermissionAnalyzeService _devicePermissionAnalyzeService;
|
|
|
|
protected IDbContext DbContext { get; }
|
|
|
|
protected BasePermissionAnalyzeService(IServiceProvider serviceProvider)
|
|
{
|
|
ICurrentUser currentUser = serviceProvider.GetService<ICurrentUser>();
|
|
DbContext = serviceProvider.GetService<IDbContext>();
|
|
CurrentTenantId = currentUser.GetStringTenantId();
|
|
_devicePermissionAnalyzeService = serviceProvider.GetService<IDevicePermissionAnalyzeService>();
|
|
}
|
|
|
|
private string CurrentTenantId { get; }
|
|
|
|
public async Task<DevicePermissionAssignResponse> AnalyzeAsync(DevicePermissionSaveRequest request)
|
|
{
|
|
var source = request.UniqueType + "-" + request.AssignType;
|
|
|
|
var tasksToAdd = new List<DeviceTaskEntity>();
|
|
var tasksToDelete = new List<DeviceTaskEntity>();
|
|
|
|
await CheckWhetherAssignToTopDeviceGroupAsync(request);
|
|
await CheckAssignedToTenantAsync(request);
|
|
await CheckAssignAppointmentAndBusinessTripGroupAsync(request);
|
|
|
|
var dps = await _devicePermissionAnalyzeService.GetDevicePermissionsAsync(request);
|
|
|
|
try
|
|
{
|
|
(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(), request.Type);
|
|
|
|
var userTenantDeviceCodes = devicesToDelete.IsPresent() && request.AssignType != AssignTypeEnumType.Tenant
|
|
? await _devicePermissionAnalyzeService.GetUserAssignDeviceCodesWithTypeInTenantAsync(gainfoNos, request.UniqueType, request.GetActualAssignValue(), request.AssignType)
|
|
: new Dictionary<string, List<TenantAssignTypeDeviceCode>>();
|
|
|
|
foreach (var gainfoNo in gainfoNos)
|
|
{
|
|
IEnumerable<DeviceEntity> currentDevicesToDelete = devicesToDelete;
|
|
if (userTenantDeviceCodes.Any())
|
|
{
|
|
var myDeviceCodes = userTenantDeviceCodes[gainfoNo].SelectMany(x => x.AssignTypes).SelectMany(x => x.Codes);
|
|
var actToDeleteCodes = codesToDelete.Except(myDeviceCodes);
|
|
currentDevicesToDelete = devicesToDelete.Where(p => actToDeleteCodes.Contains(p.Code));
|
|
}
|
|
|
|
tasksToAdd.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,
|
|
Source = source,
|
|
Priority = 0,
|
|
TenantId = x.TenantId,
|
|
}).ToList());
|
|
|
|
tasksToDelete.AddRange(currentDevicesToDelete.Select(x => new DeviceTaskEntity
|
|
{
|
|
Type = DeviceTaskEnumType.Delete,
|
|
DeviceType = x.Type,
|
|
UserId = null,
|
|
UserNo = gainfoNo,
|
|
DeviceUniqueNo = x.UniqueNo,
|
|
Status = DeviceTaskStatusEnumType.Wait,
|
|
Version = 0,
|
|
ResultMessage = null,
|
|
Source = source,
|
|
Priority = 0,
|
|
TenantId = x.TenantId,
|
|
}).ToList());
|
|
}
|
|
|
|
await ChunkInsertAsync(tasksToAdd);
|
|
await ChunkInsertAsync(tasksToDelete);
|
|
}
|
|
finally
|
|
{
|
|
await PersistDataAsync(dps, request);
|
|
}
|
|
|
|
return new DevicePermissionAssignResponse(tasksToAdd.Count, tasksToDelete.Count);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 获取分配当前类型关联的用户
|
|
/// </summary>
|
|
/// <param name="assignValue"></param>
|
|
/// <param name="deviceType"></param>
|
|
/// <returns></returns>
|
|
protected abstract Task<List<string>> GetGainfoNosAsync(string assignValue, DeviceTypeEnumType deviceType);
|
|
|
|
|
|
//************************************************************************************************************************
|
|
|
|
|
|
private 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("设备组存在关联设备已分配到厂区中");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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("不可分配顶级分组节点");
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
private async Task CheckAssignAppointmentAndBusinessTripGroupAsync(DevicePermissionSaveRequest request)
|
|
{
|
|
if (request.UniqueType == DeviceAssignmentTypeEnumType.Group && request.AssignType != AssignTypeEnumType.User)
|
|
{
|
|
if (await DbContext.Queryable<DeviceGroupEntity>().Where(x => request.Codes.Contains(x.Code))
|
|
.Where(x => x.AsAppointment || x.IsBusinessTrip)
|
|
.AnyAsync())
|
|
{
|
|
true.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);
|
|
}
|
|
}
|
|
|
|
/// <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();
|
|
}
|
|
} |