fix: replace member.save() with findByIdAndUpdate in login.post.js

This commit is contained in:
Jennie Robinson Faber 2026-04-04 13:22:36 +01:00
parent a7b04bfd3c
commit e592b962ec

View file

@ -1,5 +1,6 @@
// server/api/auth/login.post.js // server/api/auth/login.post.js
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import { randomUUID } from "crypto";
import { Resend } from "resend"; import { Resend } from "resend";
import Member from "../../models/member.js"; import Member from "../../models/member.js";
import { connectDB } from "../../utils/mongoose.js"; import { connectDB } from "../../utils/mongoose.js";
@ -11,6 +12,14 @@ const resend = new Resend(process.env.RESEND_API_KEY);
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
await connectDB(); await connectDB();
const baseUrl = process.env.BASE_URL;
if (!baseUrl) {
throw createError({
statusCode: 500,
statusMessage: "BASE_URL environment variable is not set",
});
}
const { email } = await validateBody(event, emailSchema); const { email } = await validateBody(event, emailSchema);
const GENERIC_MESSAGE = "If this email is registered, we've sent a login link."; const GENERIC_MESSAGE = "If this email is registered, we've sent a login link.";
@ -25,16 +34,23 @@ export default defineEventHandler(async (event) => {
} }
const config = useRuntimeConfig(event); const config = useRuntimeConfig(event);
const jti = randomUUID();
const token = jwt.sign( const token = jwt.sign(
{ memberId: member._id }, { memberId: member._id, jti },
config.jwtSecret, config.jwtSecret,
{ expiresIn: "15m" }, { expiresIn: "15m" },
); );
const headers = getHeaders(event); // Store jti so we can burn it on first use
const baseUrl = await Member.findByIdAndUpdate(
process.env.BASE_URL || member._id,
`${headers.host?.includes("localhost") ? "http" : "https"}://${headers.host}`; { $set: { magicLinkJti: jti, magicLinkJtiUsed: false } },
{ runValidators: false }
);
// Token goes in the fragment — never sent to server, never logged
const magicLink = `${baseUrl}/verify#${token}`;
try { try {
await resend.emails.send({ await resend.emails.send({
@ -44,7 +60,7 @@ export default defineEventHandler(async (event) => {
text: `Hi, text: `Hi,
Sign in to Ghost Guild: Sign in to Ghost Guild:
${baseUrl}/api/auth/verify?token=${token} ${magicLink}
This link expires in 15 minutes. If you didn't request it, ignore this email.`, This link expires in 15 minutes. If you didn't request it, ignore this email.`,
}); });