🔐 Servicio de findAll - API Extracción de usuarios
⚙️ Funcionamiento interno de la API
Section titled “⚙️ Funcionamiento interno de la API”El API completo de extracción de usuarios es el siguiente:
import { findMany } from '../../../utils/strapi-queries';import { USER, FIELDS_USER, ADMINISTRATOR, SUPER_ADMIN } from '../../../constants/structures/collections/user';import { POPULATE_ALL } from '../../../constants/structures/common.fields';import { NOT_FOUND } from '../../../constants/errors/common.errors';import { ERROR_FETCHING_USERS, ERROR_UNAUTHORIZED, ERROR_UNAUTHORIZED_ADMIN,} from '../../../constants/errors/userCollection';
export default { async findAll(ctx) { try { const requester = ctx.state.user; if (!requester) return ctx.unauthorized(ERROR_UNAUTHORIZED);
const isAdmin = requester?.role?.name === ADMINISTRATOR || requester?.role?.name === SUPER_ADMIN; if (!isAdmin) return ctx.forbidden(ERROR_UNAUTHORIZED_ADMIN);
const users = await findMany(USER, FIELDS_USER, null, POPULATE_ALL);
if (users === NOT_FOUND) { return ctx.send([]); }
return ctx.send(users); } catch (error) { strapi.log.error(ERROR_FETCHING_USERS, error); return ctx.internalServerError(ERROR_FETCHING_USERS); } },};Esta API está encargada de extraer todos los usuarios registrados en el sistema. Por razones de seguridad, solo los usuarios con roles administrativos (ADMINISTRATOR o SUPER_ADMIN) tienen permisos para ejecutar esta operación.
🧑💻 findAll
Section titled “🧑💻 findAll”findAll permite obtener un listado completo de usuarios del sistema, incluyendo todas sus relaciones pobladas. Este endpoint está protegido y requiere autenticación administrativa.
🔐 Verificación de autenticación del usuario solicitante
Section titled “🔐 Verificación de autenticación del usuario solicitante”const requester = ctx.state.user;if (!requester) return ctx.unauthorized(ERROR_UNAUTHORIZED);El proceso comienza extrayendo el usuario autenticado desde ctx.state.user. Este objeto es poblado automáticamente por el middleware de autenticación de Strapi cuando se envía un JWT válido en los headers de la petición.
Si no existe un usuario autenticado (requester es null o undefined), se devuelve inmediatamente una respuesta 401 Unauthorized con el mensaje de error correspondiente (ERROR_UNAUTHORIZED).
🛡️ Validación de permisos administrativos
Section titled “🛡️ Validación de permisos administrativos”const isAdmin = requester?.role?.name === ADMINISTRATOR || requester?.role?.name === SUPER_ADMIN;if (!isAdmin) return ctx.forbidden(ERROR_UNAUTHORIZED_ADMIN);Una vez confirmado que existe un usuario autenticado, se verifica que tenga uno de los roles permitidos para esta operación:
ADMINISTRATOR: Rol de administrador estándarSUPER_ADMIN: Rol de super administrador con privilegios extendidos
La validación se realiza comparando el nombre del rol del usuario solicitante (requester?.role?.name) con las constantes definidas. El operador opcional chaining (?.) previene errores si la estructura del objeto no existe.
Si el usuario no tiene ninguno de estos roles, se retorna una respuesta 403 Forbidden con el error ERROR_UNAUTHORIZED_ADMIN, indicando que aunque está autenticado, no tiene permisos suficientes para realizar esta operación.
🔍 Consulta de todos los usuarios en la base de datos
Section titled “🔍 Consulta de todos los usuarios en la base de datos”const users = await findMany(USER, FIELDS_USER, null, POPULATE_ALL);Después de validar los permisos, se realiza la consulta a la base de datos utilizando la función auxiliar findMany. Los parámetros son:
USER: Constante que identifica la colección de usuarios en StrapiFIELDS_USER: Arreglo de campos específicos que se desean recuperarnull: Filtros de búsqueda (en este caso, ninguno, ya que se requieren todos los usuarios)POPULATE_ALL: Constante que indica que se deben poblar todas las relaciones del usuario (roles, componentes anidados, etc.)
Esta función encapsula la lógica de consulta de Strapi y retorna el resultado de la búsqueda.
📋 Manejo del caso sin resultados
Section titled “📋 Manejo del caso sin resultados”if (users === NOT_FOUND) { return ctx.send([]);}Si la consulta no encuentra ningún usuario (situación poco probable en un sistema en producción), la función findMany retorna la constante NOT_FOUND. En este caso, se devuelve un arreglo vacío [] al cliente con status 200 OK.
Esto permite al frontend manejar consistentemente la ausencia de datos sin necesidad de verificar diferentes códigos de error.
📤 Respuesta exitosa con listado de usuarios
Section titled “📤 Respuesta exitosa con listado de usuarios”return ctx.send(users);Si la consulta es exitosa y retorna usuarios, se envían directamente al cliente con status 200 OK. El arreglo users contiene todos los registros encontrados, con sus campos y relaciones completamente pobladas según lo especificado en FIELDS_USER y POPULATE_ALL.
⚠️ Manejo de errores inesperados
Section titled “⚠️ Manejo de errores inesperados”catch (error) { strapi.log.error(ERROR_FETCHING_USERS, error); return ctx.internalServerError(ERROR_FETCHING_USERS);}Todo el flujo está envuelto en un bloque try-catch para capturar cualquier error inesperado durante la ejecución (problemas de conexión a base de datos, errores de configuración, etc.).
Cuando ocurre un error:
- Se registra en los logs de Strapi mediante
strapi.log.errorcon el mensaje descriptivo y el objeto de error completo - Se retorna una respuesta
500 Internal Server Erroral cliente con el mensajeERROR_FETCHING_USERS
Esto evita que errores internos expongan información sensible del sistema al usuario final.
📤 Ejemplo de solicitud
Section titled “📤 Ejemplo de solicitud”URL: /api/user-endpoints/find-all
Método: GET
Headers requeridos:
Authorization: Bearer <JWT_TOKEN>Body: No requiere body (es una petición GET)
✅ Respuestas esperadas
Section titled “✅ Respuestas esperadas”✔️ Consulta exitosa con usuarios
Section titled “✔️ Consulta exitosa con usuarios”[ { "id": 1, "documentId": "abc123def456", "username": "admin@sistema.com", "email": "admin@sistema.com", "confirmed": true, "phone": "5551234567", "role": { "id": 1, "name": "Administrator", "description": "Administrador del sistema" }, "identificationNumber": "ABC123456", "nameLastName": "Juan Pérez", "verticalsUserPasswords": [ { "vertical": "Pharma", "originWps": false, "verticalPassword": "$2b$10$..." } ] }, { "id": 2, "documentId": "xyz789ghi012", "username": "usuario@prueba.com", "email": "usuario@prueba.com", "confirmed": false, "phone": "5559876543", "role": { "id": 2, "name": "Authenticated", "description": "Usuario autenticado" }, "identificationNumber": "XYZ987654", "nameLastName": "María González", "verticalsUserPasswords": [ { "vertical": "Tech", "originWps": true, "verticalPassword": null } ] }]✔️ Consulta exitosa sin usuarios
Section titled “✔️ Consulta exitosa sin usuarios”[]❌ Usuario no autenticado
Section titled “❌ Usuario no autenticado”Status: 401 Unauthorized
{ "data": null, "error": { "status": 401, "name": "UnauthorizedError", "message": "ERROR_UNAUTHORIZED", "details": {} }}Esta respuesta ocurre cuando no se envía un token JWT válido en los headers o cuando el token ha expirado.
❌ Usuario sin permisos administrativos
Section titled “❌ Usuario sin permisos administrativos”Status: 403 Forbidden
{ "data": null, "error": { "status": 403, "name": "ForbiddenError", "message": "ERROR_UNAUTHORIZED_ADMIN", "details": {} }}Esta respuesta ocurre cuando el usuario está autenticado pero su rol no es ADMINISTRATOR ni SUPER_ADMIN.
❌ Error interno del servidor
Section titled “❌ Error interno del servidor”Status: 500 Internal Server Error
{ "data": null, "error": { "status": 500, "name": "InternalServerError", "message": "ERROR_FETCHING_USERS", "details": {} }}Esta respuesta ocurre cuando hay un error inesperado durante la ejecución (problemas de base de datos, configuración incorrecta, etc.).
🔒 Consideraciones de seguridad
Section titled “🔒 Consideraciones de seguridad”- Autenticación obligatoria: Este endpoint NO puede ser accedido sin un JWT válido
- Autorización por rol: Solo usuarios con roles
ADMINISTRATORoSUPER_ADMINpueden ejecutar esta operación - Datos sensibles: La respuesta incluye información completa de usuarios, incluyendo hashes de contraseñas (aunque cifrados). Este endpoint debe ser usado con precaución y nunca expuesto públicamente
- Logging de errores: Todos los errores se registran en los logs del sistema para auditoría y debugging
💡 Requisito previo — Usuario administrativo
Section titled “💡 Requisito previo — Usuario administrativo”Para poder probar y ejecutar correctamente los endpoints administrativos (como findAll), es necesario contar con un usuario que tenga un rol administrativo. A continuación se indican los pasos recomendados desde el panel de administración de Strapi:
-
Verificar o crear el rol administrativo:
- Panel Strapi →
Settings→Users & Permissions→Roles. - Comprueba que exista un rol llamado
AdministratoroSuper Admin. Si no existe, crea uno nuevo y asigna los permisos administrativos necesarios.
- Panel Strapi →
-
Crear el usuario administrativo:
- Panel Strapi →
Content Manager→Users→Add new user. - Rellena
email,usernameypassword. - En
Role, seleccionaAdministratoroSuper Admin(el rol creado/verificado).
- Panel Strapi →
-
Usar el usuario para obtener un JWT y probar endpoints:
- Autentica con las credenciales del usuario administrativo para obtener el JWT.
- Incluye el header
Authorization: Bearer <JWT_TOKEN>en las peticiones a endpoints protegidos.