Files
L-Ami-Fiduciaire/app/Http/Controllers/TeamController.php

262 lines
8.6 KiB
PHP
Raw Normal View History

<?php
namespace App\Http\Controllers;
use App\Concerns\AuthorizesPermissions;
use App\Concerns\HasWorkspaceScope;
use App\Enums\Permission;
use App\Enums\WorkspaceUserRole;
use App\Http\Requests\InviteTeamMemberRequest;
use App\Http\Requests\UpdatePermissionsRequest;
use App\Http\Requests\UpdateTeamMemberRoleRequest;
use App\Mail\TeamInvitationMail;
use App\Models\TeamInvitation;
use App\Models\User;
use App\Models\WorkspaceUser;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Inertia\Inertia;
use Inertia\Response;
class TeamController extends Controller
{
use AuthorizesPermissions;
use HasWorkspaceScope;
/**
* Display the team management page.
*/
public function index(): Response
{
$workspaceUser = auth()->user()->currentWorkspaceUser();
// Block Workers entirely — team page is Owner/Manager only
if ($workspaceUser->role->is(WorkspaceUserRole::Worker)) {
abort(404);
}
$workspace = $this->currentWorkspace();
$isOwner = $workspaceUser->role->is(WorkspaceUserRole::Owner);
// Load members with pivot data
$members = $workspace->users()
->withPivot('id', 'role', 'permissions', 'created_at')
->get()
->map(function ($user) use ($isOwner) {
$pivotRole = $user->pivot->role;
$role = $pivotRole?->value ?? $pivotRole;
$data = [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'role' => $role,
'joined_at' => $user->pivot->created_at,
'status' => 'active',
'workspace_user_id' => $user->pivot->id,
'updateRoleUrl' => route('team.updateRole', $user->pivot->id),
'removeUrl' => route('team.remove', $user->pivot->id),
];
// Add permissions data for Manager members (only visible to Owners)
if ($pivotRole instanceof WorkspaceUserRole && $pivotRole->is(WorkspaceUserRole::Manager) && $isOwner) {
$data['permissions'] = $user->pivot->permissions ?? [];
$data['permissionsUrl'] = route('team.updatePermissions', $user->pivot->id);
}
return $data;
});
// Load pending invitations
$pendingInvitations = TeamInvitation::where('workspace_id', $workspace->id)
->whereNull('accepted_at')
->where('expires_at', '>', now())
->get()
->map(fn ($inv) => [
'id' => $inv->id,
'email' => $inv->email,
'role' => $inv->role,
'invited_at' => $inv->created_at,
'status' => 'pending',
]);
// Can manage team: Owner always, Manager checks permission
$canManageTeam = $workspaceUser->role->is(WorkspaceUserRole::Owner)
|| ($workspaceUser->permissions[Permission::CanManageTeam] ?? false);
return Inertia::render('team/Index', [
'members' => $members,
'pendingInvitations' => $pendingInvitations,
'canManageTeam' => $canManageTeam,
'isOwner' => $isOwner,
'availablePermissions' => $isOwner ? $this->permissionLabels() : [],
'authUserId' => auth()->id(),
'inviteUrl' => route('team.invite'),
'roles' => $this->roleLabels(),
]);
}
/**
* Invite a new team member.
*/
public function invite(InviteTeamMemberRequest $request): RedirectResponse
{
$workspace = $this->currentWorkspace();
$invitation = TeamInvitation::create([
'workspace_id' => $workspace->id,
'email' => $request->validated('email'),
'role' => $request->validated('role'),
'invited_by' => auth()->id(),
'expires_at' => now()->addDays(7),
]);
Mail::to($invitation->email)->send(new TeamInvitationMail($workspace, $invitation));
return redirect()->back()->with('success', 'Invitation envoyée');
}
/**
* Update a team member's role.
*/
public function updateRole(UpdateTeamMemberRoleRequest $request, int $workspaceUserId): RedirectResponse
{
$this->authorizePermission(Permission::CanManageTeam);
$workspaceUser = WorkspaceUser::where('id', $workspaceUserId)
->where('workspace_id', session('current_workspace_id'))
->firstOrFail();
if ($workspaceUser->role->is(WorkspaceUserRole::Owner)) {
abort(404);
}
if ($workspaceUser->user_id === auth()->id()) {
abort(404);
}
$oldRole = $workspaceUser->role->value;
$newRole = $request->validated('role');
DB::transaction(function () use ($workspaceUser, $oldRole, $newRole) {
$workspaceUser->update([
'role' => $newRole,
'permissions' => config("permissions.defaults.{$newRole}", []),
]);
$targetUser = User::findOrFail($workspaceUser->user_id);
activity()
->performedOn($workspaceUser)
->withProperties([
'target_user' => $targetUser->name,
'old_role' => $oldRole,
'new_role' => $newRole,
])
->log('role_changed');
});
return redirect()->back()->with('success', 'Rôle mis à jour');
}
/**
* Update a Manager's individual permissions.
*/
public function updatePermissions(UpdatePermissionsRequest $request, int $workspaceUserId): RedirectResponse
{
$workspaceUser = WorkspaceUser::where('id', $workspaceUserId)
->where('workspace_id', session('current_workspace_id'))
->firstOrFail();
// Only Manager permissions can be toggled
if (! $workspaceUser->role->is(WorkspaceUserRole::Manager)) {
abort(404);
}
$newPermissions = $request->validated('permissions');
DB::transaction(function () use ($workspaceUser, $newPermissions) {
$oldPermissions = $workspaceUser->permissions ?? [];
$workspaceUser->update([
'permissions' => $newPermissions,
]);
$targetUser = User::findOrFail($workspaceUser->user_id);
activity()
->performedOn($workspaceUser)
->withProperties([
'target_user' => $targetUser->name,
'old_permissions' => $oldPermissions,
'new_permissions' => $newPermissions,
])
->log('permissions_updated');
});
return redirect()->back()->with('success', 'Permissions mises à jour');
}
/**
* Remove a team member from the workspace.
*/
public function remove(int $workspaceUserId): RedirectResponse
{
$this->authorizePermission(Permission::CanManageTeam);
$workspaceUser = WorkspaceUser::where('id', $workspaceUserId)
->where('workspace_id', session('current_workspace_id'))
->firstOrFail();
if ($workspaceUser->role->is(WorkspaceUserRole::Owner)) {
abort(404);
}
if ($workspaceUser->user_id === auth()->id()) {
abort(404);
}
$targetUser = User::findOrFail($workspaceUser->user_id);
DB::transaction(function () use ($workspaceUser, $targetUser) {
$workspaceUser->delete();
activity()
->withProperties([
'target_user' => $targetUser->name,
'target_email' => $targetUser->email,
'role' => $workspaceUser->role->value,
])
->log('member_removed');
});
return redirect()->back()->with('success', 'Membre retiré');
}
/**
* Get role labels for the frontend.
*
* @return array<string, string>
*/
protected function roleLabels(): array
{
return [
'manager' => 'Gestionnaire',
'worker' => 'Collaborateur',
];
}
/**
* Get permission labels (French) for the frontend.
*
* @return array<string, string>
*/
protected function permissionLabels(): array
{
return [
Permission::CanManageTeam => "Gérer l'équipe",
Permission::CanViewActivityLogs => "Voir les journaux d'activité",
Permission::CanConfigurePortal => 'Configurer le portail client',
];
}
}