Skip to content

Admin Account Management & Domain-Restricted Registration

Problem

  1. Admin account management: When logged into the admin backend (/admin), there's no way to manage your own account (change email, password). The account management pages at /account use a completely different layout, breaking the admin experience.

  2. Open registration: Anyone with any email can register. We need to restrict registration to pre-approved email domains, managed via the admin UI.

Design

Feature 1: Admin Account Management

New controller: AdminAccountController at /admin/account

Routes: - GET /admin/account — Show account settings (change email, change password forms) - POST /admin/account/change-email — Process email change - GET /admin/account/verify-email/{token} — Verify new email - POST /admin/account/cancel-email-change — Cancel pending email change - POST /admin/account/change-password — Process password change

Reuses existing forms (ChangeEmailFormType, AccountChangePasswordFormType) and services (EmailVerificationService, UserPasswordHasherInterface). No account deletion from admin panel.

Admin layout additions: - User dropdown in admin header (top-right): shows logged-in email, links to "My Account" and "Log out" - Sidebar link under "Main" section - Template: templates/admin/account/index.html.twig using admin card/form styles

Feature 2: Domain-Restricted Registration

New entity: AllowedDomain - id (int, auto-increment) - domain (string, unique) — e.g. "atraxion.com" - createdAt (datetime_immutable)

Admin CRUD: AdminAllowedDomainController at /admin/allowed-domains - List, create, delete (no edit — domains are simple strings) - Follows existing AbstractAdminController pattern - Sidebar link under "Main" section

Registration validation: - Custom Symfony validator constraint AllowedEmailDomain - Applied to the email field in RegistrationFormType - Logic: if AllowedDomain table has entries, email domain must match one. If table is empty, all domains allowed - Error message: "Registration is restricted to approved email domains."

Decisions

  • Admin account pages are a separate controller (not a layout-switching refactor of AccountController) to keep things clean and follow the existing admin pattern
  • Domain list stored in database with admin CRUD (not env vars or config files) for runtime flexibility
  • Hard block on unapproved domains (no approval queue)
  • Empty domain table = open registration (prevents lockout during setup)
  • No edit for allowed domains — delete and re-add is simpler for a single-field entity