diff --git a/app/Policies/ActivityLogPolicy.php b/app/Policies/ActivityLogPolicy.php new file mode 100644 index 0000000..e04c5ba --- /dev/null +++ b/app/Policies/ActivityLogPolicy.php @@ -0,0 +1,33 @@ +can('activity-log.view'); + } + + /** + * 查看操作日志详情 + */ + public function view(User $user, Activity $activity): bool + { + return $user->can('activity-log.view'); + } + + /** + * 导出操作日志 + */ + public function export(User $user): bool + { + return $user->can('activity-log.export'); + } +} diff --git a/app/Policies/DocumentPolicy.php b/app/Policies/DocumentPolicy.php index 68422bd..40da146 100644 --- a/app/Policies/DocumentPolicy.php +++ b/app/Policies/DocumentPolicy.php @@ -24,20 +24,21 @@ class DocumentPolicy /** * 判断用户是否可以查看文档列表 - * 所有已认证用户都可以查看文档列表(但列表会根据权限过滤) + * 需求:权限检查 + 分组访问控制 * * @param User $user * @return bool */ public function viewAny(User $user): bool { - // 所有已认证用户都可以查看文档列表 - return true; + // 检查用户是否有查看文档的权限 + return $user->can('document.view'); } /** * 判断用户是否可以查看特定文档 - * 需求:3.1, 3.4, 7.1, 7.2, 7.3 + * 需求:3.1, 3.4, 7.1, 7.2, 7.3 + 权限检查 + * - 首先检查用户是否有 document.view 权限 * - 全局文档:所有用户都可以查看 * - 专用文档:只有所属分组的用户可以查看 * - 记录未授权访问尝试 @@ -48,6 +49,12 @@ class DocumentPolicy */ public function view(User $user, Document $document): bool { + // 首先检查用户是否有查看文档的权限 + if (!$user->can('document.view')) { + $this->securityLogger->logUnauthorizedAccess($user, $document, 'view'); + return false; + } + // 如果是全局文档,所有用户都可以查看 if ($document->type === 'global') { return true; @@ -79,21 +86,21 @@ class DocumentPolicy /** * 判断用户是否可以创建文档 - * 假设所有已认证用户都可以创建文档(可根据实际需求调整) + * 需求:权限检查 * * @param User $user * @return bool */ public function create(User $user): bool { - // 所有已认证用户都可以创建文档 - return true; + return $user->can('document.create'); } /** * 判断用户是否可以更新文档 - * 只有文档的上传者可以更新文档(可根据实际需求调整为管理员也可以) - * 需求:7.3 + * 需求:7.3 + 权限检查 + * - 首先检查用户是否有 document.update 权限 + * - 只有文档的上传者可以更新文档 * * @param User $user * @param Document $document @@ -101,6 +108,12 @@ class DocumentPolicy */ public function update(User $user, Document $document): bool { + // 首先检查用户是否有更新文档的权限 + if (!$user->can('document.update')) { + $this->securityLogger->logUnauthorizedAccess($user, $document, 'update'); + return false; + } + // 只有文档的上传者可以更新 $canUpdate = $document->uploaded_by === $user->id; @@ -114,8 +127,9 @@ class DocumentPolicy /** * 判断用户是否可以删除文档 - * 只有文档的上传者可以删除文档(可根据实际需求调整为管理员也可以) - * 需求:7.3 + * 需求:7.3 + 权限检查 + * - 首先检查用户是否有 document.delete 权限 + * - 只有文档的上传者可以删除文档 * * @param User $user * @param Document $document @@ -123,6 +137,12 @@ class DocumentPolicy */ public function delete(User $user, Document $document): bool { + // 首先检查用户是否有删除文档的权限 + if (!$user->can('document.delete')) { + $this->securityLogger->logUnauthorizedAccess($user, $document, 'delete'); + return false; + } + // 只有文档的上传者可以删除 $canDelete = $document->uploaded_by === $user->id; @@ -136,10 +156,11 @@ class DocumentPolicy /** * 判断用户是否可以下载文档 - * 需求:4.1, 4.2, 7.1, 7.2, 7.3 - * 下载权限与查看权限相同: - * - 全局文档:所有用户都可以下载 - * - 专用文档:只有所属分组的用户可以下载 + * 需求:4.1, 4.2, 7.1, 7.2, 7.3 + 权限检查 + * - 首先检查用户是否有 document.download 权限 + * - 下载权限与查看权限相同: + * - 全局文档:所有用户都可以下载 + * - 专用文档:只有所属分组的用户可以下载 * - 记录未授权下载尝试 * * @param User $user @@ -148,13 +169,36 @@ class DocumentPolicy */ public function download(User $user, Document $document): bool { - // 下载权限与查看权限相同 - $canDownload = $this->view($user, $document); - - // 注意:view 方法已经记录了未授权访问,这里不需要重复记录 - // 但如果需要区分 view 和 download 操作,可以在这里单独记录 - - return $canDownload; + // 首先检查用户是否有下载文档的权限 + if (!$user->can('document.download')) { + $this->securityLogger->logUnauthorizedAccess($user, $document, 'download'); + return false; + } + + // 下载权限与查看权限相同(但不需要 document.view 权限) + // 如果是全局文档,所有用户都可以下载 + if ($document->type === 'global') { + return true; + } + + // 如果是专用文档,检查用户是否属于该文档的分组 + if ($document->type === 'dedicated') { + if (!$document->group_id) { + $this->securityLogger->logUnauthorizedAccess($user, $document, 'download'); + return false; + } + + $hasAccess = $user->groups()->where('groups.id', $document->group_id)->exists(); + + if (!$hasAccess) { + $this->securityLogger->logUnauthorizedAccess($user, $document, 'download'); + } + + return $hasAccess; + } + + $this->securityLogger->logUnauthorizedAccess($user, $document, 'download'); + return false; } /** diff --git a/app/Policies/GroupPolicy.php b/app/Policies/GroupPolicy.php new file mode 100644 index 0000000..d405342 --- /dev/null +++ b/app/Policies/GroupPolicy.php @@ -0,0 +1,72 @@ +can('group.view'); + } + + /** + * 查看分组详情 + */ + public function view(User $user, Group $group): bool + { + return $user->can('group.view'); + } + + /** + * 创建分组 + */ + public function create(User $user): bool + { + return $user->can('group.create'); + } + + /** + * 更新分组 + */ + public function update(User $user, Group $group): bool + { + return $user->can('group.update'); + } + + /** + * 删除分组 + */ + public function delete(User $user, Group $group): bool + { + // 首先检查权限 + if (!$user->can('group.delete')) { + return false; + } + + // 检查是否有关联文档 + if ($group->documents()->count() > 0) { + return false; + } + + // 检查是否有关联用户 + if ($group->users()->count() > 0) { + return false; + } + + return true; + } + + /** + * 批量删除分组 + */ + public function deleteAny(User $user): bool + { + return $user->can('group.delete'); + } +} diff --git a/app/Policies/SopTemplatePolicy.php b/app/Policies/SopTemplatePolicy.php index 5e13e62..184b323 100644 --- a/app/Policies/SopTemplatePolicy.php +++ b/app/Policies/SopTemplatePolicy.php @@ -12,7 +12,7 @@ class SopTemplatePolicy */ public function viewAny(User $user): bool { - return true; + return $user->can('sop-template.view'); } /** @@ -20,7 +20,7 @@ class SopTemplatePolicy */ public function view(User $user, SopTemplate $sopTemplate): bool { - return true; + return $user->can('sop-template.view'); } /** @@ -28,7 +28,7 @@ class SopTemplatePolicy */ public function create(User $user): bool { - return true; + return $user->can('sop-template.create'); } /** @@ -36,6 +36,11 @@ class SopTemplatePolicy */ public function update(User $user, SopTemplate $sopTemplate): bool { + // 首先检查权限 + if (!$user->can('sop-template.update')) { + return false; + } + // 已发布的模板不能直接编辑 if ($sopTemplate->status === 'published') { return false; @@ -49,6 +54,11 @@ class SopTemplatePolicy */ public function delete(User $user, SopTemplate $sopTemplate): bool { + // 首先检查权限 + if (!$user->can('sop-template.delete')) { + return false; + } + // 已发布的模板不能删除 if ($sopTemplate->status === 'published') { return false; @@ -62,6 +72,11 @@ class SopTemplatePolicy */ public function publish(User $user, SopTemplate $sopTemplate): bool { + // 首先检查权限 + if (!$user->can('sop-template.publish')) { + return false; + } + return $sopTemplate->status === 'draft'; } @@ -70,6 +85,11 @@ class SopTemplatePolicy */ public function archive(User $user, SopTemplate $sopTemplate): bool { + // 首先检查权限 + if (!$user->can('sop-template.archive')) { + return false; + } + return $sopTemplate->status === 'published'; } } diff --git a/app/Policies/SystemSettingPolicy.php b/app/Policies/SystemSettingPolicy.php new file mode 100644 index 0000000..ee0ae1c --- /dev/null +++ b/app/Policies/SystemSettingPolicy.php @@ -0,0 +1,33 @@ +can('system-setting.view'); + } + + /** + * 查看系统设置详情 + */ + public function view(User $user, SystemSetting $systemSetting): bool + { + return $user->can('system-setting.view'); + } + + /** + * 更新系统设置 + */ + public function update(User $user, SystemSetting $systemSetting): bool + { + return $user->can('system-setting.update'); + } +} diff --git a/app/Policies/TerminalPolicy.php b/app/Policies/TerminalPolicy.php index a54f374..88670f3 100644 --- a/app/Policies/TerminalPolicy.php +++ b/app/Policies/TerminalPolicy.php @@ -15,8 +15,7 @@ class TerminalPolicy */ public function viewAny(User $user): bool { - // 所有已认证用户都可以查看终端列表 - return true; + return $user->can('terminal.view'); } /** @@ -28,8 +27,7 @@ class TerminalPolicy */ public function view(User $user, Terminal $terminal): bool { - // 所有已认证用户都可以查看终端详情 - return true; + return $user->can('terminal.view'); } /** @@ -40,8 +38,7 @@ class TerminalPolicy */ public function create(User $user): bool { - // 所有已认证用户都可以创建终端 - return true; + return $user->can('terminal.create'); } /** @@ -53,8 +50,7 @@ class TerminalPolicy */ public function update(User $user, Terminal $terminal): bool { - // 所有已认证用户都可以更新终端 - return true; + return $user->can('terminal.update'); } /** @@ -66,8 +62,19 @@ class TerminalPolicy */ public function delete(User $user, Terminal $terminal): bool { - // 所有已认证用户都可以删除终端 - return true; + return $user->can('terminal.delete'); + } + + /** + * 判断用户是否可以同步终端配置 + * + * @param User $user + * @param Terminal $terminal + * @return bool + */ + public function sync(User $user, Terminal $terminal): bool + { + return $user->can('terminal.sync'); } /** @@ -79,8 +86,7 @@ class TerminalPolicy */ public function restore(User $user, Terminal $terminal): bool { - // 所有已认证用户都可以恢复终端 - return true; + return $user->can('terminal.delete'); } /** @@ -92,7 +98,6 @@ class TerminalPolicy */ public function forceDelete(User $user, Terminal $terminal): bool { - // 所有已认证用户都可以永久删除终端 - return true; + return $user->can('terminal.delete'); } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 2c5f168..6414718 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -37,5 +37,8 @@ class AppServiceProvider extends ServiceProvider Gate::policy(SopTemplate::class, SopTemplatePolicy::class); Gate::policy(\Spatie\Permission\Models\Role::class, \App\Policies\RolePolicy::class); Gate::policy(\App\Models\User::class, \App\Policies\UserPolicy::class); + Gate::policy(\App\Models\SystemSetting::class, \App\Policies\SystemSettingPolicy::class); + Gate::policy(\Spatie\Activitylog\Models\Activity::class, \App\Policies\ActivityLogPolicy::class); + Gate::policy(\App\Models\Group::class, \App\Policies\GroupPolicy::class); } }