We have now successfully centralized our authorization logic into a services layer, but we still have many issues to address.
What's Still Wrong
Despite our fixes, the codebase has fundamental problems that will only get worse as the application grows.
1. Duplication Everywhere
Count how many times this exact pattern appears:
if (user == null || user.role !== "admin") {
// Redirect/Error
}
If we add a new rule (e.g., "managers can create/edit projects"), we need to find and update every occurrence. Miss one? Security vulnerability.
2. No Single Source of Truth
Where do you go to understand "who can create a document"? There's no clear answer:
- The page component has a check
- The service layer has a check
- The UI conditionally renders buttons
Each place has its own version of the "truth."
3. Hard to Read Permission Logic
What does this check actually mean?
if (user.role !== "author" && user.role !== "admin") {
return redirect(`/projects/${projectId}`)
}
Compare that to:
if (!canCreateDocument(user)) {
return redirect(`/projects/${projectId}`)
}
The second version is self-documenting. The first requires mental parsing.
4. Adding New Permissions is Painful
Imagine we need to add a new rule: "Documents can be marked as 'confidential' and only the creator can edit them."
With the current architecture, we'd need to:
- Update every edit page
- Update every edit service layer function
- Update all the UI conditionals
- Hope we didn't miss anything
Key Takeaways
Before moving on, remember these principles:
- Always check on the server - Client-side checks are for UX, not security
- Centralize permission logic - One place to define, one place to update
- Use descriptive functions -
canEditDocument(user, doc)beats inline conditionals - Plan for change - Permission rules will evolve; make that evolution painless
What's Next
In the next section, we'll implement Role-Based Access Control (RBAC). We'll create a permissions layer that:
- Defines all permissions in one place
- Provides helper functions for readable code
- Makes adding new permissions straightforward