Add error handling for database failures in signup/login/profile
None of the database calls in these three places were wrapped in try/catch, so any database hiccup (disk issue, lock contention, etc.) surfaced as an unhandled 500 with a useless generic message and no server-side log to explain why. Found this while testing every page's redirects end to end: a broken test setup on my end (an old server process left running against a deleted database file) produced exactly this failure mode, which would look identical to a real intermittent outage to an end user. Now: signup and profile-update return a clear "try again in a moment" message with the real error logged server-side; login logs the real error but still shows the existing generic "incorrect email or password" message to the client (matches current behavior, avoids leaking account existence). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VL5YUEf2B9LG4xdVUQwcSg
This commit is contained in:
3 files changed
+49
-26
No files matched your search
@@ -28,11 +28,19 @@ export async function PATCH(request: Request) {
|
|||||||
return NextResponse.json({ error: message }, { status: 400 });
|
return NextResponse.json({ error: message }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await prisma.user.update({
|
try {
|
||||||
where: { id: session.user.id },
|
const user = await prisma.user.update({
|
||||||
data: parsed.data,
|
where: { id: session.user.id },
|
||||||
select: { id: true, name: true, email: true, age: true, bio: true },
|
data: parsed.data,
|
||||||
});
|
select: { id: true, name: true, email: true, age: true, bio: true },
|
||||||
|
});
|
||||||
|
|
||||||
return NextResponse.json({ user });
|
return NextResponse.json({ user });
|
||||||
|
} catch (err) {
|
||||||
|
console.error("profile update failed:", err);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "We couldn't save your changes right now. Please try again in a moment." },
|
||||||
|
{ status: 503 },
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+20
-12
@@ -26,17 +26,25 @@ export async function POST(request: Request) {
|
|||||||
|
|
||||||
const { name, email, password, age } = parsed.data;
|
const { name, email, password, age } = parsed.data;
|
||||||
|
|
||||||
const existing = await prisma.user.findUnique({ where: { email } });
|
try {
|
||||||
if (existing) {
|
const existing = await prisma.user.findUnique({ where: { email } });
|
||||||
return NextResponse.json({ error: "An account with that email already exists" }, { status: 409 });
|
if (existing) {
|
||||||
|
return NextResponse.json({ error: "An account with that email already exists" }, { status: 409 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const passwordHash = await bcrypt.hash(password, 12);
|
||||||
|
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: { name, email, age, passwordHash },
|
||||||
|
select: { id: true, email: true, name: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json({ user }, { status: 201 });
|
||||||
|
} catch (err) {
|
||||||
|
console.error("signup failed:", err);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "We couldn't create your account right now. Please try again in a moment." },
|
||||||
|
{ status: 503 },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const passwordHash = await bcrypt.hash(password, 12);
|
|
||||||
|
|
||||||
const user = await prisma.user.create({
|
|
||||||
data: { name, email, age, passwordHash },
|
|
||||||
select: { id: true, email: true, name: true },
|
|
||||||
});
|
|
||||||
|
|
||||||
return NextResponse.json({ user }, { status: 201 });
|
|
||||||
}
|
}
|
||||||
+15
-8
@@ -18,17 +18,24 @@ export const authOptions: AuthOptions = {
|
|||||||
async authorize(credentials) {
|
async authorize(credentials) {
|
||||||
if (!credentials?.email || !credentials?.password) return null;
|
if (!credentials?.email || !credentials?.password) return null;
|
||||||
|
|
||||||
await ensureDb();
|
try {
|
||||||
|
await ensureDb();
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
where: { email: credentials.email.toLowerCase() },
|
where: { email: credentials.email.toLowerCase() },
|
||||||
});
|
});
|
||||||
if (!user) return null;
|
if (!user) return null;
|
||||||
|
|
||||||
const valid = await bcrypt.compare(credentials.password, user.passwordHash);
|
const valid = await bcrypt.compare(credentials.password, user.passwordHash);
|
||||||
if (!valid) return null;
|
if (!valid) return null;
|
||||||
|
|
||||||
return { id: user.id, email: user.email, name: user.name };
|
return { id: user.id, email: user.email, name: user.name };
|
||||||
|
} catch (err) {
|
||||||
|
// Logged so a database hiccup is visible server-side, even though
|
||||||
|
// the client only ever sees a generic "incorrect email or password".
|
||||||
|
console.error("login authorize() failed:", err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in new issue
Block a user