Overview
VIGIA provides comprehensive user management capabilities including authentication, role-based access control (RBAC), and integration with employee records. Users can be managed at both the master (SaaS) level and individual tenant level.User Model
Users in VIGIA are defined by theUser model located at backend/app/models/user.py:17-80:
Core Fields
| Field | Type | Description |
|---|---|---|
id | Integer | Primary key |
username | String(64) | Unique username (optional) |
email | String(255) | Unique email address (required) |
hashed_password | String(255) | Bcrypt hashed password |
is_active | Boolean | Account activation status |
roles | Array[String] | PostgreSQL array of role names |
custom_permissions | JSON | Override permissions per user |
empleado_id | Integer | Foreign key to employee record |
created_at | DateTime | Account creation timestamp |
updated_at | DateTime | Last modification timestamp |
Example User Record
Authentication
Login Flow
Authentication is handled throughbackend/app/routers/auth.py:169-223:
- Client submits credentials via OAuth2 password flow to
/auth/login - System validates username/email and password
- Checks user status (active, has roles)
- Generates JWT token with claims:
sub: User ID (string)uid: User ID (integer)username: Usernameemail: Email addressrole: Primary roleroles: Array of all rolestenant: Tenant subdomain or “legacy”trace: Request trace ID
Multi-Tenant Authentication
VIGIA supports multi-tenant authentication via theX-Tenant header:
backend/app/routers/auth.py:128-146):
X-Tenantheader (highest priority)tenantclaim in JWT token- “legacy” mode (single-tenant)
Password Security
Passwords are hashed using bcrypt via passlib (backend/app/core/security.py:1-16):
Roles and Permissions
Available Roles
VIGIA defines system roles inbackend/app/models/roles.py:27-34:
Role Model
Roles are stored in theroles table with the following structure (backend/app/models/roles.py:60-117):
| Field | Type | Description |
|---|---|---|
id | Integer | Primary key |
name | String(64) | Unique role name |
description | String(255) | Human-readable description |
active | Boolean | Role activation status |
permissions | JSONB | Module-level permissions |
is_system | Boolean | System role (cannot delete) |
Permission Structure
Permissions are stored as JSONB with module-level granularity:Role Assignment
Users can have roles assigned via two mechanisms:- Array column (
users.roles): PostgreSQL VARCHAR[] array - Many-to-many relationship (
user_rolestable): Traditional M2M join
roles_names() method (backend/app/models/user.py:66-76) provides unified access:
User Management Operations
Creating Users
Users are created during tenant provisioning (backend/app/services/tenants.py:98-153):
Password Reset
VIGIA provides two password reset endpoints:1. User Self-Service (/auth/change-password)
Requires current password verification (backend/app/routers/auth.py:260-282):
2. Admin Reset (/admin/clientes/{id}/reset-password)
Allows administrators to reset user passwords (backend/app/routers/admin_clientes.py:146-208):
Manual Mode (admin provides password):
Activation and Deactivation
Toggle user status by updatingis_active:
backend/app/routers/auth.py:186-187).
Employee Integration
Users can be linked to employee records viaempleado_id foreign key.
Employee Model
TheEmpleado model (backend/app/models/empleado.py:5-72) stores comprehensive HR data:
Identity:
tipo_doc,dni: Document type and numberape_pat,ape_mat,nombres: Full name componentssexo,nacionalidad,f_nacimiento: Personal details
estado: Employment status (activo, inactivo, cesado)cargo: Job titlearea,centro_costo: Department and cost centerf_ingreso_rxh,f_ingreso_planilla: Start datesf_cese,cese_motivo: Termination details
email,tel_personal: Contact informationdireccion,distrito: Addresscontacto_emerg,tel_emerg: Emergency contact
User-Employee Relationship
TheUser model defines a relationship to Empleado (backend/app/models/user.py:49-53):
Benefits of Employee Linking
- Unified HR data: Single source of truth for employee information
- Automatic deactivation: When employee status changes to “cesado”, user account can be automatically deactivated
- Audit trails: Link user actions to specific employees
- Reporting: Generate reports by department, role, or employee status
Token Configuration
JWT tokens are configured via environment variables (backend/app/core/config.py:70-74):
Token Validation
Tokens are validated on protected endpoints viaoauth2_scheme dependency:
Security Best Practices
Password Requirements
- Minimum length: 6 characters (enforced at
backend/app/routers/auth.py:268) - Hashing: Bcrypt with automatic salt
- Storage: Never store plaintext passwords
Token Security
- Expiration: Set appropriate
ACCESS_TOKEN_EXPIRE_MINUTES - Secret rotation: Rotate
SECRET_KEYperiodically - HTTPS only: Never transmit tokens over HTTP
- Trace IDs: Every auth request logs a trace ID for auditing
Multi-Tenant Isolation
- Database separation: Each tenant has isolated database
- Token binding: JWT includes tenant claim
- Header validation:
X-Tenantheader prevents cross-tenant access - Session isolation: Database connections use tenant-specific connection strings
Monitoring and Auditing
Authentication events are logged with trace IDs (backend/app/routers/auth.py:65-67):
- Login attempts (success/failure)
- Password changes
- User lookups
- Database selection
- Password verifications
API Endpoints
Authentication
POST /api/v1/auth/login- User loginGET /api/v1/auth/me- Get current user infoGET /api/v1/auth/whoami- Get authenticated user detailsPOST /api/v1/auth/change-password- Change own passwordPOST /api/v1/auth/reset-password- Admin password reset