Files
trackbugs/app/Http/Controllers/ProjectMemberController.php

174 lines
5.5 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Mail\ProjectInvitationMail;
use App\Models\Project;
use App\Models\ProjectInvitation;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\View\View;
class ProjectMemberController extends Controller
{
/**
* Display team members for a project
*/
public function index(Project $project): View
{
$this->authorize('view', $project);
$members = $project->users()
->withPivot('role', 'created_at')
->orderBy('project_user.created_at', 'desc')
->get();
$pendingInvitations = $project->invitations()
->whereNull('accepted_at')
->where('expires_at', '>', now())
->with('inviter')
->orderBy('created_at', 'desc')
->get();
return view('projects.members.index', [
'project' => $project,
'members' => $members,
'pendingInvitations' => $pendingInvitations,
]);
}
/**
* Invite a new member to the project
*/
public function invite(Request $request, Project $project): RedirectResponse
{
$this->authorize('manageMembers', $project);
$validated = $request->validate([
'email' => 'required|email',
'role' => 'required|in:member,admin',
]);
// Check if user is already a member
$existingUser = User::where('email', $validated['email'])->first();
if ($existingUser && $project->users()->where('users.id', $existingUser->id)->exists()) {
return back()->withErrors(['email' => 'This user is already a member of the project.']);
}
// Check if there's already a pending invitation
$existingInvitation = $project->invitations()
->where('email', $validated['email'])
->whereNull('accepted_at')
->where('expires_at', '>', now())
->first();
if ($existingInvitation) {
return back()->withErrors(['email' => 'An invitation has already been sent to this email.']);
}
// Create invitation
$invitation = $project->invitations()->create([
'email' => $validated['email'],
'role' => $validated['role'],
'invited_by' => auth()->id(),
]);
// Send invitation email
Mail::to($invitation->email)->send(new ProjectInvitationMail($invitation));
return back()->with('success', 'Invitation sent successfully.');
}
/**
* Accept an invitation
*/
public function acceptInvitation(string $token): RedirectResponse
{
$invitation = ProjectInvitation::where('token', $token)->firstOrFail();
if ($invitation->isExpired()) {
return redirect()->route('dashboard')->withErrors(['error' => 'This invitation has expired.']);
}
if ($invitation->accepted_at) {
return redirect()->route('dashboard')->withErrors(['error' => 'This invitation has already been accepted.']);
}
// Check if the logged-in user's email matches
if (auth()->user()->email !== $invitation->email) {
return redirect()->route('dashboard')->withErrors(['error' => 'This invitation was sent to a different email address.']);
}
$invitation->accept(auth()->user());
return redirect()->route('projects.issues.index', $invitation->project)
->with('success', 'You have joined the project successfully.');
}
/**
* Update a member's role
*/
public function updateRole(Request $request, Project $project, User $user): RedirectResponse
{
$this->authorize('manageMembers', $project);
$validated = $request->validate([
'role' => 'required|in:member,admin,owner',
]);
// Don't allow changing your own role
if ($user->id === auth()->id()) {
return back()->withErrors(['error' => 'You cannot change your own role.']);
}
// Check if user is a member of the project
if (!$project->users()->where('users.id', $user->id)->exists()) {
return back()->withErrors(['error' => 'User is not a member of this project.']);
}
$project->users()->updateExistingPivot($user->id, ['role' => $validated['role']]);
return back()->with('success', 'Member role updated successfully.');
}
/**
* Remove a member from the project
*/
public function destroy(Project $project, User $user): RedirectResponse
{
$this->authorize('manageMembers', $project);
// Don't allow removing yourself
if ($user->id === auth()->id()) {
return back()->withErrors(['error' => 'You cannot remove yourself from the project.']);
}
// Check if user is a member
if (!$project->users()->where('users.id', $user->id)->exists()) {
return back()->withErrors(['error' => 'User is not a member of this project.']);
}
$project->users()->detach($user->id);
return back()->with('success', 'Member removed from project successfully.');
}
/**
* Cancel a pending invitation
*/
public function cancelInvitation(Project $project, ProjectInvitation $invitation): RedirectResponse
{
$this->authorize('manageMembers', $project);
if ($invitation->project_id !== $project->id) {
abort(404);
}
$invitation->delete();
return back()->with('success', 'Invitation cancelled successfully.');
}
}