ledgerrz/app/Http/Controllers/DynamicInvitationController.php
Daan Meijer 06cd53fe91
Some checks failed
linter / quality (push) Failing after 1m8s
tests / ci (8.3) (push) Failing after 48s
tests / ci (8.4) (push) Failing after 1m6s
tests / ci (8.5) (push) Failing after 1m4s
added invitations
2026-06-16 16:29:17 +02:00

113 lines
3.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Mail\DynamicInvitationMail;
use App\Models\Dynamic;
use App\Models\DynamicInvitation;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class DynamicInvitationController extends Controller
{
/**
* Store a newly created invitation in storage.
*/
public function store(Request $request, Dynamic $dynamic)
{
// 1. Authorize - only owners can send invitations!
$isOwner = $dynamic->participants()
->where('user_id', $request->user()->id)
->where('role', 'owner')
->exists();
if (!$isOwner) {
abort(403, 'Only dynamic owners can invite other users.');
}
// 2. Validate
$request->validate([
'email' => ['required', 'email'],
'role' => ['required', 'string', 'in:owner,participant,editor,viewer'],
]);
$email = $request->input('email');
$role = $request->input('role');
// Check if user is already a participant of this dynamic
$isParticipant = $dynamic->participants()->where('email', $email)->exists();
if ($isParticipant) {
return redirect()->back()->withErrors([
'email' => 'This user is already a participant of this dynamic.',
]);
}
// Check if there is an active pending invitation for this user
$hasPendingInvite = $dynamic->invitations()
->where('email', $email)
->where('expires_at', '>', now())
->exists();
if ($hasPendingInvite) {
return redirect()->back()->withErrors([
'email' => 'An active invitation is already pending for this email address.',
]);
}
// 3. Create Invitation
$invitation = $dynamic->invitations()->create([
'email' => $email,
'role' => $role,
'token' => Str::random(40),
'expires_at' => now()->addDays(7),
]);
// 4. Send Email
Mail::to($email)->send(new DynamicInvitationMail($invitation, $request->user()->name));
return redirect()->back()->with('success', 'Invitation successfully sent!');
}
/**
* Accept the specified invitation.
*/
public function accept(Request $request, string $token)
{
// Must be signed!
if (!$request->hasValidSignature()) {
abort(401, 'Invalid or expired signature.');
}
$invitation = DynamicInvitation::where('token', $token)->firstOrFail();
if ($invitation->isExpired()) {
abort(403, 'This invitation has expired.');
}
// Ensure the logged in user's email matches the invitation's email!
// "Only the user with the specified email address should be able to access the link."
if ($request->user()->email !== $invitation->email) {
abort(403, 'This invitation was sent to a different email address.');
}
DB::transaction(function () use ($request, $invitation) {
// Attach user to dynamic as a participant with the specified role
$dynamic = $invitation->dynamic;
$dynamic->participants()->attach($request->user()->id, ['role' => $invitation->role]);
// Log to Dynamic chat activity log!
$dynamic->chat->messages()->create([
'user_id' => $request->user()->id,
'content' => "System: {$request->user()->name} joined the Dynamic as a " . strtoupper($invitation->role) . " after accepting an invitation.",
]);
// Delete the invitation record
$invitation->delete();
});
return redirect()->route('dynamics.show', $invitation->dynamic_id)->with('success', 'Successfully joined the dynamic!');
}
}