UNPKG

aegis-auth

Version:

A credentials-based auth solution for Next.js (and other Node projects) with IP rate-limiting, account lockouts, and sessions in DB.

104 lines 4.07 kB
import { VerificationType } from "@prisma/client"; import { sendVerificationEmail } from "../emails"; import { hashPassword } from "../security"; import { ErrorCodes, } from "../types"; import { clientSafeUser, limitIpAttempts, } from "../utils"; import { registerSchema } from "../validations"; import { createVerification } from "./createVerification"; export async function registerUser(context, input) { var _a; const { prisma, config, limiters, parsedRequest } = context; const { ipAddress } = parsedRequest !== null && parsedRequest !== void 0 ? parsedRequest : {}; try { if (config.rateLimiting.register.enabled && ipAddress) { const limiter = limiters.register; const limit = await limitIpAttempts({ ipAddress, limiter }); if (!limit.success) { config.logger.securityEvent("RATE_LIMIT_EXCEEDED", { route: "register", ipAddress, }); return { success: false, status: 429, message: "Too many attempts. Try again later.", code: ErrorCodes.RATE_LIMIT_EXCEEDED, }; } } const credentials = registerSchema.safeParse(input); if (!credentials.success) { config.logger.securityEvent("INVALID_INPUT", Object.assign({ route: "register", ipAddress }, input)); return { success: false, status: 400, message: "Invalid input provided", code: ErrorCodes.INVALID_INPUT, }; } const { username, email, password } = credentials.data; const existingUser = (await prisma.user.findFirst({ where: { OR: [{ username: username }, { email: email }], }, })); if (existingUser) { config.logger.securityEvent("DUPLICATE_USER", Object.assign({ route: "register", ipAddress }, input)); return { success: false, status: 409, message: "User already exists", code: ErrorCodes.DUPLICATE_USER, }; } const hashedPassword = await hashPassword({ password: password, config, }); const user = (await prisma.user.create({ data: { username: username, email: email, password: hashedPassword, isEmailVerified: !config.accountSecurity.requireEmailVerification, }, })); if (config.accountSecurity.requireEmailVerification) { const verification = await createVerification(context, { userId: user.id, type: VerificationType.EMAIL_VERIFICATION, }); if (!verification.success || !((_a = verification.data) === null || _a === void 0 ? void 0 : _a.verification)) { return { success: false, status: 500, message: "Failed to create verification", code: ErrorCodes.INTERNAL_SERVER_ERROR, }; } const { token } = verification.data.verification; await sendVerificationEmail({ toEmail: user.email, token, config }); } config.logger.securityEvent("USER_REGISTERED", { userId: user.id, ipAddress, }); const clientUser = clientSafeUser({ user }); return { success: true, status: 201, message: "User registered", data: { user: clientUser }, }; } catch (err) { config.logger.error("Unexpected error in registerUser", { error: err }); return { success: false, status: 500, message: "Internal Server Error", code: ErrorCodes.INTERNAL_SERVER_ERROR, }; } } //# sourceMappingURL=registerUser.js.map