peas/packages/web/src/routes/api/signup.ts

136 lines
3.5 KiB
TypeScript

import { Hono } from "hono";
import pool from "../../lib/database.js";
import type { RowDataPacket } from "mysql2";
import { getKeys as TurnstileKeys, isEnabled as Turnstile } from "../../lib/turnstile.js";
import { getConnInfo } from "@hono/node-server/conninfo";
import { hash as generatePasswordHash } from "bcrypt";
import { v4 as uuid } from "uuid";
import MailVerifySend from "../../lib/mailverify.js";
const SignUpAPI = new Hono();
SignUpAPI.post("/", async (c) => {
const body = await c.req.json();
if (
body.username === undefined ||
body.email === undefined ||
body.password === undefined
) {
return c.json({
success: false,
error: "input_lack",
}, 400);
}
if (
body.username.length < 3 ||
body.username.length > 15 ||
body.password.length < 8 ||
body.password.length > 15
) {
return c.json({
success: false,
error: "length_different",
}, 400);
}
if (
await Turnstile() &&
body.turnstile === undefined
) {
return c.json({
success: false,
error: "input_lack",
}, 400);
}
if (await Turnstile()) {
const sendData = new FormData();
const ip = getConnInfo(c).remote.address;
if (ip !== undefined) {
sendData.append("remoteip", ip);
}
sendData.append("secret", (await TurnstileKeys())[1]);
sendData.append("response", body.turnstile);
sendData.append("idempotency_key", uuid())
try {
const req = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
method: "POST",
cache: "no-store",
body: sendData,
});
if (!req.ok) {
return c.json({
success: false,
error: "turnstile_request_failed",
}, 500);
}
const res = await req.json();
if (res.success === false) {
return c.json({
success: false,
error: "turnstile_failed",
}, 400);
}
} catch (err) {
return c.json({
success: false,
error: "turnstile_request_failed",
}, 500);
}
}
const [duplicateUsers] = await pool.execute<RowDataPacket[]>(
"SELECT * FROM users WHERE id = ?",
[body.username],
);
const [duplicateEmails] = await pool.execute<RowDataPacket[]>(
"SELECT * FROM users WHERE email = ?",
[body.email],
);
if (duplicateUsers.length > 0) {
return c.json({
success: false,
error: "username_duplicate",
}, 400);
}
if (duplicateEmails.length > 0) {
return c.json({
success: false,
error: "email_duplicate",
}, 400);
}
const passwordHash = await generatePasswordHash(body.password, 10);
const [result] = await pool.execute<RowDataPacket[]>(
"INSERT INTO `users` (`id`, `password`, `email`, `mailverified`, `time`) VALUES (?, ?, ?, '0', current_timestamp(3))",
[body.username, passwordHash, body.email],
);
if ((result as RowDataPacket).affectedRows === 1) {
const send = await MailVerifySend(body.username, body.email, c.get("language"));
if (send === true) {
return c.json({
success: true,
}, 201);
} else {
return c.json({
success: false,
error: send,
}, 500);
}
} else {
return c.json({
success: false,
error: "account_create_failed",
}, 500);
}
});
export default SignUpAPI;