Commit Graph

2 Commits

Author SHA1 Message Date
Darko Gjorgjijoski
c1994887ef Support invitations for unregistered users
When inviting an email without an InvoiceShelf account, the email now
links to a registration page (/register?invitation={token}) instead of
login. After registering, the invitation is auto-accepted.

Backend:
- InvitationRegistrationController: public details() and register()
  endpoints. Registration validates token + email match, creates account,
  auto-accepts invitation, returns Sanctum token.
- AuthController: login now accepts optional invitation_token param to
  auto-accept invitation for existing users clicking the email link.
- CompanyInvitationMail: conditional URL based on user existence.
- Web route for /invitations/{token}/decline (email decline link).

Frontend:
- RegisterWithInvitation.vue: fetches invitation details, shows company
  name + role, registration form with pre-filled email.
- Router: /register route added.

Tests: 3 new tests (invitation details, register + accept, email mismatch).
2026-04-03 23:26:58 +02:00
Darko Gjorgjijoski
92a1baced4 Add company invitation system (backend)
New feature allowing company owners/admins to invite users by email with
a specific company-scoped role.

Database:
- New company_invitations table (company_id, email, role_id, token,
  status, invited_by, expires_at)

Backend:
- CompanyInvitation model with pending/forUser scopes
- InvitationService: invite, accept, decline, getPendingForUser
- CompanyInvitationMail with markdown email template
- InvitationController (company-scoped): list, send, cancel invitations
- InvitationResponseController (user-scoped): pending, accept, decline
- BootstrapController returns pending_invitations in response
- CompanyMiddleware handles zero-company users gracefully

Tests: 9 feature tests covering invite, accept, decline, cancel, expire,
duplicate prevention, and bootstrap integration.
2026-04-03 22:58:55 +02:00