Autorização e Controle de Acesso (RBAC)
Autenticação verifica quem você é. Autorização verifica o que você pode fazer.
RBAC - Role-Based Access Control
typescript
// Roles do sistemaenum Role { USER = 'USER', ADMIN = 'ADMIN',} // Permissões por roleconst permissions = { USER: ['read:products', 'create:orders', 'read:own-orders'], ADMIN: ['read:products', 'create:products', 'update:products', 'delete:products', 'read:orders', 'update:orders', 'read:users', 'update:users'],};Middleware de Autorização
typescript
// src/middlewares/authorize.middleware.tsimport { Request, Response, NextFunction } from 'express';import { ForbiddenError, UnauthorizedError } from '../errors'; type Role = 'USER' | 'ADMIN'; export function authorize(...allowedRoles: Role[]) { return (req: Request, res: Response, next: NextFunction) => { if (!req.user) { throw new UnauthorizedError('Autenticação necessária'); } const userRole = req.user.role as Role; if (!allowedRoles.includes(userRole)) { throw new ForbiddenError('Você não tem permissão para esta ação'); } next(); };} // Verificar se é o próprio usuário ou adminexport function authorizeOwnerOrAdmin(userIdParam: string = 'id') { return (req: Request, res: Response, next: NextFunction) => { if (!req.user) { throw new UnauthorizedError('Autenticação necessária'); } const resourceUserId = req.params[userIdParam]; const isOwner = req.user.userId === resourceUserId; const isAdmin = req.user.role === 'ADMIN'; if (!isOwner && !isAdmin) { throw new ForbiddenError('Acesso negado'); } next(); };}Usando nas Rotas
typescript
// src/routes/user.routes.tsimport { Router } from 'express';import { authenticate } from '../middlewares/auth.middleware';import { authorize, authorizeOwnerOrAdmin } from '../middlewares/authorize.middleware'; const router = Router(); // Qualquer usuário autenticadorouter.get('/profile', authenticate, userController.getProfile); // Apenas adminsrouter.get('/', authenticate, authorize('ADMIN'), userController.findAll);router.delete('/:id', authenticate, authorize('ADMIN'), userController.delete); // Próprio usuário ou adminrouter.put('/:id', authenticate, authorizeOwnerOrAdmin('id'), userController.update); export default router;Verificação em Services
typescript
// src/services/order.service.tsexport class OrderService { async findById(orderId: string, requestingUser: { userId: string; role: string }) { const order = await this.orderRepository.findById(orderId); if (!order) { throw new NotFoundError('Pedido'); } // Verificar permissão const isOwner = order.userId === requestingUser.userId; const isAdmin = requestingUser.role === 'ADMIN'; if (!isOwner && !isAdmin) { throw new ForbiddenError('Você não pode acessar este pedido'); } return order; } async cancel(orderId: string, requestingUser: { userId: string; role: string }) { const order = await this.findById(orderId, requestingUser); // Usuários só podem cancelar pedidos pendentes if (requestingUser.role !== 'ADMIN' && order.status !== 'PENDING') { throw new ForbiddenError('Apenas pedidos pendentes podem ser cancelados'); } return this.orderRepository.update(orderId, { status: 'CANCELLED' }); }}Permissões Granulares
typescript
// src/utils/permissions.tsexport const PERMISSIONS = { // Produtos 'products:read': ['USER', 'ADMIN'], 'products:create': ['ADMIN'], 'products:update': ['ADMIN'], 'products:delete': ['ADMIN'], // Pedidos 'orders:read-own': ['USER', 'ADMIN'], 'orders:read-all': ['ADMIN'], 'orders:update-status': ['ADMIN'], // Usuários 'users:read-own': ['USER', 'ADMIN'], 'users:read-all': ['ADMIN'], 'users:update-own': ['USER', 'ADMIN'], 'users:update-all': ['ADMIN'], 'users:delete': ['ADMIN'],} as const; export function hasPermission(role: string, permission: keyof typeof PERMISSIONS): boolean { return PERMISSIONS[permission].includes(role as any);} // Middlewareexport function requirePermission(permission: keyof typeof PERMISSIONS) { return (req: Request, res: Response, next: NextFunction) => { if (!req.user || !hasPermission(req.user.role, permission)) { throw new ForbiddenError('Permissão negada'); } next(); };}Resumo
- ✅ RBAC para controle de acesso baseado em roles
- ✅ Middlewares de autorização reutilizáveis
- ✅ Verificação owner vs admin
- ✅ Permissões granulares
Próxima aula: Upload de Arquivos! 📁