diff --git a/package-lock.json b/package-lock.json index cde009b..a84eda7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "jsonwebtoken": "^9.0.3", "morgan": "^1.10.1", "multer": "^2.1.1", + "nodemailer": "^8.0.10", "nodemon": "^3.1.14", "pg": "^8.19.0", "resend": "^6.12.4", @@ -4310,6 +4311,15 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/nodemailer": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.10.tgz", + "integrity": "sha512-BLFuSth7QtHOkBzyqTehWWyub0NTRDuK2Q2SQfnGLsrJnzyU+Yeh4WpV1eZGuARFj1xQJHIdnTuJZLP+b9R1GQ==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "3.1.14", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", diff --git a/package.json b/package.json index 5c9c634..6d4689b 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "jsonwebtoken": "^9.0.3", "morgan": "^1.10.1", "multer": "^2.1.1", + "nodemailer": "^8.0.10", "nodemon": "^3.1.14", "pg": "^8.19.0", "resend": "^6.12.4", diff --git a/src/lib/email.service.js b/src/lib/email.service.js index 62ab507..4dc4ddf 100644 --- a/src/lib/email.service.js +++ b/src/lib/email.service.js @@ -1,13 +1,22 @@ -import { Resend } from "resend"; +import nodemailer from "nodemailer"; export const sendPasswordResetEmail = async (email, token) => { - const resend = new Resend(process.env.RESEND_API_KEY); + const transporter = nodemailer.createTransport({ + host: process.env.EMAIL_HOST, + port: parseInt(process.env.EMAIL_PORT || "587"), + secure: false, + auth: { + user: process.env.EMAIL_USER, + pass: process.env.EMAIL_PASS, + }, + }); + const frontendUrl = process.env.FRONTEND_URL || "http://localhost:5173"; const resetUrl = `${frontendUrl}/restablecer-contrasena/${token}`; - const from = process.env.RESEND_FROM_EMAIL || "OpenMarket "; + const from = process.env.EMAIL_FROM; - const { error } = await resend.emails.send({ - from, + await transporter.sendMail({ + from: `"OpenMarket" <${from}>`, to: email, subject: "Recuperación de contraseña", html: ` @@ -26,8 +35,4 @@ export const sendPasswordResetEmail = async (email, token) => { `, }); - - if (error) { - throw new Error(`Error al enviar el correo de recuperación: ${error.message}`); - } }; diff --git a/src/modules/global/dtos/commerce/store.request.dto.js b/src/modules/global/dtos/commerce/store.request.dto.js index 89b373b..202cfd3 100644 --- a/src/modules/global/dtos/commerce/store.request.dto.js +++ b/src/modules/global/dtos/commerce/store.request.dto.js @@ -58,8 +58,8 @@ export const CreateStoreDTO = z .min(1, "address no puede estar vacío"), latitude: z.number({ error: "latitude es requerido" }), longitude: z.number({ error: "longitude es requerido" }), - base_price: z.number({ error: "base_price es requerido" }).nonnegative("base_price no puede ser negativo"), - distance_price: z.number({ error: "distance_price es requerido" }).nonnegative("distance_price no puede ser negativo") + base_price: z.number({ error: "base_price es requerido" }).nonnegative("base_price no puede ser negativo").max(99999999.99, "base_price supera el valor máximo permitido"), + distance_price: z.number({ error: "distance_price es requerido" }).nonnegative("distance_price no puede ser negativo").max(99999999.99, "distance_price supera el valor máximo permitido") }); // ─── UPDATE ────────────────────────────────────────────────────── @@ -113,8 +113,8 @@ export const UpdateStoreDTO = z address: z.string().min(1, "address no puede estar vacío").optional(), latitude: z.number().optional(), longitude: z.number().optional(), - base_price: z.number().nonnegative("base_price no puede ser negativo").optional(), - distance_price: z.number().nonnegative("distance_price no puede ser negativo").optional() + base_price: z.number().nonnegative("base_price no puede ser negativo").max(99999999.99, "base_price supera el valor máximo permitido").optional(), + distance_price: z.number().nonnegative("distance_price no puede ser negativo").max(99999999.99, "distance_price supera el valor máximo permitido").optional() }) .refine( (data) => Object.values(data).some((value) => value !== undefined),