Admin User v1
This commit is contained in:
202
backend/src/features/admin/README.md
Normal file
202
backend/src/features/admin/README.md
Normal 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`
|
||||
Reference in New Issue
Block a user