Admin Panel
EasyAdmin backoffice for managing users and subscriptions
Admin Panel
The admin panel is built with EasyAdmin and provides a backoffice for managing users and subscriptions.
What's Included
- User management with search, filter, and role editing
- Subscription management with status tracking
- Secure form-based login with rate limiting
Access
The admin panel is available at /admin. You must have the ROLE_ADMIN role to access it.
Creating an Admin User
- Register a user through the API
- Promote them to admin:
docker compose exec php bin/console app:user:promote-admin user@example.com
Login
The admin panel uses form-based login at /admin/login (separate from the API's JWT auth). Login is protected by rate limiting: 5 attempts per 15 minutes.
Dashboard
- Title: Backoffice
- Default view: Redirects to the Users list
- Menu sections: User Management (Users) and Subscriptions (Subscriptions)
Users
Fields
| Field | Type | Editable | Notes |
|---|---|---|---|
| id | ID | No | Hidden on forms |
| name | Text | No | Displayed but disabled |
| No | Always disabled | ||
| emailValidated | Boolean | No | Rendered as icon, not switch |
| provider | Text | No | email, google, apple, etc. |
| roles | Choice | Yes | ROLE_USER, ROLE_ADMIN — editable on edit page |
| createdAt | DateTime | No | Hidden on forms |
| updatedAt | DateTime | No | Visible on detail page only |
Search
Search by name or email.
Filters
| Filter | Type | Options |
|---|---|---|
| Text | Free text | |
| Name | Text | Free text |
| Email Validated | Boolean | Yes / No |
| Provider | Text | Free text |
| Roles | Choice | ROLE_USER, ROLE_ADMIN |
Disabled Actions
- Delete — users cannot be deleted from the admin panel
- Create — users must register through the API
Subscriptions
Fields
| Field | Type | Editable | Notes |
|---|---|---|---|
| id | ID | No | Hidden on forms |
| userId | Text | No | Always disabled |
| planType | Text | No | Free Plan, Starter, Pro |
| paymentType | Text | No | Recurring or One-Time |
| status | Choice | Yes | Active, Past Due, Canceled, Expired |
| billingInterval | Text | No | Monthly or Yearly |
| stripeCustomerId | Text | No | Visible on detail/edit pages |
| stripeSubscriptionId | Text | No | Visible on detail/edit pages |
| stripePaymentIntentId | Text | No | Visible on detail/edit pages only |
| currentPeriodEnd | DateTime | No | Always disabled |
| createdAt | DateTime | No | Hidden on forms |
| updatedAt | DateTime | No | Visible on detail page only |
Search
Search by userId, stripeCustomerId, or stripeSubscriptionId.
Filters
| Filter | Type | Options |
|---|---|---|
| Status | Choice | Active, Past Due, Canceled, Expired |
| Plan Type | Choice | Free Plan, Starter Plan, Pro Plan |
| Billing Interval | Choice | Monthly, Yearly |
| Payment Type | Choice | Recurring, One-Time |
Disabled Actions
- Delete — subscriptions cannot be deleted from the admin panel
- Create — subscriptions are created through Stripe checkout
Security
- Access control — requires
ROLE_ADMINrole - Authentication — form-based login (separate from API JWT auth)
- Login throttling — 5 attempts per 15 minutes per IP
- CSRF protection — enabled on login form
- Password hashing — bcrypt with cost factor 12 (same as API)