Skip to content

๐Ÿ”’ Middleware โ€‹

The Express server uses several middleware layers for security, authentication, and request processing.

๐Ÿ“š Middleware Stack โ€‹

Applied in order in app.ts:

  1. ๐Ÿช– Helmet โ€” Security headers
  2. ๐ŸŒ CORS โ€” Cross-origin request handling
  3. ๐Ÿ“‹ Morgan โ€” HTTP request logging (disabled in test)
  4. ๐Ÿšฆ Rate Limiter โ€” Request throttling (disabled in test)
  5. ๐Ÿ“จ Raw Body โ€” For Stripe webhooks (/api/payments/webhook)
  6. ๐Ÿ“ JSON Parser โ€” express.json()
  7. ๐Ÿ”— URL-Encoded Parser โ€” express.urlencoded()
  8. ๐Ÿ”‘ Passport โ€” OAuth initialization
  9. ๐Ÿ“ 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.

typescript
// 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.

typescript
// Allows guest checkout
router.post('/orders', optionalAuth, createOrder);

requireStaff โ€‹

Checks that req.user.type === 'staff'. Rejects customers with 403.

typescript
router.get('/orders', authenticate, requireStaff, listOrders);

requireRole(...roles) โ€‹

Higher-order middleware that checks if the user's role is in the allowed list.

typescript
// Only SUPER_ADMIN and MANAGER can create menu items
router.post('/items', authenticate, requireStaff, requireRole('SUPER_ADMIN', 'MANAGER'), createMenuItem);

๐ŸŽซ Token Generation โ€‹

typescript
function generateToken(payload: JwtPayload): string

Creates a JWT with the configured JWT_SECRET and JWT_EXPIRES_IN.

The payload includes:

FieldTypeDescription
idstringUser or customer ID
emailstringEmail address
type"staff" or "customer"Account type
roleRole enumOnly 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
typescript
router.post('/items/:id/image', authenticate, requireStaff, upload.single('image'), uploadMenuItemImage);

๐Ÿšฆ Rate Limiting โ€‹

Uses express-rate-limit:

SettingValue
Window15 minutes
Max requests100 per IP
HeadersStandard RateLimit-*
SkipTest environment