diff --git a/src/pages/api/create-account.js b/src/pages/api/create-account.js deleted file mode 100644 index 498f5d8..0000000 --- a/src/pages/api/create-account.js +++ /dev/null @@ -1,118 +0,0 @@ -import { NextResponse } from "next/server"; - -import Stripe from 'stripe'; -const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); - -import db from '@/db'; -import { withRateLimiter } from '@/lib/rateLimiter'; - -import { scrypt, randomBytes, timingSafeEqual, randomUUID } from 'crypto'; -import { promisify } from 'util'; - -import { setCookie } from 'cookies-next'; -import { v4 as uuidv4 } from 'uuid'; - -// Promisify scrypt for better async/await usage -const scryptPromise = promisify(scrypt); - -// Generate a random salt with a default length of 16 bytes -function genSalt(bytes = 16) { - return randomBytes(bytes).toString('hex'); -}; - -// Hash the password with the provided salt and rounds (default 64 rounds) -async function hash(salt, password, rounds = 64) { - const derivedKey = await scryptPromise(password, salt, rounds); - return derivedKey.toString('hex'); -} - -// Verify the password against the stored hash and salt -async function verify(password, hash, salt, rounds = 64) { - const keyBuffer = Buffer.from(hash, 'hex'); - const derivedKey = await scryptPromise(password, salt, rounds); - return timingSafeEqual(keyBuffer, derivedKey); -} - -// Generate a URL for redirecting with a custom error message -function makeMsg(csi, email, text) { - return `/reactors/create-account?csi=${csi}&msg=${encodeURIComponent(text)}&email=${encodeURIComponent(email)}`; -} - -// Create a new user in the database -const createUser = async (email, salt, hashRes) => { - await db.run('insert into users (email, salt, password_hash) values (?, ?, ?);', email, salt, hashRes); - const { id: userId } = await db.get('select id from users where email=?', email); - return userId; -}; - -// Create a new subscription for the user -const createSubscription = async (userId, type) => { - await db.run('insert into subscriptions (uuid, user_id, type) values (?, ?, ?);', randomUUID(), userId, type); -}; - -async function handler(req, res) { - if (req.method === 'POST') { - const { email, password, passwordagain, csi, patreon_magic_key } = req.body; - - // Validate email, password, and csi - if (email && password && password === passwordagain && (csi || patreon_magic_key)) { - // Check for minimum password length - if (password.length < 12) { - return res.redirect(303, makeMsg(csi, email, 'Please enter a password that is at least 12 characters long.')); - } - - // Retrieve Stripe session and email or get verify patreon magic key - const session = (csi && await stripe.checkout.sessions.retrieve(csi)) || - (patreon_magic_key === process.env.PATREON_MAGIC_KEY ? { customer_details: { email } } : false); - const emailFromSession = session && session.customer_details.email; - const sessionType = session && session?.metadata?.type; - - // Validate session and email - if (!session || !emailFromSession || email !== emailFromSession) { - console.error('Unexpected error occurred'); - if (!session) { console.error('unable to get session'); } - if (!emailFromSession) { console.error('unable to get email from session'); } - if (!email === emailFromSession) { console.error('session email does not match form email'); } - return res.redirect(303, '/reactors/create-account?unexpected_error=true'); - } - - // Check if user already exists - const existingUser = await db.get('select id from users where email=?', email); - if (existingUser) { - console.error('User already exists'); - return res.redirect(303, '/reactors/create-account?unexpected_error=true'); - } - - // Create new user and subscription - const salt = genSalt(); - const hashRes = await hash(salt, password); - const userId = await createUser(email, salt, hashRes); - await createSubscription(userId, sessionType); - console.log('User created successfully'); - const sessionId = uuidv4(); - const maxAge = 60 * 60 * 24 * 365; - const today = new Date(); - const expiresDate = new Date(today.getTime() + (1000 * maxAge)); - await db.run('insert into sessions (user_id, session_id, expires) values (?, ?, ?);', userId, sessionId, expiresDate.toISOString()); - setCookie('session', sessionId, { req, res, maxAge, httpOnly: true, sameSite: true, secure: process.env.NODE_ENV === 'production' }); - return res.redirect(303, '/reactors/account'); - } else { - // Handle missing or invalid form data - if (!email || !csi) { - console.error('Missing email or csi'); - return res.redirect(303, '/reactors/create-account?unexpected_error=true'); - } - if (!password) { - return res.redirect(303, makeMsg(csi, email, 'Please enter a password')); - } - if (password !== passwordagain) { - return res.redirect(303, makeMsg(csi, email, 'Passwords did not match. Please try again.')) - } - } - } else { - // Handle any other HTTP method - res.status(405).json({ error: 'Method not allowed. Only POST method is supported.' }); - } -} - -export default withRateLimiter(handler, true); diff --git a/src/pages/api/sign-in.js b/src/pages/api/sign-in.js index fa037e7..dedb642 100644 --- a/src/pages/api/sign-in.js +++ b/src/pages/api/sign-in.js @@ -1,6 +1,3 @@ -import Stripe from 'stripe'; -const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); - import { setCookie } from 'cookies-next'; import { v4 as uuidv4 } from 'uuid';