import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; import { getUserByEmail, getUserByToken, resetUser, } from "../user/user.service"; import { createSession, deleteSession } from "./auth.service"; import { hash, verify } from "argon2"; import { validatePassword } from "../utils/password"; export async function authRoutes(fastify: FastifyInstance) { fastify.post( "/register", { schema: { body: { type: "object", required: ["password", "token"], properties: { password: { type: "string" }, token: { type: "string" }, }, }, }, }, async (req: FastifyRequest, res: FastifyReply) => { const { password, token } = req.body as { password: string; token: string; }; try { const userInDB = await getUserByToken(token); if (!userInDB) return res.code(404).send({ error: "not found" }); if (new Date() > userInDB.token.expiry) return res.code(400).send({ error: "link expired" }); if (!validatePassword(password)) return res.code(400).send({ error: "weak password. Make sure the password has atleast 2 uppercase, 2 lowercase, 2 numeric and 2 special characters", }); const hashedPassword = await hash(password); userInDB.passwordHash = hashedPassword; await userInDB.save(); } catch (err) { return err; } } ); fastify.post( "/login", { schema: { body: { type: "object", required: ["email", "password"], properties: { email: { type: "string" }, password: { type: "string" }, }, }, }, }, async (req: FastifyRequest, res: FastifyReply) => { const { email, password } = req.body as { email: string; password: string; }; try { const userInDB = await getUserByEmail(email); if (!userInDB) return res.code(401).send({ error: "invalid email or password" }); if (!userInDB.passwordHash) return res.code(401).send({ error: "invalid email or password" }); const match = await verify(userInDB.passwordHash, password); if (!match) return res.code(401).send({ error: "invalid email or password" }); const newSession = await createSession( userInDB.id, req.ip, req.headers["user-agent"] ); userInDB.lastLogin = new Date(); await userInDB.save(); res.send({ session_token: newSession.sid }); } catch (err) { return err; } } ); fastify.delete( "/logout", {}, async (req: FastifyRequest, res: FastifyReply) => { if (!req.headers.authorization) return res.code(200).send(); const auth = req.headers.authorization.split(" ")[1]; await deleteSession(auth); return res.code(200).send(); } ); fastify.post( "/reset", { schema: { body: { type: "object", properties: { email: { type: "string" }, }, }, }, }, async (req: FastifyRequest, res: FastifyReply) => { const { email } = req.body as { email: string }; try { const userInDB = await getUserByEmail(email); if (userInDB) { await resetUser(userInDB.pid); } return res.code(200).send(); } catch (err) { return err; } } ); }