tlv84yb7n: Build the sign-in screen and signed-in placeholder shell
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
// Browser-side calls to this app's own /api/session. No token, password or
|
||||
// session id is stored or logged here; the session lives in an httpOnly cookie.
|
||||
|
||||
export type Person = { name: string; email: string; pictureUrl: string | null };
|
||||
|
||||
export const WRONG_CREDENTIALS = "Email or password is incorrect.";
|
||||
export const GENERIC_FAILURE = "Could not sign you in. Try again.";
|
||||
|
||||
type Fetch = typeof fetch;
|
||||
|
||||
function toPerson(body: unknown): Person | null {
|
||||
if (!body || typeof body !== "object") return null;
|
||||
const r = body as Record<string, unknown>;
|
||||
if (typeof r.email !== "string") return null;
|
||||
return {
|
||||
name: typeof r.name === "string" ? r.name : "",
|
||||
email: r.email,
|
||||
pictureUrl: typeof r.pictureUrl === "string" ? r.pictureUrl : null,
|
||||
};
|
||||
}
|
||||
|
||||
/** GET /api/session: the person, or null when signed out or unreachable. */
|
||||
export async function loadSession(f: Fetch = fetch): Promise<Person | null> {
|
||||
try {
|
||||
const res = await f("/api/session", { credentials: "same-origin", cache: "no-store" });
|
||||
if (!res.ok) return null;
|
||||
return toPerson(await res.json());
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export type SignInResult = { ok: true; person: Person } | { ok: false; message: string };
|
||||
|
||||
/** POST /api/session. A 401 is always the one wrong-credentials message. */
|
||||
export async function signIn(email: string, password: string, f: Fetch = fetch): Promise<SignInResult> {
|
||||
try {
|
||||
const res = await f("/api/session", {
|
||||
method: "POST",
|
||||
credentials: "same-origin",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
if (res.status === 401) return { ok: false, message: WRONG_CREDENTIALS };
|
||||
if (!res.ok) return { ok: false, message: GENERIC_FAILURE };
|
||||
const person = toPerson(await res.json());
|
||||
return person ? { ok: true, person } : { ok: false, message: GENERIC_FAILURE };
|
||||
} catch {
|
||||
return { ok: false, message: GENERIC_FAILURE };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user