Make user sync configurable and visible
Add optional apiBase for /api endpoints and surface sync failures so admins know when ncue_user writes are not reaching the backend. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
29
script.js
29
script.js
@@ -446,10 +446,12 @@
|
|||||||
function getAuthConfig() {
|
function getAuthConfig() {
|
||||||
const cfg = globalThis.AUTH_CONFIG && typeof globalThis.AUTH_CONFIG === "object" ? globalThis.AUTH_CONFIG : {};
|
const cfg = globalThis.AUTH_CONFIG && typeof globalThis.AUTH_CONFIG === "object" ? globalThis.AUTH_CONFIG : {};
|
||||||
const allowEndUserConfig = Boolean(cfg.allowEndUserConfig);
|
const allowEndUserConfig = Boolean(cfg.allowEndUserConfig);
|
||||||
|
const apiBase = String(cfg.apiBase || "").trim(); // optional, e.g. https://api.ncue.net
|
||||||
const auth0 = cfg.auth0 && typeof cfg.auth0 === "object" ? cfg.auth0 : {};
|
const auth0 = cfg.auth0 && typeof cfg.auth0 === "object" ? cfg.auth0 : {};
|
||||||
const allowedEmails = Array.isArray(cfg.allowedEmails) ? cfg.allowedEmails : [];
|
const allowedEmails = Array.isArray(cfg.allowedEmails) ? cfg.allowedEmails : [];
|
||||||
const base = {
|
const base = {
|
||||||
allowEndUserConfig,
|
allowEndUserConfig,
|
||||||
|
apiBase,
|
||||||
auth0: {
|
auth0: {
|
||||||
domain: String(auth0.domain || "").trim(),
|
domain: String(auth0.domain || "").trim(),
|
||||||
clientId: String(auth0.clientId || "").trim(),
|
clientId: String(auth0.clientId || "").trim(),
|
||||||
@@ -466,6 +468,7 @@
|
|||||||
// override가 있으면 우선 적용 (서버 재배포 없이 테스트 가능)
|
// override가 있으면 우선 적용 (서버 재배포 없이 테스트 가능)
|
||||||
return {
|
return {
|
||||||
allowEndUserConfig,
|
allowEndUserConfig,
|
||||||
|
apiBase,
|
||||||
auth0: {
|
auth0: {
|
||||||
domain: override.auth0.domain || base.auth0.domain,
|
domain: override.auth0.domain || base.auth0.domain,
|
||||||
clientId: override.auth0.clientId || base.auth0.clientId,
|
clientId: override.auth0.clientId || base.auth0.clientId,
|
||||||
@@ -479,6 +482,17 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function apiUrl(pathname) {
|
||||||
|
const cfg = getAuthConfig();
|
||||||
|
const base = cfg.apiBase;
|
||||||
|
if (!base) return pathname; // same-origin
|
||||||
|
try {
|
||||||
|
return new URL(pathname, base).toString();
|
||||||
|
} catch {
|
||||||
|
return pathname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function currentUrlNoQuery() {
|
function currentUrlNoQuery() {
|
||||||
// Auth0 callback 후 URL 정리용
|
// Auth0 callback 후 URL 정리용
|
||||||
const u = new URL(location.href);
|
const u = new URL(location.href);
|
||||||
@@ -649,7 +663,7 @@
|
|||||||
async function syncUserToServerWithIdToken(idToken) {
|
async function syncUserToServerWithIdToken(idToken) {
|
||||||
try {
|
try {
|
||||||
const cfg = getAuthConfig();
|
const cfg = getAuthConfig();
|
||||||
const r = await fetch("/api/auth/sync", {
|
const r = await fetch(apiUrl("/api/auth/sync"), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${idToken}`,
|
Authorization: `Bearer ${idToken}`,
|
||||||
@@ -657,11 +671,18 @@
|
|||||||
"X-Auth0-ClientId": cfg.auth0.clientId,
|
"X-Auth0-ClientId": cfg.auth0.clientId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!r.ok) return null;
|
if (!r.ok) {
|
||||||
|
toastOnce(
|
||||||
|
"syncfail",
|
||||||
|
`사용자 저장(API)이 실패했습니다. (${r.status}) 정적 호스팅이면 /api 를 서버로 프록시하거나 apiBase를 설정해야 합니다.`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
if (data && data.ok) return Boolean(data.canManage);
|
if (data && data.ok) return Boolean(data.canManage);
|
||||||
return null;
|
return null;
|
||||||
} catch {
|
} catch {
|
||||||
|
toastOnce("syncerr", "사용자 저장(API)에 연결하지 못했습니다. /api 서버 연결을 확인하세요.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -673,14 +694,14 @@
|
|||||||
// Prefer sendBeacon to survive navigation
|
// Prefer sendBeacon to survive navigation
|
||||||
try {
|
try {
|
||||||
const blob = new Blob([payload], { type: "application/json" });
|
const blob = new Blob([payload], { type: "application/json" });
|
||||||
const ok = navigator.sendBeacon("/api/auth/logout", blob);
|
const ok = navigator.sendBeacon(apiUrl("/api/auth/logout"), blob);
|
||||||
if (ok) return;
|
if (ok) return;
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
// Fallback fetch keepalive (best-effort)
|
// Fallback fetch keepalive (best-effort)
|
||||||
try {
|
try {
|
||||||
fetch("/api/auth/logout", {
|
fetch(apiUrl("/api/auth/logout"), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${idToken}`,
|
Authorization: `Bearer ${idToken}`,
|
||||||
|
|||||||
Reference in New Issue
Block a user