login for RN app
This commit is contained in:
@@ -1,7 +1,38 @@
|
||||
// Single source of truth for all backend communication.
|
||||
|
||||
/** WebView consoles stringify objects as [object Object]; log JSON text. */
|
||||
function logApi(tag, details) {
|
||||
let text;
|
||||
try {
|
||||
text = JSON.stringify(details, null, 2);
|
||||
} catch {
|
||||
text = String(details);
|
||||
}
|
||||
console.log(`[api] ${tag} ${text}`);
|
||||
}
|
||||
|
||||
function readableHeaders(headers) {
|
||||
const out = {};
|
||||
headers.forEach((value, key) => {
|
||||
out[key] = value;
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
async function http(path, { method = 'GET', body } = {}) {
|
||||
const headers = { 'Content-Type': 'application/json' };
|
||||
const url = new URL(path, window.location.origin).href;
|
||||
|
||||
logApi('request', {
|
||||
method,
|
||||
path,
|
||||
url,
|
||||
origin: window.location.origin,
|
||||
credentials: 'include',
|
||||
// HttpOnly cookies are invisible here; this only shows JS-readable cookies.
|
||||
documentCookie: document.cookie || '(empty)',
|
||||
hasBody: Boolean(body),
|
||||
});
|
||||
|
||||
const res = await fetch(path, {
|
||||
method,
|
||||
@@ -10,6 +41,18 @@ async function http(path, { method = 'GET', body } = {}) {
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
|
||||
const responseHeaders = readableHeaders(res.headers);
|
||||
// Browsers hide Set-Cookie from JS; if it's missing here that proves nothing.
|
||||
logApi('response', {
|
||||
method,
|
||||
path,
|
||||
status: res.status,
|
||||
statusText: res.statusText,
|
||||
ok: res.ok,
|
||||
responseHeaders,
|
||||
documentCookieAfter: document.cookie || '(empty)',
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
let message = res.statusText;
|
||||
let data;
|
||||
@@ -19,13 +62,21 @@ async function http(path, { method = 'GET', body } = {}) {
|
||||
} catch {
|
||||
message = (await res.text().catch(() => message)) || message;
|
||||
}
|
||||
logApi('error-body', { method, path, status: res.status, message, data });
|
||||
const err = new Error(message || `Request failed (${res.status})`);
|
||||
err.status = res.status;
|
||||
err.data = data;
|
||||
throw err;
|
||||
}
|
||||
if (res.status === 204) return null;
|
||||
return res.json();
|
||||
const json = await res.json();
|
||||
logApi('ok-body', {
|
||||
method,
|
||||
path,
|
||||
keys: json && typeof json === 'object' ? Object.keys(json) : typeof json,
|
||||
hasUser: Boolean(json?.user),
|
||||
});
|
||||
return json;
|
||||
}
|
||||
|
||||
export const article = {
|
||||
@@ -65,11 +116,24 @@ export const auth = {
|
||||
},
|
||||
|
||||
async loginWithGoogle(idToken) {
|
||||
logApi('loginWithGoogle', {
|
||||
idTokenLength: idToken?.length ?? 0,
|
||||
idTokenPrefix: idToken ? `${idToken.slice(0, 12)}…` : null,
|
||||
});
|
||||
const data = await http('/api/auth/login', {
|
||||
method: 'POST',
|
||||
body: { idToken },
|
||||
});
|
||||
return { user: data.user };
|
||||
// Confirm whether the session cookie actually works (not just login JSON).
|
||||
const session = await auth.me();
|
||||
logApi('session-after-login', {
|
||||
loginUser: data.user?.email ?? data.user?.sub ?? data.user ?? null,
|
||||
meUser: session.user?.email ?? session.user?.sub ?? session.user ?? null,
|
||||
meForbidden: session.forbidden ?? false,
|
||||
meMessage: session.message ?? null,
|
||||
sessionOk: Boolean(session.user),
|
||||
});
|
||||
return { user: data.user, session };
|
||||
},
|
||||
|
||||
async logout() {
|
||||
|
||||
Reference in New Issue
Block a user