From 00948f5cc09aa774f92cbcf693c6e7e783110ca5 Mon Sep 17 00:00:00 2001 From: ogt Date: Thu, 25 Jun 2026 15:51:37 +0800 Subject: [PATCH] fix: prevent drive auth browser launch --- config.py | 2 +- docs/AI_INTELLIGENCE_MODULE_SOT.md | 1 + services/google_drive_service.py | 18 ++++++++++++++++-- tests/test_google_drive_auth.py | 2 +- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/config.py b/config.py index 1ec589e..ae75fb5 100644 --- a/config.py +++ b/config.py @@ -402,7 +402,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.689" +SYSTEM_VERSION = "V10.690" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/AI_INTELLIGENCE_MODULE_SOT.md b/docs/AI_INTELLIGENCE_MODULE_SOT.md index 4ed78b3..a2a7471 100644 --- a/docs/AI_INTELLIGENCE_MODULE_SOT.md +++ b/docs/AI_INTELLIGENCE_MODULE_SOT.md @@ -766,3 +766,4 @@ POSTGRES_HOST=momo-db | 2026-06-25 | 價格語意不得反轉 | V10.687 起 dashboard 的 `gap_pct >= 5` 一律顯示為「PChome 價格優勢」與 win tone;`gap_pct <= -5` 一律顯示為「MOMO 低價壓力」與 risk tone,避免把 PChome 較便宜誤標為價格壓力。 | | 2026-06-25 | 覆核 note 不得保留反向價格詞 | V10.688 起單位價覆核 note 不再使用「不應誤判為 PChome 價格壓力」這類否定式錯誤詞,改用「需先檢查 PChome 售價、折扣與組合」等可執行語句。 | | 2026-06-25 | 舊覆核資料輸出層也要清洗價格語意 | V10.689 起 dashboard template 會在輸出 `unit_price_insight.summary` 時清除舊資料殘留的反向價格詞,避免快取或歷史 row 繼續把錯誤字句顯示給營運使用者。 | +| 2026-06-25 | Google Drive 背景匯入不得尋找本機瀏覽器 | V10.690 起 `GoogleDriveService.authenticate()` 預設拒絕背景 OAuth;即使人工明確開啟互動授權,也使用 `open_browser=False` 並輸出授權網址,不在 scheduler/app 容器內尋找 runnable browser。 | diff --git a/services/google_drive_service.py b/services/google_drive_service.py index 8100e18..9c1ebe0 100644 --- a/services/google_drive_service.py +++ b/services/google_drive_service.py @@ -30,6 +30,7 @@ CREDENTIALS_FILE = 'config/google_credentials.json' TOKEN_FILE = 'config/google_token.json' _LEGACY_PICKLE_FILE = 'config/google_token.pickle' INTERACTIVE_AUTH_ENV = 'GOOGLE_DRIVE_ALLOW_INTERACTIVE_AUTH' +INTERACTIVE_AUTH_TIMEOUT_ENV = 'GOOGLE_DRIVE_INTERACTIVE_AUTH_TIMEOUT_SECONDS' def _interactive_auth_allowed() -> bool: @@ -37,6 +38,13 @@ def _interactive_auth_allowed() -> bool: return os.getenv(INTERACTIVE_AUTH_ENV, "").strip().lower() in {"1", "true", "yes", "on"} +def _interactive_auth_timeout_seconds() -> int: + try: + return max(60, int(os.getenv(INTERACTIVE_AUTH_TIMEOUT_ENV, "300"))) + except (TypeError, ValueError): + return 300 + + class GoogleDriveService: """Google Drive 服務類別""" @@ -140,8 +148,14 @@ class GoogleDriveService: flow = InstalledAppFlow.from_client_secrets_file( CREDENTIALS_FILE, SCOPES ) - # 對於「電腦版應用程式」類型,使用預設行為讓 Google 自動選擇埠號 - self.credentials = flow.run_local_server() + # 即使是人工授權,也只印授權 URL,不在伺服器/容器內自動尋找瀏覽器。 + self.credentials = flow.run_local_server( + open_browser=False, + timeout_seconds=_interactive_auth_timeout_seconds(), + authorization_prompt_message=( + "請在可登入 Google 的瀏覽器開啟以下網址完成授權:{url}" + ), + ) # 儲存憑證供下次使用(JSON 格式,安全無 RCE 風險) if not self._save_credentials(): diff --git a/tests/test_google_drive_auth.py b/tests/test_google_drive_auth.py index 73cbfe9..9251b1a 100644 --- a/tests/test_google_drive_auth.py +++ b/tests/test_google_drive_auth.py @@ -34,7 +34,7 @@ if not os.path.exists('config/google_credentials.json'): print("✅ 找到憑證檔案") print() print("正在啟動 OAuth 2.0 認證流程...") -print("瀏覽器將自動開啟,請完成授權。") +print("終端機會顯示授權網址,請在可登入 Google 的瀏覽器開啟後完成授權。") print() os.environ["GOOGLE_DRIVE_ALLOW_INTERACTIVE_AUTH"] = "true"