From e47a42462a8d53a5b5fa8f2a8b2e8ea3455105c2 Mon Sep 17 00:00:00 2001 From: seo Date: Thu, 2 Jul 2026 19:05:22 +0900 Subject: [PATCH] =?UTF-8?q?=EB=9F=B0=EC=B2=98=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EB=B0=94=EB=A1=9C=EA=B0=80=EA=B8=B0=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++- js/main.js | 74 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9a661a5..03e2361 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,9 @@ ## 운영 메모 -메인 버튼은 기존 4개를 유지합니다. Rhymix 사이트 관리자 로그인 상태에서는 미니앱 실행 시 공통 암호를 묻지 않습니다. 이때 `/custom/launcher/api.php?adminSession=1` 또는 `session=1` 응답에서 관리자 공통 접근 쿠키를 함께 발급해, 이동한 미니앱 내부 세션 검사에서도 바로 통과합니다. +일반 사용자 화면은 나의 찾기, 콕 찌르기, 니모, GIT 4개 버튼만 표시합니다. PC 켜기 항목은 운영 코드에 주석으로 보존해 두고 화면에서는 제외합니다. + +Rhymix 사이트 관리자 로그인 상태에서는 나의 찾기, 콕 찌르기, 니모, 프로젝트, Block, Notice, Weblog, Speed Stats를 4개씩 2줄로 표시합니다. 관리자 상태에서 미니앱을 실행하면 공통 암호를 묻지 않습니다. 이때 `/custom/launcher/api.php?adminSession=1` 또는 `session=1` 응답에서 관리자 공통 접근 쿠키를 함께 발급해, 이동한 미니앱 내부 세션 검사에서도 바로 통과합니다. 공통 암호로 로그인한 일반 인증 쿠키는 30분만 유지합니다. 사이트 관리자 세션이 확인되어 발급된 관리자 인증 쿠키는 반영구 운영값으로 10년 유지합니다. `/custom/launcher/api.php?session=1`은 현재 브라우저가 가진 공통 쿠키 또는 사이트 관리자 세션을 확인하고, `/custom/launcher/api.php?adminSession=1`은 관리 버튼 노출처럼 실제 Rhymix 관리자 세션이 필요한 화면에서만 사용합니다. diff --git a/js/main.js b/js/main.js index d2824ca..782dbc8 100644 --- a/js/main.js +++ b/js/main.js @@ -4,19 +4,21 @@ let failIndex = 0; const apiUrl = '/custom/launcher/api.php'; const PIN_LENGTH = 4; -const iconItems = [ +const userIconItems = [ { id: 'findmydevice', img: '/custom/launcher/img/find-my.svg', label: '나의 찾기', onclick: () => requireAccess(() => location.href = '/findmydevice') }, + /* { id: 'wakeonlan', img: '/custom/launcher/img/wakeonlan-svgrepo-com.svg', label: 'PC 켜기', onclick: () => requireAccess(wakeComputer) }, + */ { id: 'poke', img: '/custom/launcher/img/R1280x0.jpg', @@ -28,14 +30,59 @@ const iconItems = [ img: '/custom/launcher/img/car.png', label: '니모', onclick: () => requireAccess(() => location.href = 'https://seo.chaegeon.com/car/monitor.php') + }, + { + id: 'git', + img: 'https://git.chaegeon.com/assets/img/favicon.svg', + label: 'GIT', + onclick: () => requireAccess(() => location.href = 'https://git.chaegeon.com') + } +]; + +const adminIconItems = [ + userIconItems[0], + userIconItems[1], + userIconItems[2], + { + id: 'project', + img: 'https://git.chaegeon.com/assets/img/favicon.svg', + label: '프로젝트', + onclick: () => requireAccess(() => location.href = 'https://git.chaegeon.com') + }, + { + id: 'block', + img: '/admin/favicon/block/favicon.svg', + label: 'Block', + onclick: () => requireAccess(() => location.href = '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') + }, + { + id: 'weblog', + img: '/weblog/favicon.svg', + label: 'Weblog', + onclick: () => requireAccess(() => location.href = 'https://chaegeon.com/weblog/index.php') + }, + { + id: 'speedstats', + img: '/custom/speedtest/favicon.ico', + label: 'Speed Stats', + onclick: () => requireAccess(() => location.href = 'https://chaegeon.com/custom/speedtest/results/stats.php') } ]; async function renderIcons() { - shortcut.className = 'find-container'; + const session = await getSession(); + const isAdmin = !!session.admin; + const items = isAdmin ? adminIconItems : userIconItems; + shortcut.className = `find-container ${isAdmin ? 'launcher-admin-grid' : ''}`; shortcut.innerHTML = ''; - iconItems.forEach(item => { + items.forEach(item => { const div = document.createElement('div'); div.className = 'iconContainer'; div.id = item.id; @@ -54,7 +101,7 @@ async function renderIcons() { shortcut.appendChild(div); }); - if (!await hasAdminSession()) { + if (!isAdmin) { return; } @@ -67,23 +114,22 @@ async function renderIcons() { } async function hasAdminSession() { + const session = await getSession(); + return !!session.admin; +} + +async function getSession() { try { - const session = await fetch(`${apiUrl}?adminSession=1`, { credentials: 'same-origin' }).then(res => res.json()); - return !!session.admin; + return await fetch(`${apiUrl}?session=1`, { credentials: 'same-origin' }).then(res => res.json()); } catch (_) { - return false; + return { authenticated: false, admin: false }; } } async function requireAccess(nextAction) { try { - if (await hasAdminSession()) { - nextAction && nextAction(); - return; - } - - const session = await fetch(`${apiUrl}?session=1`, { credentials: 'same-origin' }).then(res => res.json()); - if (session.authenticated) { + const session = await getSession(); + if (session.admin || session.authenticated) { nextAction && nextAction(); return; }