create(); $workspace = Workspace::factory()->create(); $workspace->users()->attach($user->id, [ 'role' => $role, 'permissions' => $permissions, ]); session(['current_workspace_id' => $workspace->id]); return [$user, $workspace]; } function createPermWorkspaceMember(Workspace $workspace, string $role, array $permissions = []): User { $member = User::factory()->create(); $workspace->users()->attach($member->id, [ 'role' => $role, 'permissions' => $permissions, ]); return $member; } function getPermWorkspaceUserId(Workspace $workspace, User $user): int { return WorkspaceUser::where('workspace_id', $workspace->id) ->where('user_id', $user->id) ->firstOrFail() ->id; } // ── 4.1: Owner can update Manager permissions ── test('owner can update manager permissions', function () { [$owner, $workspace] = setupPermTestUser(WorkspaceUserRole::Owner); $manager = createPermWorkspaceMember($workspace, WorkspaceUserRole::Manager, [ Permission::CanManageTeam => false, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => false, ]); $pivotId = getPermWorkspaceUserId($workspace, $manager); $response = $this->actingAs($owner)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ Permission::CanManageTeam => true, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => true, ], ]); $response->assertRedirect(); $response->assertSessionHas('success', 'Permissions mises à jour'); $updatedPivot = WorkspaceUser::find($pivotId); expect($updatedPivot->permissions[Permission::CanManageTeam])->toBeTrue() ->and($updatedPivot->permissions[Permission::CanViewActivityLogs])->toBeTrue() ->and($updatedPivot->permissions[Permission::CanConfigurePortal])->toBeTrue(); }); // ── 4.2: Manager cannot update permissions (even with can_manage_team) ── test('manager with can_manage_team cannot update permissions', function () { [$manager, $workspace] = setupPermTestUser(WorkspaceUserRole::Manager, [ Permission::CanManageTeam => true, ]); $otherManager = createPermWorkspaceMember($workspace, WorkspaceUserRole::Manager, [ Permission::CanManageTeam => false, ]); $pivotId = getPermWorkspaceUserId($workspace, $otherManager); $response = $this->actingAs($manager)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ Permission::CanManageTeam => true, ], ]); $response->assertNotFound(); }); // ── 4.3: Worker cannot access permissions endpoint ── test('worker cannot access permissions endpoint', function () { [$worker, $workspace] = setupPermTestUser(WorkspaceUserRole::Worker); $manager = createPermWorkspaceMember($workspace, WorkspaceUserRole::Manager); $pivotId = getPermWorkspaceUserId($workspace, $manager); $response = $this->actingAs($worker)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ Permission::CanManageTeam => true, ], ]); $response->assertNotFound(); }); // ── 4.4: Cannot update Owner's permissions ── test('cannot update owner permissions', function () { [$owner, $workspace] = setupPermTestUser(WorkspaceUserRole::Owner); $otherOwner = createPermWorkspaceMember($workspace, WorkspaceUserRole::Owner); $pivotId = getPermWorkspaceUserId($workspace, $otherOwner); $response = $this->actingAs($owner)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ Permission::CanManageTeam => true, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => true, ], ]); $response->assertNotFound(); }); // ── 4.5: Cannot update Worker's permissions ── test('cannot update worker permissions', function () { [$owner, $workspace] = setupPermTestUser(WorkspaceUserRole::Owner); $worker = createPermWorkspaceMember($workspace, WorkspaceUserRole::Worker); $pivotId = getPermWorkspaceUserId($workspace, $worker); $response = $this->actingAs($owner)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ Permission::CanManageTeam => true, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => true, ], ]); $response->assertNotFound(); }); // ── 4.6: Invalid permission key is rejected ── test('invalid permission key is rejected', function () { [$owner, $workspace] = setupPermTestUser(WorkspaceUserRole::Owner); $manager = createPermWorkspaceMember($workspace, WorkspaceUserRole::Manager); $pivotId = getPermWorkspaceUserId($workspace, $manager); $response = $this->actingAs($owner)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ 'invalid_permission_key' => true, ], ]); $response->assertSessionHasErrors('permissions'); }); // ── 4.7: Activity log entry created on permission change ── test('activity log entry created on permission change', function () { [$owner, $workspace] = setupPermTestUser(WorkspaceUserRole::Owner); $manager = createPermWorkspaceMember($workspace, WorkspaceUserRole::Manager, [ Permission::CanManageTeam => false, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => false, ]); $pivotId = getPermWorkspaceUserId($workspace, $manager); $this->actingAs($owner)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ Permission::CanManageTeam => true, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => false, ], ]); $log = Activity::latest('id')->first(); expect($log->description)->toBe('permissions_updated') ->and($log->properties['target_user'])->toBe($manager->name) ->and($log->properties['old_permissions'][Permission::CanManageTeam])->toBeFalse() ->and($log->properties['new_permissions'][Permission::CanManageTeam])->toBeTrue(); }); // ── 4.8: Toggling can_manage_team off removes invite capability on next page load ── test('toggling can_manage_team off removes invite capability on next page load', function () { [$owner, $workspace] = setupPermTestUser(WorkspaceUserRole::Owner); $manager = createPermWorkspaceMember($workspace, WorkspaceUserRole::Manager, [ Permission::CanManageTeam => true, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => false, ]); $pivotId = getPermWorkspaceUserId($workspace, $manager); // Toggle can_manage_team OFF $this->actingAs($owner)->put(route('team.updatePermissions', $pivotId), [ 'permissions' => [ Permission::CanManageTeam => false, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => false, ], ]); // Now load team page as the manager — canManageTeam should be false session(['current_workspace_id' => $workspace->id]); $response = $this->actingAs($manager)->get(route('team.index')); $response->assertOk(); $response->assertInertia(fn ($page) => $page ->component('team/Index') ->where('canManageTeam', false) ); }); // ── Cross-workspace isolation: Owner cannot update permissions in another workspace ── test('owner cannot update manager permissions in another workspace', function () { [$owner, $workspaceA] = setupPermTestUser(WorkspaceUserRole::Owner); // Create a separate workspace B with its own manager $workspaceB = Workspace::factory()->create(); $managerB = User::factory()->create(); $workspaceB->users()->attach($managerB->id, [ 'role' => WorkspaceUserRole::Manager, 'permissions' => [ Permission::CanManageTeam => false, ], ]); $pivotIdB = WorkspaceUser::where('workspace_id', $workspaceB->id) ->where('user_id', $managerB->id) ->firstOrFail() ->id; // Session is set to workspace A — attempt to update manager in workspace B $response = $this->actingAs($owner)->put(route('team.updatePermissions', $pivotIdB), [ 'permissions' => [ Permission::CanManageTeam => true, Permission::CanViewActivityLogs => true, Permission::CanConfigurePortal => true, ], ]); $response->assertNotFound(); // Verify permissions were NOT changed $pivot = WorkspaceUser::find($pivotIdB); expect($pivot->permissions[Permission::CanManageTeam])->toBeFalse(); });