diff --git a/app/Domains/Api/Resources/LinkResource.php b/app/Domains/Api/Resources/LinkResource.php index 2abe0af..665cad0 100644 --- a/app/Domains/Api/Resources/LinkResource.php +++ b/app/Domains/Api/Resources/LinkResource.php @@ -2,11 +2,12 @@ namespace App\Domains\Api\Resources; +use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; class LinkResource extends JsonResource { - public function toArray($request): array + public function toArray(Request $request): array { return [ 'id' => $this->ulid, diff --git a/app/Http/Controllers/Api/V1/LinkController.php b/app/Http/Controllers/Api/V1/LinkController.php index 86b0b97..6b25d8b 100644 --- a/app/Http/Controllers/Api/V1/LinkController.php +++ b/app/Http/Controllers/Api/V1/LinkController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api\V1; use App\Domains\Api\Resources\LinkResource; use App\Domains\Link\Actions\CreateLink; +use App\Domains\Link\Actions\DeleteLink; use App\Domains\Link\Models\Link; use App\Domains\Workspace\Models\Workspace; use App\Http\Controllers\Controller; @@ -28,10 +29,11 @@ class LinkController extends Controller $this->authorize('update', $workspace); $validated = $request->validate([ - 'target_url' => 'required|url|max:2048', + 'target_url' => 'required|url:http,https|max:2048', 'slug' => 'nullable|string|max:64|alpha_dash', 'title' => 'nullable|string|max:255', 'tags' => 'nullable|array', + 'tags.*' => 'string|max:64', ]); $link = $action->handle($workspace, $request->user(), $validated); @@ -41,7 +43,7 @@ class LinkController extends Controller ->setStatusCode(201); } - public function destroy(string $workspaceUlid, string $linkUlid): \Illuminate\Http\Response + public function destroy(Request $request, string $workspaceUlid, string $linkUlid, DeleteLink $action): \Illuminate\Http\Response { $workspace = Workspace::where('ulid', $workspaceUlid)->firstOrFail(); $this->authorize('update', $workspace); @@ -50,7 +52,7 @@ class LinkController extends Controller ->where('workspace_id', $workspace->id) ->firstOrFail(); - $link->delete(); + $action->handle($link); return response()->noContent(); } diff --git a/app/Http/Controllers/Api/V1/WorkspaceController.php b/app/Http/Controllers/Api/V1/WorkspaceController.php index 9b8041c..5475530 100644 --- a/app/Http/Controllers/Api/V1/WorkspaceController.php +++ b/app/Http/Controllers/Api/V1/WorkspaceController.php @@ -12,8 +12,9 @@ class WorkspaceController extends Controller { $workspaces = $request->user() ->workspaces() - ->get(['id', 'ulid', 'name', 'slug']); + ->select(['ulid', 'name', 'slug']) + ->paginate(50); - return response()->json(['data' => $workspaces]); + return response()->json($workspaces); } } diff --git a/tests/Feature/Api/V1/LinkApiTest.php b/tests/Feature/Api/V1/LinkApiTest.php index 6209d8f..4cc1601 100644 --- a/tests/Feature/Api/V1/LinkApiTest.php +++ b/tests/Feature/Api/V1/LinkApiTest.php @@ -31,3 +31,34 @@ it('creates link via API', function () { $response->assertCreated() ->assertJsonPath('data.target_url', 'https://example.com'); }); + +it('deletes a link via API', function () { + $user = User::factory()->create(); + $workspace = (new \App\Domains\Workspace\Actions\CreateWorkspace)->handle($user, ['name' => 'Test']); + $link = Link::factory()->create(['workspace_id' => $workspace->id]); + $token = $user->createToken('api-test')->plainTextToken; + + $response = $this->withToken($token) + ->deleteJson("/api/v1/workspaces/{$workspace->ulid}/links/{$link->ulid}"); + + $response->assertNoContent(); + $this->assertSoftDeleted($link); +}); + +it('rejects delete from non-member', function () { + $owner = User::factory()->create(); + $outsider = User::factory()->create(); + $workspace = (new \App\Domains\Workspace\Actions\CreateWorkspace)->handle($owner, ['name' => 'Test']); + $link = Link::factory()->create(['workspace_id' => $workspace->id]); + $token = $outsider->createToken('api-test')->plainTextToken; + + $response = $this->withToken($token) + ->deleteJson("/api/v1/workspaces/{$workspace->ulid}/links/{$link->ulid}"); + + $response->assertForbidden(); +}); + +it('rejects unauthenticated requests', function () { + $response = $this->getJson('/api/v1/workspaces/ULID/links'); + $response->assertUnauthorized(); +});