Files
KnowledgeBase/app/Policies/DocumentPolicy.php
T
lizhuoran 386fe42f76 feat(权限): 完善所有策略的权限检查
- 更新 DocumentPolicy 添加权限检查
  - viewAny/view/create/update/delete/download 都检查相应权限
  - 保留现有的分组访问控制逻辑
  - 保留安全日志记录功能
- 更新 TerminalPolicy 添加权限检查
  - 所有方法都基于 terminal.* 权限
  - 新增 sync 方法用于配置同步权限检查
- 更新 SopTemplatePolicy 添加权限检查
  - 所有方法都基于 sop-template.* 权限
  - 保留现有的状态检查逻辑(已发布不可编辑/删除)
- 创建 SystemSettingPolicy
  - 实现 viewAny/view/update 权限检查
- 创建 ActivityLogPolicy
  - 实现 viewAny/view/export 权限检查
- 创建 GroupPolicy
  - 实现完整的 CRUD 权限检查
  - 删除前检查关联文档和用户
- 在 AppServiceProvider 中注册所有策略
2026-03-11 10:08:22 +08:00

246 lines
7.4 KiB
PHP

<?php
namespace App\Policies;
use App\Models\Document;
use App\Models\User;
use App\Services\SecurityLogger;
use Illuminate\Auth\Access\Response;
class DocumentPolicy
{
/**
* 安全日志记录器
*/
protected SecurityLogger $securityLogger;
/**
* 构造函数
*/
public function __construct(SecurityLogger $securityLogger)
{
$this->securityLogger = $securityLogger;
}
/**
* 判断用户是否可以查看文档列表
* 需求:权限检查 + 分组访问控制
*
* @param User $user
* @return bool
*/
public function viewAny(User $user): bool
{
// 检查用户是否有查看文档的权限
return $user->can('document.view');
}
/**
* 判断用户是否可以查看特定文档
* 需求:3.1, 3.4, 7.1, 7.2, 7.3 + 权限检查
* - 首先检查用户是否有 document.view 权限
* - 全局文档:所有用户都可以查看
* - 专用文档:只有所属分组的用户可以查看
* - 记录未授权访问尝试
*
* @param User $user
* @param Document $document
* @return bool
*/
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;
}
// 如果是专用文档,检查用户是否属于该文档的分组
if ($document->type === 'dedicated') {
// 如果文档没有关联分组,拒绝访问
if (!$document->group_id) {
$this->securityLogger->logUnauthorizedAccess($user, $document, 'view');
return false;
}
// 检查用户是否属于该文档的分组
$hasAccess = $user->groups()->where('groups.id', $document->group_id)->exists();
// 如果没有权限,记录未授权访问尝试
if (!$hasAccess) {
$this->securityLogger->logUnauthorizedAccess($user, $document, 'view');
}
return $hasAccess;
}
// 其他情况拒绝访问
$this->securityLogger->logUnauthorizedAccess($user, $document, 'view');
return false;
}
/**
* 判断用户是否可以创建文档
* 需求:权限检查
*
* @param User $user
* @return bool
*/
public function create(User $user): bool
{
return $user->can('document.create');
}
/**
* 判断用户是否可以更新文档
* 需求:7.3 + 权限检查
* - 首先检查用户是否有 document.update 权限
* - 只有文档的上传者可以更新文档
*
* @param User $user
* @param Document $document
* @return bool
*/
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;
// 如果没有权限,记录未授权访问尝试
if (!$canUpdate) {
$this->securityLogger->logUnauthorizedAccess($user, $document, 'update');
}
return $canUpdate;
}
/**
* 判断用户是否可以删除文档
* 需求:7.3 + 权限检查
* - 首先检查用户是否有 document.delete 权限
* - 只有文档的上传者可以删除文档
*
* @param User $user
* @param Document $document
* @return bool
*/
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;
// 如果没有权限,记录未授权访问尝试
if (!$canDelete) {
$this->securityLogger->logUnauthorizedAccess($user, $document, 'delete');
}
return $canDelete;
}
/**
* 判断用户是否可以下载文档
* 需求:4.1, 4.2, 7.1, 7.2, 7.3 + 权限检查
* - 首先检查用户是否有 document.download 权限
* - 下载权限与查看权限相同:
* - 全局文档:所有用户都可以下载
* - 专用文档:只有所属分组的用户可以下载
* - 记录未授权下载尝试
*
* @param User $user
* @param Document $document
* @return bool
*/
public function download(User $user, Document $document): bool
{
// 首先检查用户是否有下载文档的权限
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;
}
/**
* 判断用户是否可以恢复已删除的文档
* 需求:7.3
*
* @param User $user
* @param Document $document
* @return bool
*/
public function restore(User $user, Document $document): bool
{
// 只有文档的上传者可以恢复
$canRestore = $document->uploaded_by === $user->id;
// 如果没有权限,记录未授权访问尝试
if (!$canRestore) {
$this->securityLogger->logUnauthorizedAccess($user, $document, 'restore');
}
return $canRestore;
}
/**
* 判断用户是否可以永久删除文档
* 需求:7.3
*
* @param User $user
* @param Document $document
* @return bool
*/
public function forceDelete(User $user, Document $document): bool
{
// 只有文档的上传者可以永久删除
$canForceDelete = $document->uploaded_by === $user->id;
// 如果没有权限,记录未授权访问尝试
if (!$canForceDelete) {
$this->securityLogger->logUnauthorizedAccess($user, $document, 'forceDelete');
}
return $canForceDelete;
}
}