feat: app shell with sidebar + bug fixes
UI: - Add persistent sidebar (210px) with band switcher dropdown, Library/Player/Settings nav, user avatar row, and sign-out button - Align design system CSS vars to CLAUDE.md spec (#0f0f12 bg, #e8a22a amber accent, rgba borders/text) - Remove light mode toggle (no light mode in v1) - Homepage auto-redirects to first band; shows create-band form only when no bands exist - Strip full-page wrappers from all pages (shell owns layout) - Remove debug console.log statements from SongPage Bug fixes: - nginx: trailing slash on `location ^~ /api/v1/bands/` caused 301 redirect on POST, dropping the request body — removed trailing slash - API: _member_from_request (used by nc-scan stream) only accepted Bearer token, not httpOnly cookie — add rh_token cookie fallback - API: internal_secret config field now has a dev default so the service starts without INTERNAL_SECRET env var set Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ class Settings(BaseSettings):
|
||||
|
||||
# Security
|
||||
secret_key: str
|
||||
internal_secret: str # Shared secret for internal service-to-service calls
|
||||
internal_secret: str = "dev-change-me-in-production" # Shared secret for internal service-to-service calls
|
||||
jwt_algorithm: str = "HS256"
|
||||
access_token_expire_minutes: int = 60 # 1 hour
|
||||
|
||||
|
||||
@@ -79,12 +79,18 @@ async def _member_from_request(
|
||||
token: str | None = Query(None),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
) -> Member:
|
||||
"""Resolve member from Authorization header or ?token= query param."""
|
||||
"""Resolve member from Authorization header, ?token= query param, or httpOnly cookie.
|
||||
|
||||
The cookie fallback allows fetch()-based callers (which send credentials:include)
|
||||
to use the same endpoint as EventSource callers (which must use ?token=).
|
||||
"""
|
||||
auth_header = request.headers.get("Authorization")
|
||||
if auth_header:
|
||||
scheme, param = get_authorization_scheme_param(auth_header)
|
||||
if scheme.lower() == "bearer":
|
||||
token = param
|
||||
if not token:
|
||||
token = request.cookies.get("rh_token")
|
||||
if not token:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token required")
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user