NexGenStudioDev/FastKit
Feature Request: Create Pluggable Role-Based Middleware for Route Access Control
オープン
#3 opened on 2025/06/27
TypeScriptbackenddocumentationenhancementgood first issuehelp wantednpm
Repository metrics
- Stars
- (1 個のスター)
- PR merge metrics
- (PR metrics pending)
説明
Description
We want to build a reusable role-based middleware called allowRoles to help developers restrict access to routes in an Express app based on the logged-in user’s role. This middleware should be:
- Easy to plug in and use anywhere without modifying existing controllers.
- Flexible to allow any combination of roles.
- Clear in sending proper HTTP status codes and messages when access is denied.
- Based on roles stored in constants so they are consistent and easy to update.
🧱 Why This Is Important
- Role-based access control (RBAC) is a common security need.
- Separating role checks into middleware keeps controllers focused on business logic.
- Developers want a simple, out-of-the-box solution that fits many use cases.
- Avoids repeating role-check logic in multiple places.
- Allows teams to customize roles and messages without touching core middleware code.
✅ Tasks for allowRoles Middleware
- Create allowRoles Middleware
- Make a function
allowRoles(...allowedRoles)that accepts one or more role names (strings). - It should read the user role from
req.user.role. - This assumes that a
verifyTokenmiddleware runs first to authenticate the user and attach user info toreq.user. - If the user is not authenticated (
req.userorreq.user.rolemissing), respond with:- Status code: 401 Unauthorized
- Message:
"User must be authenticated."
- If the user role is not in the allowed roles, respond with:
- Status code: 403 Forbidden
- Message:
"Access denied: insufficient role permissions."
- If the user role matches one of the allowed roles, call
next()to continue. - Export this middleware function so developers can import and use it in their routes easily.
- Make a function
2. Define Role and Error Constants
Create a constants file (e.g., role.constant.ts) to keep all role names and error messages in one place.
Export an object containing default roles, for example:
export const ROLES = {
ADMIN: 'admin',
STUDENT: 'student',
USER: 'user',
};
3. Export an object containing error messages:
export const ROLE_ERRORS = {
FORBIDDEN: 'Access denied: insufficient role permissions.',
UNAUTHORIZED: 'User must be authenticated.',
};
- This helps keep error messages and role names consistent across the app.
- Make sure the middleware uses these constants.
- Update Documentation and Provide Usage Examples
- Add clear instructions in the README or docs on how to use allowRoles.
- Show examples of how to use protect routes:
import { verifyToken } from './middlewares/auth.middleware';
import { allowRoles } from './middlewares/role.middleware';
router.get(
'/admin-dashboard',
verifyToken,
allowRoles('admin'),
DashboardController.getAdminView
);
router.get(
'/student-data',
verifyToken,
allowRoles('student', 'admin'),
StudentController.getData
);
- Emphasize that verifyToken must run before allowRoles.
✨ Expected Outcome
- Developers can easily add role-based access control to any route with just a few lines of code.
- Controllers remain clean and focused solely on their main tasks.
- The app maintains a clear and consistent approach to handling unauthorized (
401) and forbidden (403) access. - The system is flexible and extensible enough to adapt to different role needs and future requirements.
🙋🏻♂️ Looking For
We welcome your feedback and contributions! Specifically:
- Suggestions on improving the middleware implementation or enhancing error handling.
- Ideas and best practices for supporting complex role hierarchies or fine-grained permission-based access control.
- Contributors interested in writing tests, improving documentation, or adding usage examples.
- Proposals to extend this middleware’s concepts to other popular frameworks like NestJS or Fastify.
- Feel free to open issues or submit pull requests to help evolve this project!
🎯 Example Final Usage
router.get(
'/protected-route',
verifyToken,
allowRoles('admin', 'user'),
ProtectedController.handleRequest
);