feat: User management #2

Merged
blacklight merged 36 commits from feat/user-management into main 2026-08-19 15:02:05 +02:00
Owner
  • Configuration schema and examples
  • User model role and auth fields
  • UserLink model and profile serialization
  • Redis service helper
  • Access-token dependency and route auth wiring
  • Refresh-token service
  • Registration service
  • Login, refresh, and logout API endpoints
  • Auth endpoint rate limiting
  • Users profile API and route-order bug
  • Admin user management API
  • Invite model and invite service
  • Admin invite API and invite CLI
  • Email sending infrastructure
  • Email verification API
  • Password reset API
  • CLI role and approval commands
  • Federation profile sync
  • OAuth2 client model and admin client API
  • OAuth2 authorization-code + PKCE provider
  • Test infrastructure for Redis and auth helpers
  • Comprehensive acceptance tests
  • Final integration and cleanup

Closes: #1

- [x] Configuration schema and examples - [x] User model role and auth fields - [x] UserLink model and profile serialization - [x] Redis service helper - [x] Access-token dependency and route auth wiring - [x] Refresh-token service - [x] Registration service - [x] Login, refresh, and logout API endpoints - [x] Auth endpoint rate limiting - [x] Users profile API and route-order bug - [x] Admin user management API - [x] Invite model and invite service - [x] Admin invite API and invite CLI - [x] Email sending infrastructure - [x] Email verification API - [x] Password reset API - [x] CLI role and approval commands - [x] Federation profile sync - [x] OAuth2 client model and admin client API - [x] OAuth2 authorization-code + PKCE provider - [x] Test infrastructure for Redis and auth helpers - [x] Comprehensive acceptance tests - [x] Final integration and cleanup Closes: #1
feat(auth): add registration modes, email config, and token settings
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
c16af00777
Expand AuthConfig to support registration modes, email verification,
configurable token expiries, and rate limiting. Add EmailConfig for
SMTP settings. Update access token creation to use minutes. Add tests
for authentication, user management, admin CLI, and config loading.
feat(users): add role enum and replace is_admin flag
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
fee8720e56
Introduces a UserRole str-enum and validates the role column at the
model and service layers.

The admin API and CLI now return and set the role field instead of
is_admin.

Tests are updated for the new field and defaults.
chore(drone): restrict github-mirror step to main push events
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
613432b9cc
fix(user): correct users.role check constraint
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
a96f49f32c
feat(users): add profile links and public user profile endpoint
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
7c7ee3eeba
- Add UserLink model and user->links relationship with cascade delete
- Include links in user profile responses and add link input validation
- Implement /users/{username} fetch with active-user 404 behavior
- Add tests for link validation, serialization, routing, and endpoint behavior
feat(redis): add shared async client and lifespan integration
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
61774dbbf4
Adds songhive.services.redis with lazy initialization and close helpers.
Wires the client into the FastAPI lifespan for uvicorn and explicit
startup/shutdown for the Tornado path. Includes unit tests for singleton,
close, and re-initialization behavior.
feat(auth): implement get_current_user and add auth tests
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
5b0c215f42
- Resolve the TODO placeholder in get_current_user so it validates
  Bearer tokens, loads the user from the database, and checks is_active.
- Add get_user_by_id service helper for user lookup by primary key.
- Restrict token extraction to the Authorization header and remove
  query-string support.
- Allow init_db to accept an existing async engine and force
  re-initialization for tests.
- Share a single engine across test fixtures and override get_db once
  per TestClient session.
feat(users): add refresh token service with rotation and revocation
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
4ff82a9cf0
Implement JWT access token pairing with opaque refresh tokens stored
in Redis by SHA-256 hash. Supports token validation, rotation, and
revocation. Add fakeredis dev dependency and unit tests.
fix(users): validate link URL schemes and split public profile response
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
82320f74a3
Enforce http:// or https:// for user links in the model and API
schema to block unsafe schemes like javascript: and data:.

Introduce PublicUserResponse to omit the internal user id from
public profile endpoints, while keeping it in the authenticated
/me response.

Update User.links to use back_populates and add matching tests.
feat(users): implemented user registration
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
20996591ac
- Defer is_active until email verification when required
- Translate duplicate registration races to 409 Conflict
- Validate invite codes before duplicate username/email checks
- Use pydantic EmailStr for consistent email validation
- Expand tests for boundary cases and concurrency
feat(auth): add register/login and refresh token rotation
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2a55a3fae2
- Add Redis dependency and wire client in tests
- Implement register, login, refresh and logout endpoints
- Add username-or-email lookup and atomic refresh token rotation
- Expand auth/token test coverage for refresh and concurrency
blacklight changed title from feat: User management to WIP: feat: User management 2026-08-18 20:06:35 +02:00
feat: add Redis-backed rate limiting for auth endpoints
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
70b27fc480
- Add fixed-window limiter middleware with IP/path and optional identifier keys
- Apply limiting to register/refresh and per-username limiting for login
- Add unit/integration tests for limiter behavior and failure-open mode
chore: add mypy/isort config and tighten typing
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
fe4a320b6a
- Run isort/mypy in CI and document local commands
- Move isort config to pyproject; add mypy settings
- Fix revoke_refresh_token signature and update auth/tests
- Add small type hints for request state, toml load, CORS parsing
feat: add PATCH /users/me profile update with link replacement
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2284bc46f4
- Add update_profile manager for partial updates and link replace/clear
- Wire new endpoint to update scalars and user links
- Add tests for update_profile and PATCH /me auth/validation
chore(ci): add isort to Drone lint dependencies
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
eb7902cdf5
chore(ci): add mypy to lint step dependency
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
31b79943c4
Add explicit typing/casts for headers, JWT payloads, bcrypt, and SQLAlchemy
scalar results in order to fix mypy issues.
chore(mypy): disable warn_return_any
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
13abb9fde8
feat(admin): add user management endpoints and tests
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
ce02e7d5d0
- Implement list/promote/demote/approve/activate/deactivate admin routes
- Add user manager actions w/ last-active-admin safeguards and 404 handling
- Allow create_user to set initial is_active
- Add API tests covering auth, pagination, lifecycle actions, and edge cases
feat(users): add invite codes for invite-only registration
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
653265fba5
- Add Invite model + User relationship
- Implement invite service (create/validate/consume/revoke)
- Wire invite validation/consumption into registration
- Add invite tests and fixtures
feat(admin): manage invite codes via API and CLI
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
ba3a8bda27
- Add admin endpoints to list/create/revoke invites with total-count header
- Extend admin CLI with create-invite/list-invites and ISO datetime parsing
- Add invite listing/count helpers and expand API/CLI test coverage
feat: add SMTP email service and Celery email tasks
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
24d3b6eacc
- Add plain-text SMTP helpers + verification/password reset templates
- Add Celery tasks and route them to an email queue
- Add tests covering SMTP behavior, content, and misconfiguration handling
- Hash verification/reset tokens; store raw tokens only transiently
- Add verify-email and password-reset endpoints with rate limiting
- Track refresh tokens per user in Redis and support bulk revocation
- Revoke all refresh tokens on password reset; update tests accordingly
feat(rate-limit): add per-account throttling and expand coverage
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
7126d0149e
- Add rate_limit_account dependency keyed by current user
- Apply throttling to admin mutations, PATCH /users/me, and auth logout
- Add tests for logout, per-username login, patch me, and admin invites
feat(rate-limit): apply per-username rate limit to password reset request
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
fc2e62176c
- Use check_rate_limit with the submitted username/email as the
  identifier, matching the /login pattern.
- Add tests for token reuse, inactive user reset, and per-username
  throttling.
feat(cli): add demote/approve admin commands and role option
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
39729980c8
- Add demote-user and approve-user subcommands
- Support --role on create-user (mutually exclusive with --admin)
- Use user_manager for promote/demote/approve and report role on creation
- Extend CLI admin test coverage for new options and commands
feat(users): sync ActivityPub actor on profile updates
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
6212cd729d
- Commit profile changes before actor sync in PATCH /users/me
- Include avatar and profile links in actor documents
- Cache federation storage instance by DB URL for reuse
- Add tests for actor doc fields, sync behavior, and commit persistence
feat(oauth): add oauth2 client model and admin client API
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
09acae81a6
Introduce the OAuth2Client registry so administrators can create, list,
and delete OAuth2 clients.

Client secrets are generated with secrets.token_urlsafe, hashed with
bcrypt, and exposed only once on creation. Redirect URIs and grant types
are validated, with a default grant type of authorization_code.

Includes unit/integration tests.
feat(admin): add OAuth client detail endpoint
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
0df4154fdc
- Add GET /admin/oauth/clients/{client_id} with 404 handling
- Centralize default grant types constant and reuse in validation
- Extend OAuth tests for timestamps, custom grant types, and new endpoint
feat(auth): add OAuth2 auth code + PKCE token endpoints
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
749922f694
- Add /oauth/authorize, /oauth/token, /oauth/revoke, /oauth/introspect routes
- Implement Redis-backed auth code, token issue/refresh, introspection, revocation
- Add provider flow tests covering PKCE, public clients, and error cases
test: add shared auth/user fixtures and stabilize Redis usage in tests
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
aa916cce0a
- Monkeypatch Redis client in TestClient fixture to avoid real connections
- Add make_user and auth_headers helpers; update admin/oauth tests to use them
- Remove mypy tests.* override from pyproject.toml
chore(deps): add python-multipart requirement
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
db40879191
fix(security): harden config, CORS, OAuth, and avatar URL validation
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
8b23d556f9
- Require strong JWT secret_key; default CORS allow-list and safe credentials
- Restrict OAuth redirect URIs to https (allow http only for localhost/loopback)
- Atomically consume auth codes/refresh tokens; require client auth for introspection
- Validate/strip avatar_url and only federate http(s) icons
fix(app): handle SIGINT/SIGTERM via asyncio signal handlers
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
253ee732ef
- Add fallback to signal.signal when add_signal_handler is unavailable
- Add integration test to ensure prompt shutdown on SIGINT/SIGTERM
blacklight changed title from WIP: feat: User management to feat: User management 2026-08-19 13:57:40 +02:00
chore(tests): removed redundant configuration in pyproject.toml
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
97889b4ace
fix: stabilize Black formatting for test_app.py and pin target-version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
867d3ba707
Black 26 (latest in CI) was targeting Python 3.15 and reformatting the
multiline f-string in tests/test_app.py differently than Black 25 (local).
Set [tool.black] target-version to py310 and refactor the config helper to
avoid a multiline f-string layout that differs across Black versions.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
blacklight deleted branch feat/user-management 2026-08-19 15:02:05 +02:00
Sign in to join this conversation.
No description provided.