where('organisation_id', $org->id) ->pending() ->where('expires_at', '>', now()) ->first(); if ($existingInvitation) { throw ValidationException::withMessages([ 'email' => ['Er is al een openstaande uitnodiging voor dit e-mailadres.'], ]); } $existingMember = $org->users()->where('email', $email)->first(); if ($existingMember) { throw ValidationException::withMessages([ 'email' => ['Gebruiker is al lid van deze organisatie.'], ]); } $invitation = UserInvitation::create([ 'email' => $email, 'invited_by_user_id' => $invitedBy->id, 'organisation_id' => $org->id, 'role' => $role, 'token' => strtolower((string) Str::ulid()), 'status' => 'pending', 'expires_at' => now()->addDays(7), ]); Mail::to($email)->queue(new InvitationMail($invitation)); activity('invitation') ->performedOn($invitation) ->causedBy($invitedBy) ->withProperties(['email' => $email, 'role' => $role]) ->log("Invited {$email} as {$role}"); return $invitation; } public function accept(UserInvitation $invitation, ?string $password = null): User { if (! $invitation->isPending() || $invitation->isExpired()) { throw ValidationException::withMessages([ 'token' => ['Deze uitnodiging is niet meer geldig.'], ]); } $user = User::where('email', $invitation->email)->first(); if (! $user) { if (! $password) { throw ValidationException::withMessages([ 'password' => ['Een wachtwoord is vereist om een nieuw account aan te maken.'], ]); } $user = User::create([ 'name' => Str::before($invitation->email, '@'), 'email' => $invitation->email, 'password' => $password, 'email_verified_at' => now(), ]); } $organisation = $invitation->organisation; if (! $organisation->users()->where('user_id', $user->id)->exists()) { $organisation->users()->attach($user, ['role' => $invitation->role]); } $invitation->markAsAccepted(); activity('invitation') ->performedOn($invitation) ->causedBy($user) ->withProperties(['email' => $invitation->email]) ->log("Accepted invitation for {$organisation->name}"); return $user; } public function expireOldInvitations(): int { return UserInvitation::where('status', 'pending') ->where('expires_at', '<', now()) ->update(['status' => 'expired']); } }