Spaces:
Runtime error
Runtime error
Harden Space OAuth startup
Browse files- app.py +2 -1
- tests/test_space.py +48 -0
- waterleaf/space.py +26 -0
- waterleaf/ui.py +4 -2
app.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
from waterleaf.runtime import build_application
|
|
|
|
| 2 |
from waterleaf.web import create_web_app
|
| 3 |
|
|
|
|
| 4 |
application = build_application()
|
| 5 |
app = create_web_app(application)
|
| 6 |
-
|
|
|
|
| 1 |
from waterleaf.runtime import build_application
|
| 2 |
+
from waterleaf.space import configure_hf_space_environment
|
| 3 |
from waterleaf.web import create_web_app
|
| 4 |
|
| 5 |
+
configure_hf_space_environment()
|
| 6 |
application = build_application()
|
| 7 |
app = create_web_app(application)
|
|
|
tests/test_space.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
from waterleaf.space import (
|
| 4 |
+
OAUTH_VARIABLES,
|
| 5 |
+
configure_hf_space_environment,
|
| 6 |
+
has_hf_oauth,
|
| 7 |
+
is_hf_space,
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def _clear_space_environment(monkeypatch):
|
| 12 |
+
for name in (*OAUTH_VARIABLES, "SPACE_ID", "SPACE_HOST", "SYSTEM"):
|
| 13 |
+
monkeypatch.delenv(name, raising=False)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def test_local_environment_does_not_enable_space_oauth(monkeypatch):
|
| 17 |
+
_clear_space_environment(monkeypatch)
|
| 18 |
+
|
| 19 |
+
configure_hf_space_environment()
|
| 20 |
+
|
| 21 |
+
assert not is_hf_space()
|
| 22 |
+
assert not has_hf_oauth()
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def test_complete_oauth_environment_configures_gradio_space(monkeypatch):
|
| 26 |
+
_clear_space_environment(monkeypatch)
|
| 27 |
+
monkeypatch.setenv("SPACE_HOST", "build-small-hackathon-waterleaf.hf.space")
|
| 28 |
+
for name in OAUTH_VARIABLES:
|
| 29 |
+
monkeypatch.setenv(name, f"test-{name.casefold()}")
|
| 30 |
+
|
| 31 |
+
configure_hf_space_environment()
|
| 32 |
+
|
| 33 |
+
assert is_hf_space()
|
| 34 |
+
assert has_hf_oauth()
|
| 35 |
+
assert os.environ["SYSTEM"] == "spaces"
|
| 36 |
+
assert os.environ["SPACE_ID"] == "build-small-hackathon-waterleaf.hf.space"
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def test_incomplete_oauth_environment_is_not_enabled(monkeypatch):
|
| 40 |
+
_clear_space_environment(monkeypatch)
|
| 41 |
+
monkeypatch.setenv("SPACE_HOST", "build-small-hackathon-waterleaf.hf.space")
|
| 42 |
+
monkeypatch.setenv("OAUTH_CLIENT_ID", "client")
|
| 43 |
+
|
| 44 |
+
configure_hf_space_environment()
|
| 45 |
+
|
| 46 |
+
assert is_hf_space()
|
| 47 |
+
assert not has_hf_oauth()
|
| 48 |
+
assert os.environ.get("SYSTEM") is None
|
waterleaf/space.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
OAUTH_VARIABLES = (
|
| 6 |
+
"OAUTH_CLIENT_ID",
|
| 7 |
+
"OAUTH_CLIENT_SECRET",
|
| 8 |
+
"OAUTH_SCOPES",
|
| 9 |
+
"OPENID_PROVIDER_URL",
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def is_hf_space() -> bool:
|
| 14 |
+
return bool(os.getenv("SPACE_ID") or os.getenv("SPACE_HOST"))
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def has_hf_oauth() -> bool:
|
| 18 |
+
return all(os.getenv(name) for name in OAUTH_VARIABLES)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def configure_hf_space_environment() -> None:
|
| 22 |
+
if not is_hf_space() or not has_hf_oauth():
|
| 23 |
+
return
|
| 24 |
+
space_id = os.getenv("SPACE_ID") or os.environ["SPACE_HOST"]
|
| 25 |
+
os.environ.setdefault("SYSTEM", "spaces")
|
| 26 |
+
os.environ.setdefault("SPACE_ID", space_id)
|
waterleaf/ui.py
CHANGED
|
@@ -19,6 +19,7 @@ from waterleaf.models import (
|
|
| 19 |
)
|
| 20 |
from waterleaf.rate_limit import SlidingWindowRateLimiter
|
| 21 |
from waterleaf.services.demo import DemoTaxonomy, build_demo_identification
|
|
|
|
| 22 |
|
| 23 |
CSS = """
|
| 24 |
:root {
|
|
@@ -83,13 +84,14 @@ def build_ui(
|
|
| 83 |
) -> gr.Blocks:
|
| 84 |
identification = identification or application.identification or build_demo_identification()
|
| 85 |
taxonomy = taxonomy or application.taxonomy or DemoTaxonomy()
|
| 86 |
-
|
|
|
|
| 87 |
guest_limiter = SlidingWindowRateLimiter(limit=3, window_seconds=3600)
|
| 88 |
|
| 89 |
def owner_from_profile(profile: gr.OAuthProfile | None) -> str | None:
|
| 90 |
if profile is not None:
|
| 91 |
return profile.username
|
| 92 |
-
if not
|
| 93 |
return os.getenv("WATERLEAF_LOCAL_USER", "local-gardener")
|
| 94 |
return None
|
| 95 |
|
|
|
|
| 19 |
)
|
| 20 |
from waterleaf.rate_limit import SlidingWindowRateLimiter
|
| 21 |
from waterleaf.services.demo import DemoTaxonomy, build_demo_identification
|
| 22 |
+
from waterleaf.space import has_hf_oauth, is_hf_space
|
| 23 |
|
| 24 |
CSS = """
|
| 25 |
:root {
|
|
|
|
| 84 |
) -> gr.Blocks:
|
| 85 |
identification = identification or application.identification or build_demo_identification()
|
| 86 |
taxonomy = taxonomy or application.taxonomy or DemoTaxonomy()
|
| 87 |
+
space_environment = is_hf_space()
|
| 88 |
+
oauth_enabled = has_hf_oauth()
|
| 89 |
guest_limiter = SlidingWindowRateLimiter(limit=3, window_seconds=3600)
|
| 90 |
|
| 91 |
def owner_from_profile(profile: gr.OAuthProfile | None) -> str | None:
|
| 92 |
if profile is not None:
|
| 93 |
return profile.username
|
| 94 |
+
if not space_environment:
|
| 95 |
return os.getenv("WATERLEAF_LOCAL_USER", "local-gardener")
|
| 96 |
return None
|
| 97 |
|