Skip to content

✨ Servicio de Cambio de Contraseña en Vertical por Medio de API

La API update-password fue diseñada para permitir a los usuarios autenticados modificar la contraseña de una vertical de manera segura. Esta API está protegida por autenticación JWT-> Se obtiene con la nueva API de Login, lo que garantiza que solo los usuarios autenticados puedan modificar su información.


🔐 Autenticación

El acceso a esta API requiere un token JWT válido. Este token debe enviarse en el encabezado de la solicitud como:

Authorization: Bearer TU_TOKEN_JWT

Si el token es inválido o no se proporciona, la API rechazará la solicitud.


🧠 Controlador

Este archivo contiene la lógica principal para el manejo de la actualización de la contraseña de una vertical.

Ruta del archivo

  • src/api/user-endpoints/controllers/update-password.ts

⚙️ Funcionamiento interno de la API

El componente completo del registro es el siguiente:

export default {
async updatePassword(ctx) {
try {
const { vertical, currentPassword, newPassword } = ctx.request.body;
validateKeys(ctx.request.body, VALID_NEW_PASSWORD_KEYS, FIELD_ROOT);
validateRequiredFields(ctx.request.body, VALID_NEW_PASSWORD_KEYS);
const recivedUser = ctx.state.user;
if (!recivedUser) {
return ctx.unauthorized(ERROR_UNAUTHORIZED);
}
const { email } = recivedUser;
const user = await findOne(
USER,
FIELDS_USER,
{ email: email },
COMPONENT_NAME_USER_PASSWORDS
);
if (!user) return ctx.notFound(ERROR_USER_NOT_FOUND);
if (currentPassword === newPassword) {
return ctx.badRequest(ERROR_SAME_PASSWORD);
}
const passwordComponent = user.verticalsUserPasswords?.find(
(item) => item.vertical === vertical
);
if (!passwordComponent) {
return ctx.badRequest(ERROR_VERTICAL_PASSWORD_NOT_FOUND);
}
const match = await bcrypt.compare(
currentPassword,
passwordComponent.verticalPassword
);
if (!match) {
return ctx.unauthorized(ERROR_INVALID_PASSWORD);
}
await updateVerticalPassword(email, vertical, newPassword);
return ctx.send({ message: user });
} catch (error) {
return ctx.badRequest(error, ERROR_UPDATE);
}
},
};

Cuando se realiza una solicitud a esta API, el primer paso es la validación del cuerpo para garantizar que no se estén enviando campos inesperados o mal estructurados.

asegurandose contengan únicamente las propiedades válidas.

🧾 Datos esperados en el cuerpo de la solicitud (body)

El cuerpo debe enviarse en formato JSON y puede incluir los siguientes campos:

  • vertical (obligatorio): nombre de la vertical para la cual se está cambiando la contraseña.
  • currentPassword (obligatorio): contraseña antigua de la vertical.
  • newPassword (obligatorio): nueva contraseña que se asociará a la vertical.

Antes de procesar cualquier operación, el controlador valida que solo se estén enviando las claves permitidas, tanto a nivel raíz como en las direcciones anidadas.

validateKeys(ctx.request.body, VALID_NEW_PASSWORD_KEYS, FIELD_ROOT);
validateRequiredFields(ctx.request.body, VALID_NEW_PASSWORD_KEYS);

Luego, el sistema intenta localizar un usuario existente con el correo electrónico proporcionado por el token.

const recivedUser = ctx.state.user;
if (!recivedUser) {
return ctx.unauthorized(ERROR_UNAUTHORIZED);
}
const { email } = recivedUser;
const user = await findOne(
USER,
FIELDS_USER,
{ email: email },
COMPONENT_NAME_USER_PASSWORDS
);

Se comprueba que las contraseñas antigua y nueva no sean la misma. Y q la contraseña antigua coincida con la pasada por el body.

if (currentPassword === newPassword) {
return ctx.badRequest(ERROR_SAME_PASSWORD);
}
const passwordComponent = user.verticalsUserPasswords?.find(
(item) => item.vertical === vertical
);
if (!passwordComponent) {
return ctx.badRequest(ERROR_VERTICAL_PASSWORD_NOT_FOUND);
}
const match = await bcrypt.compare(
currentPassword,
passwordComponent.verticalPassword
);
if (!match) {
return ctx.unauthorized(ERROR_INVALID_PASSWORD);
}

Finalmente se llama a la funcion para actualizr la contraseña 👍

await updateVerticalPassword(email, vertical, newPassword);

🔐 ¿Qué hace exactamente updateVerticalPassword?

  • Vease su funcionamiento Aquí.

📤 Ejemplo de solicitud

URL: /api/user-endpoints/updatee-password

Método: POST

Body ejemplo:

{
"vertical": "Emergencias",
"currentPassword": "1234",
"newPassword": "123456"
}

✅ Respuestas esperadas

✔️ Registro exitoso

{
"message": {
"id": 22,
"documentId": "p800i3wc6h36p6jnghtbhv8c",
"username": "Marti",
"email": "example@example.com",
"confirmed": false,
"phone": null,
"origin": "local",
"identificationNumber": "01234567X",
"nameLastName": "Marta Quiros",
"verticalsUserPasswords": [
{
"id": 18,
"vertical": "Emergencias",
"verticalPassword": "$2a$10$xxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxx.xxxxxxxxxxx"
}
]
}
}

❌ Campos inválidos o faltantes

{
"data": null,
"error": {
"status": 400,
"name": "Error",
"message": "Missing required parameters: vertical",
"details": "Error on update "
}
}
{
"data": null,
"error": {
"status": 400,
"name": "Error",
"message": "Not Allowed fields at root: email",
"details": "Error on update "
}
}

❌ La nueva contraseña es igual que la antigua

{
"data": null,
"error": {
"status": 400,
"name": "BadRequestError",
"message": "New password can not be the same as the old one",
"details": {}
}
}

🔗 Funciones auxiliares

  • validateKeys, validateRequiredFields: validación de la estructura del body.

  • validateFieldPatterns: asegura que contraseñas cumplan con las reglas.

    🐿️ -> Veanse aqui validaciones de campos.

  • findOne, updateDocument: funciones de acceso a la base de datos.

  • sendEmail: abstracta el envío de correos con plantillas multilenguaje.

    🐿️ -> Veanse aqui strapi queries.

  • updateVerticalPassword: actualiza la contraseña cifrada de la vertical correspondiente.

    🐿️ -> Veanse aqui strapi passwords.