Wire quick login in fallback mode
When external script.js fails and inline fallback runs, connect Naver/Kakao/Google buttons to Auth0 loginWithRedirect (by connection) and show logout/user state after authentication. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
154
index.html
154
index.html
@@ -22,10 +22,18 @@
|
|||||||
// 2) Allowed Callback URLs / Allowed Logout URLs에 현재 사이트 주소를 등록하세요.
|
// 2) Allowed Callback URLs / Allowed Logout URLs에 현재 사이트 주소를 등록하세요.
|
||||||
// 예: https://drive.daewoongai.com/apps/dashboard/
|
// 예: https://drive.daewoongai.com/apps/dashboard/
|
||||||
window.AUTH_CONFIG = {
|
window.AUTH_CONFIG = {
|
||||||
|
// end-user가 설정 모달을 사용하는지 여부(기본: false)
|
||||||
|
allowEndUserConfig: false,
|
||||||
auth0: {
|
auth0: {
|
||||||
domain: "",
|
domain: "",
|
||||||
clientId: "",
|
clientId: "",
|
||||||
},
|
},
|
||||||
|
// Auth0 connection 이름(선택). 예: google-oauth2 / kakao / naver
|
||||||
|
connections: {
|
||||||
|
google: "",
|
||||||
|
kakao: "",
|
||||||
|
naver: "",
|
||||||
|
},
|
||||||
// 관리 허용 이메일(대소문자 무시)
|
// 관리 허용 이메일(대소문자 무시)
|
||||||
allowedEmails: [],
|
allowedEmails: [],
|
||||||
};
|
};
|
||||||
@@ -383,6 +391,7 @@
|
|||||||
|
|
||||||
const STORAGE_KEY = "links_home_v1";
|
const STORAGE_KEY = "links_home_v1";
|
||||||
const THEME_KEY = "links_home_theme_v1";
|
const THEME_KEY = "links_home_theme_v1";
|
||||||
|
const AUTH_OVERRIDE_KEY = "links_home_auth_override_v1";
|
||||||
|
|
||||||
const el = {
|
const el = {
|
||||||
q: document.getElementById("q"),
|
q: document.getElementById("q"),
|
||||||
@@ -395,6 +404,13 @@
|
|||||||
btnImport: document.getElementById("btnImport"),
|
btnImport: document.getElementById("btnImport"),
|
||||||
btnExport: document.getElementById("btnExport"),
|
btnExport: document.getElementById("btnExport"),
|
||||||
btnTheme: document.getElementById("btnTheme"),
|
btnTheme: document.getElementById("btnTheme"),
|
||||||
|
snsLogin: document.getElementById("snsLogin"),
|
||||||
|
btnNaver: document.getElementById("btnNaver"),
|
||||||
|
btnKakao: document.getElementById("btnKakao"),
|
||||||
|
btnGoogle: document.getElementById("btnGoogle"),
|
||||||
|
btnLogout: document.getElementById("btnLogout"),
|
||||||
|
user: document.getElementById("user"),
|
||||||
|
userText: document.getElementById("userText"),
|
||||||
toast: document.getElementById("toast"),
|
toast: document.getElementById("toast"),
|
||||||
modal: document.getElementById("modal"),
|
modal: document.getElementById("modal"),
|
||||||
btnClose: document.getElementById("btnClose"),
|
btnClose: document.getElementById("btnClose"),
|
||||||
@@ -662,6 +678,138 @@
|
|||||||
applyTheme(prefersLight ? "light" : "dark");
|
applyTheme(prefersLight ? "light" : "dark");
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// Auth (fallback): wire SNS quick login buttons
|
||||||
|
const auth = {
|
||||||
|
client: null,
|
||||||
|
user: null,
|
||||||
|
ready: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
function loadAuthOverride() {
|
||||||
|
const raw = localStorage.getItem(AUTH_OVERRIDE_KEY);
|
||||||
|
const data = raw ? safeJsonParse(raw, null) : null;
|
||||||
|
if (!data || typeof data !== "object") return null;
|
||||||
|
const auth0 = data.auth0 && typeof data.auth0 === "object" ? data.auth0 : {};
|
||||||
|
const connections = data.connections && typeof data.connections === "object" ? data.connections : {};
|
||||||
|
const allowedEmails = Array.isArray(data.allowedEmails) ? data.allowedEmails : [];
|
||||||
|
return {
|
||||||
|
auth0: {
|
||||||
|
domain: String(auth0.domain || "").trim(),
|
||||||
|
clientId: String(auth0.clientId || "").trim(),
|
||||||
|
},
|
||||||
|
connections: {
|
||||||
|
google: String(connections.google || "").trim(),
|
||||||
|
kakao: String(connections.kakao || "").trim(),
|
||||||
|
naver: String(connections.naver || "").trim(),
|
||||||
|
},
|
||||||
|
allowedEmails: allowedEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAuthConfig() {
|
||||||
|
const cfg = window.AUTH_CONFIG && typeof window.AUTH_CONFIG === "object" ? window.AUTH_CONFIG : {};
|
||||||
|
const auth0 = cfg.auth0 && typeof cfg.auth0 === "object" ? cfg.auth0 : {};
|
||||||
|
const connections = cfg.connections && typeof cfg.connections === "object" ? cfg.connections : {};
|
||||||
|
const allowedEmails = Array.isArray(cfg.allowedEmails) ? cfg.allowedEmails : [];
|
||||||
|
const base = {
|
||||||
|
auth0: {
|
||||||
|
domain: String(auth0.domain || "").trim(),
|
||||||
|
clientId: String(auth0.clientId || "").trim(),
|
||||||
|
},
|
||||||
|
connections: {
|
||||||
|
google: String(connections.google || "").trim(),
|
||||||
|
kakao: String(connections.kakao || "").trim(),
|
||||||
|
naver: String(connections.naver || "").trim(),
|
||||||
|
},
|
||||||
|
allowedEmails: allowedEmails.map((e) => String(e).trim().toLowerCase()).filter(Boolean),
|
||||||
|
};
|
||||||
|
const over = loadAuthOverride();
|
||||||
|
if (!over) return base;
|
||||||
|
return {
|
||||||
|
auth0: {
|
||||||
|
domain: over.auth0.domain || base.auth0.domain,
|
||||||
|
clientId: over.auth0.clientId || base.auth0.clientId,
|
||||||
|
},
|
||||||
|
connections: {
|
||||||
|
google: over.connections.google || base.connections.google,
|
||||||
|
kakao: over.connections.kakao || base.connections.kakao,
|
||||||
|
naver: over.connections.naver || base.connections.naver,
|
||||||
|
},
|
||||||
|
allowedEmails: over.allowedEmails.length ? over.allowedEmails : base.allowedEmails,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentUrlNoQuery() {
|
||||||
|
const u = new URL(location.href);
|
||||||
|
u.searchParams.delete("code");
|
||||||
|
u.searchParams.delete("state");
|
||||||
|
return u.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureAuthClient() {
|
||||||
|
if (auth.client) return auth.client;
|
||||||
|
const cfg = getAuthConfig();
|
||||||
|
if (!cfg.auth0.domain || !cfg.auth0.clientId) return null;
|
||||||
|
if (typeof window.createAuth0Client !== "function") return null;
|
||||||
|
auth.client = await window.createAuth0Client({
|
||||||
|
domain: cfg.auth0.domain,
|
||||||
|
clientId: cfg.auth0.clientId,
|
||||||
|
authorizationParams: {
|
||||||
|
redirect_uri: location.origin === "null" ? location.href : location.origin + location.pathname,
|
||||||
|
},
|
||||||
|
cacheLocation: "localstorage",
|
||||||
|
useRefreshTokens: true,
|
||||||
|
});
|
||||||
|
return auth.client;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initAuth() {
|
||||||
|
auth.ready = true;
|
||||||
|
const client = await ensureAuthClient();
|
||||||
|
if (!client) {
|
||||||
|
// No config: keep buttons visible but disabled style
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const u = new URL(location.href);
|
||||||
|
const isCallback = u.searchParams.has("code") && u.searchParams.has("state");
|
||||||
|
if (isCallback) {
|
||||||
|
try {
|
||||||
|
await client.handleRedirectCallback();
|
||||||
|
} finally {
|
||||||
|
history.replaceState({}, document.title, currentUrlNoQuery());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const isAuthed = await client.isAuthenticated();
|
||||||
|
auth.user = isAuthed ? await client.getUser() : null;
|
||||||
|
if (el.btnLogout) el.btnLogout.hidden = !auth.user;
|
||||||
|
if (el.snsLogin) el.snsLogin.hidden = Boolean(auth.user);
|
||||||
|
if (el.user) el.user.hidden = !auth.user;
|
||||||
|
if (el.userText && auth.user) el.userText.textContent = auth.user.email || auth.user.name || "로그인됨";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loginWithConnection(provider) {
|
||||||
|
const cfg = getAuthConfig();
|
||||||
|
const client = await ensureAuthClient();
|
||||||
|
if (!client) {
|
||||||
|
toast("간편로그인은 관리자 설정 후 사용 가능합니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const conn = cfg.connections[provider] || "";
|
||||||
|
if (!conn) {
|
||||||
|
toast("관리자가 Auth0 connection 이름을 설정해야 합니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await client.loginWithRedirect({ authorizationParams: { connection: conn } });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function logout() {
|
||||||
|
const client = await ensureAuthClient();
|
||||||
|
if (!client) return;
|
||||||
|
await client.logout({
|
||||||
|
logoutParams: { returnTo: location.origin === "null" ? location.href : location.origin + location.pathname },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Wire events
|
// Wire events
|
||||||
if (el.q)
|
if (el.q)
|
||||||
el.q.addEventListener("input", () => {
|
el.q.addEventListener("input", () => {
|
||||||
@@ -777,7 +925,13 @@
|
|||||||
applyTheme(cur === "dark" ? "light" : "dark");
|
applyTheme(cur === "dark" ? "light" : "dark");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (el.btnNaver) el.btnNaver.addEventListener("click", () => loginWithConnection("naver").catch(() => toast("로그인에 실패했습니다.")));
|
||||||
|
if (el.btnKakao) el.btnKakao.addEventListener("click", () => loginWithConnection("kakao").catch(() => toast("로그인에 실패했습니다.")));
|
||||||
|
if (el.btnGoogle) el.btnGoogle.addEventListener("click", () => loginWithConnection("google").catch(() => toast("로그인에 실패했습니다.")));
|
||||||
|
if (el.btnLogout) el.btnLogout.addEventListener("click", () => logout().catch(() => toast("로그아웃에 실패했습니다.")));
|
||||||
|
|
||||||
render();
|
render();
|
||||||
|
initAuth().catch(() => {});
|
||||||
toast("스크립트 로딩 문제로 폴백 모드로 실행 중입니다.");
|
toast("스크립트 로딩 문제로 폴백 모드로 실행 중입니다.");
|
||||||
}, 200);
|
}, 200);
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user