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
JavaScript
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