Administration
Admin dashboard with user and organization management.
Overview
The admin area is available at /admin and restricted to users with ROLE_SUPER_ADMIN. It has a dedicated layout, independent of the public layout.
| Feature | Detail |
|---|---|
| Dashboard | src/Controller/Admin/DashboardController.php |
| User management | src/Controller/Admin/UsersController.php |
| Organization management | src/Controller/Admin/OrganizationsController.php |
| Account deletion | src/Service/Auth/AccountDeletionService.php |
| Organization deletion | src/Service/Organization/OrganizationDeletionService.php |
| Admin layout | templates/admin/base.html.twig |
| Sidebar Stimulus | assets/controllers/sidebar_controller.js |
Access & security
Access to the admin area is protected by a dedicated Symfony firewall (pattern ^/admin, before the main firewall). Only ROLE_SUPER_ADMIN can access it.
| Feature | Detail |
|---|---|
| Required role | ROLE_SUPER_ADMIN |
| Dedicated login page | GET /admin/login |
| Promote a super admin | php bin/console app:admin:promote <email> |
| Admin access log | src/EventSubscriber/AdminAccessSubscriber.php |
The TenantSubscriber skips all /admin routes — the tenant context is not resolved in the admin area.
Layout & responsive sidebar
The admin layout uses a fixed sidebar on desktop (≥ 1024px) and an off-canvas drawer on mobile, driven by the Stimulus sidebar controller.
assets/styles/components/_admin.scss
Stimulus sidebar (drawer)
The sidebar is driven by sidebar_controller.js. It handles open/close, scroll locking, and closing on Escape key.
data-controller="sidebar"
data-sidebar-target="panel" data-sidebar-target="overlay" data-action="sidebar#toggle"
assets/controllers/sidebar_controller.js
User management
UsersController exposes 4 routes protected by ROLE_SUPER_ADMIN. All POST actions are CSRF-protected.
| Route | Action |
|---|---|
GET /admin/users | List all users |
GET /admin/users/{id} | Detail: identity, security, organizations |
POST /admin/users/{id}/toggle-admin | Grant or revoke ROLE_SUPER_ADMIN |
POST /admin/users/{id}/delete | Force-delete account |
Self-protection: a super admin cannot delete themselves or remove their own rights from the UI.
Admin deletion calls AccountDeletionService::forceDelete() which bypasses the sole-owner organization check.
src/Service/Auth/AccountDeletionService.php
Organization management
OrganizationsController exposes 3 routes protected by ROLE_SUPER_ADMIN. All POST actions are CSRF-protected.
| Route | Action |
|---|---|
GET /admin/organizations | List all organizations |
GET /admin/organizations/{id} | Detail: info, subscription, members |
POST /admin/organizations/{id}/delete | Fully delete the organization |
OrganizationDeletionService explicitly deletes subscriptions (no cascade remove on that relation) then removes the organization (cascade on members and invitations).
src/Service/Organization/OrganizationDeletionService.php