From a481c0ee5ea49e005430e7d75be4f8a4b67cef4a Mon Sep 17 00:00:00 2001 From: diced Date: Fri, 6 Jan 2023 15:04:43 -0800 Subject: [PATCH] fix: #264 --- src/components/Theming.tsx | 2 +- src/pages/api/auth/create.ts | 6 ++-- src/pages/api/auth/register.ts | 66 ++++++++++++++++++++++++++++++++++ src/pages/auth/register.tsx | 2 +- 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 src/pages/api/auth/register.ts diff --git a/src/components/Theming.tsx b/src/components/Theming.tsx index b8757ae..4762d08 100644 --- a/src/components/Theming.tsx +++ b/src/components/Theming.tsx @@ -133,7 +133,7 @@ export default function ZiplineTheming({ Component, pageProps, ...props }) { }} > - + {props.children ? props.children : } diff --git a/src/pages/api/auth/create.ts b/src/pages/api/auth/create.ts index fc92555..4a3c0c5 100644 --- a/src/pages/api/auth/create.ts +++ b/src/pages/api/auth/create.ts @@ -12,10 +12,8 @@ const logger = Logger.get('user'); async function handler(req: NextApiReq, res: NextApiRes) { // handle invites - if (!config.features.user_registration && !req.body.code) - return res.badRequest('user registration is disabled'); - else if (req.body.code) { - if (!config.features.invites && req.body.code) return res.badRequest('invites are disabled'); + if (req.body.code) { + if (!config.features.invites) return res.badRequest('invites are disabled'); const { code, username, password } = req.body as { code?: string; diff --git a/src/pages/api/auth/register.ts b/src/pages/api/auth/register.ts new file mode 100644 index 0000000..18826c1 --- /dev/null +++ b/src/pages/api/auth/register.ts @@ -0,0 +1,66 @@ +import { readFile } from 'fs/promises'; +import config from 'lib/config'; +import Logger from 'lib/logger'; +import { NextApiReq, NextApiRes, withZipline } from 'lib/middleware/withZipline'; +import { guess } from 'lib/mimes'; +import prisma from 'lib/prisma'; +import { createToken, hashPassword } from 'lib/util'; +import { jsonUserReplacer } from 'lib/utils/client'; +import { extname } from 'path'; + +const logger = Logger.get('user'); + +async function handler(req: NextApiReq, res: NextApiRes) { + if (!config.features.user_registration) return res.badRequest('user registration is disabled'); + + const { username, password, administrator } = req.body as { + username: string; + password: string; + administrator: boolean; + }; + + if (!username) return res.badRequest('no username'); + if (!password) return res.badRequest('no password'); + + const existing = await prisma.user.findFirst({ + where: { + username, + }, + }); + if (existing) return res.badRequest('user exists'); + + const hashed = await hashPassword(password); + + let avatar; + if (config.features.default_avatar) { + logger.debug(`using default avatar ${config.features.default_avatar}`); + + const buf = await readFile(config.features.default_avatar); + const mimetype = await guess(extname(config.features.default_avatar)); + logger.debug(`guessed mimetype ${mimetype} for ${config.features.default_avatar}`); + + avatar = `data:${mimetype};base64,${buf.toString('base64')}`; + } + + const newUser = await prisma.user.create({ + data: { + password: hashed, + username, + token: createToken(), + administrator, + avatar, + }, + }); + + logger.debug(`registered user ${JSON.stringify(newUser, jsonUserReplacer)}`); + + delete newUser.password; + + logger.info(`User ${newUser.username} (${newUser.id}) registered`); + + return res.json(newUser); +} + +export default withZipline(handler, { + methods: ['POST'], +}); diff --git a/src/pages/auth/register.tsx b/src/pages/auth/register.tsx index 161006b..f123552 100644 --- a/src/pages/auth/register.tsx +++ b/src/pages/auth/register.tsx @@ -51,7 +51,7 @@ export default function Register({ code, title, user_registration }) { }; const createUser = async () => { - const res = await useFetch('/api/auth/create', 'POST', { + const res = await useFetch(`/api/auth/${user_registration ? 'register' : 'create'}`, 'POST', { code: user_registration ? null : code, username, password,