Update launcher session handling

This commit is contained in:
seo committed 2026-08-12 21:35:20 +09:00
1 parent 21486b606b
commit f8da17b9db
2 files changed
+133 -16

No files matched your search

+18 -3
View File
@@ -52,7 +52,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($action === 'logout') {
custom_clear_auth_cookie();
$scope = (string)($data['scope'] ?? '');
if ($scope === 'admin') {
custom_clear_auth_cookie();
} elseif (function_exists('custom_clear_non_admin_auth_cookie')) {
custom_clear_non_admin_auth_cookie(false);
} else {
custom_clear_auth_cookie();
}
custom_json(['result' => 'ok']);
}
@@ -93,12 +100,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (isset($_GET['session'])) {
$denied = custom_login_denied_state();
if (!empty($denied['denied'])) {
$blockedType = (string)($denied['type'] ?? '');
if (!empty($denied['denied']) && !($blockedType !== 'ip' && custom_is_site_admin())) {
if ($blockedType === 'ip') {
custom_clear_auth_cookie();
} elseif (function_exists('custom_clear_non_admin_auth_cookie')) {
custom_clear_non_admin_auth_cookie(true);
} else {
custom_clear_auth_cookie();
}
custom_json([
'authenticated' => false,
'admin' => false,
'loginBlocked' => true,
'blockedType' => $denied['type'] ?? '',
'blockedType' => $blockedType,
'blockedMessage' => $denied['message'] ?? '현재 로그인할 수 없는 상태입니다.',
]);
}
+115 -13
View File
@@ -5,12 +5,91 @@ let lastRenderedAdmin = null;
const apiUrl = '/custom/launcher/api.php';
const PIN_LENGTH = 4;
function isClientLoginBlocked() {
try {
return sessionStorage.getItem('login_blocked') === '1';
} catch (_) {
return false;
}
}
const LAUNCHER_LOGIN_BLOCKED_COOKIE_NAMES = {
member: 'chaegeon_member_blocked',
ip: 'chaegeon_ip_blocked',
login_fail: 'chaegeon_login_fail_blocked',
sms_verify_fail: 'chaegeon_sms_verify_blocked',
client: 'chaegeon_member_blocked'
};
const LAUNCHER_LOGIN_BLOCKED_LEGACY_COOKIE = 'chaegeon_login_blocked';
function clientLoginBlockedCookieName(type) {
return LAUNCHER_LOGIN_BLOCKED_COOKIE_NAMES[type || 'member'] || LAUNCHER_LOGIN_BLOCKED_COOKIE_NAMES.member;
}
function writeClientLoginBlockedCookie(name, blocked) {
const secure = location.protocol === 'https:' ? '; Secure' : '';
document.cookie = `${name}=${blocked ? '1' : ''}; path=/; max-age=${blocked ? '1800' : '0'}; SameSite=Strict${secure}`;
}
function clearClientLoginBlockedCookies(exceptName) {
[
LAUNCHER_LOGIN_BLOCKED_LEGACY_COOKIE,
LAUNCHER_LOGIN_BLOCKED_COOKIE_NAMES.member,
LAUNCHER_LOGIN_BLOCKED_COOKIE_NAMES.ip,
LAUNCHER_LOGIN_BLOCKED_COOKIE_NAMES.login_fail,
LAUNCHER_LOGIN_BLOCKED_COOKIE_NAMES.sms_verify_fail
].forEach(name => {
if (name !== exceptName) writeClientLoginBlockedCookie(name, false);
});
}
function setClientLoginBlockedCookie(type = 'member') {
const name = clientLoginBlockedCookieName(type);
clearClientLoginBlockedCookies(name);
writeClientLoginBlockedCookie(name, true);
}
function rememberClientLoginBlocked(type, message) {
try {
sessionStorage.setItem('login_blocked', '1');
sessionStorage.setItem('login_blocked_type', type || 'member');
if (message) sessionStorage.setItem('login_blocked_reason', message);
} catch (_) {}
setClientLoginBlockedCookie(type || 'member');
}
function isLauncherLoginBlockedAllowedHomePage() {
const path = location.pathname.toLowerCase();
return location.protocol === 'https:' && location.hostname === 'chaegeon.com' && (path === '/' || path === '/home' || path.startsWith('/home/'));
}
function replaceLauncherToChaegeonHome() {
if (isLauncherLoginBlockedAllowedHomePage()) return false;
location.replace('https://chaegeon.com/');
return true;
}
function redirectIfClientLoginBlocked() {
if (!isClientLoginBlocked()) return false;
let type = 'member';
try {
type = sessionStorage.getItem('login_blocked_type') || 'member';
} catch (_) {}
setClientLoginBlockedCookie(type);
replaceLauncherToChaegeonHome();
return true;
}
function openLauncherTarget(url) {
window.open(url, '_blank', 'noopener');
}
const userIconItems = [
{
id: 'findmydevice',
img: '/custom/launcher/img/find-my.svg',
label: '나의 찾기',
onclick: () => requireAccess(() => location.href = '/findmydevice')
onclick: () => requireAccess(() => openLauncherTarget('/findmydevice'))
},
{
id: 'poke',
@@ -22,13 +101,13 @@ const userIconItems = [
id: 'car',
img: '/custom/launcher/img/car.png',
label: '니모',
onclick: () => requireAccess(() => location.href = 'https://seo.chaegeon.com/car/monitor.php')
onclick: () => requireAccess(() => openLauncherTarget('https://chaegeon.com/custom/car/monitor.php'))
},
{
id: 'project',
img: 'https://git.chaegeon.com/assets/img/favicon.svg',
label: '프로젝트',
onclick: () => location.href = 'https://git.chaegeon.com/explore/repos'
onclick: () => openLauncherTarget('https://git.chaegeon.com/explore/repos')
}
];
@@ -47,26 +126,29 @@ const adminIconItems = [
id: 'block',
img: '/admin/favicon/block/favicon.svg',
label: 'Block',
onclick: () => requireAccess(() => location.href = 'https://chaegeon.com/admin/index.php')
onclick: () => requireAccess(() => openLauncherTarget('https://chaegeon.com/admin/index.php'))
},
{
id: 'notice',
img: '/admin/favicon/notice/favicon.svg',
label: 'Notice',
onclick: () => requireAccess(() => location.href = 'https://chaegeon.com/admin/notice.php')
onclick: () => requireAccess(() => openLauncherTarget('https://chaegeon.com/admin/notice.php'))
},
{
id: 'speedstats',
img: '/custom/speedtest/favicon.ico',
label: 'Speed Stats',
onclick: () => requireAccess(() => location.href = 'https://chaegeon.com/custom/speedtest/results/stats.php')
onclick: () => requireAccess(() => openLauncherTarget('https://chaegeon.com/custom/speedtest/results/stats.php'))
}
];
async function renderIcons() {
if (redirectIfClientLoginBlocked()) return;
const session = await getSession();
if (session.loginBlocked) {
renderLoginBlocked(session);
rememberClientLoginBlocked(session.blockedType, session.blockedMessage);
replaceLauncherToChaegeonHome();
return;
}
@@ -125,10 +207,13 @@ async function getSession() {
}
async function requireAccess(nextAction) {
if (redirectIfClientLoginBlocked()) return;
try {
const session = await getSession();
if (session.loginBlocked) {
renderLoginBlocked(session);
rememberClientLoginBlocked(session.blockedType, session.blockedMessage);
replaceLauncherToChaegeonHome();
return;
}
@@ -142,6 +227,13 @@ async function requireAccess(nextAction) {
showPasswordForm(nextAction);
}
async function finishPasswordSuccess(onSuccess) {
if (typeof onSuccess === 'function') {
onSuccess();
}
await renderIcons();
}
async function refreshAdminModeIfNeeded() {
if (lastRenderedAdmin !== true) return;
const isAdmin = await hasAdminSession();
@@ -172,6 +264,8 @@ function renderLoginBlocked(session = {}) {
}
function showPasswordForm(onSuccess) {
if (redirectIfClientLoginBlocked()) return;
shortcut.className = 'password-container';
shortcut.innerHTML = '';
@@ -190,12 +284,16 @@ function showPasswordForm(onSuccess) {
column.appendChild(inputRow);
shortcut.appendChild(column);
let submitting = false;
const submit = async () => {
if (redirectIfClientLoginBlocked()) return;
if (submitting) return;
const password = onlyDigits(input.value);
input.value = password;
if (password.length !== PIN_LENGTH) return;
try {
submitting = true;
const messageRes = await fetch(`${apiUrl}?failMessages=1`);
const messagesJson = await messageRes.json();
const failMessages = messagesJson.failMessages || [];
@@ -208,12 +306,14 @@ function showPasswordForm(onSuccess) {
});
const data = await res.json();
if (data.loginBlocked) {
rememberClientLoginBlocked(data.blockedType, data.blockedMessage);
replaceLauncherToChaegeonHome();
return;
}
if (res.ok && data.result === 'ok') {
if (typeof onSuccess === 'function') {
onSuccess();
} else {
renderIcons();
}
await finishPasswordSuccess(onSuccess);
return;
}
@@ -222,9 +322,11 @@ function showPasswordForm(onSuccess) {
failIndex = (failIndex + 1) % Math.max(1, failMessages.length);
input.value = '';
input.focus();
submitting = false;
} catch (_) {
column.appendChild(msg);
msg.textContent = '요청을 처리하지 못했습니다.';
submitting = false;
}
};