import { Context } from 'elysia' import { getClientIp, getDatabaseConnection, jsonResponse } from '../../../../lib/util' import isEmail from 'validator/lib/isEmail' import { berryDashUserData, users } from '../../../../lib/tables' import { eq, or } from 'drizzle-orm' import bcrypt from 'bcryptjs' import { randomBytes } from 'crypto' type Body = { username: string password: string email: string } export async function handler (context: Context) { const dbInfo0 = getDatabaseConnection(0) const dbInfo1 = getDatabaseConnection(1) if (!dbInfo0 || !dbInfo1) return jsonResponse( { success: false, message: 'Failed to connect to database', data: null }, 500 ) const { connection: connection0, db: db0 } = dbInfo0 const { connection: connection1, db: db1 } = dbInfo1 const body = context.body as Body if (!body.username || !body.password || !body.email) { connection0.end() connection1.end() return jsonResponse( { success: false, message: 'Username, password and email must be in POST data', data: null }, 400 ) } if (!/^[a-zA-Z0-9]{3,16}$/.test(body.username)) { connection0.end() connection1.end() return jsonResponse( { success: false, message: 'Username must be 3-16 characters, letters and numbers only', data: null }, 400 ) } if (!isEmail(body.email)) { connection0.end() connection1.end() return jsonResponse( { success: false, message: 'Email is invalid', data: null }, 400 ) } if ( !/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d!@#$%^&*()_\-+=]{8,}$/.test(body.password) ) { connection0.end() connection1.end() return jsonResponse( { success: false, message: 'Password must be at least 8 characters with at least one letter and one number', data: null }, 400 ) } const existingCheck = await db0 .select({ id: users.id }) .from(users) .where(or(eq(users.username, body.email), eq(users.email, body.email))) .limit(1) .execute() if (existingCheck[0]) { connection0.end() connection1.end() return jsonResponse( { success: false, message: 'Username or email is already taken', data: null }, 409 ) } const hashedPassword = await bcrypt.hash(body.password, 10) const token = randomBytes(256).toString('hex') const ip = getClientIp(context) const time = Math.floor(Date.now() / 1000) if (!ip) { connection0.end() connection1.end() return jsonResponse( { success: false, message: 'Failed to get required info', data: null }, 400 ) } const result = await db0 .insert(users) .values({ username: body.username, password: hashedPassword, email: body.email, registerTime: time, latestIp: ip }) .execute() await db1 .insert(berryDashUserData) .values({ id: result[0].insertId, token }) .execute() return jsonResponse( { success: true, message: null, data: null }, 200 ) }