Commit Graph
2 Commits
Author SHA1 Message Date
131af9c25a fix(access-code): refetch server providers after access code is accepted (#1081)
ServerProvidersInit fetches /api/server-providers on mount, which on an
ACCESS_CODE-gated deployment happens before any access cookie exists. The
middleware answers 401 and fetchServerProviders returns early, leaving the
settings store on its blank defaults. AccessCodeModal calls onSuccess without
reloading and nothing else calls fetchServerProviders, so every
server-configured provider reads as unconfigured for the whole session until
the user manually reloads.

Re-run the fetch from AccessCodeGuard's onSuccess, once the cookie makes the
request authorizable.

Co-authored-by: thanos-openclaw <thanos@openclaw.local>
Co-authored-by: wyuc <wang-yc24@mails.tsinghua.edu.cn>
2026-08-12 12:16:32 +08:00
c071e02d83 feat: ACCESS_CODE site-level authentication (#407) (#411)
* feat(access-code): add status API endpoint

Returns whether ACCESS_CODE is enabled and whether the current user is
authenticated via cookie, to support the frontend access gate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(access-code): add verify API endpoint

Creates POST /api/access-code/verify that validates ACCESS_CODE env var
and sets an HttpOnly 7-day cookie on success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(access-code): add Next.js middleware to gate API routes

Intercepts all requests when ACCESS_CODE env var is set. API routes
return 401 without the openmaic_access cookie; page requests pass
through so the frontend can render the access-code modal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(i18n): add accessCode translations for all 4 locales

Add accessCode top-level key to en-US, zh-CN, ja-JP, and ru-RU locale
files with title, placeholder, submit, and error strings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add ACCESS_CODE documentation to .env.example

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add AccessCodeGuard component and integrate into root layout

Wraps page children with an access-code gate that checks /api/access-code/status on mount and renders AccessCodeModal when authentication is required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(access-code): add AccessCodeModal component

Adds the modal dialog component that prompts users for an access code,
using existing Dialog/Button/Input UI components and i18n translation keys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(access-code): fix lint error and format files

- Fix useEffect setState pattern in access-code-guard.tsx
- Format middleware.ts and layout.tsx with Prettier

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style(access-code): redesign modal as full-screen gate

Replace generic Radix Dialog with a custom full-screen gate:
- Mesh gradient background with noise texture
- Frosted glass card with backdrop-blur
- Staggered motion animations on mount
- Inline submit button inside input field
- Success state animation before dismissal
- Proper dark mode support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(access-code): address code review findings

Critical:
- Middleware now validates HMAC-signed cookie tokens, not just existence
- Verify endpoint uses timingSafeEqual for constant-time comparison
- Cookie value is now `timestamp.HMAC(ACCESS_CODE, timestamp)` instead of UUID

Important:
- Middleware 401 response includes `errorCode` matching apiError shape
- Status endpoint uses apiSuccess wrapper for consistency
- Remove unused `accessCode.submit` i18n key from all 4 locales

Suggestions:
- Guard renders children during loading (overlay on top, not blocking)
- Network error defaults to enabled=true (safer than silently disabling)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(access-code): use Web Crypto API in middleware for Edge Runtime

Node.js crypto module is not available in Next.js Edge Runtime.
Replace createHmac/timingSafeEqual with crypto.subtle HMAC and
manual constant-length XOR comparison.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: 杨慎 <117187635+cosarah@users.noreply.github.com>
2026-04-12 22:14:14 +08:00