Backend
Middleware
Backend middleware — tenant resolution, auth, and role guards.
Tenant Middleware
Resolves organizationId from the request context and attaches it to req.organizationId. It looks in three places in order:
req.user.organizationId(authenticated user)req.query.organizationIdx-tenant-slugheader → DB lookup
// src/middleware/tenant.middleware.ts
import { resolveOptionalTenant, resolveRequiredTenant } from '../middleware/tenant.middleware'
// Use on routes where org context is optional
router.post('/login', resolveOptionalTenant, login)
// Use on routes where org context is required
router.get('/', resolveRequiredTenant, getItems)
The resolveTenant(required: boolean) factory:
- If
required = false: continues silently if org cannot be determined. - If
required = true: throwsUnprocessableEntityErrorif org cannot be determined.
Auth Middleware
Comes from codi-node-utils. Validates the Authorization: Bearer <token> header and checks the JWT is not revoked:
import { authenticate } from '@codisolutions23/node-utils'
import { useRevokedTokenRepo } from '../repositories/revoked-token.repo'
import { accessTokenSecret } from '../config'
const { existsByJti } = useRevokedTokenRepo()
const authMiddleware = authenticate(accessTokenSecret, existsByJti)
// Use per-route:
router.get('/profile', authMiddleware, getProfile)
On success, attaches req.user (decoded JWT payload) and req.token (raw token) to the request.
Role Guard Middleware
Role guards are built on requireRoles(roles[], ...) from src/middleware/role-guard.middleware.ts. Pre-composed exports:
export const requireAdmin = requireRoles([UserType.ADMIN], ...)
export const requireOwner = requireRoles([UserType.OWNER, UserType.ADMIN], ...)
export const requireBranchManagerOrAbove = requireRoles(
[UserType.ADMIN, UserType.OWNER, UserType.BRANCH_MANAGER], ...
)
Usage:
// Route file — build middleware instances once and reuse
const authMiddleware = authenticate(accessTokenSecret, existsByJti)
const adminMiddleware = requireAdmin(accessTokenSecret, existsByJti)
const branchManagerMiddleware = requireBranchManagerOrAbove(accessTokenSecret, existsByJti)
router.get('/', authMiddleware, getAll)
router.post('/', branchManagerMiddleware, create)
router.delete('/:id', adminMiddleware, remove)
Middleware Order in app.ts
// src/app.ts
app.use(helmet())
app.use(cors(corsOptions))
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 200 }))
// Routes
app.use('/api', routes)
// Error handler — must be last
app.use(errorHandler)
errorHandler is imported from codi-node-utils and must be registered after all routes.