added team create permission
This commit is contained in:
@@ -14,6 +14,7 @@ enum Permission: string
|
|||||||
case ProjectRead = 'project:read';
|
case ProjectRead = 'project:read';
|
||||||
case ProjectWrite = 'project:write';
|
case ProjectWrite = 'project:write';
|
||||||
case ProjectAdmin = 'project:admin';
|
case ProjectAdmin = 'project:admin';
|
||||||
|
case TeamCreate = 'team:create';
|
||||||
case TeamInvite = 'team:invite';
|
case TeamInvite = 'team:invite';
|
||||||
case TeamManage = 'team:manage';
|
case TeamManage = 'team:manage';
|
||||||
case TeamAdmin = 'team:admin';
|
case TeamAdmin = 'team:admin';
|
||||||
@@ -26,6 +27,7 @@ enum Permission: string
|
|||||||
self::ProjectRead => 'Project read',
|
self::ProjectRead => 'Project read',
|
||||||
self::ProjectWrite => 'Project write',
|
self::ProjectWrite => 'Project write',
|
||||||
self::ProjectAdmin => 'Project admin',
|
self::ProjectAdmin => 'Project admin',
|
||||||
|
self::TeamCreate => 'Team create',
|
||||||
self::TeamInvite => 'Team invite',
|
self::TeamInvite => 'Team invite',
|
||||||
self::TeamManage => 'Team manage',
|
self::TeamManage => 'Team manage',
|
||||||
self::TeamAdmin => 'Team admin',
|
self::TeamAdmin => 'Team admin',
|
||||||
@@ -35,7 +37,7 @@ enum Permission: string
|
|||||||
public function scope(): PermissionScope
|
public function scope(): PermissionScope
|
||||||
{
|
{
|
||||||
return match ($this) {
|
return match ($this) {
|
||||||
self::GlobalAdmin, self::ProjectCreate => PermissionScope::Global,
|
self::GlobalAdmin, self::ProjectCreate, self::TeamCreate => PermissionScope::Global,
|
||||||
self::ProjectRead, self::ProjectWrite, self::ProjectAdmin => PermissionScope::Project,
|
self::ProjectRead, self::ProjectWrite, self::ProjectAdmin => PermissionScope::Project,
|
||||||
self::TeamInvite, self::TeamManage, self::TeamAdmin => PermissionScope::Team,
|
self::TeamInvite, self::TeamManage, self::TeamAdmin => PermissionScope::Team,
|
||||||
};
|
};
|
||||||
@@ -64,13 +66,8 @@ enum Permission: string
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->impliedPermissions() as $impliedPermission) {
|
return array_any($this->impliedPermissions(), fn ($impliedPermission) => $impliedPermission->includes($permission));
|
||||||
if ($impliedPermission->includes($permission)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAssignableTo(Model|string $assignee): bool
|
public function isAssignableTo(Model|string $assignee): bool
|
||||||
@@ -118,6 +115,7 @@ enum Permission: string
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
self::GlobalAdmin,
|
self::GlobalAdmin,
|
||||||
|
self::TeamCreate,
|
||||||
self::ProjectCreate,
|
self::ProjectCreate,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class TeamController extends Controller
|
|||||||
public function index(Request $request): Response
|
public function index(Request $request): Response
|
||||||
{
|
{
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
$canCreateTeams = $this->permissionService->allows($user, Permission::GlobalAdmin);
|
$canCreateTeams = $this->permissionService->allows($user, Permission::TeamCreate);
|
||||||
$manageableTeamIds = $this->permissionService->manageableTeamIds($user);
|
$manageableTeamIds = $this->permissionService->manageableTeamIds($user);
|
||||||
|
|
||||||
abort_unless($canCreateTeams || $manageableTeamIds !== [], 403);
|
abort_unless($canCreateTeams || $manageableTeamIds !== [], 403);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class HandleInertiaRequests extends Middleware
|
|||||||
'name' => config('app.name'),
|
'name' => config('app.name'),
|
||||||
'auth' => [
|
'auth' => [
|
||||||
'permissions' => [
|
'permissions' => [
|
||||||
'canManageTeams' => $user !== null && $this->permissionService->canManageAnyTeam($user),
|
'canManageTeams' => $user !== null && ($this->permissionService->canManageAnyTeam($user) || $this->permissionService->allows($user, Permission::TeamCreate)),
|
||||||
'globalAdmin' => $user !== null && $this->permissionService->allows($user, Permission::GlobalAdmin),
|
'globalAdmin' => $user !== null && $this->permissionService->allows($user, Permission::GlobalAdmin),
|
||||||
'projectCreate' => $user !== null && $this->permissionService->allows($user, Permission::ProjectCreate),
|
'projectCreate' => $user !== null && $this->permissionService->allows($user, Permission::ProjectCreate),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class StoreTeamRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
return $this->user()?->can('access-admin') ?? false;
|
return $this->user()?->can('create-team') ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -56,7 +56,9 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
Gate::define('access-admin', fn (User $user): bool => $permissionService->allows($user, Permission::GlobalAdmin));
|
Gate::define('access-admin', fn (User $user): bool => $permissionService->allows($user, Permission::GlobalAdmin));
|
||||||
Gate::define('create-project', fn (User $user): bool => $permissionService->allows($user, Permission::ProjectCreate));
|
Gate::define('create-project', fn (User $user): bool => $permissionService->allows($user, Permission::ProjectCreate));
|
||||||
|
Gate::define('create-team', fn (User $user): bool => $permissionService->allows($user, Permission::TeamCreate));
|
||||||
Gate::define('manage-teams', fn (User $user): bool => $permissionService->canManageAnyTeam($user));
|
Gate::define('manage-teams', fn (User $user): bool => $permissionService->canManageAnyTeam($user));
|
||||||
|
Gate::define('view-teams', fn (User $user): bool => Gate::forUser($user)->any(['create-team', 'manage-teams']));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+2
-2
@@ -105,10 +105,10 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Route::get('teams', [TeamController::class, 'index'])
|
Route::get('teams', [TeamController::class, 'index'])
|
||||||
->middleware('can:manage-teams')
|
->middleware('can:view-teams')
|
||||||
->name('teams.index');
|
->name('teams.index');
|
||||||
Route::post('teams', [TeamController::class, 'store'])
|
Route::post('teams', [TeamController::class, 'store'])
|
||||||
->middleware('can:access-admin')
|
->middleware('can:create-team')
|
||||||
->name('teams.store');
|
->name('teams.store');
|
||||||
Route::patch('teams/{team}/members', [TeamController::class, 'updateMembers'])
|
Route::patch('teams/{team}/members', [TeamController::class, 'updateMembers'])
|
||||||
->name('teams.members.update');
|
->name('teams.members.update');
|
||||||
|
|||||||
@@ -88,6 +88,56 @@ class TeamControllerTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure admins can view the teams management page.
|
||||||
|
*/
|
||||||
|
public function test_non_admins_with_team_create_permission_can_view_the_teams_management_page(): void
|
||||||
|
{
|
||||||
|
$createTeamUser = User::factory()->create();
|
||||||
|
$member = User::factory()->create([
|
||||||
|
'name' => 'Regular User',
|
||||||
|
'email' => 'member@example.com',
|
||||||
|
]);
|
||||||
|
$team = Team::factory()->create([
|
||||||
|
'name' => 'Platform Team',
|
||||||
|
]);
|
||||||
|
$team->users()->attach($member);
|
||||||
|
|
||||||
|
$this->syncGlobalPermissions($createTeamUser, ['team:create']);
|
||||||
|
|
||||||
|
$this->actingAs($createTeamUser)
|
||||||
|
->get(route('teams.index'))
|
||||||
|
->assertOk()
|
||||||
|
->assertInertia(fn (Assert $page) => $page
|
||||||
|
->component('teams/Index')
|
||||||
|
->where('canCreateTeams', true)
|
||||||
|
->where('teams.0.name', 'Platform Team')
|
||||||
|
->where('teams.0.user_ids.0', $member->id)
|
||||||
|
->where('teams.0.users.0.email', 'member@example.com'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure admins can create teams.
|
||||||
|
*/
|
||||||
|
public function test_non_admins_with_team_create_permission_can_create_teams(): void
|
||||||
|
{
|
||||||
|
$createTeamUser = User::factory()->create();
|
||||||
|
|
||||||
|
$this->syncGlobalPermissions($createTeamUser, ['team:create']);
|
||||||
|
|
||||||
|
$this->actingAs($createTeamUser)
|
||||||
|
->post(route('teams.store'), [
|
||||||
|
'name' => 'Delivery Team',
|
||||||
|
])
|
||||||
|
->assertRedirect(route('teams.index'))
|
||||||
|
->assertSessionHas('status', 'Delivery Team was created.');
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('teams', [
|
||||||
|
'name' => 'Delivery Team',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure users without team management access cannot view the teams page.
|
* Ensure users without team management access cannot view the teams page.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user