143 lines
3.5 KiB
TypeScript
143 lines
3.5 KiB
TypeScript
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;
|
|
}
|
|
}
|
|
);
|
|
}
|