diff --git a/routes/admin.php b/routes/admin.php new file mode 100644 index 0000000..b9d6e09 --- /dev/null +++ b/routes/admin.php @@ -0,0 +1,17 @@ +prefix('admin') + ->name('admin.') + ->group(function (): void { + Route::prefix('users') + ->name('users.') + ->controller(UserManagementController::class) + ->group(function (): void { + Route::get('/', 'index')->name('index'); + Route::patch('{user}/permissions', 'update')->name('update'); + }); + }); diff --git a/routes/projects.php b/routes/projects.php new file mode 100644 index 0000000..0e8f24f --- /dev/null +++ b/routes/projects.php @@ -0,0 +1,161 @@ +prefix('projects') + ->name('projects.') + ->group(function (): void { + Route::get('/', [ProjectController::class, 'index'])->name('index'); + + Route::middleware('can:create-project')->group(function (): void { + Route::get('create', [ProjectController::class, 'create'])->name('create'); + Route::post('/', [ProjectController::class, 'store'])->name('store'); + }); + + Route::prefix('{project}') + ->group(function (): void { + Route::middleware('can:view-project,project')->group(function (): void { + Route::get('/', [ProjectController::class, 'show'])->name('show'); + Route::get('board', [ProjectBoardController::class, 'index'])->name('board.index'); + Route::get('backlog', [ProjectController::class, 'backlog'])->name('backlog.index'); + }); + + Route::delete('/', [ProjectController::class, 'destroy']) + ->middleware('can:access-admin') + ->name('destroy'); + + Route::middleware('can:admin-project,project')->group(function (): void { + Route::get('access', [ProjectController::class, 'access'])->name('access'); + + Route::prefix('permissions')->name('permissions.')->group(function (): void { + Route::patch('users/{user}', [ProjectController::class, 'updateUserPermissions']) + ->name('users.update'); + Route::patch('teams/{team}', [ProjectController::class, 'updateTeamPermissions']) + ->name('teams.update'); + }); + }); + + Route::scopeBindings()->group(function (): void { + Route::prefix('tickets') + ->name('tickets.') + ->group(function (): void { + Route::middleware('can:write-project,project')->group(function (): void { + Route::get('create', [ProjectTicketController::class, 'create'])->name('create'); + Route::post('/', [ProjectTicketController::class, 'store'])->name('store'); + }); + + Route::prefix('{ticket}')->group(function (): void { + Route::get('/', [ProjectTicketController::class, 'show']) + ->middleware('can:view-project,project') + ->name('show'); + + Route::middleware('can:write-project,project')->group(function (): void { + Route::patch('/', [ProjectTicketController::class, 'update'])->name('update'); + Route::patch('status', [ProjectBoardController::class, 'move'])->name('status.update'); + + Route::prefix('branches') + ->name('branches.') + ->controller(ProjectTicketBranchController::class) + ->group(function (): void { + Route::get('validate', 'validate')->name('validate'); + Route::post('/', 'store')->name('store'); + }); + + Route::prefix('links') + ->name('links.') + ->controller(ProjectTicketLinkController::class) + ->group(function (): void { + Route::post('/', 'store')->name('store'); + Route::delete('{ticketLink}', 'destroy') + ->withoutScopedBindings() + ->name('destroy'); + }); + }); + }); + }); + + Route::prefix('settings') + ->name('settings.') + ->middleware('can:admin-project,project') + ->group(function (): void { + Route::get('general', [ProjectController::class, 'general'])->name('general'); + + Route::get('board', [ProjectBoardSettingsController::class, 'show'])->name('board'); + + Route::prefix('board') + ->name('board.') + ->controller(ProjectBoardSettingsController::class) + ->group(function (): void { + Route::prefix('columns')->name('columns.')->group(function (): void { + Route::post('/', 'store')->name('store'); + Route::patch('{boardColumn}', 'update')->name('update'); + Route::delete('{boardColumn}', 'destroy')->name('destroy'); + }); + + Route::prefix('statuses')->name('statuses.')->group(function (): void { + Route::post('/', 'storeStatus')->name('store'); + Route::patch('{ticketStatus}', 'updateStatus')->name('update'); + Route::delete('{ticketStatus}', 'destroyStatus')->name('destroy'); + Route::patch('{ticketStatus}/transitions', 'updateStatusTransitions') + ->name('transitions.update'); + }); + }); + + Route::get('metadata', [ProjectTicketMetadataSettingsController::class, 'show']) + ->name('metadata'); + Route::patch('metadata', [ProjectTicketMetadataSettingsController::class, 'update']) + ->name('metadata.update'); + + Route::prefix('metadata') + ->name('metadata.') + ->controller(ProjectTicketMetadataSettingsController::class) + ->group(function (): void { + Route::prefix('types')->name('types.')->group(function (): void { + Route::post('/', 'storeType')->name('store'); + Route::patch('{ticketType}', 'updateType')->name('update'); + Route::delete('{ticketType}', 'destroyType')->name('destroy'); + }); + + Route::prefix('priorities')->name('priorities.')->group(function (): void { + Route::post('/', 'storePriority')->name('store'); + Route::patch('{ticketPriority}', 'updatePriority')->name('update'); + Route::delete('{ticketPriority}', 'destroyPriority')->name('destroy'); + }); + + Route::prefix('fields')->name('fields.')->group(function (): void { + Route::post('/', 'storeFieldDefinition')->name('store'); + Route::patch('{ticketFieldDefinition}', 'updateFieldDefinition')->name('update'); + Route::delete('{ticketFieldDefinition}', 'destroyFieldDefinition')->name('destroy'); + }); + + Route::prefix('link-types')->name('link-types.')->group(function (): void { + Route::post('/', 'storeLinkType')->name('store'); + Route::patch('{ticketLinkType}', 'updateLinkType')->name('update'); + Route::delete('{ticketLinkType}', 'destroyLinkType')->name('destroy'); + }); + }); + + Route::get('repositories', [ProjectRepositorySettingsController::class, 'show']) + ->name('repositories'); + + Route::prefix('repositories') + ->name('repositories.') + ->controller(ProjectRepositorySettingsController::class) + ->group(function (): void { + Route::post('/', 'store')->name('store'); + Route::patch('{repositoryConnection}', 'update')->name('update'); + Route::delete('{repositoryConnection}', 'destroy')->name('destroy'); + }); + }); + }); + }); + }); diff --git a/routes/settings.php b/routes/settings.php index 484c10f..c03052c 100644 --- a/routes/settings.php +++ b/routes/settings.php @@ -5,30 +5,41 @@ use App\Http\Controllers\Settings\ProfileController; use App\Http\Controllers\Settings\SecurityController; use Illuminate\Support\Facades\Route; -Route::middleware(['auth'])->group(function () { - Route::redirect('settings', '/settings/profile'); +Route::middleware('auth') + ->prefix('settings') + ->group(function (): void { + Route::redirect('/', '/settings/profile'); - Route::get('settings/profile', [ProfileController::class, 'edit'])->name('profile.edit'); - Route::patch('settings/profile', [ProfileController::class, 'update'])->name('profile.update'); -}); + Route::controller(ProfileController::class) + ->prefix('profile') + ->group(function (): void { + Route::get('/', 'edit')->name('profile.edit'); + Route::patch('/', 'update')->name('profile.update'); + }); + }); -Route::middleware(['auth', 'verified'])->group(function () { - Route::delete('settings/profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); +Route::middleware(['auth', 'verified']) + ->prefix('settings') + ->group(function (): void { + Route::delete('profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); - Route::get('settings/security', [SecurityController::class, 'edit'])->name('security.edit'); + Route::controller(SecurityController::class)->group(function (): void { + Route::get('security', 'edit')->name('security.edit'); - Route::put('settings/password', [SecurityController::class, 'update']) - ->middleware('throttle:6,1') - ->name('user-password.update'); + Route::put('password', 'update') + ->middleware('throttle:6,1') + ->name('user-password.update'); + }); - Route::get('settings/git-connections', [GitConnectionController::class, 'edit']) - ->name('git-connections.edit'); - Route::post('settings/git-connections', [GitConnectionController::class, 'store']) - ->name('git-connections.store'); - Route::patch('settings/git-connections/{gitConnection}', [GitConnectionController::class, 'update']) - ->name('git-connections.update'); - Route::delete('settings/git-connections/{gitConnection}', [GitConnectionController::class, 'destroy']) - ->name('git-connections.destroy'); + Route::prefix('git-connections') + ->name('git-connections.') + ->controller(GitConnectionController::class) + ->group(function (): void { + Route::get('/', 'edit')->name('edit'); + Route::post('/', 'store')->name('store'); + Route::patch('{gitConnection}', 'update')->name('update'); + Route::delete('{gitConnection}', 'destroy')->name('destroy'); + }); - Route::inertia('settings/appearance', 'settings/Appearance')->name('appearance.edit'); -}); + Route::inertia('appearance', 'settings/Appearance')->name('appearance.edit'); + }); diff --git a/routes/teams.php b/routes/teams.php new file mode 100644 index 0000000..ee990f5 --- /dev/null +++ b/routes/teams.php @@ -0,0 +1,22 @@ +prefix('teams') + ->name('teams.') + ->controller(TeamController::class) + ->group(function (): void { + Route::get('/', 'index') + ->middleware('can:view-teams') + ->name('index'); + + Route::post('/', 'store') + ->middleware('can:create-team') + ->name('store'); + + Route::patch('{team}/members', 'updateMembers')->name('members.update'); + Route::patch('{team}/permissions/users/{user}', 'updateUserPermissions') + ->name('permissions.users.update'); + }); diff --git a/routes/web.php b/routes/web.php index e47a323..2fa1e60 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,15 +1,5 @@ group(function () { Route::inertia('dashboard', 'Dashboard')->name('dashboard'); - - Route::get('projects', [ProjectController::class, 'index']) - ->name('projects.index'); - Route::get('projects/create', [ProjectController::class, 'create']) - ->middleware('can:create-project') - ->name('projects.create'); - Route::post('projects', [ProjectController::class, 'store']) - ->middleware('can:create-project') - ->name('projects.store'); - Route::get('projects/{project}', [ProjectController::class, 'show']) - ->middleware('can:view-project,project') - ->name('projects.show'); - - Route::delete('projects/{project}', [ProjectController::class, 'destroy']) - ->middleware('can:access-admin') - ->name('projects.destroy'); - - Route::get('projects/{project}/access', [ProjectController::class, 'access']) - ->middleware('can:admin-project,project') - ->name('projects.access'); - Route::patch('projects/{project}/permissions/users/{user}', [ProjectController::class, 'updateUserPermissions']) - ->middleware('can:admin-project,project') - ->name('projects.permissions.users.update'); - Route::patch('projects/{project}/permissions/teams/{team}', [ProjectController::class, 'updateTeamPermissions']) - ->middleware('can:admin-project,project') - ->name('projects.permissions.teams.update'); - - Route::scopeBindings()->group(function (): void { - Route::get('projects/{project}/board', [ProjectBoardController::class, 'index']) - ->middleware('can:view-project,project') - ->name('projects.board.index'); - Route::get('projects/{project}/backlog', [ProjectController::class, 'backlog']) - ->middleware('can:view-project,project') - ->name('projects.backlog.index'); - Route::get('projects/{project}/tickets/create', [ProjectTicketController::class, 'create']) - ->middleware('can:write-project,project') - ->name('projects.tickets.create'); - Route::post('projects/{project}/tickets', [ProjectTicketController::class, 'store']) - ->middleware('can:write-project,project') - ->name('projects.tickets.store'); - Route::get('projects/{project}/tickets/{ticket}', [ProjectTicketController::class, 'show']) - ->middleware('can:view-project,project') - ->name('projects.tickets.show'); - Route::patch('projects/{project}/tickets/{ticket}', [ProjectTicketController::class, 'update']) - ->middleware('can:write-project,project') - ->name('projects.tickets.update'); - Route::get('projects/{project}/tickets/{ticket}/branches/validate', [ProjectTicketBranchController::class, 'validate']) - ->middleware('can:write-project,project') - ->name('projects.tickets.branches.validate'); - Route::post('projects/{project}/tickets/{ticket}/branches', [ProjectTicketBranchController::class, 'store']) - ->middleware('can:write-project,project') - ->name('projects.tickets.branches.store'); - Route::post('projects/{project}/tickets/{ticket}/links', [ProjectTicketLinkController::class, 'store']) - ->middleware('can:write-project,project') - ->name('projects.tickets.links.store'); - Route::delete('projects/{project}/tickets/{ticket}/links/{ticketLink}', [ProjectTicketLinkController::class, 'destroy']) - ->middleware('can:write-project,project') - ->withoutScopedBindings() - ->name('projects.tickets.links.destroy'); - Route::patch('projects/{project}/tickets/{ticket}/status', [ProjectBoardController::class, 'move']) - ->middleware('can:write-project,project') - ->name('projects.tickets.status.update'); - Route::get('projects/{project}/settings/general', [ProjectController::class, 'general']) - ->middleware('can:admin-project,project') - ->name('projects.settings.general'); - Route::get('projects/{project}/settings/board', [ProjectBoardSettingsController::class, 'show']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board'); - Route::post('projects/{project}/settings/board/columns', [ProjectBoardSettingsController::class, 'store']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board.columns.store'); - Route::patch('projects/{project}/settings/board/columns/{boardColumn}', [ProjectBoardSettingsController::class, 'update']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board.columns.update'); - Route::delete('projects/{project}/settings/board/columns/{boardColumn}', [ProjectBoardSettingsController::class, 'destroy']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board.columns.destroy'); - Route::post('projects/{project}/settings/board/statuses', [ProjectBoardSettingsController::class, 'storeStatus']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board.statuses.store'); - Route::patch('projects/{project}/settings/board/statuses/{ticketStatus}', [ProjectBoardSettingsController::class, 'updateStatus']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board.statuses.update'); - Route::delete('projects/{project}/settings/board/statuses/{ticketStatus}', [ProjectBoardSettingsController::class, 'destroyStatus']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board.statuses.destroy'); - Route::patch('projects/{project}/settings/board/statuses/{ticketStatus}/transitions', [ProjectBoardSettingsController::class, 'updateStatusTransitions']) - ->middleware('can:admin-project,project') - ->name('projects.settings.board.statuses.transitions.update'); - Route::get('projects/{project}/settings/metadata', [ProjectTicketMetadataSettingsController::class, 'show']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata'); - Route::get('projects/{project}/settings/repositories', [ProjectRepositorySettingsController::class, 'show']) - ->middleware('can:admin-project,project') - ->name('projects.settings.repositories'); - Route::post('projects/{project}/settings/repositories', [ProjectRepositorySettingsController::class, 'store']) - ->middleware('can:admin-project,project') - ->name('projects.settings.repositories.store'); - Route::patch('projects/{project}/settings/repositories/{repositoryConnection}', [ProjectRepositorySettingsController::class, 'update']) - ->middleware('can:admin-project,project') - ->name('projects.settings.repositories.update'); - Route::delete('projects/{project}/settings/repositories/{repositoryConnection}', [ProjectRepositorySettingsController::class, 'destroy']) - ->middleware('can:admin-project,project') - ->name('projects.settings.repositories.destroy'); - Route::post('projects/{project}/settings/metadata/types', [ProjectTicketMetadataSettingsController::class, 'storeType']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.types.store'); - Route::patch('projects/{project}/settings/metadata/types/{ticketType}', [ProjectTicketMetadataSettingsController::class, 'updateType']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.types.update'); - Route::patch('projects/{project}/settings/metadata', [ProjectTicketMetadataSettingsController::class, 'update']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.update'); - Route::delete('projects/{project}/settings/metadata/types/{ticketType}', [ProjectTicketMetadataSettingsController::class, 'destroyType']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.types.destroy'); - Route::post('projects/{project}/settings/metadata/priorities', [ProjectTicketMetadataSettingsController::class, 'storePriority']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.priorities.store'); - Route::patch('projects/{project}/settings/metadata/priorities/{ticketPriority}', [ProjectTicketMetadataSettingsController::class, 'updatePriority']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.priorities.update'); - Route::delete('projects/{project}/settings/metadata/priorities/{ticketPriority}', [ProjectTicketMetadataSettingsController::class, 'destroyPriority']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.priorities.destroy'); - Route::post('projects/{project}/settings/metadata/fields', [ProjectTicketMetadataSettingsController::class, 'storeFieldDefinition']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.fields.store'); - Route::patch('projects/{project}/settings/metadata/fields/{ticketFieldDefinition}', [ProjectTicketMetadataSettingsController::class, 'updateFieldDefinition']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.fields.update'); - Route::delete('projects/{project}/settings/metadata/fields/{ticketFieldDefinition}', [ProjectTicketMetadataSettingsController::class, 'destroyFieldDefinition']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.fields.destroy'); - Route::post('projects/{project}/settings/metadata/link-types', [ProjectTicketMetadataSettingsController::class, 'storeLinkType']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.link-types.store'); - Route::patch('projects/{project}/settings/metadata/link-types/{ticketLinkType}', [ProjectTicketMetadataSettingsController::class, 'updateLinkType']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.link-types.update'); - Route::delete('projects/{project}/settings/metadata/link-types/{ticketLinkType}', [ProjectTicketMetadataSettingsController::class, 'destroyLinkType']) - ->middleware('can:admin-project,project') - ->name('projects.settings.metadata.link-types.destroy'); - }); - - Route::get('teams', [TeamController::class, 'index']) - ->middleware('can:view-teams') - ->name('teams.index'); - Route::post('teams', [TeamController::class, 'store']) - ->middleware('can:create-team') - ->name('teams.store'); - Route::patch('teams/{team}/members', [TeamController::class, 'updateMembers']) - ->name('teams.members.update'); - Route::patch('teams/{team}/permissions/users/{user}', [TeamController::class, 'updateUserPermissions']) - ->name('teams.permissions.users.update'); }); -Route::middleware(['auth', 'verified', 'can:access-admin']) - ->prefix('admin') - ->name('admin.') - ->group(function () { - Route::get('users', [UserManagementController::class, 'index'])->name('users.index'); - Route::patch('users/{user}/permissions', [UserManagementController::class, 'update'])->name('users.update'); - }); - +require __DIR__.'/admin.php'; +require __DIR__.'/projects.php'; require __DIR__.'/settings.php'; +require __DIR__.'/teams.php';