feat: add optional authentication with login, registration, and admin dashboard#336
Merged
Merged
Conversation
Closes HKUDS#227. Auth is disabled by default (AUTH_ENABLED=false) so localhost usage is unaffected. Set AUTH_ENABLED=true + NEXT_PUBLIC_AUTH_ENABLED=true to require login when hosting publicly. Backend - New deeptutor/services/auth.py: bcrypt password hashing, JWT create/decode, multi-user JSON store with role + created_at schema, auto-migration of old flat-hash format, first-user → admin bootstrap - New deeptutor/api/routers/auth.py: require_auth / require_admin FastAPI dependencies; public endpoints /login /logout /status /register /is_first_user; admin-only /users /users/{u}/role - deeptutor/api/main.py: Depends(require_auth) applied to all 14 protected routers - deeptutor/api/routers/unified_ws.py: cookie-based JWT check before ws.accept() when AUTH_ENABLED - Added bcrypt>=4.0.0 and python-jose[cryptography]>=3.3.0 to requirements/server.txt and pyproject.toml extras Frontend - web/middleware.ts: route protection; /login and /register are public - web/lib/api.ts: apiFetch wrapper — credentials:include + 401→login - web/lib/auth.ts: login/logout/fetchAuthStatus + register() + checkIsFirstUser() - web/lib/admin-api.ts: listUsers / deleteUser / setUserRole - web/lib/session-api.ts: credentials:include on all fetches; expectJson redirects to /login on 401 instead of throwing - web/app/(auth)/login/page.tsx: auto-redirects to /register when no users exist; shows success banner after registration - web/app/(auth)/register/page.tsx: new registration page with first-user admin notice and password confirmation - web/app/(admin)/admin/users/page.tsx: admin dashboard — user table with role toggle and delete; guards against self-demotion/deletion - AdminLink and LogoutButton hidden when AUTH_ENABLED=false - .env.example and README.md updated with auth vars and setup guide Made-with: Cursor
Introduces PocketBase as an optional sidecar for authentication and session/KB storage, activated only when POCKETBASE_URL is set in .env. Falls back to the existing SQLite/JSON backend when not configured. Backend: - SessionStoreProtocol (typing.Protocol) + get_session_store() factory - PocketBaseSessionStore: JSONL write-ahead buffer, batch-flush on turn end - pocketbase_client.py: singleton admin client, 60s in-memory token cache - auth.py: additive PocketBase path (email-based login/register) - CORS: explicit origins instead of wildcard (wildcard+credentials fails) - WebSocket: validate token at connect time when AUTH_ENABLED Infrastructure: - docker-compose: pocketbase service with healthcheck + depends_on - scripts/pb_setup.py: idempotent PocketBase collection bootstrap - requirements/server.txt: pocketbase>=0.12.0 Frontend: - Register/login: username field -> email field for PocketBase mode - auth.ts: normalise FastAPI 422 errors to plain strings - agents page: guard bots.map() against non-array responses - settings page: graceful fetch error handling - *.env.local added to .gitignore Docs: README PocketBase sidecar setup section added
Collaborator
|
Thank you!!!! |
Collaborator
|
I'll take a look at it very soon |
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Continuation of #252, re-targeted to
multi-userand aligned to v1.1.0.Implements optional authentication for public deployments. Auth is disabled by default (
AUTH_ENABLED=false), so all existing localhost users are completely unaffected.Auth (simple, no PocketBase)
require_auth/require_adminFastAPI dependenciesPocketBase sidecar (optional)
POCKETBASE_URLis set — falls back to SQLite/JSON otherwiseSessionStoreProtocol+PocketBaseSessionStorewith JSONL write-ahead bufferSetup
AUTH_ENABLED=true+NEXT_PUBLIC_AUTH_ENABLED=true/register— first user becomes admin