Skip to main content

Overview

MotorDesk implements a hierarchical role-based access control (RBAC) system with four distinct user roles, each designed for specific responsibilities within a fleet management business.
All user roles are centrally defined in src/constants/roles/roles.ts for easy maintenance and consistency across the application.

Available Roles

The system defines four roles with decreasing levels of access:
src/constants/roles/roles.ts
export enum UserRole {
    OWNER = 'DUEÑO',
    ADMIN = 'ADMINISTRADOR',
    SELLER = 'VENDEDOR',
    CASHIER = 'CAJERO',
}

Role Hierarchy

Role Details

1. DUEÑO (Owner)

Business Owner

The highest level of access with complete control over the system. Typically the business owner or primary stakeholder.
Access Level: Full system access Key Responsibilities:
  • Complete business configuration
  • Tax and legal settings (RUC, SUNAT credentials)
  • User management (create, modify, delete users)
  • Branch management
  • Financial reports and analytics
  • System-wide settings
  • Electronic billing configuration
Permissions:
  • View all business metrics
  • Access financial reports
  • Export data across all branches
  • View profit/loss statements
  • Create new users with any role
  • Edit user information and roles
  • Delete or deactivate users
  • Assign branch access to users
  • Reset user passwords
  • Create new branch locations
  • Configure branch settings
  • Assign users to branches
  • View cross-branch analytics
  • Configure pricing and margins
  • Set discount policies
  • Manage payment methods
  • Configure tax settings
  • Access all financial reports
  • Electronic billing setup (SUNAT)
  • Invoice series configuration
  • Backup and data management
  • Integration settings
How to Become Owner:
src/hooks/useAuth.ts
// Owners are created through registration
const newUser: User = {
  id: `user-new-${Date.now()}`,
  branchIds: [],
  nombre: nombreNuevo,
  email: emailNuevo.toLowerCase(),
  rol: UserRole.OWNER, // Automatically assigned on registration
};
Only one owner is created during initial system registration. Additional owners can be created by the existing owner through the Settings panel.

2. ADMINISTRADOR (Administrator)

Branch Administrator

Second-highest access level with administrative capabilities for day-to-day operations.
Access Level: Full operational access (limited system settings) Key Responsibilities:
  • Daily operations management
  • Staff supervision
  • Inventory management
  • Customer relationship management
  • Sales oversight
  • Report generation
Permissions:
  • Create and process all invoice types
  • Issue refunds and credit notes
  • Apply discounts (within limits)
  • View sales history
  • Cancel or modify invoices
  • Add/edit/delete products
  • Manage stock levels
  • Set product pricing
  • Create product categories
  • Import/export product data
  • Full CRUD on customer records
  • Manage customer vehicles
  • View customer history
  • Export customer data
  • Generate sales reports
  • View inventory reports
  • Access customer analytics
  • Export reports
  • View seller/cashier activities
  • Assign tasks to team members
  • Cannot create or delete users
Restrictions:
  • Cannot access system configuration
  • Cannot create or delete users
  • Cannot modify owner settings
  • Limited to assigned branches only
Example: Admin User
const adminUser: User = {
  id: "user-001",
  branchIds: ["branch-001", "branch-002"], // Can access multiple branches
  nombre: "Carlos Vendedor",
  email: "[email protected]",
  rol: "ADMINISTRADOR"
};

3. VENDEDOR (Seller)

Sales Representative

Front-line staff focused on sales and customer service.
Access Level: Sales and customer interaction Key Responsibilities:
  • Process sales and create invoices
  • Customer registration
  • Vehicle information entry
  • Product search and recommendation
  • Service documentation
Permissions:
  • Create invoices and receipts
  • Add products to sales
  • Calculate totals and taxes
  • Print/email invoices
  • Create proforma invoices
  • Register new customers
  • Update customer information
  • Add vehicle records
  • Update vehicle service history
  • View customer purchase history
  • Search product catalog
  • View product availability
  • View product prices
  • Cannot modify prices or inventory
  • View own sales statistics
  • Generate daily sales summary
  • Limited access to reports
Restrictions:
  • Cannot modify product prices
  • Cannot access inventory management
  • Cannot delete invoices
  • Cannot apply large discounts (policy-dependent)
  • Cannot access financial reports
  • Cannot manage users
Example: Seller User
const sellerUser: User = {
  id: "user-002",
  branchIds: ["branch-001"], // Typically assigned to one branch
  nombre: "Ana Vendedora",
  email: "[email protected]",
  rol: "VENDEDOR"
};

4. CAJERO (Cashier)

Cashier

Specialized role focused on payment processing and transaction recording.
Access Level: Payment processing and transaction closure Key Responsibilities:
  • Process payments
  • Handle cash transactions
  • Close sales
  • Issue receipts
  • Daily cash reconciliation
Permissions:
  • Accept cash payments
  • Process card transactions
  • Issue payment receipts
  • Handle mixed payment methods
  • Process refunds (with approval)
  • View pending transactions
  • Close sales
  • Print receipts
  • Email invoices to customers
  • Open/close register
  • Record cash movements
  • Generate cash count reports
  • Handle change requests
  • Daily cash summary
  • Transaction log
  • Personal sales totals
Restrictions:
  • Cannot create new sales (only process payments)
  • Cannot access inventory
  • Cannot modify customer records
  • Cannot access financial reports
  • Cannot manage products or pricing
  • Cannot manage users
  • Limited to single branch
Example: Cashier User
const cashierUser: User = {
  id: "user-004",
  branchIds: ["branch-003"], // Single branch assignment
  nombre: "Marta Cajera",
  email: "[email protected]",
  rol: "CAJERO"
};

Role Comparison Matrix

FeatureDUEÑOADMINISTRADORVENDEDORCAJERO
System Configuration
User Management
Branch Management
Create Sales
Process Payments
Manage Inventory
Modify Prices
Manage Customers
Full Reports Access
Own Sales Reports
Multi-Branch Access
Electronic Billing Setup

Implementing Role-Based Access

Checking User Role

Access the current user’s role from the Redux store:
Example: Role Check
import { useSelector } from 'react-redux';
import { type RootState } from '@/store';
import { UserRole } from '@constants/roles/roles';

const MyComponent = () => {
  const user = useSelector((state: RootState) => state.auth.user);
  
  const isOwner = user?.rol === UserRole.OWNER;
  const isAdmin = user?.rol === UserRole.ADMIN;
  const canManageInventory = isOwner || isAdmin;
  
  return (
    <div>
      {canManageInventory && (
        <button>Manage Inventory</button>
      )}
    </div>
  );
};

Creating Permission Guards

Create reusable permission check functions:
utils/permissions.ts
import { UserRole } from '@constants/roles/roles';
import type { User } from '@/store/slices/authSlice';

export const canManageUsers = (user: User | null): boolean => {
  return user?.rol === UserRole.OWNER;
};

export const canManageInventory = (user: User | null): boolean => {
  return user?.rol === UserRole.OWNER || user?.rol === UserRole.ADMIN;
};

export const canCreateSales = (user: User | null): boolean => {
  return [
    UserRole.OWNER,
    UserRole.ADMIN,
    UserRole.SELLER
  ].includes(user?.rol as UserRole);
};

export const canProcessPayments = (user: User | null): boolean => {
  // All authenticated users can process payments
  return user !== null;
};

export const hasAccessToBranch = (
  user: User | null,
  branchId: string
): boolean => {
  if (!user) return false;
  if (user.rol === UserRole.OWNER) return true; // Owners access all
  return user.branchIds.includes(branchId);
};

Component-Level Protection

Protect UI components based on permissions:
Example: Conditional Rendering
import { canManageInventory } from '@/utils/permissions';

const InventoryButton = () => {
  const user = useSelector((state: RootState) => state.auth.user);
  
  if (!canManageInventory(user)) {
    return null; // Hide component if no permission
  }
  
  return (
    <Button onClick={handleInventoryClick}>
      Manage Inventory
    </Button>
  );
};

Route-Level Protection

Protect entire routes based on role:
Example: Protected Route
import { Navigate } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { UserRole } from '@constants/roles/roles';

const ProtectedRoute = ({ 
  children, 
  allowedRoles 
}: { 
  children: React.ReactNode;
  allowedRoles: UserRole[];
}) => {
  const user = useSelector((state: RootState) => state.auth.user);
  
  if (!user || !allowedRoles.includes(user.rol)) {
    return <Navigate to="/unauthorized" replace />;
  }
  
  return <>{children}</>;
};

// Usage:
<Route
  path="/settings"
  element={
    <ProtectedRoute allowedRoles={[UserRole.OWNER]}>
      <Settings />
    </ProtectedRoute>
  }
/>

Branch Access Control

Users can be assigned to specific branches:
Example: Branch Assignment
const user: User = {
  id: "user-003",
  branchIds: ["branch-001", "branch-002"], // Access to 2 branches
  nombre: "Luis Técnico",
  email: "[email protected]",
  rol: UserRole.SELLER
};

// Check branch access
const hasBranchAccess = (
  user: User,
  targetBranchId: string
): boolean => {
  // Owners have access to all branches
  if (user.rol === UserRole.OWNER) return true;
  
  // Other roles check their assigned branches
  return user.branchIds.includes(targetBranchId);
};
DUEÑO (Owner) users automatically have access to all branches regardless of their branchIds array.

Managing Users

Creating New Users

Only owners can create new users (typically through Settings):
Example: Create User
const createNewUser = async (
  nombre: string,
  email: string,
  rol: UserRole,
  branchIds: string[]
) => {
  // Verify current user is owner
  const currentUser = store.getState().auth.user;
  if (currentUser?.rol !== UserRole.OWNER) {
    throw new Error('Only owners can create users');
  }
  
  const newUser: User = {
    id: `user-${Date.now()}`,
    nombre,
    email: email.toLowerCase(),
    rol,
    branchIds
  };
  
  // Save to database
  await saveUser(newUser);
};

Role Assignment Best Practices

1

Assess responsibilities

Determine what the user needs to do daily:
  • Full business control? → DUEÑO
  • Daily operations & staff management? → ADMINISTRADOR
  • Customer service & sales? → VENDEDOR
  • Payment processing only? → CAJERO
2

Apply principle of least privilege

Assign the minimum role needed for the user to perform their job. You can always upgrade later.
3

Assign branch access

  • Owners: Automatic access to all branches
  • Admins: Can manage multiple branches
  • Sellers/Cashiers: Usually single branch
4

Review regularly

Audit user roles and permissions quarterly to ensure they match current responsibilities.

Security Considerations

Important Security Notes:
  • Always validate user roles on the backend/API level, not just in the UI
  • UI-level protection can be bypassed; enforce permissions server-side
  • Log all permission-based actions for audit trails
  • Implement session timeouts for inactive users
  • Require password confirmation for role changes

Common Scenarios

Scenario 1: New Branch Opening

1

Owner creates branch

Use Settings → Branch Management to create new branch location
2

Create branch admin

Create user with ADMINISTRADOR role, assign to new branch
3

Add staff

Admin or Owner creates VENDEDOR and CAJERO users for the branch

Scenario 2: Employee Promotion

Example: Promote User
const promoteUser = (userId: string, newRole: UserRole) => {
  // Verify permission
  const currentUser = store.getState().auth.user;
  if (currentUser?.rol !== UserRole.OWNER) {
    throw new Error('Only owners can change roles');
  }
  
  // Update user role
  updateUser(userId, { rol: newRole });
  
  // Log the change
  logAudit({
    action: 'USER_ROLE_CHANGED',
    userId,
    oldRole: getUser(userId).rol,
    newRole,
    changedBy: currentUser.id
  });
};

Scenario 3: Temporary Access Needs

Need to grant temporary elevated access (e.g., seller covering for admin)?
  1. Create a temporary user account with elevated role
  2. Set expiration date in user metadata
  3. Automatically revoke access after expiration
  4. Or: Implement a “temporary permissions” system separate from roles

Next Steps

Authentication

Learn how login and registration work

Settings Management

Configure users and team settings

State Management

Understand Redux store structure

API Reference

Explore hooks and utilities

Build docs developers (and LLMs) love