๐ Middleware โ
The Express server uses several middleware layers for security, authentication, and request processing.
๐ Middleware Stack โ
Applied in order in app.ts:
- ๐ช Helmet โ Security headers
- ๐ CORS โ Cross-origin request handling
- ๐ Morgan โ HTTP request logging (disabled in test)
- ๐ฆ Rate Limiter โ Request throttling (disabled in test)
- ๐จ Raw Body โ For Stripe webhooks (
/api/payments/webhook) - ๐ JSON Parser โ
express.json() - ๐ URL-Encoded Parser โ
express.urlencoded() - ๐ Passport โ OAuth initialization
- ๐ Static Files โ Serve
/uploads/directory
๐ Authentication Middleware โ
Defined in packages/server/src/middleware/auth.ts:
authenticate โ
Requires a valid JWT Bearer token. Decodes the token and attaches the user to req.user.
// Rejects with 401 if token is missing or invalid
router.get('/me', authenticate, getMe);optionalAuth โ
Parses the JWT if present but does not reject unauthenticated requests. Used for endpoints that support both authenticated and guest users.
// Allows guest checkout
router.post('/orders', optionalAuth, createOrder);requireStaff โ
Checks that req.user.type === 'staff'. Rejects customers with 403.
router.get('/orders', authenticate, requireStaff, listOrders);requireRole(...roles) โ
Higher-order middleware that checks if the user's role is in the allowed list.
// Only SUPER_ADMIN and MANAGER can create menu items
router.post('/items', authenticate, requireStaff, requireRole('SUPER_ADMIN', 'MANAGER'), createMenuItem);๐ซ Token Generation โ
function generateToken(payload: JwtPayload): stringCreates a JWT with the configured JWT_SECRET and JWT_EXPIRES_IN.
The payload includes:
| Field | Type | Description |
|---|---|---|
id | string | User or customer ID |
email | string | Email address |
type | "staff" or "customer" | Account type |
role | Role enum | Only for staff |
๐ค Upload Middleware โ
Defined in packages/server/src/middleware/upload.ts:
Uses Multer for multipart file uploads:
- ๐พ Storage: Disk storage in
uploads/directory - ๐ท๏ธ Filenames: UUID-based to prevent collisions
- ๐ผ๏ธ File filter: JPEG, PNG, WebP, GIF only
- ๐ Size limit: 5 MB
router.post('/items/:id/image', authenticate, requireStaff, upload.single('image'), uploadMenuItemImage);๐ฆ Rate Limiting โ
Uses express-rate-limit:
| Setting | Value |
|---|---|
| Window | 15 minutes |
| Max requests | 100 per IP |
| Headers | Standard RateLimit-* |
| Skip | Test environment |