Admin User v1

This commit is contained in:
Eric Gullickson
2025-11-05 19:04:06 -06:00
parent e4e7e32a4f
commit 8174e0d5f9
48 changed files with 11289 additions and 1112 deletions

View File

@@ -0,0 +1,202 @@
# Admin Feature
Self-contained feature capsule for MotoVaultPro admin role and access control management.
## Architecture
```
admin/
├── api/
│ ├── admin.controller.ts # HTTP request handlers
│ └── admin.routes.ts # Route registration
├── domain/
│ ├── admin.types.ts # TypeScript interfaces
│ └── admin.service.ts # Business logic
├── data/
│ └── admin.repository.ts # Database access (parameterized queries)
├── migrations/
│ └── 001_create_admin_users.sql # Database schema
└── tests/
├── unit/ # Service/guard tests
└── integration/ # API endpoint tests
```
## Database Schema
### admin_users table
```sql
CREATE TABLE admin_users (
auth0_sub VARCHAR(255) PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
role VARCHAR(50) NOT NULL DEFAULT 'admin',
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(255) NOT NULL,
revoked_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
### admin_audit_logs table
```sql
CREATE TABLE admin_audit_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
actor_admin_id VARCHAR(255) NOT NULL,
target_admin_id VARCHAR(255),
action VARCHAR(100) NOT NULL,
resource_type VARCHAR(100),
resource_id VARCHAR(255),
context JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```
## Usage
### Phase 1: Access Control Foundations
Provides:
- `AdminRepository` - Database access with parameterized queries
- `AdminService` - Business logic for admin operations
- `admin-guard` plugin - Authorization enforcement (decorator on Fastify)
- `request.userContext` - Enhanced with `isAdmin`, `adminRecord`
### Phase 2: Admin Management APIs
Will provide:
- `/api/admin/admins` - List all admins (GET)
- `/api/admin/admins` - Add admin (POST)
- `/api/admin/admins/:auth0Sub/revoke` - Revoke admin (PATCH)
- `/api/admin/admins/:auth0Sub/reinstate` - Reinstate admin (PATCH)
- `/api/admin/audit-logs` - View audit trail (GET)
### Phase 3: Platform Catalog CRUD (COMPLETED)
Provides complete CRUD operations for platform vehicle catalog data:
**Makes:**
- `GET /api/admin/catalog/makes` - List all makes
- `POST /api/admin/catalog/makes` - Create new make
- `PUT /api/admin/catalog/makes/:makeId` - Update make
- `DELETE /api/admin/catalog/makes/:makeId` - Delete make
**Models:**
- `GET /api/admin/catalog/makes/:makeId/models` - List models for a make
- `POST /api/admin/catalog/models` - Create new model
- `PUT /api/admin/catalog/models/:modelId` - Update model
- `DELETE /api/admin/catalog/models/:modelId` - Delete model
**Years:**
- `GET /api/admin/catalog/models/:modelId/years` - List years for a model
- `POST /api/admin/catalog/years` - Create new year
- `PUT /api/admin/catalog/years/:yearId` - Update year
- `DELETE /api/admin/catalog/years/:yearId` - Delete year
**Trims:**
- `GET /api/admin/catalog/years/:yearId/trims` - List trims for a year
- `POST /api/admin/catalog/trims` - Create new trim
- `PUT /api/admin/catalog/trims/:trimId` - Update trim
- `DELETE /api/admin/catalog/trims/:trimId` - Delete trim
**Engines:**
- `GET /api/admin/catalog/trims/:trimId/engines` - List engines for a trim
- `POST /api/admin/catalog/engines` - Create new engine
- `PUT /api/admin/catalog/engines/:engineId` - Update engine
- `DELETE /api/admin/catalog/engines/:engineId` - Delete engine
**Change Logs:**
- `GET /api/admin/catalog/change-logs?limit=100&offset=0` - Retrieve platform catalog change history
**Features:**
- All mutations wrapped in database transactions
- Automatic cache invalidation (platform:* keys)
- Complete audit trail in platform_change_log table
- Referential integrity validation (prevents orphan deletions)
- requireAdmin guard on all endpoints
### Phase 4: Station Oversight
Provides:
- `GET /api/admin/stations` - List all stations globally with pagination and search
- `POST /api/admin/stations` - Create new station
- `PUT /api/admin/stations/:stationId` - Update station details
- `DELETE /api/admin/stations/:stationId` - Delete station (soft delete by default, ?force=true for hard delete)
- `GET /api/admin/users/:userId/stations` - List user's saved stations
- `DELETE /api/admin/users/:userId/stations/:stationId` - Remove user's saved station (soft delete by default, ?force=true for hard delete)
All station mutations invalidate related Redis caches and log audit trails.
## Extending the Feature
### Adding a new admin endpoint
1. Add handler method to `AdminController`
2. Register route in `admin.routes.ts` with `app.requireAdmin` guard
3. Add service method if business logic needed
4. Add repository method for database operations
Example:
```typescript
// In admin.routes.ts
fastify.get('/admin/users', {
preHandler: [fastify.requireAdmin]
}, adminController.getUsers.bind(adminController));
// In AdminController
async getUsers(request: FastifyRequest, reply: FastifyReply) {
const actorId = request.userContext?.userId;
const users = await this.adminService.getAllUsers();
return reply.code(200).send(users);
}
// Audit logging
await this.adminService.logAuditAction(actorId, 'VIEW', null, 'users');
```
## Security Considerations
1. **Admin Guard**: All admin endpoints require `preHandler: [fastify.requireAdmin]`
2. **Parameterized Queries**: All database operations use parameterized queries (no SQL concatenation)
3. **Audit Logging**: All sensitive actions logged with actor, target, action, and context
4. **Last Admin Protection**: Cannot revoke the last active admin
5. **Soft Deletes**: Admins are soft-deleted (revoked_at), never hard-deleted
## Testing
### Unit tests (no database)
```bash
npm test -- features/admin/tests/unit
```
Tests:
- Admin guard authorization logic
- Admin service business rules
- Repository error handling
### Integration tests (with database)
```bash
npm test -- features/admin/tests/integration
```
Tests:
- Full API endpoints
- Database persistence
- Audit logging
- Admin guard in request context
## Migrations
Run migrations during container startup:
```bash
docker compose exec mvp-backend npm run migrate
```
Initial seed: First admin user is seeded in migration with:
- `auth0_sub`: `system|bootstrap`
- `email`: `admin@motovaultpro.com`
- `role`: `admin`