diff --git a/app/Http/Controllers/BoardsController.php b/app/Http/Controllers/BoardsController.php index 7543477f..339b2f69 100644 --- a/app/Http/Controllers/BoardsController.php +++ b/app/Http/Controllers/BoardsController.php @@ -9,7 +9,8 @@ class BoardsController extends Controller { public function show(Project $project, Board $board) { - abort_if($project->private && !auth()->user()?->hasAdminAccess(), 404); + abort_unless($project->isVisibleForCurrentUser(), 404); + abort_unless($board->visible, 404); return view('board', [ 'project' => $project, diff --git a/routes/web.php b/routes/web.php index c231bea6..a8371e09 100644 --- a/routes/web.php +++ b/routes/web.php @@ -52,7 +52,9 @@ Route::get('projects/{project}/items/{item}/ai', [ItemController::class, 'ai'])->name('projects.items.ai'); Route::post('projects/{project}/items/{item}/vote', [ItemController::class, 'vote'])->middleware('authed')->name('projects.items.vote'); Route::post('projects/{project}/items/{item}/update-board', [ItemController::class, 'updateBoard'])->middleware('authed')->name('projects.items.update-board'); -Route::get('projects/{project}/boards/{board}', [BoardsController::class, 'show'])->name('projects.boards.show'); +Route::get('projects/{project}/boards/{board}', [BoardsController::class, 'show']) + ->scopeBindings() + ->name('projects.boards.show'); Route::get('activity', \App\Http\Controllers\ActivityController::class)->name('activity'); Route::get('mcp/docs', \App\Http\Controllers\McpController::class)->name('mcp.docs'); diff --git a/tests/Feature/Controllers/BoardsControllerTest.php b/tests/Feature/Controllers/BoardsControllerTest.php index 90f5f8f2..2638f92f 100644 --- a/tests/Feature/Controllers/BoardsControllerTest.php +++ b/tests/Feature/Controllers/BoardsControllerTest.php @@ -18,6 +18,21 @@ get(route('projects.boards.show', [$project,$board]))->assertOk(); }); +test('hidden boards return not found', function () { + $project = Project::factory()->create(); + $board = Board::factory()->for($project)->create(['visible' => false]); + + get(route('projects.boards.show', [$project, $board]))->assertNotFound(); +}); + +test('boards from another project return not found', function () { + $project = Project::factory()->create(); + $otherProject = Project::factory()->create(); + $board = Board::factory()->for($otherProject)->create(['visible' => true]); + + get(route('projects.boards.show', [$project, $board]))->assertNotFound(); +}); + test('breadcrumbs', function () { $project = Project::factory()->create();