Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Danielings/Pasantia-Proyecto/llms.txt

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

User management in the Sistema de Inventario Tecnológico is handled entirely through the /api/usuarios resource. All write operations are executed inside Firestore transactions to guarantee consistency — for example, duplicate username and cédula checks are atomic with the document creation. Every meaningful change is recorded in the bitacora collection so there is a full audit trail of who changed what and when.

Create a User — POST /api/usuarios

Creating a new user requires a JSON body with all mandatory fields. The frontend enforces these constraints through a Zod schema (userSchema.ts) before the request even reaches the server; the backend re-validates business rules (duplicate checks, required strings) inside the route handler.

Required Fields

FieldTypeValidation
usernamestringMinimum 4 characters; must be unique (case-insensitive)
passwordstringMinimum 6 characters; bcrypt-hashed (10 rounds) before storage
cedulastringFormat V-XXXXXXXX or E-XXXXXXXX (7–8 digits after prefix)
nombrestringLetters and spaces only
apellidostringLetters and spaces only
correostringValid email address
telefonostringVenezuelan carriers: 0414, 0416, 0424, 0426, or 0412 followed by 7 digits
rolenumOne of "Superadministrador", "Administrador", "Visualizador"
regionstringGeographic region for sede assignment
estadostringVenezuelan state for sede assignment
ciudadstringCity for sede assignment
sedestringOffice/branch name
pisostringFloor within the sede

Example Request

curl -X POST http://localhost:3001/api/usuarios \
  -H "Content-Type: application/json" \
  -d '{
    "username": "jperez",
    "password": "secreto123",
    "cedula": "V-12345678",
    "nombre": "Juan",
    "apellido": "Pérez",
    "correo": "jperez@empresa.com",
    "telefono": "04141234567",
    "rol": "Administrador",
    "region": "Capital",
    "estado": "Distrito Capital",
    "ciudad": "Caracas",
    "sede": "Torre Centro",
    "piso": "3"
  }'

Example Response

{
  "message": "Usuario creado exitosamente.",
  "id_usuario": "aB3kLmNpQrSt"
}

What Happens Internally

The route executes a Firestore transaction that performs three steps atomically:
1

Duplicate validation

The transaction queries the usuarios collection for any existing document with the same usernameNorm (lowercased username) or cedula. If either query returns a result, a 400 Bad Request is thrown and the transaction is aborted — no data is written.
2

Password hashing

The plaintext password is hashed with bcrypt.hash(password, 10) (10 salt rounds). The plaintext value is never stored.
3

Location upsert and user document creation

A location record is created in the ubicaciones collection if it does not already exist (identified by a deterministic ID derived from the location fields). The new user document is then written to the usuarios collection, embedding both the id_ubicacion reference and a denormalized ubicacion object so that reads never require a JOIN.

List Users — GET /api/usuarios

This endpoint is restricted to Superadministrador accounts (enforced by the esSuperAdmin middleware). It returns all users whose estado field equals "activo", with the nested ubicacion object flattened to top-level fields.
curl http://localhost:3001/api/usuarios \
  --cookie "acceso_token=<your_token>"

Example Response

[
  {
    "id_usuario": "aB3kLmNpQrSt",
    "cedula": "V-12345678",
    "nombre": "Juan",
    "apellido": "Pérez",
    "correo": "jperez@empresa.com",
    "telefono": "04141234567",
    "estado_persona": "activo",
    "username": "jperez",
    "rol": "Administrador",
    "region": "Capital",
    "estado": "Distrito Capital",
    "ciudad": "Caracas",
    "sede": "Torre Centro",
    "piso": "3"
  }
]

Update a User — PUT /api/usuarios/:id

Updating a user follows the same field structure as creation. The route requires an active session (enforced by verificarToken) but does not restrict which role can call it beyond that.
curl -X PUT http://localhost:3001/api/usuarios/aB3kLmNpQrSt \
  --cookie "acceso_token=<your_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "jperez",
    "cedula": "V-12345678",
    "nombre": "Juan Carlos",
    "apellido": "Pérez",
    "correo": "jperez@empresa.com",
    "telefono": "04141234567",
    "rol": "Administrador",
    "region": "Capital",
    "estado": "Distrito Capital",
    "ciudad": "Caracas",
    "sede": "Torre Centro",
    "piso": "4"
  }'
Password updates are optional. If the password field is omitted or sent as an empty string (""), the existing hashed password is preserved. When a non-empty password is provided, it is bcrypt-hashed before the update. After writing the updated document, the route calls generarCambios(oldData, newData) to produce a diff array. If any fields changed, a new document is written to the bitacora collection recording the editor’s username, the target user ID, the action "Actualización de usuario", and the list of changed fields.

Example Response

{
  "message": "Usuario actualizado y cambios registrados en bitácora."
}

Soft-Delete a User — PUT /api/usuarios/eliminado/:id

Deactivating a user sets their estado field to "inactivo" and timestamps the change. The user document remains in Firestore and can be audited. Inactive users cannot log in — the login route checks usuario.estado !== "activo" and returns HTTP 403.
curl -X PUT http://localhost:3001/api/usuarios/eliminado/aB3kLmNpQrSt \
  --cookie "acceso_token=<your_token>"

Example Response

{
  "message": "Usuario eliminado (lógicamente)."
}
A bitacora entry is written with accion: "Eliminar usuario" and the deactivated user’s username in the detalles array.
Deletion is always logical (soft-delete). No user document is ever removed from Firestore. This ensures the audit log (bitacora) remains intact and past inventory changes can always be traced back to the user who made them. To permanently purge a user, a Firestore console operation by a database administrator would be required.

Get Own Profile — GET /api/usuarios/me

Any authenticated user can retrieve their full Firestore document via this endpoint. The route uses the correo field from the decoded JWT to look up the corresponding document in the usuarios collection.
curl http://localhost:3001/api/usuarios/me \
  --cookie "acceso_token=<your_token>"

Example Response

{
  "autenticado": true,
  "user": {
    "id": "aB3kLmNpQrSt",
    "username": "jperez",
    "cedula": "V-12345678",
    "nombre": "Juan Carlos",
    "apellido": "Pérez",
    "correo": "jperez@empresa.com",
    "telefono": "04141234567",
    "rol": "Administrador",
    "estado": "activo",
    "ubicacion": {
      "region": "Capital",
      "estado": "Distrito Capital",
      "ciudad": "Caracas",
      "sede": "Torre Centro",
      "piso": "4"
    },
    "id_ubicacion": "capital__distrito_capital__caracas__torre_centro__4"
  }
}
This endpoint returns the full Firestore document — including all location fields — and is the recommended source for pre-populating user profile edit forms on the frontend. It differs from GET /api/me, which only returns the lightweight JWT payload (correo, username, rol, sede).

Build docs developers (and LLMs) love