fix: final review pass — email collision, orphaned-run loop, null confidence guards
- changeEmail validates and refuses an address another account owns (users.email is UNIQUE; a collision was a 500 inside the settings form). - /app/[id] no longer redirects a 'running' row to itself; it renders what exists and says the run was interrupted. - ScoreBar / OptionRow / VerdictBlock survive null numbers from the model instead of throwing and losing the block (seen live: '[openui] runtime/render-error: Component ScoreBar render failed'). - drop the ad-hoc render-debug scripts now that Playwright covers the browser. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
07dd3d6bf8
commit
5160a00db5
+6
-4
@@ -2,7 +2,7 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { userByEmail, getSettings, renameAnalysis, deleteAnalysis, db } from "@/lib/db";
|
||||
import { signUpNewUser, verifyPassword, startSession, endSession, requireUser, emailOk, hashPassword } from "@/lib/auth";
|
||||
import { signUpNewUser, verifyPassword, startSession, endSession, requireUser, changeEmail, emailOk, hashPassword } from "@/lib/auth";
|
||||
import { saveSettingsForm } from "@/lib/settings";
|
||||
|
||||
export async function signUp(_: unknown, fd: FormData) {
|
||||
@@ -36,16 +36,18 @@ export async function remove(_: unknown, fd: FormData) {
|
||||
|
||||
export async function saveSettingsAction(_: unknown, fd: FormData) {
|
||||
const u = await requireUser();
|
||||
const email = String(fd.get("email") ?? "").trim().toLowerCase();
|
||||
const email = String(fd.get("email") ?? "").trim();
|
||||
const password = String(fd.get("password") ?? "");
|
||||
if (email && !emailOk(email)) return { ok: false, error: "Enter a valid email address." };
|
||||
if (password && password.length < 10) return { ok: false, error: "Use at least 10 characters." };
|
||||
saveSettingsForm(u.id, fd);
|
||||
// The wizard sends `after`: a configured user must land on the readiness screen, and the setup page
|
||||
// forwards configured users away from steps 1-2, so "Saved." would never be seen there.
|
||||
if (String(fd.get("after") ?? "").startsWith("/setup")) redirect("/setup?step=3");
|
||||
if (password) db.prepare("UPDATE users SET pass = ? WHERE id = ?").run(hashPassword(password), u.id);
|
||||
if (email) db.prepare("UPDATE users SET email = ? WHERE id = ?").run(email, u.id);
|
||||
if (email) {
|
||||
const r = changeEmail(u.id, email);
|
||||
if (!r.ok) return r;
|
||||
}
|
||||
revalidatePath("/settings");
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user