Browse Source

Merge branch 'create-library' into dev

moell 1 year ago
parent
commit
984b937ae8

+ 71 - 0
app/Http/Controllers/API/LibraryController.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace App\Http\Controllers\API;
+
+use App\Http\Controllers\Controller;
+use App\Http\Requests\API\Library\CreateOrUpdateRequest;
+use App\Http\Resources\API\LibraryResource;
+use App\Models\Library;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+
+class LibraryController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     */
+    public function store(CreateOrUpdateRequest $request)
+    {
+        Library::query()->create([
+            ...$request->all(),
+            'created_by' => Auth::id(),
+            'company_id' => Auth::user()->company_id,
+            'whitelist' => $request->whitelist ? sprintf(",%s", implode(',', $request->whitelist)) : null,
+        ]);
+
+        return $this->created();
+    }
+
+    /**
+     * Display the specified resource.
+     */
+    public function show(string $id)
+    {
+        $library = Library::query()->findOrFail($id);
+
+        return new LibraryResource($library);
+    }
+
+    /**
+     * Update the specified resource in storage.
+     */
+    public function update(Request $request, string $id)
+    {
+        $library = Library::query()->findOrFail($id);
+
+        $library->fill($request->only([
+            'name', 'acl', 'asset_id', 'project_id',
+        ]));
+        $library->whitelist = $request->whitelist ? sprintf(",%s", implode(',', $request->whitelist)) : null;
+
+        $library->save();
+
+        return $this->noContent();
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     */
+    public function destroy(string $id)
+    {
+        //
+    }
+}

+ 61 - 0
app/Http/Requests/API/Library/CreateOrUpdateRequest.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace App\Http\Requests\API\Library;
+
+use App\Http\Requests\RuleHelper;
+use App\Models\Enums\LibraryACL;
+use App\Models\Enums\LibraryType;
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Validation\Rule;
+use Illuminate\Validation\Rules\Enum;
+
+class CreateOrUpdateRequest extends FormRequest
+{
+    use RuleHelper;
+
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
+     */
+    public function rules(): array
+    {
+        $rules = [
+            'name' => 'required',
+            'type' => [
+                'required',
+                new Enum(LibraryType::class)
+            ],
+            'acl' => [
+                'required',
+                new Enum(LibraryACL::class),
+            ],
+            'whitelist' => $this->usersCompanyRules(),
+        ];
+
+        switch ($this->request->get("type")) {
+            case LibraryType::ASSET->value:
+                $rules['asset_id'] = [
+                    'required',
+                    Rule::exists('assets', 'id')->where($this->userCompanyWhere()),
+                ];
+                break;
+            case LibraryType::PROJECT->value:
+                $rules['project_id'] = [
+                    'required',
+                    Rule::exists('projects', 'id')->where($this->userCompanyWhere()),
+                ];
+                break;
+        }
+
+        return $rules;
+    }
+}

+ 28 - 0
app/Http/Resources/API/LibraryResource.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Http\Resources\API;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class LibraryResource extends JsonResource
+{
+    /**
+     * Transform the resource into an array.
+     *
+     * @return array<string, mixed>
+     */
+    public function toArray(Request $request): array
+    {
+        return [
+            'id' => $this->id,
+            'name' => $this->name,
+            'asset_id' => $this->asset_id,
+            'project_id' => $this->project_id,
+            'acl' => $this->acl,
+            'whitelist' => $this->whitelist,
+            'created_at' => (string)$this->created_at,
+            'updated_at' => (string)$this->updated_at,
+        ];
+    }
+}

+ 10 - 0
app/Models/Enums/LibraryACL.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Models\Enums;
+
+enum LibraryACL: string
+{
+    case PRIVATE = 'private';
+
+    case CUSTOM = 'custom';
+}

+ 12 - 0
app/Models/Enums/LibraryType.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace App\Models\Enums;
+
+enum LibraryType: string
+{
+    case ASSET = 'asset';
+
+    case PROJECT = 'project';
+
+    case CUSTOM = 'custom';
+}

+ 21 - 0
app/Models/Library.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Models;
+
+use App\Models\Scopes\CompanyScope;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Library extends Model
+{
+    use HasFactory;
+
+    protected $guarded = [
+        'id'
+    ];
+
+    protected static function booted(): void
+    {
+        static::addGlobalScope(new CompanyScope);
+    }
+}

+ 31 - 0
database/factories/LibraryFactory.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace Database\Factories;
+
+use App\Models\Asset;
+use App\Models\Enums\LibraryACL;
+use App\Models\Enums\LibraryType;
+use Illuminate\Database\Eloquent\Factories\Factory;
+use Illuminate\Support\Facades\Auth;
+
+/**
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Library>
+ */
+class LibraryFactory extends Factory
+{
+    /**
+     * Define the model's default state.
+     *
+     * @return array<string, mixed>
+     */
+    public function definition(): array
+    {
+        return [
+            "name" => fake()->text(10),
+            "acl" => LibraryACL::CUSTOM->value,
+            "asset_id" => Asset::factory()->create(),
+            "company_id" => Auth::user()->company_id,
+            "type" => LibraryType::ASSET->value,
+        ];
+    }
+}

+ 35 - 0
database/migrations/2024_02_27_115452_create_libraries_table.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('libraries', function (Blueprint $table) {
+            $table->id();
+            $table->string("type", 20);
+            $table->integer("asset_id")->nullable()->index();
+            $table->integer("company_id")->index();
+            $table->integer("project_id")->nullable()->index();
+            $table->string("name", 60);
+            $table->string("acl", 20)->default("private");
+            $table->string("whitelist")->nullable();
+            $table->integer("created_by")->nullable();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('libraries');
+    }
+};

+ 2 - 0
routes/api.php

@@ -34,7 +34,9 @@ Route::middleware(['auth:sanctum'])->group(function () {
             'custom-field' => API\CustomFieldController::class,
             'naming-rule' => API\NameRuleController::class,
             'task' => API\TaskController::class,
+            'library' => API\LibraryController::class,
         ]);
+
         Route::patch("requirement/{requirement_id}/close",[API\RequirementController::class, 'close'])->name('requirement.close');
         Route::get("requirement/{asset_id}/asset", [API\RequirementController::class, "byAsset"])->name("requirement.byAsset");
         Route::patch("requirement/{plan_id}/plan", [API\RequirementController::class, "linkPlan"])->name("requirement.linkPlan");

+ 58 - 0
tests/Feature/API/LibraryTest.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace Tests\Feature\API;
+
+use App\Models\Library;
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Illuminate\Foundation\Testing\WithFaker;
+use Illuminate\Support\Facades\Auth;
+use Tests\Feature\TestCase;
+
+class LibraryTest extends TestCase
+{
+    public function test_create_library(): void
+    {
+        $form = Library::factory()->make();
+        $form->whitelist = [
+            Auth::id(),
+        ];
+
+        $response = $this->post(route('library.store'), $form->toArray());
+
+        $response->assertStatus(201);
+    }
+
+    public function test_library_update(): void
+    {
+        $library = Library::factory()->create();
+
+        $form = Library::factory()->make();
+
+        $response = $this->put(route('library.update', ['library' => $library->id]), $form->toArray());
+
+        $response->assertStatus(204);
+
+        $newAsset = Library::find($library->id);
+
+        $this->assertEquals($form->name, $newAsset->name);
+    }
+
+    public function test_library_show(): void
+    {
+        $library = Library::factory()->create();
+
+        $response = $this->get(route('library.show', ['library' => $library->id]));
+
+        $response->assertStatus(200)
+            ->assertJsonStructure([
+                'data' => [
+                    'id',
+                    'name',
+                    'asset_id',
+                    'project_id',
+                    'acl',
+                    'whitelist'
+                ]
+            ]);
+    }
+}