-
Notifications
You must be signed in to change notification settings - Fork 0
fix: IBK 기업은행 점검 기간 중에는 서비스 이용을 차단 #180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,13 @@ | ||
| import { ExternalLinkIcon } from "lucide-react"; | ||
| import { useEffect, useState } from "react"; | ||
| import { Button } from "@/components/ui/button"; | ||
| import { | ||
| Dialog, | ||
| DialogContent, | ||
| DialogDescription, | ||
| DialogHeader, | ||
| DialogTitle, | ||
| } from "@/components/ui/dialog"; | ||
| import { useExternalBrowser } from "@/hooks/useExternalBrowser"; | ||
| import { Analytics } from "@/service/analytics"; | ||
| import BrowserRedirectPage from "./BrowserRedirectPage"; | ||
|
|
@@ -8,78 +16,125 @@ const GOOGLE_LOGIN_URL = `${import.meta.env.VITE_API_URL}/oauth2/authorization/g | |
| const AEGIS_HOMEPAGE_URL = "https://dkuaegis.org/"; | ||
| const GMAIL_GUIDE_URL = "https://sites.google.com/dankook.ac.kr/help"; | ||
|
|
||
| // IBK 기업은행 점검 시간 체크 함수 | ||
| const isMaintenanceTime = (): boolean => { | ||
| const now = new Date(); | ||
| const month = now.getMonth() + 1; // 0-based이므로 +1 | ||
| const date = now.getDate(); | ||
| const hours = now.getHours(); | ||
|
|
||
| // 3월 1일 0시~12시 (0시부터 11시 59분까지) | ||
| return month === 3 && date === 1 && hours >= 0 && hours < 12; | ||
| }; | ||
|
|
||
| const LoginPage = () => { | ||
| const { isKakaoInApp } = useExternalBrowser(); | ||
| const [showMaintenanceModal, setShowMaintenanceModal] = useState(false); | ||
| const [isMaintenance, setIsMaintenance] = useState(false); | ||
|
|
||
| useEffect(() => { | ||
| const maintenance = isMaintenanceTime(); | ||
| setIsMaintenance(maintenance); | ||
| if (maintenance) { | ||
| setShowMaintenanceModal(true); | ||
| } | ||
| }, []); | ||
|
|
||
| if (isKakaoInApp) { | ||
| return <BrowserRedirectPage />; | ||
| } | ||
|
|
||
| return ( | ||
| <div className="line-breaks flex min-h-screen flex-col items-center justify-center bg-background"> | ||
| <div className="w-full max-w-[400px] space-y-6 p-4"> | ||
| <div className="flex flex-col space-y-2 text-center"> | ||
| <img | ||
| src="/aegis-logo.webp" | ||
| alt="Aegis Logo" | ||
| className="mx-auto mb-4 h-32 w-32" | ||
| /> | ||
| <h1 className="font-semibold text-2xl tracking-tight"> | ||
| Aegis 회원 가입 | ||
| </h1> | ||
| <p className="text-muted-foreground text-sm"> | ||
| 단국대학교 구글 계정으로 로그인해주세요 | ||
| </p> | ||
| <> | ||
| <Dialog | ||
| open={showMaintenanceModal} | ||
| onOpenChange={setShowMaintenanceModal} | ||
| > | ||
| <DialogContent> | ||
| <DialogHeader> | ||
| <DialogTitle>시스템 점검 안내</DialogTitle> | ||
| <DialogDescription className="pt-4 text-base"> | ||
| IBK 기업은행 시스템 점검으로 인해 | ||
| <br /> | ||
| <strong className="text-foreground">3월 1일 0시 ~ 12시</strong> | ||
| 까지 | ||
| <br /> | ||
| 회원 가입이 불가능합니다. | ||
| <br /> | ||
| <br /> | ||
| 점검 종료 후 이용해주시기 바랍니다. | ||
| </DialogDescription> | ||
| </DialogHeader> | ||
| </DialogContent> | ||
| </Dialog> | ||
|
|
||
| <div className="line-breaks flex min-h-screen flex-col items-center justify-center bg-background"> | ||
| <div className="w-full max-w-[400px] space-y-6 p-4"> | ||
| <div className="flex flex-col space-y-2 text-center"> | ||
| <img | ||
| src="/aegis-logo.webp" | ||
| alt="Aegis Logo" | ||
| className="mx-auto mb-4 h-32 w-32" | ||
| /> | ||
| <h1 className="font-semibold text-2xl tracking-tight"> | ||
| Aegis 회원 가입 | ||
| </h1> | ||
| <p className="text-muted-foreground text-sm"> | ||
| 단국대학교 구글 계정으로 로그인해주세요 | ||
| </p> | ||
| </div> | ||
| {!isMaintenance && ( | ||
| <Button | ||
| onClick={() => { | ||
| Analytics.safeTrack("Google_Login_Click", { | ||
| category: "Auth", | ||
| method: "Google", | ||
| }); | ||
| }} | ||
| className="w-full" | ||
| asChild | ||
| > | ||
| <a href={GOOGLE_LOGIN_URL}>Google로 로그인</a> | ||
| </Button> | ||
| )} | ||
|
Comment on lines
+86
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# 점검/로그인 차단 관련 로직이 저장소 내에 존재하는지 확인
rg -n -C2 'oauth2/authorization/google|isMaintenanceTime|isMaintenance' --type typescript --type tsx --type tsRepository: dkuaegis/aegis-join Length of output: 97 🏁 Script executed: #!/bin/bash
# 백엔드 OAuth 엔드포인트 관련 로직 검색
rg -n -C3 'oauth2|authorization|google' --type java --type kotlin --type python --type js -iRepository: dkuaegis/aegis-join Length of output: 93 🏁 Script executed: #!/bin/bash
# 점검 모드 관련 서버 사이드 로직 확인
rg -n 'maintenance|점검|isMaintenanceTime' -A3 -B3 | head -100Repository: dkuaegis/aegis-join Length of output: 2449 🏁 Script executed: #!/bin/bash
# 백엔드 OAuth 구현 및 인증 엔드포인트 찾기
fd -e java -e kt -e py | head -20Repository: dkuaegis/aegis-join Length of output: 45 🏁 Script executed: #!/bin/bash
# GOOGLE_LOGIN_URL 정의 및 OAuth 엔드포인트 확인
rg -n "GOOGLE_LOGIN_URL|oauth2/authorization"Repository: dkuaegis/aegis-join Length of output: 261 🏁 Script executed: #!/bin/bash
# 인증/OAuth 관련 서버 사이드 로직 검색
rg -n "authorize|oauth|authentication|Authorization" -C2 | head -150Repository: dkuaegis/aegis-join Length of output: 802 🏁 Script executed: #!/bin/bash
# 저장소 전체 구조 확인 - 백엔드 코드 유무
find . -name "*.java" -o -name "*.kt" -o -name "*.py" -o -name "application.yml" -o -name "application.yaml" 2>/dev/null | head -20Repository: dkuaegis/aegis-join Length of output: 45 🏁 Script executed: #!/bin/bash
# package.json 및 프로젝트 구조 확인
cat package.json | head -30Repository: dkuaegis/aegis-join Length of output: 997 🏁 Script executed: #!/bin/bash
# 환경 변수 및 API 설정 확인
rg -n "VITE_API_URL|API_BASE_URL|backends|proxy"Repository: dkuaegis/aegis-join Length of output: 389 OAuth 엔드포인트 접근 차단이 백엔드에서도 강제되어야 합니다. 현재 구현은 프론트엔드에서만 버튼을 숨기고 있어, 🤖 Prompt for AI Agents |
||
| <Button | ||
| onClick={() => { | ||
| Analytics.safeTrack("Go_Homepage_Click", { | ||
| category: "Auth", | ||
| method: "Email", | ||
| }); | ||
| }} | ||
| className="w-full" | ||
| asChild | ||
| > | ||
| <a | ||
| href={AEGIS_HOMEPAGE_URL} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| > | ||
| Aegis 홈페이지 | ||
| </a> | ||
| </Button> | ||
| </div> | ||
| <Button | ||
| onClick={() => { | ||
| Analytics.safeTrack("Google_Login_Click", { | ||
| category: "Auth", | ||
| method: "Google", | ||
| }); | ||
| }} | ||
| className="w-full" | ||
| asChild | ||
| > | ||
| <a href={GOOGLE_LOGIN_URL}>Google로 로그인</a> | ||
| </Button> | ||
| <Button | ||
| onClick={() => { | ||
| Analytics.safeTrack("Go_Homepage_Click", { | ||
| category: "Auth", | ||
| method: "Email", | ||
| }); | ||
| }} | ||
| className="w-full" | ||
| asChild | ||
| > | ||
| <div className="flex flex-col text-center"> | ||
| <a | ||
| href={AEGIS_HOMEPAGE_URL} | ||
| href={GMAIL_GUIDE_URL} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="inline-flex items-center justify-center gap-1 font-extrabold text-muted-foreground text-sm underline" | ||
| onClick={() => { | ||
| Analytics.safeTrack("Gmail_Guide_Click", { | ||
| category: "Link", | ||
| method: "Guide", | ||
| }); | ||
| }} | ||
| > | ||
| Aegis 홈페이지 | ||
| 단국대 Gmail 생성 가이드 | ||
| <ExternalLinkIcon className="h-4 w-4" /> | ||
| </a> | ||
| </Button> | ||
| </div> | ||
| <div className="flex flex-col text-center"> | ||
| <a | ||
| href={GMAIL_GUIDE_URL} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="inline-flex items-center justify-center gap-1 font-extrabold text-muted-foreground text-sm underline" | ||
| onClick={() => { | ||
| Analytics.safeTrack("Gmail_Guide_Click", { | ||
| category: "Link", | ||
| method: "Guide", | ||
| }); | ||
| }} | ||
| > | ||
| 단국대 Gmail 생성 가이드 | ||
| <ExternalLinkIcon className="h-4 w-4" /> | ||
| </a> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 143
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 3161
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 90
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 90
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 1059
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 232
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 45
🏁 Script executed:
# Check if there's a backend directory or if this is frontend-only ls -laRepository: dkuaegis/aegis-join
Length of output: 1459
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 1569
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 262
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 1429
🏁 Script executed:
# Check if there's any maintenance blocking in the OAuth or login flow cat -n src/api/errorMessage.tsRepository: dkuaegis/aegis-join
Length of output: 3688
🏁 Script executed:
Repository: dkuaegis/aegis-join
Length of output: 2617
로컬 시각 기반 점검 판별로 운영 기준 시각과 불일치 및 매년 반복 차단됩니다.
현재 구현은 브라우저의 로컬 시간대를 따르므로 사용자 위치 시간대에 따라 오판 가능성이 있고, 연도 조건이 없어 매년 3월 1일마다 반복 차단됩니다. 일회성 2026년 3월 1일 점검이라면 절대 시각 기반 비교로 고정해야 합니다.
🔧 제안 수정안
추가로 useEffect 의존성 배열이 비어있어 페이지를 열어둔 상태에서 점검 해제 시각 전환이 반영되지 않습니다. 또한 UI 숨김만으로는 서버 측 OAuth 엔드포인트 직접 접근을 차단하지 못하므로, 백엔드에서도 유사한 점검 시간 검증이 필요합니다.
🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이번만 핫픽스로 하고 이후에 기존 코드로 롤백하고자 하는데도 문제가 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KwonDeaGeun, 일회성 핫픽스 후 롤백하신다면 연도 조건 누락으로 인한 매년 반복 차단 문제는 해결됩니다.다만 다음 두 가지는 일회성 핫픽스라도 여전히 고려가 필요합니다:
타임존 문제: 현재 코드는
new Date()로 로컬 시각을 사용하므로, 해외에 있는 사용자나 시스템 시간대 설정이 다른 사용자는 의도하지 않은 시간에 차단되거나 차단이 풀릴 수 있습니다. 한국 시각 기준으로 정확히 제어하려면 KST(UTC+9) 고정이 필요합니다.백엔드 검증 부재: UI에서만 Google 로그인 버튼을 숨겨도, 사용자가
GOOGLE_LOGIN_URL을 직접 브라우저 주소창에 입력하거나 개발자 도구로 우회하면 OAuth 인증이 진행됩니다. 점검 기간 중 실제로 차단하려면 백엔드에서도 동일한 시간 체크가 필요합니다.핫픽스로 급하게 적용하시는 상황이라면 현재 코드로도 대부분의 한국 사용자에게는 정상 작동할 것으로 보입니다. 하지만 가능하다면 위 두 가지를 추가로 보완하시는 것을 권장드립니다.