Admin Backend Overview#
The admin_backend_api is a Shelf-based HTTP server that provides administrative management capabilities for the ContainerPub platform. It handles user management, Keycloak-based authentication, feature role assignment, early access administration, and platform observability.
Architecture#
Server Entry Point#
bin/server.dart
The server initializes logging, loads configuration from environment variables, sets up the Keycloak client, initializes the database, and starts the HTTP server on the configured port (default: 8081).
Middleware Pipeline#
The request pipeline applies middleware in this order:
logRequests()- Built-in Shelf request logging-
corsMiddleware()- Allows all origins, methods, and custom headers (including dev-auth bypass headers) -
errorHandlingMiddleware()- Catches unhandled exceptions, returns 500 with Sentry reporting -
jsonContentTypeMiddleware()- Addsapplication/jsoncontent-type if missing - Router - The mounted admin router handles all route matching
Project Structure#
admin_backend_api/
├── bin/
│ └── server.dart # Entry point
├── lib/
│ ├── app.dart # App factory (creates the Handler pipeline)
│ ├── app_context.dart # AppContext: config + keycloak + DB init
│ ├── auth/
│ │ ├── admin_auth_middleware.dart # Bearer token validation
│ │ ├── admin_principal.dart # AdminPrincipal data class
│ │ ├── admin_role.dart # AdminRole enum (viewer / full_admin)
│ │ ├── authorization.dart # Write-access guard middleware
│ │ └── request_context.dart # Request extension for adminPrincipal
│ ├── common/
│ │ ├── common.dart # Shared Logger
│ │ ├── error_reporting.dart # Sentry + logging error capture
│ │ ├── json_middleware.dart # CORS, JSON content-type, error handling
│ │ ├── json_response.dart # Convenience JSON response helpers
│ │ ├── masking.dart # Email masking utility
│ │ └── request_parsing.dart # JSON body reader + int parser
│ ├── config/
│ │ └── app_config.dart # Env-based configuration
│ ├── handlers/
│ │ ├── auth_handler.dart # Login/refresh/logout/verify/me
│ │ ├── users_handler.dart # User CRUD + status management
│ │ ├── tiers_handler.dart # Tier CRUD + assignment
│ │ ├── organizations_handler.dart # Org CRUD + membership
│ │ ├── user_feature_roles_handler.dart # Feature role grant/remove/stats
│ │ ├── early_access_features_handler.dart # Feature flag CRUD
│ │ ├── early_access_request_handler.dart # EA request management
│ │ ├── early_access_form_schema_handler.dart # Form schema management
│ │ └── observability_handler.dart # System metrics + logs
│ ├── routes/
│ │ └── admin_router.dart # All route registrations
│ └── services/
│ ├── users_service.dart # User CRUD, status, temp passwords
│ ├── tiers_service.dart # Tier CRUD + assignment logic
│ ├── organizations_service.dart # Org CRUD + membership logic
│ ├── user_feature_roles_service.dart # Keycloak role grant/remove/stats
│ ├── feature_flags_service.dart # Feature flag CRUD
│ ├── early_access_admin_service.dart # EA request logic
│ ├── early_access_form_schema_admin_service.dart # Form schema logic
│ ├── observability_service.dart # InfluxDB queries + PII sanitization
│ └── token_claims_parser.dart # JWT role extraction
└── test/
└── server_test.dart # Auth middleware + masking tests
Authentication & Authorization#
The admin backend uses Keycloak OIDC for authentication and role-based access control (RBAC) for authorization.
Admin Roles#
| Role | Permission | Description |
|---|---|---|
full_admin | Read + Write | Full administrative access |
viewer | Read only | Can view data but not modify |
Two-Layer Middleware#
Layer 1: adminAuthMiddleware — Validates the Bearer token via Keycloak introspection, extracts roles from the JWT, and constructs an
AdminPrincipal. Returns 401 if token is missing or invalid, 403 if the user lacks any admin role.
Layer 2: requireWriteAccess() — Checks the AdminPrincipal role. If
viewer (no canWrite), returns 403. Applied only to write operations (POST, PUT, PATCH, DELETE).
Route-Level Auth#
Routes use two helper functions:
_withAuth()— Read access (adminAuthMiddleware only)-
_withWriteAuth()— Write access (adminAuthMiddleware + requireWriteAccess)
Handlers & Services#
Auth Handler#
Manages admin session lifecycle: login, token refresh, logout, session verification, and current user info.
Users Handler#
Full user management: list, get, update, disable (block), enable, delete (soft-delete), and temporary password generation.
Organizations Handler#
Create, read, update organizations. Add and remove members.
Tiers Handler#
Define service tiers and assign/unassign users to them.
User Feature Roles Handler#
Manage Keycloak client-level feature roles: view assigned roles, grant new roles, remove roles, and get aggregate role statistics.
Early Access Handlers#
Three handlers manage the early access system:
- Request Handler — Review, approve, reject early access requests with capacity enforcement
- Features Handler — Manage feature flags for early access
- Form Schema Handler — Define and manage registration form schemas
Observability Handler#
System-wide monitoring: error rate overview, log retrieval, error log filtering, and load metrics from InfluxDB.
Database Tables#
The admin backend initializes these PostgreSQL tables on startup:
| Table | Purpose |
|---|---|
tiers | Service tier definitions (name, description, metadata) |
user_tiers | Junction: user_uuid → tier_id assignments |
organizations | Organization definitions (name, owner) |
organization_members | Junction: user_uuid → org_uuid with role |
It also uses shared tables from the database package:
users— User accounts and statususer_information— Extended user profile dataearly_access_requests— Early access registration requestsearly_access_features— Feature flag configurationearly_access_audit_logs— Admin action audit trailearly_access_form_schemas— Registration form definitions
Key Design Patterns#
- Handler-Service Separation — Handlers parse requests and format responses. Business logic lives in services.
-
Soft-Delete — Users are never physically removed.
disableUser()setsstatus = 'blocked',deleteUser()setsstatus = 'deleted'. -
Email Masking — Emails in list responses are masked (e.g.,
jo***@example.com). Names show only initials (JD***). -
Temporary Passwords — Generated with
Random.secure(), hashed via BCrypt, and emailed to users. - Audit Logging — The early access system records all admin actions with actor, action, and metadata.
-
Error Reporting — All unhandled errors are captured by
ErrorReporting.captureException()and sent to both console and Sentry.
Configuration#
Environment variables (via .env file):
| Variable | Description |
|---|---|
KEYCLOAK_URL | Keycloak server URL |
KEYCLOAK_REALM | Keycloak realm name |
KEYCLOAK_CLIENT_ID | Admin client ID |
KEYCLOAK_CLIENT_SECRET | Admin client secret |
DATABASE_URL | PostgreSQL connection string |
FULL_ADMIN_ROLE |
Role name for write access (default: full_admin) |
VIEWER_ROLE | Role name for read-only (default: viewer) |
FEATURE_ROLES_CLIENT_ID | Keycloak client ID for feature roles |
ADMIN_CLIENT_ID | Keycloak client ID for admin app |
DEFAULT_USER_FEATURE_ROLES | CSV list of default roles for new users |
BACKEND_GRANTABLE_FEATURE_ROLES | CSV list of roles admins can grant |
EMAIL_API_KEY | ForwardEmail API key |
ALLOW_DEV_AUTH_BYPASS | Enable dev auth bypass (dev only) |
DSN_SENTRY | Sentry DSN for error tracking |
Running#
cd admin_backend_api
dart pub get
dart run bin/server.dart
Next Steps#
- Read Admin API Reference for complete endpoint documentation
- Read Keycloak Authentication for auth system details
- Read User Management for users, orgs, tiers, and roles
- Read Early Access Admin for early access administration