Update launcher session handling
This commit is contained in:
1 parent
21486b606b
commit
f8da17b9db
2 files changed
+132
-15
No files matched your search
@@ -52,7 +52,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
|
||||
if ($action === 'logout') {
|
||||
$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
@@ -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 (res.ok && data.result === 'ok') {
|
||||
if (typeof onSuccess === 'function') {
|
||||
onSuccess();
|
||||
} else {
|
||||
renderIcons();
|
||||
if (data.loginBlocked) {
|
||||
rememberClientLoginBlocked(data.blockedType, data.blockedMessage);
|
||||
replaceLauncherToChaegeonHome();
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.ok && data.result === 'ok') {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user