diff --git a/SimpleAdmin.Application/Services/Onboarding/Audit/OnboardingAuditService.cs b/SimpleAdmin.Application/Services/Onboarding/Audit/OnboardingAuditService.cs index 32bc5e6..29606fa 100644 --- a/SimpleAdmin.Application/Services/Onboarding/Audit/OnboardingAuditService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/Audit/OnboardingAuditService.cs @@ -9,16 +9,19 @@ public class OnboardingAuditService : IOnboardingAuditService private readonly IConfigService _config; private readonly IOnboardingContractSnapshotService _snapshotService; private readonly IOnboardingEmployeeContractSnapshotService _employeeContractSnapshotService; + private readonly IOnboardingDataPermissionService _dataPermission; public OnboardingAuditService( IConfigService config, IOnboardingContractSnapshotService snapshotService, - IOnboardingEmployeeContractSnapshotService employeeContractSnapshotService) + IOnboardingEmployeeContractSnapshotService employeeContractSnapshotService, + IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; _config = config; _snapshotService = snapshotService; _employeeContractSnapshotService = employeeContractSnapshotService; + _dataPermission = dataPermission; } /// @@ -79,8 +82,9 @@ public class OnboardingAuditService : IOnboardingAuditService employee.ExtraInfoJson = global::System.Text.Json.JsonSerializer.Serialize(employeeInfo); employee.Status = CommonStatusConst.ENABLE; employee.CreateTime = DateTime.Now; - employee.CreateUserId = UserManager.UserId; - employee.CreateUser = UserManager.Name; + // 员工档案归属于原任务创建人,而不是执行审核的人。 + employee.CreateUserId = task.CreateUserId; + employee.CreateUser = task.CreateUser; employee.UpdateTime = null; employee.UpdateUserId = null; employee.UpdateUser = null; @@ -106,6 +110,27 @@ public class OnboardingAuditService : IOnboardingAuditService await _snapshotService.Build(task.Id, employeeInfo); await _db.Insertable(employee).ExecuteCommandAsync(); + + // 全局插入审计会把 CreateUserId 设置为当前审核人。管理员代审核他人任务时, + // 员工档案仍应归属于原任务创建人,否则普通人事将无法继续维护自己发起的员工。 + if (task.CreateUserId.HasValue && task.CreateUserId != UserManager.UserId) + { + await _db.Updateable() + .SetColumns(item => new ObEmployee + { + CreateUserId = task.CreateUserId, + CreateUser = task.CreateUser + }) + .Where(item => item.Id == employee.Id) + .ExecuteCommandAsync(); + + var ownerPersisted = await _db.Queryable() + .AnyAsync(item => item.Id == employee.Id + && item.CreateUserId == task.CreateUserId); + if (!ownerPersisted) + throw Oops.Bah("员工档案创建人归属保存失败,请稍后重试"); + } + await _employeeContractSnapshotService.Build(employee.Id, task.Id); task.EmployeeId = employee.Id; @@ -171,6 +196,15 @@ public class OnboardingAuditService : IOnboardingAuditService throw Oops.Bah("当前任务不在审核中"); } + await _dataPermission.EnsureCanManage( + task.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); + + // 人事管理员/超级管理员可处理全部任务;普通人事还必须属于配置的审核人。 + if (await _dataPermission.CanManage(null, OnboardingPermissionCodes.TaskManageAll)) + return task; + var config = await _config.GetByConfigKey(CateGoryConst.CONFIG_BIZ_DEFINE, "onboard.reviewer.userIds") ?? throw Oops.Bah("请配置入职审核人"); // 审核人由全局配置与公司专属配置合并得出,不依赖独立业务表。 diff --git a/SimpleAdmin.Application/Services/Onboarding/Common/IOnboardingDataPermissionService.cs b/SimpleAdmin.Application/Services/Onboarding/Common/IOnboardingDataPermissionService.cs new file mode 100644 index 0000000..b5caf7e --- /dev/null +++ b/SimpleAdmin.Application/Services/Onboarding/Common/IOnboardingDataPermissionService.cs @@ -0,0 +1,13 @@ +namespace SimpleAdmin.Application; + +/// +/// 入职业务数据操作权限校验。 +/// +public interface IOnboardingDataPermissionService : ITransient +{ + Task CanManage(long? createUserId, string manageAllPermissionCode); + + Task EnsureCanManage(long? createUserId, string manageAllPermissionCode, string dataName); + + Task EnsureCanManage(IEnumerable createUserIds, string manageAllPermissionCode, string dataName); +} diff --git a/SimpleAdmin.Application/Services/Onboarding/Common/OnboardingDataPermissionService.cs b/SimpleAdmin.Application/Services/Onboarding/Common/OnboardingDataPermissionService.cs new file mode 100644 index 0000000..ef93e66 --- /dev/null +++ b/SimpleAdmin.Application/Services/Onboarding/Common/OnboardingDataPermissionService.cs @@ -0,0 +1,50 @@ +namespace SimpleAdmin.Application; + +/// +/// 入职业务数据操作权限校验。 +/// 普通人事可查看全部业务数据,但只能操作本人创建的数据;拥有模块“管理全部”按钮权限的人员可操作全部数据。 +/// +public class OnboardingDataPermissionService : IOnboardingDataPermissionService +{ + private readonly ISysUserService _sysUserService; + + public OnboardingDataPermissionService(ISysUserService sysUserService) + { + _sysUserService = sysUserService; + } + + public async Task CanManage(long? createUserId, string manageAllPermissionCode) + { + if (UserManager.SuperAdmin) + return true; + + if (createUserId.HasValue && createUserId.Value == UserManager.UserId) + return true; + + var buttonCodes = await _sysUserService.GetButtonCodeList(UserManager.UserId); + return buttonCodes.Contains(manageAllPermissionCode); + } + + public async Task EnsureCanManage(long? createUserId, string manageAllPermissionCode, string dataName) + { + if (!await CanManage(createUserId, manageAllPermissionCode)) + throw Oops.Bah($"只能操作本人创建的{dataName}"); + } + + public async Task EnsureCanManage( + IEnumerable createUserIds, + string manageAllPermissionCode, + string dataName) + { + var owners = createUserIds.Distinct().ToList(); + if (owners.Count == 0) + return; + + if (UserManager.SuperAdmin || owners.All(id => id.HasValue && id.Value == UserManager.UserId)) + return; + + var buttonCodes = await _sysUserService.GetButtonCodeList(UserManager.UserId); + if (!buttonCodes.Contains(manageAllPermissionCode)) + throw Oops.Bah($"所选数据中包含他人创建的{dataName},不能操作"); + } +} diff --git a/SimpleAdmin.Application/Services/Onboarding/Common/OnboardingPermissionCodes.cs b/SimpleAdmin.Application/Services/Onboarding/Common/OnboardingPermissionCodes.cs new file mode 100644 index 0000000..cef1494 --- /dev/null +++ b/SimpleAdmin.Application/Services/Onboarding/Common/OnboardingPermissionCodes.cs @@ -0,0 +1,13 @@ +namespace SimpleAdmin.Application; + +/// +/// 入职业务按钮权限编码。 +/// +public static class OnboardingPermissionCodes +{ + public const string SetupManageAll = "onboardingSetupManageAll"; + public const string EntryConfigManageAll = "onboardingEntryConfigManageAll"; + public const string ContractManageAll = "onboardingContractManageAll"; + public const string TaskManageAll = "onboardingTaskManageAll"; + public const string EmployeeManageAll = "onboardingEmployeeManageAll"; +} diff --git a/SimpleAdmin.Application/Services/Onboarding/Company/OnboardingCompanyService.cs b/SimpleAdmin.Application/Services/Onboarding/Company/OnboardingCompanyService.cs index 3f2a9ac..e54ebd3 100644 --- a/SimpleAdmin.Application/Services/Onboarding/Company/OnboardingCompanyService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/Company/OnboardingCompanyService.cs @@ -5,6 +5,13 @@ namespace SimpleAdmin.Application; /// public class OnboardingCompanyService : DbRepository, IOnboardingCompanyService { + private readonly IOnboardingDataPermissionService _dataPermission; + + public OnboardingCompanyService(IOnboardingDataPermissionService dataPermission) + { + _dataPermission = dataPermission; + } + /// /// 分页查询入职业务公司。 /// @@ -54,7 +61,11 @@ public class OnboardingCompanyService : DbRepository, IOnboardingComp public async Task Edit(OnboardingCompanyEditInput input) { NormalizeAndValidateQiyuesuoConfig(input); - await Detail(new BaseIdInput { Id = input.Id }); + var company = await Detail(new BaseIdInput { Id = input.Id }); + await _dataPermission.EnsureCanManage( + company.CreateUserId, + OnboardingPermissionCodes.SetupManageAll, + "公司"); await EnsureCodeUnique(input.CompanyCode, input.Id); await UpdateAsync(input.Adapt()); } @@ -67,6 +78,16 @@ public class OnboardingCompanyService : DbRepository, IOnboardingComp if (input.Ids.Count == 0) return; + var companies = await Context.Queryable() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (companies.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("公司不存在"); + await _dataPermission.EnsureCanManage( + companies.Select(item => item.CreateUserId), + OnboardingPermissionCodes.SetupManageAll, + "公司"); + var hasPositions = await Context.Queryable() .AnyAsync(it => input.Ids.Contains(it.CompanyId)); if (hasPositions) diff --git a/SimpleAdmin.Application/Services/Onboarding/ContractDocument/OnboardingContractDocumentService.cs b/SimpleAdmin.Application/Services/Onboarding/ContractDocument/OnboardingContractDocumentService.cs index 4dca707..220a35b 100644 --- a/SimpleAdmin.Application/Services/Onboarding/ContractDocument/OnboardingContractDocumentService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/ContractDocument/OnboardingContractDocumentService.cs @@ -7,11 +7,15 @@ public class OnboardingContractDocumentService : IOnboardingContractDocumentServ { private readonly SqlSugarScope _db; private readonly IFileService _fileService; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingContractDocumentService(IFileService fileService) + public OnboardingContractDocumentService( + IFileService fileService, + IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; _fileService = fileService; + _dataPermission = dataPermission; } /// @@ -298,6 +302,10 @@ public class OnboardingContractDocumentService : IOnboardingContractDocumentServ ?? throw Oops.Bah("任务合同不存在"); var task = await _db.Queryable().InSingleAsync(contract.TaskId) ?? throw Oops.Bah("入职任务不存在"); + await _dataPermission.EnsureCanManage( + task.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); var statusAllowsGeneration = task.TaskStatus == OnboardingTaskStatus.PendingFill || task.TaskStatus == OnboardingTaskStatus.Rejected || task.TaskStatus == OnboardingTaskStatus.Reviewing diff --git a/SimpleAdmin.Application/Services/Onboarding/ContractTemplate/OnboardingContractTemplateService.cs b/SimpleAdmin.Application/Services/Onboarding/ContractTemplate/OnboardingContractTemplateService.cs index 1abbfb6..73c1083 100644 --- a/SimpleAdmin.Application/Services/Onboarding/ContractTemplate/OnboardingContractTemplateService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/ContractTemplate/OnboardingContractTemplateService.cs @@ -6,10 +6,14 @@ namespace SimpleAdmin.Application; public class OnboardingContractTemplateService : DbRepository, IOnboardingContractTemplateService { private readonly IFileService _fileService; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingContractTemplateService(IFileService fileService) + public OnboardingContractTemplateService( + IFileService fileService, + IOnboardingDataPermissionService dataPermission) { _fileService = fileService; + _dataPermission = dataPermission; } /// @@ -122,7 +126,11 @@ public class OnboardingContractTemplateService : DbRepository public async Task Edit(OnboardingContractTemplateEditInput input) { - await Detail(new BaseIdInput { Id = input.Id }); + var template = await Detail(new BaseIdInput { Id = input.Id }); + await _dataPermission.EnsureCanManage( + template.CreateUserId, + OnboardingPermissionCodes.ContractManageAll, + "合同模板"); NormalizeInput(input); await ValidateBusinessScope(input.CompanyId, input.DepartmentId, input.PositionIds); await ValidateReferencedOnboardingTemplates(input); @@ -156,6 +164,16 @@ public class OnboardingContractTemplateService : DbRepository() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (templates.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("合同模板不存在"); + await _dataPermission.EnsureCanManage( + templates.Select(item => item.CreateUserId), + OnboardingPermissionCodes.ContractManageAll, + "合同模板"); + var hasOnboardingTemplates = await Context.Queryable() .AnyAsync(it => input.Ids.Contains(it.ContractTemplateId)); if (hasOnboardingTemplates) @@ -209,6 +227,7 @@ public class OnboardingContractTemplateService : DbRepository().InSingleAsync(input.Id) ?? throw Oops.Bah("合同版本不存在"); + await EnsureTemplateCanManage(version.TemplateId); var isUsedInOnboardingTemplate = await Context.Queryable() .AnyAsync(it => it.ContractTemplateVersionId == version.Id); @@ -258,7 +277,11 @@ public class OnboardingContractTemplateService : DbRepository public async Task AddVersion(OnboardingContractVersionAddInput input) { - await Detail(new BaseIdInput { Id = input.TemplateId }); + var template = await Detail(new BaseIdInput { Id = input.TemplateId }); + await _dataPermission.EnsureCanManage( + template.CreateUserId, + OnboardingPermissionCodes.ContractManageAll, + "合同模板"); var file = await Context.Queryable().InSingleAsync(input.SourceDocxFileId) ?? throw Oops.Bah("DOCX 源文件不存在"); if (!string.Equals(file.Suffix, "docx", StringComparison.OrdinalIgnoreCase)) @@ -337,6 +360,7 @@ public class OnboardingContractTemplateService : DbRepository().InSingleAsync(input.Id) ?? throw Oops.Bah("模板版本不存在"); + await EnsureTemplateCanManage(version.TemplateId); if (input.VersionStatus == ContractTemplateVersionStatus.Enabled) { @@ -374,6 +398,11 @@ public class OnboardingContractTemplateService : DbRepository() + .InSingleAsync(variable.TemplateVersionId) + ?? throw Oops.Bah("模板版本不存在"); + await EnsureTemplateCanManage(version.TemplateId); + var isUsedInTask = await Context.Queryable() .AnyAsync(it => it.TemplateVersionId == input.TemplateVersionId); if (isUsedInTask) @@ -384,6 +413,16 @@ public class OnboardingContractTemplateService : DbRepository().InSingleAsync(templateId) + ?? throw Oops.Bah("合同模板不存在"); + await _dataPermission.EnsureCanManage( + template.CreateUserId, + OnboardingPermissionCodes.ContractManageAll, + "合同模板"); + } + private static ObTemplateVariable BuildDetectedVariable(long versionId, string code, ObVariableDefinition def, int index) { var separatorIndex = code.IndexOf('.'); diff --git a/SimpleAdmin.Application/Services/Onboarding/Department/OnboardingDepartmentService.cs b/SimpleAdmin.Application/Services/Onboarding/Department/OnboardingDepartmentService.cs index ea8f215..5701d06 100644 --- a/SimpleAdmin.Application/Services/Onboarding/Department/OnboardingDepartmentService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/Department/OnboardingDepartmentService.cs @@ -5,6 +5,13 @@ /// public class OnboardingDepartmentService : DbRepository, IOnboardingDepartmentService { + private readonly IOnboardingDataPermissionService _dataPermission; + + public OnboardingDepartmentService(IOnboardingDataPermissionService dataPermission) + { + _dataPermission = dataPermission; + } + /// /// 分页查询入职业务部门。 /// @@ -78,6 +85,10 @@ public class OnboardingDepartmentService : DbRepository, IOnboardi { NormalizeInput(input); var department = await Detail(new BaseIdInput { Id = input.Id }); + await _dataPermission.EnsureCanManage( + department.CreateUserId, + OnboardingPermissionCodes.SetupManageAll, + "部门"); await EnsureCompanyCanChange(department, input.CompanyId); await EnsureCompanyExists(input.CompanyId); await EnsureCodeUnique(input.CompanyId, input.DepartmentCode, input.Id); @@ -92,6 +103,16 @@ public class OnboardingDepartmentService : DbRepository, IOnboardi if (input.Ids.Count == 0) return; + var departments = await Context.Queryable() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (departments.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("部门不存在"); + await _dataPermission.EnsureCanManage( + departments.Select(item => item.CreateUserId), + OnboardingPermissionCodes.SetupManageAll, + "部门"); + var hasPositions = await Context.Queryable() .AnyAsync(it => it.DepartmentId.HasValue && input.Ids.Contains(it.DepartmentId.Value)); if (hasPositions) diff --git a/SimpleAdmin.Application/Services/Onboarding/ElectronicSign/OnboardingElectronicSignService.cs b/SimpleAdmin.Application/Services/Onboarding/ElectronicSign/OnboardingElectronicSignService.cs index a7e68a9..d696ce1 100644 --- a/SimpleAdmin.Application/Services/Onboarding/ElectronicSign/OnboardingElectronicSignService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/ElectronicSign/OnboardingElectronicSignService.cs @@ -17,20 +17,20 @@ public class OnboardingElectronicSignService : IOnboardingElectronicSignService private readonly IQiyuesuoClient _qiyuesuoClient; private readonly IOnboardingContractDocumentService _contractDocumentService; private readonly IFileService _fileService; - private readonly IConfigService _configService; + private readonly IOnboardingDataPermissionService _dataPermission; private readonly QiyuesuoSettingOptions _setting; public OnboardingElectronicSignService( IQiyuesuoClient qiyuesuoClient, IOnboardingContractDocumentService contractDocumentService, IFileService fileService, - IConfigService configService) + IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; _qiyuesuoClient = qiyuesuoClient; _contractDocumentService = contractDocumentService; _fileService = fileService; - _configService = configService; + _dataPermission = dataPermission; _setting = App.GetConfig( "QiyuesuoSetting", true) @@ -41,7 +41,7 @@ public class OnboardingElectronicSignService : IOnboardingElectronicSignService public async Task Detail( BaseIdInput input) { - var task = await GetAuthorizedTask(input.Id); + var task = await GetTask(input.Id); return await BuildDetail(task); } @@ -290,7 +290,7 @@ public class OnboardingElectronicSignService : IOnboardingElectronicSignService public async Task PreviewEmployeeSignedDocument( OnboardingElectronicSignPreviewInput input) { - var task = await GetAuthorizedTask(input.TaskId); + var task = await GetTask(input.TaskId); var process = await GetRequiredProcess(task.Id); // 不信任前端缓存状态。每次预览前重新查询契约锁,确保员工确实已完成签署。 @@ -1247,24 +1247,24 @@ public class OnboardingElectronicSignService : IOnboardingElectronicSignService } /// - /// 电子签管理沿用入职审核人权限,不新增另一套权限来源。 + /// 电子签操作遵循任务创建人/任务管理全部权限。 /// private async Task GetAuthorizedTask(long taskId) { - var task = await _db.Queryable().InSingleAsync(taskId) - ?? throw Oops.Bah("入职任务不存在"); - var config = await _configService.GetByConfigKey( - CateGoryConst.CONFIG_BIZ_DEFINE, - "onboard.reviewer.userIds") - ?? throw Oops.Bah("请配置入职审核人"); - var reviewerIds = OnboardingReviewerConfigParser.Parse( - config.ConfigValue, - task.CompanyId); - if (!reviewerIds.Contains(UserManager.UserId)) - throw Oops.Bah("您不是该入职任务的审核人"); + var task = await GetTask(taskId); + await _dataPermission.EnsureCanManage( + task.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); return task; } + private async Task GetTask(long taskId) + { + return await _db.Queryable().InSingleAsync(taskId) + ?? throw Oops.Bah("入职任务不存在"); + } + private async Task GetLatestProcess(long taskId) { return await _db.Queryable() diff --git a/SimpleAdmin.Application/Services/Onboarding/Employee/OnboardingEmployeeService.cs b/SimpleAdmin.Application/Services/Onboarding/Employee/OnboardingEmployeeService.cs index 824c062..3b63c07 100644 --- a/SimpleAdmin.Application/Services/Onboarding/Employee/OnboardingEmployeeService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/Employee/OnboardingEmployeeService.cs @@ -11,10 +11,12 @@ namespace SimpleAdmin.Application; public class OnboardingEmployeeService : IOnboardingEmployeeService { private readonly SqlSugarScope _db; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingEmployeeService() + public OnboardingEmployeeService(IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; + _dataPermission = dataPermission; } /// @@ -184,6 +186,7 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService var employee = await _db.Queryable().InSingleAsync(input.Id) ?? throw Oops.Bah("员工档案不存在"); + await EnsureEmployeeCanManage(employee); var before = CreateHrState(employee); var regularizationStatus = employee.RegularizationStatus; var regularizationDate = employee.RegularizationDate; @@ -266,6 +269,7 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService var employee = await _db.Queryable().InSingleAsync(input.Id) ?? throw Oops.Bah("员工档案不存在"); + await EnsureEmployeeCanManage(employee); if (employee.EmploymentType == EmployeeEmploymentType.PartTime) throw Oops.Bah("兼职员工不适用转正流程,请先调整用工类型"); if (employee.RegularizationStatus == EmployeeRegularizationStatus.Regular) @@ -360,6 +364,7 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService var employee = await _db.Queryable().InSingleAsync(input.Id) ?? throw Oops.Bah("员工档案不存在"); + await EnsureEmployeeCanManage(employee); if (employee.RegularizationStatus != EmployeeRegularizationStatus.Regular) throw Oops.Bah("该员工当前不是已转正状态"); @@ -411,6 +416,14 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService /// /// 查询员工来源任务中上传的全部材料,并补充原始文件名、后缀和文件大小。 /// + private Task EnsureEmployeeCanManage(ObEmployee employee) + { + return _dataPermission.EnsureCanManage( + employee.CreateUserId, + OnboardingPermissionCodes.EmployeeManageAll, + "员工档案"); + } + private async Task> GetEmployeeMaterials(long? taskId) { if (!taskId.HasValue) diff --git a/SimpleAdmin.Application/Services/Onboarding/EntryConfig/OnboardingEntryConfigService.cs b/SimpleAdmin.Application/Services/Onboarding/EntryConfig/OnboardingEntryConfigService.cs index 88a440c..a616fb2 100644 --- a/SimpleAdmin.Application/Services/Onboarding/EntryConfig/OnboardingEntryConfigService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/EntryConfig/OnboardingEntryConfigService.cs @@ -6,10 +6,12 @@ namespace SimpleAdmin.Application; public class OnboardingEntryConfigService : IOnboardingEntryConfigService { private readonly SqlSugarScope _db; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingEntryConfigService() + public OnboardingEntryConfigService(IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; + _dataPermission = dataPermission; } /// @@ -55,10 +57,15 @@ public class OnboardingEntryConfigService : IOnboardingEntryConfigService if (input.Id.HasValue) { - var exists = await _db.Queryable().AnyAsync(x => x.Id == input.Id.Value); - if (!exists) - throw Oops.Bah("字段不存在"); - + var exists = await _db.Queryable().InSingleAsync(input.Id.Value) + ?? throw Oops.Bah("字段不存在"); + await _dataPermission.EnsureCanManage( + exists.CreateUserId, + OnboardingPermissionCodes.EntryConfigManageAll, + "入职字段"); + entity.CreateUserId = exists.CreateUserId; + entity.CreateUser = exists.CreateUser; + entity.CreateTime = exists.CreateTime; await _db.Updateable(entity).ExecuteCommandAsync(); return; } @@ -95,6 +102,16 @@ public class OnboardingEntryConfigService : IOnboardingEntryConfigService if (input.Ids.Count == 0) return; + var fields = await _db.Queryable() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (fields.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("字段不存在"); + await _dataPermission.EnsureCanManage( + fields.Select(item => item.CreateUserId), + OnboardingPermissionCodes.EntryConfigManageAll, + "入职字段"); + var isReferenced = await _db.Queryable() .AnyAsync(x => input.Ids.Contains(x.FieldId)); var isReferencedByTemplate = await _db.Queryable() @@ -145,10 +162,15 @@ public class OnboardingEntryConfigService : IOnboardingEntryConfigService if (input.Id.HasValue) { - var exists = await _db.Queryable().AnyAsync(x => x.Id == input.Id.Value); - if (!exists) - throw Oops.Bah("资料类型不存在"); - + var exists = await _db.Queryable().InSingleAsync(input.Id.Value) + ?? throw Oops.Bah("资料类型不存在"); + await _dataPermission.EnsureCanManage( + exists.CreateUserId, + OnboardingPermissionCodes.EntryConfigManageAll, + "资料类型"); + entity.CreateUserId = exists.CreateUserId; + entity.CreateUser = exists.CreateUser; + entity.CreateTime = exists.CreateTime; await _db.Updateable(entity).ExecuteCommandAsync(); return; } @@ -164,6 +186,16 @@ public class OnboardingEntryConfigService : IOnboardingEntryConfigService if (input.Ids.Count == 0) return; + var materialTypes = await _db.Queryable() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (materialTypes.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("资料类型不存在"); + await _dataPermission.EnsureCanManage( + materialTypes.Select(item => item.CreateUserId), + OnboardingPermissionCodes.EntryConfigManageAll, + "资料类型"); + var isReferenced = await _db.Queryable() .AnyAsync(x => input.Ids.Contains(x.MaterialTypeId)); var isReferencedByTemplate = await _db.Queryable() diff --git a/SimpleAdmin.Application/Services/Onboarding/Lifecycle/OnboardingTaskLifecycleService.cs b/SimpleAdmin.Application/Services/Onboarding/Lifecycle/OnboardingTaskLifecycleService.cs index e6a245c..8d77dd6 100644 --- a/SimpleAdmin.Application/Services/Onboarding/Lifecycle/OnboardingTaskLifecycleService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/Lifecycle/OnboardingTaskLifecycleService.cs @@ -6,12 +6,12 @@ namespace SimpleAdmin.Application; public class OnboardingTaskLifecycleService : IOnboardingTaskLifecycleService { private readonly SqlSugarScope _db; - private readonly IConfigService _config; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingTaskLifecycleService(IConfigService config) + public OnboardingTaskLifecycleService(IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; - _config = config; + _dataPermission = dataPermission; } /// @@ -147,14 +147,10 @@ public class OnboardingTaskLifecycleService : IOnboardingTaskLifecycleService { var task = await _db.Queryable().InSingleAsync(taskId) ?? throw Oops.Bah("入职任务不存在"); - var config = await _config.GetByConfigKey(CateGoryConst.CONFIG_BIZ_DEFINE, "onboard.reviewer.userIds") - ?? throw Oops.Bah("请配置入职审核人"); - var reviewerIds = OnboardingReviewerConfigParser.Parse(config.ConfigValue, task.CompanyId); - - if (!reviewerIds.Contains(UserManager.UserId)) - { - throw Oops.Bah("您不是该入职任务的审核人"); - } + await _dataPermission.EnsureCanManage( + task.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); return task; } diff --git a/SimpleAdmin.Application/Services/Onboarding/MaterialReview/OnboardingMaterialReviewService.cs b/SimpleAdmin.Application/Services/Onboarding/MaterialReview/OnboardingMaterialReviewService.cs index bbeb80e..cc03113 100644 --- a/SimpleAdmin.Application/Services/Onboarding/MaterialReview/OnboardingMaterialReviewService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/MaterialReview/OnboardingMaterialReviewService.cs @@ -7,11 +7,15 @@ public class OnboardingMaterialReviewService : IOnboardingMaterialReviewService { private readonly SqlSugarScope _db; private readonly IConfigService _config; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingMaterialReviewService(IConfigService config) + public OnboardingMaterialReviewService( + IConfigService config, + IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; _config = config; + _dataPermission = dataPermission; } /// @@ -48,6 +52,13 @@ public class OnboardingMaterialReviewService : IOnboardingMaterialReviewService private async Task EnsureReviewer(ObOnboardingTask task) { + await _dataPermission.EnsureCanManage( + task.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); + if (await _dataPermission.CanManage(null, OnboardingPermissionCodes.TaskManageAll)) + return; + var config = await _config.GetByConfigKey(CateGoryConst.CONFIG_BIZ_DEFINE, "onboard.reviewer.userIds") ?? throw Oops.Bah("请配置入职审核人"); var reviewerIds = OnboardingReviewerConfigParser.Parse(config.ConfigValue, task.CompanyId); diff --git a/SimpleAdmin.Application/Services/Onboarding/OnboardingTemplate/OnboardingTemplateService.cs b/SimpleAdmin.Application/Services/Onboarding/OnboardingTemplate/OnboardingTemplateService.cs index 35cc7a1..4686fd7 100644 --- a/SimpleAdmin.Application/Services/Onboarding/OnboardingTemplate/OnboardingTemplateService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/OnboardingTemplate/OnboardingTemplateService.cs @@ -6,10 +6,12 @@ namespace SimpleAdmin.Application; public class OnboardingTemplateService : IOnboardingTemplateService { private readonly SqlSugarScope _db; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingTemplateService() + public OnboardingTemplateService(IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; + _dataPermission = dataPermission; } /// @@ -59,6 +61,8 @@ public class OnboardingTemplateService : IOnboardingTemplateService return new OnboardingTemplateDetailOutput { Id = summary.Id, + CreateUserId = summary.CreateUserId, + CreateUser = summary.CreateUser, TemplateCode = summary.TemplateCode, TemplateName = summary.TemplateName, CompanyId = summary.CompanyId, @@ -108,6 +112,19 @@ public class OnboardingTemplateService : IOnboardingTemplateService ? codeOwner.Id : input.Id ?? global::SimpleAdmin.Core.Utils.CommonUtils.GetSingleId(); + if (input.Id.HasValue || isRestore) + { + var existing = isRestore + ? codeOwner + : await _db.Queryable().InSingleAsync(templateId); + if (existing == null) + throw Oops.Bah("入职模板不存在"); + await _dataPermission.EnsureCanManage( + existing.CreateUserId, + OnboardingPermissionCodes.EntryConfigManageAll, + "入职模板"); + } + var entity = new ObOnboardingTemplate { Id = templateId, @@ -154,6 +171,16 @@ public class OnboardingTemplateService : IOnboardingTemplateService if (input.Ids.Count == 0) return; + var templates = await _db.Queryable() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (templates.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("入职模板不存在"); + await _dataPermission.EnsureCanManage( + templates.Select(item => item.CreateUserId), + OnboardingPermissionCodes.EntryConfigManageAll, + "入职模板"); + var isUsed = await _db.Queryable() .AnyAsync(item => input.Ids.Contains(item.OnboardingTemplateId)); if (isUsed) @@ -422,6 +449,8 @@ public class OnboardingTemplateService : IOnboardingTemplateService return new OnboardingTemplateOutput { Id = template.Id, + CreateUserId = template.CreateUserId, + CreateUser = template.CreateUser, TemplateCode = template.TemplateCode, TemplateName = template.TemplateName, CompanyId = template.CompanyId, diff --git a/SimpleAdmin.Application/Services/Onboarding/Position/OnboardingPositionService.cs b/SimpleAdmin.Application/Services/Onboarding/Position/OnboardingPositionService.cs index 1196d4b..69119f9 100644 --- a/SimpleAdmin.Application/Services/Onboarding/Position/OnboardingPositionService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/Position/OnboardingPositionService.cs @@ -5,6 +5,13 @@ namespace SimpleAdmin.Application; /// public class OnboardingPositionService : DbRepository, IOnboardingPositionService { + private readonly IOnboardingDataPermissionService _dataPermission; + + public OnboardingPositionService(IOnboardingDataPermissionService dataPermission) + { + _dataPermission = dataPermission; + } + /// /// 分页查询入职业务岗位。 /// @@ -107,6 +114,10 @@ public class OnboardingPositionService : DbRepository, IOnboardingPo throw Oops.Bah("请选择所属部门"); var position = await Detail(new BaseIdInput { Id = input.Id }); + await _dataPermission.EnsureCanManage( + position.CreateUserId, + OnboardingPermissionCodes.SetupManageAll, + "岗位"); await EnsureScopeCanChange(position, input.CompanyId, input.DepartmentId.Value); await EnsureCompanyExists(input.CompanyId); await EnsureDepartmentExists(input.CompanyId, input.DepartmentId.Value); @@ -122,6 +133,16 @@ public class OnboardingPositionService : DbRepository, IOnboardingPo if (input.Ids.Count == 0) return; + var positions = await Context.Queryable() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (positions.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("岗位不存在"); + await _dataPermission.EnsureCanManage( + positions.Select(item => item.CreateUserId), + OnboardingPermissionCodes.SetupManageAll, + "岗位"); + var hasTasks = await Context.Queryable() .AnyAsync(it => input.Ids.Contains(it.PositionId)); if (hasTasks) diff --git a/SimpleAdmin.Application/Services/Onboarding/Task/OnboardingTaskService.cs b/SimpleAdmin.Application/Services/Onboarding/Task/OnboardingTaskService.cs index 3fb042e..7aa41d5 100644 --- a/SimpleAdmin.Application/Services/Onboarding/Task/OnboardingTaskService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/Task/OnboardingTaskService.cs @@ -8,14 +8,17 @@ public class OnboardingTaskService : IOnboardingTaskService private readonly SqlSugarScope _db; private readonly IConfigService _configService; private readonly IOnboardingContractSnapshotService _snapshotService; + private readonly IOnboardingDataPermissionService _dataPermission; public OnboardingTaskService( IConfigService configService, - IOnboardingContractSnapshotService snapshotService) + IOnboardingContractSnapshotService snapshotService, + IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; _configService = configService; _snapshotService = snapshotService; + _dataPermission = dataPermission; } /// @@ -237,6 +240,10 @@ public class OnboardingTaskService : IOnboardingTaskService var sourceTask = await _db.Queryable() .InSingleAsync(input.SourceTaskId) ?? throw Oops.Bah("原入职任务不存在"); + await _dataPermission.EnsureCanManage( + sourceTask.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); if (!sourceTask.DepartmentId.HasValue) throw Oops.Bah("原入职任务未设置部门,不能复制"); diff --git a/SimpleAdmin.Application/Services/Onboarding/TaskContractVariable/OnboardingTaskContractVariableService.cs b/SimpleAdmin.Application/Services/Onboarding/TaskContractVariable/OnboardingTaskContractVariableService.cs index 78c61ee..97fdc6d 100644 --- a/SimpleAdmin.Application/Services/Onboarding/TaskContractVariable/OnboardingTaskContractVariableService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/TaskContractVariable/OnboardingTaskContractVariableService.cs @@ -6,9 +6,13 @@ namespace SimpleAdmin.Application; public class OnboardingTaskContractVariableService : IOnboardingTaskContractVariableService { private readonly SqlSugarScope _db; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingTaskContractVariableService() - => _db = DbContext.DB; + public OnboardingTaskContractVariableService(IOnboardingDataPermissionService dataPermission) + { + _db = DbContext.DB; + _dataPermission = dataPermission; + } /// /// 查询任务下全部合同及其变量当前值。 @@ -85,6 +89,10 @@ public class OnboardingTaskContractVariableService : IOnboardingTaskContractVari var task = await _db.Queryable() .InSingleAsync(contract.TaskId) ?? throw Oops.Bah("入职任务不存在"); + await _dataPermission.EnsureCanManage( + task.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); if (task.TaskStatus != OnboardingTaskStatus.PendingFill && task.TaskStatus != OnboardingTaskStatus.Rejected) diff --git a/SimpleAdmin.Application/Services/Onboarding/TaskQuery/OnboardingTaskQueryService.cs b/SimpleAdmin.Application/Services/Onboarding/TaskQuery/OnboardingTaskQueryService.cs index 792cd14..591f981 100644 --- a/SimpleAdmin.Application/Services/Onboarding/TaskQuery/OnboardingTaskQueryService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/TaskQuery/OnboardingTaskQueryService.cs @@ -7,11 +7,15 @@ public class OnboardingTaskQueryService : IOnboardingTaskQueryService { private readonly SqlSugarScope _db; private readonly IConfigService _configService; + private readonly IOnboardingDataPermissionService _dataPermission; - public OnboardingTaskQueryService(IConfigService configService) + public OnboardingTaskQueryService( + IConfigService configService, + IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; _configService = configService; + _dataPermission = dataPermission; } /// @@ -156,6 +160,10 @@ public class OnboardingTaskQueryService : IOnboardingTaskQueryService { var task = await _db.Queryable().InSingleAsync(input.Id) ?? throw Oops.Bah("入职任务不存在"); + await _dataPermission.EnsureCanManage( + task.CreateUserId, + OnboardingPermissionCodes.TaskManageAll, + "入职任务"); var canShareLink = task.TaskStatus == OnboardingTaskStatus.PendingFill || task.TaskStatus == OnboardingTaskStatus.Rejected; if (!canShareLink) diff --git a/SimpleAdmin.Application/Services/Onboarding/VariableDefinition/OnboardingVariableDefinitionService.cs b/SimpleAdmin.Application/Services/Onboarding/VariableDefinition/OnboardingVariableDefinitionService.cs index 6b55c66..43f2065 100644 --- a/SimpleAdmin.Application/Services/Onboarding/VariableDefinition/OnboardingVariableDefinitionService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/VariableDefinition/OnboardingVariableDefinitionService.cs @@ -6,13 +6,15 @@ public class OnboardingVariableDefinitionService : IOnboardingVariableDefinitionService { private readonly SqlSugarScope _db; + private readonly IOnboardingDataPermissionService _dataPermission; /// /// 初始化合同变量字典服务。 /// - public OnboardingVariableDefinitionService() + public OnboardingVariableDefinitionService(IOnboardingDataPermissionService dataPermission) { _db = DbContext.DB; + _dataPermission = dataPermission; } /// @@ -62,6 +64,10 @@ public class OnboardingVariableDefinitionService : IOnboardingVariableDefinition var entity = await _db.Queryable().InSingleAsync(input.Id) ?? throw Oops.Bah("变量不存在"); + await _dataPermission.EnsureCanManage( + entity.CreateUserId, + OnboardingPermissionCodes.EntryConfigManageAll, + "合同变量"); if (!string.Equals(entity.VariableCode, input.VariableCode, StringComparison.Ordinal)) throw Oops.Bah("变量编码创建后不能修改"); @@ -86,6 +92,16 @@ public class OnboardingVariableDefinitionService : IOnboardingVariableDefinition if (input.Ids.Count == 0) return; + var variables = await _db.Queryable() + .Where(item => input.Ids.Contains(item.Id)) + .ToListAsync(); + if (variables.Count != input.Ids.Distinct().Count()) + throw Oops.Bah("变量不存在"); + await _dataPermission.EnsureCanManage( + variables.Select(item => item.CreateUserId), + OnboardingPermissionCodes.EntryConfigManageAll, + "合同变量"); + var hasBuiltIn = await _db.Queryable() .Where(it => input.Ids.Contains(it.Id) && it.IsBuiltIn) .AnyAsync();