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.
95 lines • 3.54 kB
JavaScript
import { VerificationType } from "@prisma/client";
import { ErrorCodes, } from "../types";
import { limitIpAttempts } from "../utils";
import { completeEmailChangeSchema } from "../validations";
import { useVerificationToken } from "./useVerificationToken";
export async function completeEmailChange(context, input) {
var _a;
const { prisma, config, limiters, parsedRequest } = context;
const { ipAddress } = parsedRequest !== null && parsedRequest !== void 0 ? parsedRequest : {};
try {
const validatedInput = completeEmailChangeSchema.safeParse(input);
if (!validatedInput.success) {
config.logger.securityEvent("INVALID_INPUT", {
route: "completeEmailChange",
ipAddress,
});
return {
success: false,
status: 400,
message: "Invalid input provided",
code: ErrorCodes.INVALID_INPUT,
};
}
const { token } = validatedInput.data;
if (config.rateLimiting.completeEmailChange.enabled && ipAddress) {
const limiter = limiters.completeEmailChange;
const limit = await limitIpAttempts({ ipAddress, limiter });
if (!limit.success) {
config.logger.securityEvent("RATE_LIMIT_EXCEEDED", {
route: "completeEmailChange",
ipAddress,
});
return {
success: false,
status: 429,
message: "Too many attempts. Try again later.",
code: ErrorCodes.RATE_LIMIT_EXCEEDED,
};
}
}
const verification = await useVerificationToken(context, {
token: token,
type: VerificationType.EMAIL_CHANGE,
});
if (!verification.success || !((_a = verification.data) === null || _a === void 0 ? void 0 : _a.verification)) {
config.logger.securityEvent("INVALID_TOKEN", {
route: "completeEmailChange",
ipAddress,
});
return {
success: false,
status: 400,
message: "Invalid token.",
code: ErrorCodes.INVALID_TOKEN,
};
}
const { verification: { userId }, } = verification.data;
const user = (await prisma.user.findUnique({
where: { id: userId },
}));
if (!user || !user.pendingEmail) {
return {
success: false,
status: 400,
message: "No pending email change found.",
code: ErrorCodes.INVALID_INPUT,
};
}
await prisma.user.update({
where: { id: userId },
data: {
email: user.pendingEmail,
pendingEmail: null,
},
});
return {
success: true,
status: 200,
message: "Email change completed successfully.",
};
}
catch (error) {
config.logger.error("Error completing email change", {
error,
ipAddress: parsedRequest === null || parsedRequest === void 0 ? void 0 : parsedRequest.ipAddress,
});
return {
success: false,
status: 500,
message: "An unexpected error occurred.",
code: ErrorCodes.INTERNAL_SERVER_ERROR,
};
}
}
//# sourceMappingURL=completeEmailChange.js.map