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.dartThe 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() - Adds application/json content-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 status
- user_information — Extended user profile data
- early_access_requests — Early access registration requests
- early_access_features — Feature flag configuration
- early_access_audit_logs — Admin action audit trail
- early_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() sets status = 'blocked', deleteUser() sets status = '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