Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/JFKoryy/autopart-pro/llms.txt

Use this file to discover all available pages before exploring further.

AutoPart Pro uses a role-based access control (RBAC) system built on JWT authentication and a lightweight authorize middleware. Every registered account is assigned one of three roles — admin, employee, or client — that is stored in the database and embedded in the user’s JWT at login time. On each subsequent request the role is decoded from the token and compared against the list of roles permitted for that endpoint.

The Three Roles

users.role  ENUM('admin', 'employee', 'client')  DEFAULT 'client'
RoleIntended ForDefault
adminStore owners and managers who need full read/write access
employeeWarehouse staff who can view and adjust stock but not manage accounts
clientEnd-customers who browse the catalog and place orders
Every new account registered via POST /api/auth/register receives the client role automatically. An admin must use PUT /api/users/:id/role to promote accounts to employee or admin.

Role Embedding in JWT

At login, the authentication controller signs a JWT that includes the user’s id, email, and role in its payload. The protect (auth) middleware decodes the token on each request and attaches the decoded payload to req.user, making req.user.role available to every downstream middleware and controller.

The authorize Middleware

backend/src/middleware/roleMiddleware.js exports a higher-order function that accepts any number of allowed role strings and returns an Express middleware:
const authorize = (...allowedRoles) => {
  return (req, res, next) => {
    // Reject if req.user is missing or their role is not in the allowed list
    if (!req.user || !allowedRoles.includes(req.user.role)) {
      return res.status(403).json({
        success: false,
        message: 'Acceso denegado. No se encontraron roles asignados.'
      });
    }

    // Role is permitted — continue to the next handler
    next();
  };
};

module.exports = { authorize };
authorize is always chained after protect so that req.user is guaranteed to be populated when the role check runs. Example from productRoutes.js:
router.post('/', protect, authorize('admin'), validateProductData, ProductController.createProduct);

Endpoint Permissions

MethodEndpointAuthRolesNotes
GET/api/productsNoPublic catalog read
GET/api/products/:idYesAnySingle product detail
GET/api/products/low-stockYesAnyProducts at or below min_stock
POST/api/productsYesadminCreate a new product
PUT/api/products/:idYesadminUpdate a product
DELETE/api/products/:idYesadminDelete a product
GET/api/salesYesAnyAdmin sees all; employee and client see own orders only
POST/api/salesYesAnyPlace a new order
GET/api/usersYesadminList all user accounts
PUT/api/users/:id/roleYesadminChange a user’s role
DELETE/api/users/:idYesadminDelete a user account
For GET /api/sales, role filtering is applied in the controller rather than the route definition. The saleController.getSales function checks req.user.role === 'admin' and calls either SaleModel.getAll() or SaleModel.getByUser(req.user.id) accordingly.

Admin User Management

The admin panel exposes three user-management operations, all under /api/users and all protected by authorize('admin'):

List Users

GET /api/users returns every account’s id, name, email, and role. The password hash is never included in the response.

Change Role

PUT /api/users/:id/role accepts { "role": "admin" | "employee" | "client" }. Any other value returns 400. The controller validates the value before updating the database.

Delete User

DELETE /api/users/:id removes the account permanently. An admin cannot delete their own account — passing their own id returns a 400 error.

Updating a User’s Role

curl -X PUT http://localhost:5000/api/users/15/role \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ADMIN_TOKEN>" \
  -d '{"role": "employee"}'
Success response:
{
  "success": true,
  "message": "Rol actualizado correctamente."
}
Invalid role response (400):
{
  "success": false,
  "message": "Rol inválido. Los roles válidos son: admin, employee, client."
}

Role Validation in the Controller

// userController.js — updateRole
if (!['admin', 'employee', 'client'].includes(role)) {
  return res.status(400).json({
    success: false,
    message: 'Rol inválido. Los roles válidos son: admin, employee, client.'
  });
}

Frontend Enforcement

On the React side, a ProtectedRoute component wraps pages that require specific roles. If the authenticated user’s role does not match the route’s requirements they are redirected rather than shown a 403 error page. The Dashboard renders different widgets and navigation items depending on the role stored in AuthContext, so admins see user-management and sales overview panels while clients only see their order history and the catalog.
Frontend role checks are a UX convenience only — they do not replace server-side authorize middleware. Every state-changing API call is independently protected on the backend regardless of what the frontend renders.

Inventory Management

See how authorize('admin') is applied to every product write endpoint.

Sales & Checkout

Understand how role determines which sales records a user can retrieve.

Build docs developers (and LLMs) love