Tables users, roles, permissions, user_roles, role_permissions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # ====================================================================== # Q: Design RBAC. How do you check permissions on each endpoint? # # Tables users, roles, permissions, user_roles, role_permissions. Permissions # use the resource:action format (assets:read, reports:export). The check is # done on permissions, not on role names, so a role can change without a deploy. # Default deny. # RBAC says "what is allowed". You also need an ownership/tenant check (does the # object belong to the user?), otherwise you have BOLA, number 1 on the OWASP # API Top 10. When the rules depend on attributes (department, country, # classification level), we move to ABAC or a policy engine (e.g. OPA). # ====================================================================== def require_permission(perm: str): def checker(user: User = Depends(current_user)) -> User: if perm not in user.permissions: # a set, loaded once per request raise HTTPException(status.HTTP_403_FORBIDDEN) return user return checker @app.get('/v1/reports/{rid}/export') def export_report(rid: int, user: User = Depends(require_permission('reports:export')), session: Session = Depends(get_session)): report = get_scoped(session, Report, rid, user.tenant_id) # + tenant check audit_log(session, user, 'reports:export', report.id) # compliance return stream_csv(report) |