Who can sign in, what they may do, how visitors register, and how the helpdesk works.
In the user guide: the Users & Access chapter and Support Tickets.
App\Models\User is an Authenticatable that implements MustVerifyEmail, HasMedia (avatar), uses Sanctum tokens (HasApiTokens), Spatie roles (HasRoles), the hand-rolled teams trait (HasTeams), notifications, soft deletes, the searchable trait and page-visit tracking. Relations: social() (OAuth links), pages(), posts() (via author_id), tickets(), profile(). activate() and inactivate() dispatch UserWasActivated / UserWasInactivated. Email verification is required only when setting('activation_required') is on.
Booking and TruCommerce keep their own Customer entities that are separate from User; staff and providers in Booking are users with extra roles.
App\Models\Role and Permission extend Spatie's models (extra columns: role description and a default-guest flag; permission group, title, description).RolePermissionsSeeder: Super Admin (id 1) and User. The id is read from dotartisan.super_admin_role and grants every ability through Gate::before.->can('manage page'). Admin UI: Users → Roles and Permissions (per-role matrix grouped by group).public_user_role setting (assigned by the UserRegistered listener).booking-admin, booking-manager, booking-provider, booking-customer) and permissions. TruCommerce and TruPayments seed permissions only and give them to Super Admin. Full list: Permissions catalogue.Create permissions for your plugin as shown in Permissions and roles.
Auth\RegisteredUserController creates the user and fires Laravel's Registered event. UserRegistered creates a default team for the user (role admin in that team) and assigns public_user_role.verification.notice, verification.verify, throttled). Admin and front each have their own copies in routes/admin_auth.php and routes/auth.php.Auth\SocialAuthController (Google and Facebook through Socialite) auto-provisions a user and stores a Social row (provider + social_id) on first sign-in. Credentials are configured in Settings → General (FACEBOOK_* / GOOGLE_*).2fa alias protects admin routes; TwoFactorMiddleware protects front/user routes. Both delegate to App\Services\Authenticator, so treat both as active.reCAPTCHA protects forms when configured (CaptchaTrait), and login is rate limited by the standard Laravel limiter.
Registered visitors get a self-service area at /user/* (routes/app.php, UserController): dashboard (the user.dashboard dashboard, fed by modules), profile, password change, two-factor, Sanctum API tokens, notifications, browser sessions, account deletion (soft delete + goodbye email, re-activation link), teams and support tickets. These routes sit behind TwoFactorMiddleware, auth and verified.
A hand-rolled Jetstream-style collaboration workspace, not content tenancy: Team, TeamRole, TeamInvitation, the HasTeams trait, TeamController and TeamInvitationController. Invitations use signed URLs and a TeamInvitation Mailable. Team roles (admin, user) and API-token abilities are declared through the Roles facade in DotartisanServiceProvider::registerWorkspaceRoles(). Keep "team role" and "CMS role" separate in your head: they are unrelated systems.
| Aspect | Detail |
|---|---|
| Models | Ticket, TicketMessage, TicketCategory, TicketActivity, TicketReference; they use the legacy HasConfigModel trait (string primary-key toggle) |
| States | OPEN → ANSWERED → CLOSED (plain strings) |
| Two UIs, one policy | Admin helpdesk (Admin\TicketController, gated by view all tickets) and visitor UI (TicketController); both authorise through TicketPolicy |
| Flow | TicketObserver writes a TicketActivity row and fires TicketOpenEvent → TicketCreatedNotification (mail + database). A reply fires TicketMessageEvent and flips the state to ANSWERED. Closing fires TicketCloseEvent, which currently has no listener |
| Config | config/tickets.php: attachments (5 files, 5 MB, pdf,png,jpg,txt), at most 3 open tickets per user, categories on, priorities low/medium/high, autoclose-days = 7 |
| Auto-close | Command dotartisan:tickets:autoclose exists but is not scheduled by default; add it to a scheduler if you want it |
routes/api.php exposes one Sanctum-protected endpoint, GET /api/v1/whoami (api.whoami). Users create personal access tokens in their account area (user.token). The API middleware group applies EnsureFrontendRequestsAreStateful, throttling and the demo guard. For a plugin API follow the existing convention: prefix v1, auth:sanctum middleware, Eloquent API resources.
Notifications use the mail and database channels only: TicketCreatedNotification, TicketUpdatedNotification, SendGoodbyeEmail, TruCommerce's ProductLowStockNotification. The only Mailable class is TeamInvitation; Booking sends transactional mail through its own notification templates. Do not assume a Mailable exists for a given email — check first.