Browse Source

project acl

moell 11 tháng trước cách đây
mục cha
commit
12cb908922
2 tập tin đã thay đổi với 53 bổ sung27 xóa
  1. 29 27
      app/Http/Controllers/API/ProjectController.php
  2. 24 0
      app/Models/Project.php

+ 29 - 27
app/Http/Controllers/API/ProjectController.php

@@ -52,12 +52,13 @@ class ProjectController extends Controller
      */
     public function index(Request $request)
     {
-        $projectAsset = Project::filter($request->all())->with('assets')->simplePaginate();
+        $projectAsset = Project::filter($request->all())->allowed()->with('assets')->simplePaginate();
+
         return ProjectResource::collection($projectAsset);
     }
 
     public function treeIndex(string $id){
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         //获取项目所关联的需求所在需求分组的id
         $requirementsGroupIds=$project->requirementsGroup ->pluck('id')->unique()->toArray();
@@ -132,7 +133,7 @@ class ProjectController extends Controller
      */
     public function show(string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         return new ProjectDetailResource($project);
     }
@@ -142,7 +143,7 @@ class ProjectController extends Controller
      */
     public function update(CreateOrUpdateRequest $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $project->fill([
             ...$request->all(),
@@ -185,7 +186,7 @@ class ProjectController extends Controller
      */
     public function destroy(string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $project->delete();
 
@@ -196,7 +197,7 @@ class ProjectController extends Controller
 
     public function closed(Request $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $project->status = ProjectStatus::CLOSED->value;
         $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project);
@@ -211,7 +212,7 @@ class ProjectController extends Controller
 
     public function start(Request $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $project->status = ProjectStatus::DOING->value;
         $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project);
@@ -229,7 +230,7 @@ class ProjectController extends Controller
 
     public function pause(Request $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $project->status = ProjectStatus::PAUSE->value;
         $changes = ModelChangeDetector::detector(ActionObjectType::PROJECT, $project);
@@ -251,7 +252,7 @@ class ProjectController extends Controller
      */
     public function postpone(PostponeRequest $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $project->fill($request->only([
             'begin', 'end'
@@ -270,7 +271,7 @@ class ProjectController extends Controller
     {
 
         $requirementIds = $request->get("requirement_id",[]);
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
 
         if(! $requirementIds){
@@ -306,7 +307,7 @@ class ProjectController extends Controller
     {
 
         $requirementIds = $request->get("requirement_id",[]);
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         if (! $requirementIds) {
             return $this->forbidden("Please select the correct requirement");
@@ -330,7 +331,7 @@ class ProjectController extends Controller
 
     public function linkRequirementByPlan(LinkRequirementByPlanRequest $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $plan = Plan::findOrFail($request->plan_id);
 
@@ -345,14 +346,14 @@ class ProjectController extends Controller
 
     public function plan(string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         return SimplePlanResource::collection($project->plans);
     }
 
     public function requirement(Request $request,string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         // 初始化 requirements 的查询构建器
         $requirementsQuery = $project->requirements();
@@ -382,7 +383,7 @@ class ProjectController extends Controller
 
     public function notLinkAssetRequirement(string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
         $requirements = $project->assets
             ? Requirement::query()->whereIn('asset_id', $project->assets?->pluck('id')->toArray())->whereNotIn('id', $project->requirements?->pluck('id')->toArray())->simplePaginate()
             : [];
@@ -390,18 +391,18 @@ class ProjectController extends Controller
         return AssetRequirementResource::collection($requirements);
     }
 
-    public function updateLinkAssets(UpdateLinkAssetsRequest $request,string $project_id)
+    public function updateLinkAssets(UpdateLinkAssetsRequest $request, string $projectId)
     {
-        $project = Project::find($project_id);
+        $project = Project::allowed($projectId)->find($projectId);
         if (is_null($project)){
         return   $this->badRequest('project does not exist');
         }
         $assetsIds = $request->assets;
-        DB::transaction(function () use ($project_id,$assetsIds) {
-            ProjectAsset::where('project_id', $project_id)->delete();
+        DB::transaction(function () use ($projectId,$assetsIds) {
+            ProjectAsset::where('project_id', $projectId)->delete();
             foreach ($assetsIds as $assetId) {
                 ProjectAsset::create([
-                    'project_id' => $project_id,
+                    'project_id' => $projectId,
                     'asset_id' => $assetId,
                 ]);
             }
@@ -412,7 +413,7 @@ class ProjectController extends Controller
 
     public function dynamic(Request $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         return $this->success([
             'data' => ActionRepository::dynamic($project, $request->all())
@@ -421,7 +422,7 @@ class ProjectController extends Controller
 
     public function kanban(Request $request, ProjectKanbanService $service, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         return $this->success([
             'data' => $service->kanban($project, $request->get("group", "requirement_asc"))
@@ -430,7 +431,7 @@ class ProjectController extends Controller
 
     public function groupView(Request $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $group = in_array(
             $request->get("group"),
@@ -445,7 +446,7 @@ class ProjectController extends Controller
 
     public function gantt(Request $request, string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         $group = in_array(
             $request->get("group"),
@@ -460,7 +461,7 @@ class ProjectController extends Controller
 
     public function printKanban(string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         return $this->success([
             'data' => [
@@ -473,7 +474,7 @@ class ProjectController extends Controller
 
     public function latestDynamic(string $id)
     {
-        $project = Project::findOrFail($id);
+        $project = Project::allowed($id)->findOrFail($id);
 
         return $this->success([
             'data' => ActionRepository::latestDynamic($project)
@@ -481,7 +482,8 @@ class ProjectController extends Controller
     }
 
     public function requirementsLinkGroup(string $id){
-        $requirementsLinksGroup = Project::findOrFail($id)->requirementsGroup->unique('id');
+        $requirementsLinksGroup = Project::allowed($id)->findOrFail($id)->requirementsGroup->unique('id');
+
         return RequirementGroupParentResource::collection($requirementsLinksGroup);
     }
 }

+ 24 - 0
app/Models/Project.php

@@ -2,11 +2,14 @@
 
 namespace App\Models;
 
+use App\Models\Enums\ProjectACL;
 use App\Models\Scopes\CompanyScope;
 use EloquentFilter\Filterable;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Support\Facades\Auth;
 
 class Project extends Model
 {
@@ -21,6 +24,27 @@ class Project extends Model
         static::addGlobalScope(new CompanyScope);
     }
 
+    /**
+     * ACL 访问控制作用域
+     *
+     * @param Builder $query
+     * @param string $id 单个操作时使用,限制范围
+     * @return void
+     */
+    public function scopeAllowed(Builder $query, string $id = null): void
+    {
+        $projectIds = Project::query()->leftJoin("team_members", "projects.id", "=", "team_members.project_id")
+            ->filter(request()->query())
+            ->when($id, fn($query) => $query->where("projects.id", $id))
+            ->where("team_members.user_id", Auth::id())
+            ->orWhere(fn($query) => $query->where("projects.acl", ProjectACL::CUSTOM->value)->where("whitelist", "like", "%,".Auth::id().",%"))
+            ->pluck("projects.id")
+            ->unique();
+
+
+        $query->whereIn("id", $projectIds->toArray());
+    }
+
     public function plans(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
     {
         return $this->belongsToMany(Plan::class, 'project_plan');