gluestick/src/app/api/register/route.ts

134 lines
3 KiB
TypeScript

import * as ldap from "@/ldap";
import prisma from "@/prisma";
import { getUser } from "@/auth";
import { getDiscordAvatar } from "@/app/oauth/discord/oauth";
import { getLogger } from "@/logger";
type RequestBody = {
username: string;
displayName: string;
email: string;
password: string;
avatarBase64: string | null;
};
export async function POST(request: Request) {
const logger = getLogger("/api/register");
const user = await getUser();
if (user == null) return new Response(null, { status: 401 });
if (user.username !== null) {
if (!(await ldap.checkUserExists(user.username))) {
logger.warn(
{ username: user.username },
"user doesn't exist in ldap anymore"
);
user.username = null;
await prisma.user.update({
where: {
id: user.id
},
data: {
username: null
}
});
} else {
logger.info(`user ${user.username} tried to register twice`);
// user already has an account, don't re-register
return new Response(null, { status: 403 });
}
}
const { username, displayName, email, password, avatarBase64 } =
(await request.json()) as RequestBody;
// runtime type verification when :pleading:
if (
username == undefined ||
typeof username !== "string" ||
displayName == undefined ||
typeof displayName !== "string" ||
email == undefined ||
typeof email !== "string" ||
password == undefined ||
typeof password !== "string"
) {
return new Response(
JSON.stringify({
ok: false,
error: "invalidBody"
}),
{ status: 400 }
);
}
if (password.length < 12) {
return new Response(
JSON.stringify({
ok: false,
error: "passwordShort"
}),
{ status: 400 }
);
}
let avatarBuf: Buffer | undefined;
if (avatarBase64 !== null && typeof avatarBase64 === "string") {
avatarBuf = Buffer.from(avatarBase64, "base64");
if (avatarBuf.length > 1_000_000) {
return new Response(
JSON.stringify({
ok: false,
error: "avatarBig"
}),
{ status: 400 }
);
}
}
const discordAuth = await prisma.discordAuth.findFirst({
where: {
userId: user.id
}
});
if (discordAuth !== null && avatarBuf === undefined) {
avatarBuf = await getDiscordAvatar(discordAuth.accessToken);
}
const users = await ldap.getUsers();
for (const user of users) {
if (user.id.toLowerCase() === username.toLowerCase()) {
return new Response(
JSON.stringify({
ok: false,
error: "usernameTaken"
}),
{ status: 400 }
);
}
}
await ldap.createUser(username, displayName, email, avatarBuf);
await ldap.setPassword(username, password);
const outputUser = await prisma.user.update({
where: {
id: user.id
},
data: {
username
}
});
logger.info(outputUser, "registered user");
return new Response(
JSON.stringify({
ok: true
}),
{ status: 201 }
);
}