github-actions[bot] commited on
Commit
3fe4567
·
1 Parent(s): dd79664

Sync from GitHub b32aec24fbce3d4b772838e2ed3310b56213b520

Browse files
README.md CHANGED
@@ -266,7 +266,7 @@ This repo now includes:
266
  1. Create or switch your Space to **Docker** SDK.
267
  2. Push this repo to your Space (or use the GitHub Action sync workflow already in `.github/workflows/deploy-hf-space.yml`).
268
  3. In Space variables/secrets, set at minimum:
269
- - `AUTH_MODE=auto` (or explicitly `hf_oauth` / `oauth`)
270
  - `APP_SESSION_SECRET=<strong-random-secret>`
271
  - `STORAGE_BASE_DIR=/data`
272
  - `OPENAI_API_KEY=<key>` (if using OpenAI features)
@@ -276,6 +276,4 @@ This repo now includes:
276
  - `HF_OAUTH_REDIRECT_URI` (your Space callback URL)
277
  - `AUTH_SUCCESS_REDIRECT_URL` (your Space URL)
278
 
279
- With `AUTH_MODE=auto`, backend auth switches to OAuth automatically when both `HF_OAUTH_CLIENT_ID` and `HF_OAUTH_CLIENT_SECRET` are configured.
280
-
281
  The container exposes Streamlit on port `7860` and points the frontend to the internal backend via `BACKEND_URL=http://127.0.0.1:8000`.
 
266
  1. Create or switch your Space to **Docker** SDK.
267
  2. Push this repo to your Space (or use the GitHub Action sync workflow already in `.github/workflows/deploy-hf-space.yml`).
268
  3. In Space variables/secrets, set at minimum:
269
+ - `AUTH_MODE=dev` (or `hf_oauth`)
270
  - `APP_SESSION_SECRET=<strong-random-secret>`
271
  - `STORAGE_BASE_DIR=/data`
272
  - `OPENAI_API_KEY=<key>` (if using OpenAI features)
 
276
  - `HF_OAUTH_REDIRECT_URI` (your Space callback URL)
277
  - `AUTH_SUCCESS_REDIRECT_URL` (your Space URL)
278
 
 
 
279
  The container exposes Streamlit on port `7860` and points the frontend to the internal backend via `BACKEND_URL=http://127.0.0.1:8000`.
app.py CHANGED
@@ -12,7 +12,6 @@ from uuid import uuid4
12
  from fastapi.concurrency import run_in_threadpool
13
  from fastapi import APIRouter, BackgroundTasks, Depends, FastAPI, File, Form, HTTPException, Request, UploadFile, status
14
  from fastapi.responses import FileResponse, RedirectResponse
15
- from dotenv import load_dotenv
16
  from pydantic import BaseModel, Field
17
  from sqlalchemy import text
18
  from sqlalchemy.orm import Session
@@ -42,8 +41,6 @@ from src.artifacts.podcast_generator import PodcastGenerator
42
  from utils.llm_client import LLMConfigError, generate_chat_completion
43
  from utils.prompt_templates import build_rag_system_prompt, build_rag_user_prompt
44
 
45
- load_dotenv()
46
-
47
 
48
  @asynccontextmanager
49
  async def lifespan(_: FastAPI):
 
12
  from fastapi.concurrency import run_in_threadpool
13
  from fastapi import APIRouter, BackgroundTasks, Depends, FastAPI, File, Form, HTTPException, Request, UploadFile, status
14
  from fastapi.responses import FileResponse, RedirectResponse
 
15
  from pydantic import BaseModel, Field
16
  from sqlalchemy import text
17
  from sqlalchemy.orm import Session
 
41
  from utils.llm_client import LLMConfigError, generate_chat_completion
42
  from utils.prompt_templates import build_rag_system_prompt, build_rag_user_prompt
43
 
 
 
44
 
45
  @asynccontextmanager
46
  async def lifespan(_: FastAPI):
auth/oauth.py CHANGED
@@ -13,14 +13,6 @@ class HFOAuthError(RuntimeError):
13
  pass
14
 
15
 
16
- def _first_env(*names: str) -> str:
17
- for name in names:
18
- value = os.getenv(name, "").strip()
19
- if value:
20
- return value
21
- return ""
22
-
23
-
24
  @dataclass(frozen=True)
25
  class HFOAuthSettings:
26
  client_id: str
@@ -32,8 +24,8 @@ class HFOAuthSettings:
32
 
33
 
34
  def get_hf_oauth_settings() -> HFOAuthSettings:
35
- client_id = _first_env("HF_OAUTH_CLIENT_ID", "OAUTH_CLIENT_ID")
36
- client_secret = _first_env("HF_OAUTH_CLIENT_SECRET", "OAUTH_CLIENT_SECRET")
37
  if not client_id or not client_secret:
38
  raise HFOAuthError("HF OAuth client configuration is missing.")
39
 
 
13
  pass
14
 
15
 
 
 
 
 
 
 
 
 
16
  @dataclass(frozen=True)
17
  class HFOAuthSettings:
18
  client_id: str
 
24
 
25
 
26
  def get_hf_oauth_settings() -> HFOAuthSettings:
27
+ client_id = os.getenv("HF_OAUTH_CLIENT_ID", "").strip()
28
+ client_secret = os.getenv("HF_OAUTH_CLIENT_SECRET", "").strip()
29
  if not client_id or not client_secret:
30
  raise HFOAuthError("HF OAuth client configuration is missing.")
31
 
auth/session.py CHANGED
@@ -30,43 +30,14 @@ class AuthBridgeTokenError(ValueError):
30
  pass
31
 
32
 
33
- def _first_env(*names: str) -> str:
34
- for name in names:
35
- value = os.getenv(name, "").strip()
36
- if value:
37
- return value
38
- return ""
39
-
40
-
41
  def get_auth_mode() -> str:
42
- configured = os.getenv("AUTH_MODE", "").strip().lower()
43
- if configured == AUTH_MODE_DEV:
44
- return AUTH_MODE_DEV
45
- if configured in {AUTH_MODE_HF, "oauth"}:
46
- return AUTH_MODE_HF
47
- if not configured or configured == "auto":
48
- has_hf_client = bool(_first_env("HF_OAUTH_CLIENT_ID", "OAUTH_CLIENT_ID"))
49
- has_hf_secret = bool(_first_env("HF_OAUTH_CLIENT_SECRET", "OAUTH_CLIENT_SECRET"))
50
- if has_hf_client and has_hf_secret:
51
- return AUTH_MODE_HF
52
- return AUTH_MODE_DEV
53
-
54
-
55
- def _resolve_session_secret() -> str:
56
- configured = os.getenv("APP_SESSION_SECRET", "").strip()
57
- if configured:
58
- return configured
59
- if get_auth_mode() == AUTH_MODE_HF:
60
- # In HF Spaces OAuth deployments, OAUTH_CLIENT_SECRET is usually injected.
61
- oauth_secret = _first_env("HF_OAUTH_CLIENT_SECRET", "OAUTH_CLIENT_SECRET")
62
- if oauth_secret:
63
- return oauth_secret
64
- return DEFAULT_DEV_SESSION_SECRET
65
 
66
 
67
  def configure_session_middleware(app) -> None:
68
  """Attach Starlette session middleware once during app setup."""
69
- secret = _resolve_session_secret()
70
  auth_mode = get_auth_mode()
71
  if auth_mode == AUTH_MODE_HF and (not secret or secret == DEFAULT_DEV_SESSION_SECRET):
72
  raise RuntimeError("APP_SESSION_SECRET must be set to a non-default value in hf_oauth mode.")
@@ -90,7 +61,7 @@ def configure_session_middleware(app) -> None:
90
 
91
 
92
  def _bridge_serializer() -> URLSafeTimedSerializer:
93
- secret = _resolve_session_secret()
94
  return URLSafeTimedSerializer(secret_key=secret, salt=AUTH_BRIDGE_SALT)
95
 
96
 
 
30
  pass
31
 
32
 
 
 
 
 
 
 
 
 
33
  def get_auth_mode() -> str:
34
+ configured = os.getenv("AUTH_MODE", AUTH_MODE_DEV).strip().lower()
35
+ return configured if configured in {AUTH_MODE_DEV, AUTH_MODE_HF} else AUTH_MODE_DEV
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
 
38
  def configure_session_middleware(app) -> None:
39
  """Attach Starlette session middleware once during app setup."""
40
+ secret = os.getenv("APP_SESSION_SECRET", DEFAULT_DEV_SESSION_SECRET).strip()
41
  auth_mode = get_auth_mode()
42
  if auth_mode == AUTH_MODE_HF and (not secret or secret == DEFAULT_DEV_SESSION_SECRET):
43
  raise RuntimeError("APP_SESSION_SECRET must be set to a non-default value in hf_oauth mode.")
 
61
 
62
 
63
  def _bridge_serializer() -> URLSafeTimedSerializer:
64
+ secret = os.getenv("APP_SESSION_SECRET", DEFAULT_DEV_SESSION_SECRET)
65
  return URLSafeTimedSerializer(secret_key=secret, salt=AUTH_BRIDGE_SALT)
66
 
67
 
frontend/app.py CHANGED
@@ -5,9 +5,6 @@ from typing import Any
5
 
6
  import requests
7
  import streamlit as st
8
- from dotenv import load_dotenv
9
-
10
- load_dotenv()
11
 
12
  st.set_page_config(page_title="NotebookLM Clone", page_icon="📚", layout="wide")
13
 
 
5
 
6
  import requests
7
  import streamlit as st
 
 
 
8
 
9
  st.set_page_config(page_title="NotebookLM Clone", page_icon="📚", layout="wide")
10
 
tests/test_auth_mode.py DELETED
@@ -1,42 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from auth.session import AUTH_MODE_DEV, AUTH_MODE_HF, get_auth_mode
4
-
5
-
6
- def test_get_auth_mode_dev_explicit(monkeypatch):
7
- monkeypatch.setenv("AUTH_MODE", "dev")
8
- monkeypatch.delenv("HF_OAUTH_CLIENT_ID", raising=False)
9
- monkeypatch.delenv("HF_OAUTH_CLIENT_SECRET", raising=False)
10
- assert get_auth_mode() == AUTH_MODE_DEV
11
-
12
-
13
- def test_get_auth_mode_oauth_alias(monkeypatch):
14
- monkeypatch.setenv("AUTH_MODE", "oauth")
15
- assert get_auth_mode() == AUTH_MODE_HF
16
-
17
-
18
- def test_get_auth_mode_auto_switches_to_hf(monkeypatch):
19
- monkeypatch.setenv("AUTH_MODE", "auto")
20
- monkeypatch.setenv("HF_OAUTH_CLIENT_ID", "client-id")
21
- monkeypatch.setenv("HF_OAUTH_CLIENT_SECRET", "client-secret")
22
- monkeypatch.delenv("OAUTH_CLIENT_ID", raising=False)
23
- monkeypatch.delenv("OAUTH_CLIENT_SECRET", raising=False)
24
- assert get_auth_mode() == AUTH_MODE_HF
25
-
26
-
27
- def test_get_auth_mode_auto_falls_back_to_dev(monkeypatch):
28
- monkeypatch.setenv("AUTH_MODE", "auto")
29
- monkeypatch.delenv("HF_OAUTH_CLIENT_ID", raising=False)
30
- monkeypatch.delenv("HF_OAUTH_CLIENT_SECRET", raising=False)
31
- monkeypatch.delenv("OAUTH_CLIENT_ID", raising=False)
32
- monkeypatch.delenv("OAUTH_CLIENT_SECRET", raising=False)
33
- assert get_auth_mode() == AUTH_MODE_DEV
34
-
35
-
36
- def test_get_auth_mode_auto_switches_to_hf_with_space_oauth_vars(monkeypatch):
37
- monkeypatch.setenv("AUTH_MODE", "auto")
38
- monkeypatch.delenv("HF_OAUTH_CLIENT_ID", raising=False)
39
- monkeypatch.delenv("HF_OAUTH_CLIENT_SECRET", raising=False)
40
- monkeypatch.setenv("OAUTH_CLIENT_ID", "space-client-id")
41
- monkeypatch.setenv("OAUTH_CLIENT_SECRET", "space-client-secret")
42
- assert get_auth_mode() == AUTH_MODE_HF
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tests/test_hf_oauth_settings.py DELETED
@@ -1,14 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from auth.oauth import get_hf_oauth_settings
4
-
5
-
6
- def test_hf_oauth_settings_accept_space_oauth_vars(monkeypatch):
7
- monkeypatch.delenv("HF_OAUTH_CLIENT_ID", raising=False)
8
- monkeypatch.delenv("HF_OAUTH_CLIENT_SECRET", raising=False)
9
- monkeypatch.setenv("OAUTH_CLIENT_ID", "space-client-id")
10
- monkeypatch.setenv("OAUTH_CLIENT_SECRET", "space-client-secret")
11
-
12
- settings = get_hf_oauth_settings()
13
- assert settings.client_id == "space-client-id"
14
- assert settings.client_secret == "space-client-secret"