jws-backend/src/controllers/09-verification-controller.ts

147 lines
3.9 KiB
TypeScript
Raw Normal View History

feat: line (#13) * add wedhook line * text message * add router get employee, request, quotation * move code * do not crash application when not set line token This feature is opt-in * dot not crash when not set line client id Main auth method is keycloak * change dotenv * fix: wrong env * refactor: change to get instead of post * refactor: remove body for employee get endpoint * feat: add work relation include * feat: include customer relation in employee * feat: add line file controller * add detail flex message and get date requestWork * chore: update deps lock * fix: error line token * fix: redirect head instead if response with body * feat: add response relation * fix: route casing * add userId in customerBranch verifyOTP * delete consile log * add is registered endpoint placeholder * feat: quotation list * fix: wrong endpoint name * feat: include relation in get by id request data * add where userId line * refactor: adjust parameter for liff app * delete code * refactor: remove post quotation endpoint * refactor: add where userId line for quotation * feat: add pending only parameter * refactor: more condition for inProgressOnly * refactor: update condition * feat: add line quotation attachment endpoint * feat: include product in request work line endpoint * refactor: pending only now cover more condition * feat: include invoice with payment relation * chore: update api docs tag * chore: clean * feat: check for registered user * fix: wrong file location * feat: add email client for sending an otp * chore: move some deps to dev deps * add otpCode otpExpires * add send-otp and verify-otp --------- Co-authored-by: Kanjana <kanjana@chamomind.com> Co-authored-by: chamomind <chamomind@localhost> Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
2025-02-20 16:07:16 +07:00
import { Body, Controller, Get, Post, Request, Route, Security, Tags } from "tsoa";
import prisma from "../db";
import nodemailer from "nodemailer";
import { notFoundError } from "../utils/error";
import { RequestWithLineUser } from "../interfaces/user";
2025-02-20 16:16:51 +07:00
import HttpError from "../interfaces/http-error";
import HttpStatus from "../interfaces/http-status";
feat: line (#13) * add wedhook line * text message * add router get employee, request, quotation * move code * do not crash application when not set line token This feature is opt-in * dot not crash when not set line client id Main auth method is keycloak * change dotenv * fix: wrong env * refactor: change to get instead of post * refactor: remove body for employee get endpoint * feat: add work relation include * feat: include customer relation in employee * feat: add line file controller * add detail flex message and get date requestWork * chore: update deps lock * fix: error line token * fix: redirect head instead if response with body * feat: add response relation * fix: route casing * add userId in customerBranch verifyOTP * delete consile log * add is registered endpoint placeholder * feat: quotation list * fix: wrong endpoint name * feat: include relation in get by id request data * add where userId line * refactor: adjust parameter for liff app * delete code * refactor: remove post quotation endpoint * refactor: add where userId line for quotation * feat: add pending only parameter * refactor: more condition for inProgressOnly * refactor: update condition * feat: add line quotation attachment endpoint * feat: include product in request work line endpoint * refactor: pending only now cover more condition * feat: include invoice with payment relation * chore: update api docs tag * chore: clean * feat: check for registered user * fix: wrong file location * feat: add email client for sending an otp * chore: move some deps to dev deps * add otpCode otpExpires * add send-otp and verify-otp --------- Co-authored-by: Kanjana <kanjana@chamomind.com> Co-authored-by: chamomind <chamomind@localhost> Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
2025-02-20 16:07:16 +07:00
2025-02-20 16:16:51 +07:00
type SendEmail = {
feat: line (#13) * add wedhook line * text message * add router get employee, request, quotation * move code * do not crash application when not set line token This feature is opt-in * dot not crash when not set line client id Main auth method is keycloak * change dotenv * fix: wrong env * refactor: change to get instead of post * refactor: remove body for employee get endpoint * feat: add work relation include * feat: include customer relation in employee * feat: add line file controller * add detail flex message and get date requestWork * chore: update deps lock * fix: error line token * fix: redirect head instead if response with body * feat: add response relation * fix: route casing * add userId in customerBranch verifyOTP * delete consile log * add is registered endpoint placeholder * feat: quotation list * fix: wrong endpoint name * feat: include relation in get by id request data * add where userId line * refactor: adjust parameter for liff app * delete code * refactor: remove post quotation endpoint * refactor: add where userId line for quotation * feat: add pending only parameter * refactor: more condition for inProgressOnly * refactor: update condition * feat: add line quotation attachment endpoint * feat: include product in request work line endpoint * refactor: pending only now cover more condition * feat: include invoice with payment relation * chore: update api docs tag * chore: clean * feat: check for registered user * fix: wrong file location * feat: add email client for sending an otp * chore: move some deps to dev deps * add otpCode otpExpires * add send-otp and verify-otp --------- Co-authored-by: Kanjana <kanjana@chamomind.com> Co-authored-by: chamomind <chamomind@localhost> Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
2025-02-20 16:07:16 +07:00
email: string;
} & ({ legalPersonNo: string } | { citizenId: string });
type VerificationPayload = {
email: string;
otp: string;
} & ({ legalPersonNo: string } | { citizenId: string });
2025-02-20 16:16:51 +07:00
let emailTransport: ReturnType<(typeof nodemailer)["createTransport"]>;
feat: line (#13) * add wedhook line * text message * add router get employee, request, quotation * move code * do not crash application when not set line token This feature is opt-in * dot not crash when not set line client id Main auth method is keycloak * change dotenv * fix: wrong env * refactor: change to get instead of post * refactor: remove body for employee get endpoint * feat: add work relation include * feat: include customer relation in employee * feat: add line file controller * add detail flex message and get date requestWork * chore: update deps lock * fix: error line token * fix: redirect head instead if response with body * feat: add response relation * fix: route casing * add userId in customerBranch verifyOTP * delete consile log * add is registered endpoint placeholder * feat: quotation list * fix: wrong endpoint name * feat: include relation in get by id request data * add where userId line * refactor: adjust parameter for liff app * delete code * refactor: remove post quotation endpoint * refactor: add where userId line for quotation * feat: add pending only parameter * refactor: more condition for inProgressOnly * refactor: update condition * feat: add line quotation attachment endpoint * feat: include product in request work line endpoint * refactor: pending only now cover more condition * feat: include invoice with payment relation * chore: update api docs tag * chore: clean * feat: check for registered user * fix: wrong file location * feat: add email client for sending an otp * chore: move some deps to dev deps * add otpCode otpExpires * add send-otp and verify-otp --------- Co-authored-by: Kanjana <kanjana@chamomind.com> Co-authored-by: chamomind <chamomind@localhost> Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
2025-02-20 16:07:16 +07:00
@Route("/api/v1/verification")
@Tags("Verification")
export class verificationController extends Controller {
@Get()
@Security("line")
async isRegistered(@Request() req: RequestWithLineUser) {
return !!(await prisma.customerBranch.findFirst({ where: { userId: req.user.sub } }));
}
@Post("/send-otp")
2025-02-20 16:16:51 +07:00
public async sendOTP(@Body() body: SendEmail) {
if (
![
process.env.SMTP_HOST,
process.env.SMTP_PORT,
process.env.SMTP_USER,
process.env.SMTP_PASS,
].every(Boolean)
) {
throw new HttpError(
HttpStatus.PRECONDITION_FAILED,
"SMTP not configured",
"smtpNotConfigured",
);
}
if (!emailTransport) {
emailTransport = nodemailer.createTransport({
host: process.env.SMTP_HOST!,
port: +process.env.SMTP_PORT!,
secure: false, // true for port 465, false for other ports
auth: {
user: process.env.SMTP_USER!,
pass: process.env.SMTP_PASS!,
},
});
}
feat: line (#13) * add wedhook line * text message * add router get employee, request, quotation * move code * do not crash application when not set line token This feature is opt-in * dot not crash when not set line client id Main auth method is keycloak * change dotenv * fix: wrong env * refactor: change to get instead of post * refactor: remove body for employee get endpoint * feat: add work relation include * feat: include customer relation in employee * feat: add line file controller * add detail flex message and get date requestWork * chore: update deps lock * fix: error line token * fix: redirect head instead if response with body * feat: add response relation * fix: route casing * add userId in customerBranch verifyOTP * delete consile log * add is registered endpoint placeholder * feat: quotation list * fix: wrong endpoint name * feat: include relation in get by id request data * add where userId line * refactor: adjust parameter for liff app * delete code * refactor: remove post quotation endpoint * refactor: add where userId line for quotation * feat: add pending only parameter * refactor: more condition for inProgressOnly * refactor: update condition * feat: add line quotation attachment endpoint * feat: include product in request work line endpoint * refactor: pending only now cover more condition * feat: include invoice with payment relation * chore: update api docs tag * chore: clean * feat: check for registered user * fix: wrong file location * feat: add email client for sending an otp * chore: move some deps to dev deps * add otpCode otpExpires * add send-otp and verify-otp --------- Co-authored-by: Kanjana <kanjana@chamomind.com> Co-authored-by: chamomind <chamomind@localhost> Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
2025-02-20 16:07:16 +07:00
const generateOTP = Math.floor(100000 + Math.random() * 900000).toString();
const expiresTime = new Date(Date.now() + 5 * 60 * 1000);
const dataCustomerBranch = await prisma.customerBranch.findFirst({
where: {
email: body.email,
...("citizenId" in body
? {
citizenId: body.citizenId,
customer: {
customerType: "PERS",
},
}
: {
legalPersonNo: body.legalPersonNo,
customer: {
customerType: "CORP",
},
}),
},
});
if (!dataCustomerBranch) throw notFoundError("Customer Branch");
2025-02-20 16:16:51 +07:00
await emailTransport.sendMail({
feat: line (#13) * add wedhook line * text message * add router get employee, request, quotation * move code * do not crash application when not set line token This feature is opt-in * dot not crash when not set line client id Main auth method is keycloak * change dotenv * fix: wrong env * refactor: change to get instead of post * refactor: remove body for employee get endpoint * feat: add work relation include * feat: include customer relation in employee * feat: add line file controller * add detail flex message and get date requestWork * chore: update deps lock * fix: error line token * fix: redirect head instead if response with body * feat: add response relation * fix: route casing * add userId in customerBranch verifyOTP * delete consile log * add is registered endpoint placeholder * feat: quotation list * fix: wrong endpoint name * feat: include relation in get by id request data * add where userId line * refactor: adjust parameter for liff app * delete code * refactor: remove post quotation endpoint * refactor: add where userId line for quotation * feat: add pending only parameter * refactor: more condition for inProgressOnly * refactor: update condition * feat: add line quotation attachment endpoint * feat: include product in request work line endpoint * refactor: pending only now cover more condition * feat: include invoice with payment relation * chore: update api docs tag * chore: clean * feat: check for registered user * fix: wrong file location * feat: add email client for sending an otp * chore: move some deps to dev deps * add otpCode otpExpires * add send-otp and verify-otp --------- Co-authored-by: Kanjana <kanjana@chamomind.com> Co-authored-by: chamomind <chamomind@localhost> Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
2025-02-20 16:07:16 +07:00
from: process.env.SMTP_USER,
to: body.email,
subject: "Your OTP Code",
text: `Your OTP Code ${generateOTP}`,
html: `<p>Your OTP code is: <strong>${generateOTP}</strong></p>`,
});
await prisma.customerBranch.update({
where: {
id: dataCustomerBranch.id,
},
data: {
otpCode: generateOTP,
otpExpires: expiresTime,
},
});
return { message: "OTP sent successfully" };
}
@Post("/verify-otp")
@Security("line")
public async verifyOTP(@Request() req: RequestWithLineUser, @Body() body: VerificationPayload) {
const customerBranch = await prisma.customerBranch.findFirst({
where: {
email: body.email,
...("citizenId" in body
? {
citizenId: body.citizenId,
customer: {
customerType: "PERS",
},
}
: {
legalPersonNo: body.legalPersonNo,
customer: {
customerType: "CORP",
},
}),
},
});
if (!customerBranch) throw notFoundError("Customer Branch");
if (
customerBranch.otpCode &&
customerBranch.otpCode === body.otp &&
customerBranch.otpExpires &&
customerBranch.otpExpires >= new Date()
) {
const dataCustomer = await prisma.customerBranch.update({
where: {
id: customerBranch.id,
},
data: {
userId: req.user.sub,
},
});
return dataCustomer;
} else {
return "OTP ไม่ถูกต้อง";
}
}
}