Files
plunk/packages/api/src/controllers/Auth.ts
T

110 lines
3.0 KiB
TypeScript

import { Controller, Get, Post } from "@overnightjs/core";
import { UserSchemas, UtilitySchemas } from "@plunk/shared";
import type { Request, Response } from "express";
import { prisma } from "../database/prisma";
import { NotAllowed, NotFound } from "../exceptions";
import { jwt } from "../middleware/auth";
import { AuthService } from "../services/AuthService";
import { UserService } from "../services/UserService";
import { Keys } from "../services/keys";
import { REDIS_ONE_MINUTE, redis } from "../services/redis";
import { createHash } from "../util/hash";
@Controller("auth")
export class Auth {
@Post("login")
public async login(req: Request, res: Response) {
const { email, password } = UserSchemas.credentials.parse(req.body);
const user = await UserService.email(email);
if (!user) {
return res.json({ success: false, data: "Incorrect email or password" });
}
if (!user.password) {
return res.json({
success: "redirect",
redirect: `/auth/reset?id=${user.id}`,
});
}
const verified = await AuthService.verifyCredentials(email, password);
if (!verified) {
return res.json({ success: false, data: "Incorrect email or password" });
}
await redis.set(Keys.User.id(user.id), JSON.stringify(user), "EX", REDIS_ONE_MINUTE * 60);
const token = jwt.sign(user.id);
const cookie = UserService.cookieOptions();
return res
.cookie(UserService.COOKIE_NAME, token, cookie)
.json({ success: true, data: { id: user.id, email: user.email } });
}
@Post("signup")
public async signup(req: Request, res: Response) {
const { email, password } = UserSchemas.credentials.parse(req.body);
const user = await UserService.email(email);
if (user) {
return res.json({
success: false,
data: "That email is already associated with another user",
});
}
const created_user = await prisma.user.create({
data: {
email,
password: await createHash(password),
},
});
await redis.set(Keys.User.id(created_user.id), JSON.stringify(created_user), "EX", REDIS_ONE_MINUTE * 60);
const token = jwt.sign(created_user.id);
const cookie = UserService.cookieOptions();
return res.cookie(UserService.COOKIE_NAME, token, cookie).json({
success: true,
data: { id: created_user.id, email: created_user.email },
});
}
@Post("reset")
public async reset(req: Request, res: Response) {
const { id, password } = UtilitySchemas.id.merge(UserSchemas.credentials.pick({ password: true })).parse(req.body);
const user = await UserService.id(id);
if (!user) {
throw new NotFound("user");
}
if (user.password) {
throw new NotAllowed();
}
await prisma.user.update({
where: { id },
data: { password: await createHash(password) },
});
await redis.del(Keys.User.id(user.id));
await redis.del(Keys.User.email(user.email));
return res.json({ success: true });
}
@Get("logout")
public logout(req: Request, res: Response) {
res.cookie(UserService.COOKIE_NAME, "", UserService.cookieOptions(new Date()));
return res.json(true);
}
}