fastapi-fullauth 0.6.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/CHANGELOG.md +53 -1
  2. fastapi_fullauth-0.7.0/Makefile +64 -0
  3. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/PKG-INFO +34 -24
  4. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/README.md +32 -22
  5. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/adapters/index.md +18 -8
  6. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/api-reference.md +14 -3
  7. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/configuration.md +3 -1
  8. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/getting-started.md +4 -1
  9. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/index.md +12 -3
  10. fastapi_fullauth-0.7.0/docs/llms-full.txt +2141 -0
  11. fastapi_fullauth-0.7.0/docs/llms.txt +30 -0
  12. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/oauth.md +23 -20
  13. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlalchemy_app/auth.py +4 -2
  14. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlmodel_app/auth.py +4 -2
  15. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/__init__.py +1 -1
  16. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/__init__.py +1 -2
  17. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/sqlalchemy/adapter.py +4 -7
  18. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/sqlmodel/adapter.py +8 -11
  19. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/config.py +4 -2
  20. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/dependencies/current_user.py +4 -4
  21. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/exceptions.py +34 -0
  22. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/flows/__init__.py +4 -0
  23. fastapi_fullauth-0.7.0/fastapi_fullauth/flows/change_password.py +31 -0
  24. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/flows/email_verify.py +3 -2
  25. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/flows/login.py +6 -7
  26. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/flows/oauth.py +2 -3
  27. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/flows/password_reset.py +7 -1
  28. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/flows/register.py +5 -0
  29. fastapi_fullauth-0.7.0/fastapi_fullauth/flows/update_profile.py +27 -0
  30. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/fullauth.py +8 -44
  31. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/hooks.py +2 -2
  32. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/middleware/csrf.py +1 -1
  33. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/oauth/base.py +4 -15
  34. fastapi_fullauth-0.7.0/fastapi_fullauth/protection/__init__.py +15 -0
  35. fastapi_fullauth-0.7.0/fastapi_fullauth/protection/lockout.py +129 -0
  36. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/router/_models.py +15 -1
  37. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/router/auth.py +24 -18
  38. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/router/oauth.py +20 -17
  39. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/router/profile.py +24 -39
  40. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/router/verify.py +3 -5
  41. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/types.py +17 -4
  42. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/mkdocs.yml +0 -1
  43. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/pyproject.toml +13 -1
  44. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/tests/conftest.py +33 -4
  45. fastapi_fullauth-0.7.0/tests/test_auth.py +809 -0
  46. fastapi_fullauth-0.7.0/tests/test_config.py +604 -0
  47. fastapi_fullauth-0.7.0/tests/test_hooks.py +185 -0
  48. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/tests/test_oauth.py +39 -16
  49. fastapi_fullauth-0.6.0/tests/test_new_endpoints.py → fastapi_fullauth-0.7.0/tests/test_profile.py +66 -117
  50. fastapi_fullauth-0.7.0/tests/test_rbac.py +446 -0
  51. fastapi_fullauth-0.6.0/tests/test_middleware.py → fastapi_fullauth-0.7.0/tests/test_security.py +112 -32
  52. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/tests/test_sqlalchemy_adapter.py +2 -2
  53. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/tests/test_sqlmodel_adapter.py +6 -24
  54. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/uv.lock +1 -1
  55. fastapi_fullauth-0.6.0/docs/adapters/memory.md +0 -34
  56. fastapi_fullauth-0.6.0/examples/memory_app/auth.py +0 -8
  57. fastapi_fullauth-0.6.0/examples/memory_app/main.py +0 -13
  58. fastapi_fullauth-0.6.0/examples/sqlmodel_app/routes.py +0 -15
  59. fastapi_fullauth-0.6.0/fastapi_fullauth/adapters/memory.py +0 -161
  60. fastapi_fullauth-0.6.0/fastapi_fullauth/migrations/__init__.py +0 -3
  61. fastapi_fullauth-0.6.0/fastapi_fullauth/protection/__init__.py +0 -4
  62. fastapi_fullauth-0.6.0/fastapi_fullauth/protection/lockout.py +0 -41
  63. fastapi_fullauth-0.6.0/fastapi_fullauth/rbac/__init__.py +0 -3
  64. fastapi_fullauth-0.6.0/tests/__init__.py +0 -0
  65. fastapi_fullauth-0.6.0/tests/test_auth_flows.py +0 -177
  66. fastapi_fullauth-0.6.0/tests/test_customization.py +0 -361
  67. fastapi_fullauth-0.6.0/tests/test_dx_improvements.py +0 -312
  68. fastapi_fullauth-0.6.0/tests/test_email_verify.py +0 -116
  69. fastapi_fullauth-0.6.0/tests/test_lockout.py +0 -52
  70. fastapi_fullauth-0.6.0/tests/test_rbac.py +0 -272
  71. fastapi_fullauth-0.6.0/tests/test_refresh_tokens.py +0 -379
  72. fastapi_fullauth-0.6.0/tests/test_roles.py +0 -161
  73. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  74. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  75. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.github/pull_request_template.md +0 -0
  76. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.github/workflows/ci.yml +0 -0
  77. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.github/workflows/docs.yml +0 -0
  78. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.github/workflows/publish.yml +0 -0
  79. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.gitignore +0 -0
  80. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/.python-version +0 -0
  81. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/CONTRIBUTING.md +0 -0
  82. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/LICENSE +0 -0
  83. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/adapters/sqlalchemy.md +0 -0
  84. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/adapters/sqlmodel.md +0 -0
  85. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/auth/custom-claims.md +0 -0
  86. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/auth/dependencies.md +0 -0
  87. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/auth/hooks.md +0 -0
  88. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/auth/passwords.md +0 -0
  89. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/contributing.md +0 -0
  90. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/migrations.md +0 -0
  91. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/security/middleware.md +0 -0
  92. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/security/rate-limiting.md +0 -0
  93. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/docs/stylesheets/home.css +0 -0
  94. {fastapi_fullauth-0.6.0/examples/memory_app → fastapi_fullauth-0.7.0/examples/sqlalchemy_app}/__init__.py +0 -0
  95. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlalchemy_app/config.py +0 -0
  96. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlalchemy_app/main.py +0 -0
  97. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlalchemy_app/models.py +0 -0
  98. {fastapi_fullauth-0.6.0/examples/memory_app → fastapi_fullauth-0.7.0/examples/sqlalchemy_app}/routes.py +0 -0
  99. {fastapi_fullauth-0.6.0/examples/sqlalchemy_app → fastapi_fullauth-0.7.0/examples/sqlmodel_app}/__init__.py +0 -0
  100. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlmodel_app/config.py +0 -0
  101. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlmodel_app/main.py +0 -0
  102. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/examples/sqlmodel_app/models.py +0 -0
  103. {fastapi_fullauth-0.6.0/examples/sqlalchemy_app → fastapi_fullauth-0.7.0/examples/sqlmodel_app}/routes.py +0 -0
  104. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/base.py +0 -0
  105. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/sqlalchemy/__init__.py +0 -0
  106. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/sqlalchemy/models.py +0 -0
  107. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/sqlmodel/__init__.py +0 -0
  108. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/adapters/sqlmodel/models.py +0 -0
  109. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/backends/__init__.py +0 -0
  110. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/backends/base.py +0 -0
  111. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/backends/bearer.py +0 -0
  112. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/backends/cookie.py +0 -0
  113. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/core/__init__.py +0 -0
  114. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/core/crypto.py +0 -0
  115. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/core/redis_blacklist.py +0 -0
  116. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/core/tokens.py +0 -0
  117. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/dependencies/__init__.py +0 -0
  118. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/dependencies/require_role.py +0 -0
  119. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/flows/logout.py +0 -0
  120. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/middleware/__init__.py +0 -0
  121. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/middleware/ratelimit.py +0 -0
  122. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/middleware/security_headers.py +0 -0
  123. /fastapi_fullauth-0.6.0/fastapi_fullauth/migrations/helpers.py → /fastapi_fullauth-0.7.0/fastapi_fullauth/migrations.py +0 -0
  124. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/oauth/__init__.py +0 -0
  125. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/oauth/github.py +0 -0
  126. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/oauth/google.py +0 -0
  127. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/protection/ratelimit.py +0 -0
  128. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/router/__init__.py +0 -0
  129. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/router/admin.py +0 -0
  130. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/utils.py +0 -0
  131. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/fastapi_fullauth/validators.py +0 -0
  132. {fastapi_fullauth-0.6.0/examples/sqlmodel_app → fastapi_fullauth-0.7.0/tests}/__init__.py +0 -0
  133. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/tests/test_crypto.py +0 -0
  134. {fastapi_fullauth-0.6.0 → fastapi_fullauth-0.7.0}/tests/test_tokens.py +0 -0
@@ -1,5 +1,57 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Breaking changes
6
+
7
+ - **InMemory adapter removed** — use SQLModel + SQLite for prototyping instead.
8
+ - **`UserID` is now `UUID`** (was `str | int | UUID`) — all adapter methods, `RefreshToken.user_id`, `OAuthAccount.user_id`, and `RoleAssignment.user_id` are now `UUID`.
9
+ - **OAuth providers passed as objects** — `FullAuth(providers=[GoogleOAuthProvider(...)])` replaces `OAUTH_PROVIDERS` dict in config. `OAuthProviderConfig` removed.
10
+ - **`OAuthProvider` simplified** — only `redirect_uris: list[str]` (removed singular `redirect_uri`). `get_redirect_uri()` removed.
11
+ - **`redirect_uri` required in authorize URL** — clients must pass `?redirect_uri=` in the OAuth authorize request.
12
+
13
+ ### Breaking changes (audit cleanup)
14
+
15
+ - **`include_user_in_login` moved to config** — use `FullAuthConfig(INCLUDE_USER_IN_LOGIN=True)` or `FULLAUTH_INCLUDE_USER_IN_LOGIN=true` env var instead of `FullAuth(include_user_in_login=True)`.
16
+ - **Login response always includes `user` field** — when `INCLUDE_USER_IN_LOGIN=False`, `user` is `null` (previously the key was absent). When `True`, `user` contains the full user schema object.
17
+
18
+ ### Added
19
+
20
+ - **Redis lockout backend** — `LOCKOUT_BACKEND="redis"` for multi-worker deployments
21
+ - `LOCKOUT_ENABLED` config — disable account lockout entirely (`False`)
22
+ - `INCLUDE_USER_IN_LOGIN` config — include user object in login/OAuth callback response
23
+ - `LoginResponse` dynamic model — login and OAuth callback routes now have proper `response_model` with typed `user` field matching the configured user schema
24
+ - `validate_profile_updates` flow — profile field filtering extracted from router to `flows/update_profile.py`
25
+ - `NoValidFieldsError`, `UnknownFieldsError` exceptions for profile update validation
26
+ - `change_password` flow — business logic extracted from profile router
27
+ - `PROTECTED_FIELDS` ClassVar on `UserSchema` — users can extend in subclasses
28
+ - Password validation moved to flows (`register`, `reset_password`, `change_password`)
29
+ - `Makefile` with `make check`, `make test`, `make lint`, `make format`, `make docs`, etc.
30
+
31
+ ### Changed
32
+
33
+ - `LockoutManager` is now an abstract base class with async methods
34
+ - `InMemoryLockoutManager` replaces the old sync `LockoutManager`
35
+ - `migrations/` package flattened to single `migrations.py` module (import paths unchanged)
36
+ - 4 `type: ignore` comments fixed (replaced with `getattr`, assertions, `model_validate`)
37
+ - Misplaced `type: ignore` comments moved inline
38
+ - 204 routes (`delete_me`, `unlink_oauth_account`) no longer return unnecessary `Response` objects
39
+ - Logout route return type corrected to `Response` (needs it for cookie deletion)
40
+ - All tests migrated from InMemory to SQLModel + SQLite
41
+ - Tests regrouped: `test_auth`, `test_profile`, `test_config`, `test_hooks`, `test_security`, `test_rbac`
42
+ - `UUID(payload.sub)` conversion at token boundaries (dependencies, router, flows)
43
+ - Removed `isinstance` str-to-UUID guards from adapters
44
+ - Removed `str(user.id)` / `str(row.user_id)` conversions — UUID used directly
45
+
46
+ ### Removed
47
+
48
+ - `InMemoryAdapter` and `examples/memory_app/`
49
+ - `OAuthProviderConfig` from config
50
+ - `OAUTH_PROVIDERS` from `FullAuthConfig`
51
+ - `FullAuth._build_oauth_providers()` and `_OAUTH_PROVIDER_REGISTRY`
52
+ - `OAuthProvider.get_redirect_uri()` method
53
+ - `rbac/` package (was empty, just re-exported from `dependencies`)
54
+
3
55
  ## 0.6.0
4
56
 
5
57
  ### Breaking changes
@@ -28,7 +80,7 @@
28
80
  - `fullauth.router` still works as before (composes all sub-routers), `fullauth.init_app(app)` unchanged
29
81
  - `hash_password()` and `password_needs_rehash()` now accept explicit `algorithm` parameter (default `argon2id`)
30
82
  - Shared request/response models extracted to `router/_models.py`
31
- - RBAC permissions (`require_role`, `require_permission`) available via `fastapi_fullauth.dependencies` (removed `rbac/` re-export package will happen in next release)
83
+ - RBAC permissions (`require_role`, `require_permission`) available via `fastapi_fullauth.dependencies`
32
84
 
33
85
  ### Removed
34
86
 
@@ -0,0 +1,64 @@
1
+ .PHONY: install test lint format check fix clean build docs
2
+
3
+ # Install dependencies
4
+ install:
5
+ uv sync --dev --extra sqlalchemy --extra sqlmodel --extra oauth --extra redis
6
+
7
+ # Run tests
8
+ test:
9
+ uv run pytest tests/ -x --tb=short
10
+
11
+ # Run tests with verbose output
12
+ test-v:
13
+ uv run pytest tests/ -v
14
+
15
+ # Run a specific test file
16
+ # Usage: make test-file FILE=test_auth
17
+ test-file:
18
+ uv run pytest tests/$(FILE).py -x --tb=short -v
19
+
20
+ # Lint check (no changes)
21
+ lint:
22
+ uv run ruff check .
23
+
24
+ # Format check (no changes)
25
+ format-check:
26
+ uv run ruff format --check .
27
+
28
+ # Fix lint issues
29
+ fix:
30
+ uv run ruff check --fix .
31
+
32
+ # Format code
33
+ format:
34
+ uv run ruff format .
35
+
36
+ # Run all checks (format + lint + tests) — run before committing
37
+ check: format-check lint test
38
+
39
+ # Fix all issues then verify
40
+ fix-all: format fix test
41
+
42
+ # Build package
43
+ build:
44
+ uv build
45
+
46
+ # Serve docs locally
47
+ docs:
48
+ uv run mkdocs serve
49
+
50
+ # Build docs
51
+ docs-build:
52
+ uv run mkdocs build
53
+
54
+ # Run example apps
55
+ run-sqlmodel:
56
+ uv run uvicorn examples.sqlmodel_app.main:app --reload
57
+
58
+ run-sqlalchemy:
59
+ uv run uvicorn examples.sqlalchemy_app.main:app --reload
60
+
61
+ # Clean build artifacts
62
+ clean:
63
+ rm -rf dist/ build/ *.egg-info .pytest_cache .ruff_cache
64
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-fullauth
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Production-grade, async-native authentication and authorization library for FastAPI
5
5
  Project-URL: Homepage, https://github.com/mdfarhankc/fastapi-fullauth
6
6
  Project-URL: Documentation, https://mdfarhankc.github.io/fastapi-fullauth
7
7
  Project-URL: Repository, https://github.com/mdfarhankc/fastapi-fullauth
8
8
  License-Expression: MIT
9
9
  License-File: LICENSE
10
- Keywords: argon2,authentication,authorization,fastapi,jwt,security
10
+ Keywords: argon2,async,authentication,authorization,bcrypt,csrf,fastapi,jwt,oauth2,password-hashing,pydantic,rbac,redis,refresh-token,role-based-access-control,security,sqlalchemy,sqlmodel
11
11
  Classifier: Development Status :: 3 - Alpha
12
12
  Classifier: Framework :: FastAPI
13
13
  Classifier: Intended Audience :: Developers
@@ -82,7 +82,7 @@ Add a complete authentication and authorization system to your **FastAPI** proje
82
82
  - **Role-based access control** — `CurrentUser`, `VerifiedUser`, `SuperUser`, `require_role()`
83
83
  - **Rate limiting** — per-route auth limits + global middleware (memory or Redis)
84
84
  - **CSRF protection** and **security headers** middleware, auto-wired
85
- - **Pluggable adapters** — SQLModel, SQLAlchemy, or in-memory
85
+ - **Pluggable adapters** — SQLModel or SQLAlchemy
86
86
  - **Generic type parameters** — define your own schemas with full IDE support and type safety
87
87
  - **Composable routers** — include only the route groups you need
88
88
  - **Event hooks** — `after_register`, `after_login`, `send_verification_email`, etc.
@@ -115,12 +115,12 @@ pip install fastapi-fullauth[all]
115
115
  ```python
116
116
  from fastapi import FastAPI
117
117
  from fastapi_fullauth import FullAuth, FullAuthConfig
118
- from fastapi_fullauth.adapters.memory import InMemoryAdapter
118
+ from fastapi_fullauth.adapters.sqlmodel import SQLModelAdapter
119
119
 
120
120
  app = FastAPI()
121
121
 
122
122
  fullauth = FullAuth(
123
- adapter=InMemoryAdapter(),
123
+ adapter=SQLModelAdapter(session_maker=session_maker, user_model=User),
124
124
  config=FullAuthConfig(SECRET_KEY="your-secret-key"),
125
125
  )
126
126
  fullauth.init_app(app)
@@ -257,26 +257,28 @@ async def editor_panel(user=Depends(require_role("editor"))):
257
257
  ## OAuth2 social login
258
258
 
259
259
  ```python
260
+ from fastapi_fullauth import FullAuth, FullAuthConfig
261
+ from fastapi_fullauth.oauth.google import GoogleOAuthProvider
262
+ from fastapi_fullauth.oauth.github import GitHubOAuthProvider
263
+
260
264
  fullauth = FullAuth(
261
265
  adapter=adapter,
262
- config=FullAuthConfig(
263
- SECRET_KEY="...",
264
- OAUTH_PROVIDERS={
265
- "google": {
266
- "client_id": "your-google-client-id",
267
- "client_secret": "your-google-secret",
268
- "redirect_uris": [
269
- "http://localhost:3000/auth/callback",
270
- "https://myapp.com/auth/callback",
271
- ],
272
- },
273
- "github": {
274
- "client_id": "your-github-client-id",
275
- "client_secret": "your-github-secret",
276
- "redirect_uri": "http://localhost:3000/auth/callback",
277
- },
278
- },
279
- ),
266
+ config=FullAuthConfig(SECRET_KEY="..."),
267
+ providers=[
268
+ GoogleOAuthProvider(
269
+ client_id="your-google-client-id",
270
+ client_secret="your-google-secret",
271
+ redirect_uris=[
272
+ "http://localhost:3000/auth/callback",
273
+ "https://myapp.com/auth/callback",
274
+ ],
275
+ ),
276
+ GitHubOAuthProvider(
277
+ client_id="your-github-client-id",
278
+ client_secret="your-github-secret",
279
+ redirect_uris=["http://localhost:3000/auth/callback"],
280
+ ),
281
+ ],
280
282
  )
281
283
  ```
282
284
 
@@ -320,6 +322,15 @@ fullauth = FullAuth(
320
322
 
321
323
  See [Configuration docs](https://mdfarhankc.github.io/fastapi-fullauth/configuration/) for all options.
322
324
 
325
+ ## AI-friendly docs
326
+
327
+ Using an AI coding assistant? Point it at our LLM-optimized docs:
328
+
329
+ - **[llms.txt](https://mdfarhankc.github.io/fastapi-fullauth/llms.txt)** — concise overview with links to all doc pages
330
+ - **[llms-full.txt](https://mdfarhankc.github.io/fastapi-fullauth/llms-full.txt)** — full documentation in a single file
331
+
332
+ Works with Claude, Cursor, Copilot, and any tool that accepts a docs URL.
333
+
323
334
  ## Development
324
335
 
325
336
  ```bash
@@ -329,7 +340,6 @@ uv sync --dev --extra sqlalchemy --extra sqlmodel
329
340
  uv run pytest tests/ -v
330
341
 
331
342
  # run examples
332
- uv run uvicorn examples.memory_app.main:app --reload
333
343
  uv run uvicorn examples.sqlmodel_app.main:app --reload
334
344
  ```
335
345
 
@@ -36,7 +36,7 @@ Add a complete authentication and authorization system to your **FastAPI** proje
36
36
  - **Role-based access control** — `CurrentUser`, `VerifiedUser`, `SuperUser`, `require_role()`
37
37
  - **Rate limiting** — per-route auth limits + global middleware (memory or Redis)
38
38
  - **CSRF protection** and **security headers** middleware, auto-wired
39
- - **Pluggable adapters** — SQLModel, SQLAlchemy, or in-memory
39
+ - **Pluggable adapters** — SQLModel or SQLAlchemy
40
40
  - **Generic type parameters** — define your own schemas with full IDE support and type safety
41
41
  - **Composable routers** — include only the route groups you need
42
42
  - **Event hooks** — `after_register`, `after_login`, `send_verification_email`, etc.
@@ -69,12 +69,12 @@ pip install fastapi-fullauth[all]
69
69
  ```python
70
70
  from fastapi import FastAPI
71
71
  from fastapi_fullauth import FullAuth, FullAuthConfig
72
- from fastapi_fullauth.adapters.memory import InMemoryAdapter
72
+ from fastapi_fullauth.adapters.sqlmodel import SQLModelAdapter
73
73
 
74
74
  app = FastAPI()
75
75
 
76
76
  fullauth = FullAuth(
77
- adapter=InMemoryAdapter(),
77
+ adapter=SQLModelAdapter(session_maker=session_maker, user_model=User),
78
78
  config=FullAuthConfig(SECRET_KEY="your-secret-key"),
79
79
  )
80
80
  fullauth.init_app(app)
@@ -211,26 +211,28 @@ async def editor_panel(user=Depends(require_role("editor"))):
211
211
  ## OAuth2 social login
212
212
 
213
213
  ```python
214
+ from fastapi_fullauth import FullAuth, FullAuthConfig
215
+ from fastapi_fullauth.oauth.google import GoogleOAuthProvider
216
+ from fastapi_fullauth.oauth.github import GitHubOAuthProvider
217
+
214
218
  fullauth = FullAuth(
215
219
  adapter=adapter,
216
- config=FullAuthConfig(
217
- SECRET_KEY="...",
218
- OAUTH_PROVIDERS={
219
- "google": {
220
- "client_id": "your-google-client-id",
221
- "client_secret": "your-google-secret",
222
- "redirect_uris": [
223
- "http://localhost:3000/auth/callback",
224
- "https://myapp.com/auth/callback",
225
- ],
226
- },
227
- "github": {
228
- "client_id": "your-github-client-id",
229
- "client_secret": "your-github-secret",
230
- "redirect_uri": "http://localhost:3000/auth/callback",
231
- },
232
- },
233
- ),
220
+ config=FullAuthConfig(SECRET_KEY="..."),
221
+ providers=[
222
+ GoogleOAuthProvider(
223
+ client_id="your-google-client-id",
224
+ client_secret="your-google-secret",
225
+ redirect_uris=[
226
+ "http://localhost:3000/auth/callback",
227
+ "https://myapp.com/auth/callback",
228
+ ],
229
+ ),
230
+ GitHubOAuthProvider(
231
+ client_id="your-github-client-id",
232
+ client_secret="your-github-secret",
233
+ redirect_uris=["http://localhost:3000/auth/callback"],
234
+ ),
235
+ ],
234
236
  )
235
237
  ```
236
238
 
@@ -274,6 +276,15 @@ fullauth = FullAuth(
274
276
 
275
277
  See [Configuration docs](https://mdfarhankc.github.io/fastapi-fullauth/configuration/) for all options.
276
278
 
279
+ ## AI-friendly docs
280
+
281
+ Using an AI coding assistant? Point it at our LLM-optimized docs:
282
+
283
+ - **[llms.txt](https://mdfarhankc.github.io/fastapi-fullauth/llms.txt)** — concise overview with links to all doc pages
284
+ - **[llms-full.txt](https://mdfarhankc.github.io/fastapi-fullauth/llms-full.txt)** — full documentation in a single file
285
+
286
+ Works with Claude, Cursor, Copilot, and any tool that accepts a docs URL.
287
+
277
288
  ## Development
278
289
 
279
290
  ```bash
@@ -283,7 +294,6 @@ uv sync --dev --extra sqlalchemy --extra sqlmodel
283
294
  uv run pytest tests/ -v
284
295
 
285
296
  # run examples
286
- uv run uvicorn examples.memory_app.main:app --reload
287
297
  uv run uvicorn examples.sqlmodel_app.main:app --reload
288
298
  ```
289
299
 
@@ -8,13 +8,11 @@ Adapters are the database layer for fastapi-fullauth. They implement `AbstractUs
8
8
  |---------|---------|---------|
9
9
  | [SQLModel](sqlmodel.md) | Any SQLAlchemy-supported DB | `pip install fastapi-fullauth[sqlmodel]` |
10
10
  | [SQLAlchemy](sqlalchemy.md) | Any SQLAlchemy-supported DB | `pip install fastapi-fullauth[sqlalchemy]` |
11
- | [In-Memory](memory.md) | Python dicts | Included (no extras) |
12
11
 
13
12
  ## Choosing an adapter
14
13
 
15
- - **SQLModel** — recommended for most projects. Clean model definitions, good type support.
14
+ - **SQLModel** — recommended for most projects. Clean model definitions, good type support. Use SQLite for prototyping.
16
15
  - **SQLAlchemy** — use if your project already uses SQLAlchemy's declarative base.
17
- - **In-Memory** — for testing and prototyping only. Data is lost on restart.
18
16
 
19
17
  ## Custom adapters
20
18
 
@@ -39,11 +37,23 @@ class MongoAdapter(AbstractUserAdapter):
39
37
 
40
38
  See the [source of AbstractUserAdapter](https://github.com/mdfarhankc/fastapi-fullauth/blob/main/fastapi_fullauth/adapters/base.py) for the full interface.
41
39
 
42
- ## Auto-derived schemas
40
+ ## Custom schemas
43
41
 
44
- All adapters support automatic schema derivation. When you add custom fields to your user model, fastapi-fullauth detects them and includes them in:
42
+ Define your own user schemas by extending `UserSchema` and `CreateUserSchema`, then pass them to the adapter:
45
43
 
46
- - **Registration schema** — extra fields appear in `POST /auth/register`
47
- - **User response schema** — extra fields appear in `GET /auth/me` and other user responses
44
+ ```python
45
+ from fastapi_fullauth import UserSchema, CreateUserSchema
46
+
47
+ class MyUserSchema(UserSchema):
48
+ display_name: str = ""
48
49
 
49
- No need to create separate Pydantic models. You can still pass explicit `user_schema` or `create_user_schema` to `SQLModelAdapter` / `FullAuth` if you want full control.
50
+ class MyCreateSchema(CreateUserSchema):
51
+ display_name: str = ""
52
+
53
+ adapter = SQLModelAdapter(
54
+ session_maker=session_maker,
55
+ user_model=User,
56
+ user_schema=MyUserSchema,
57
+ create_user_schema=MyCreateSchema,
58
+ )
59
+ ```
@@ -12,10 +12,9 @@ from fastapi_fullauth import FullAuth, FullAuthConfig
12
12
  fullauth = FullAuth(
13
13
  adapter=adapter, # required — database adapter
14
14
  config=FullAuthConfig(...), # FullAuthConfig object (see Configuration)
15
+ providers=None, # list of OAuthProvider instances
15
16
  backends=None, # [BearerBackend()] by default
16
17
  password_validator=None, # PasswordValidator instance
17
- include_user_in_login=False, # include user data in login response
18
- create_user_schema=None, # custom registration schema
19
18
  on_create_token_claims=None, # async callback for custom JWT claims
20
19
  )
21
20
  ```
@@ -66,14 +65,22 @@ from fastapi_fullauth.types import (
66
65
 
67
66
  ```python
68
67
  class UserSchema(BaseModel):
69
- id: str | int | UUID
68
+ id: UUID
70
69
  email: EmailStr
71
70
  is_active: bool = True
72
71
  is_verified: bool = False
73
72
  is_superuser: bool = False
74
73
  roles: list[str] = []
74
+
75
+ PROTECTED_FIELDS: ClassVar[set[str]] = {
76
+ "id", "email", "hashed_password", "is_active",
77
+ "is_verified", "is_superuser", "roles", "password",
78
+ "created_at", "refresh_tokens",
79
+ }
75
80
  ```
76
81
 
82
+ Extend `PROTECTED_FIELDS` in subclasses to protect custom sensitive fields from profile updates.
83
+
77
84
  ### TokenPair
78
85
 
79
86
  ```python
@@ -84,6 +91,10 @@ class TokenPair(BaseModel):
84
91
  expires_in: int | None = None
85
92
  ```
86
93
 
94
+ ### LoginResponse
95
+
96
+ Returned by login and OAuth callback routes. Extends `TokenPair` with an optional `user` field. The `user` field contains the full user schema object when `INCLUDE_USER_IN_LOGIN=True`, otherwise `null`. The user type matches your configured user schema (e.g., `MyUserSchema`).
97
+
87
98
  ### TokenPayload
88
99
 
89
100
  ```python
@@ -64,6 +64,9 @@ Pass config inline or as an object:
64
64
  | Option | Type | Default | Description |
65
65
  |--------|------|---------|-------------|
66
66
  | `LOGIN_FIELD` | `str` | `"email"` | Field used for login (`"email"`, `"username"`, etc.). |
67
+ | `INCLUDE_USER_IN_LOGIN` | `bool` | `False` | Include user object in login/OAuth callback response. |
68
+ | `LOCKOUT_ENABLED` | `bool` | `True` | Enable account lockout after failed login attempts. |
69
+ | `LOCKOUT_BACKEND` | `"memory" \| "redis"` | `"memory"` | Lockout storage backend. Use `"redis"` for multi-worker deployments. |
67
70
  | `MAX_LOGIN_ATTEMPTS` | `int` | `5` | Failed attempts before account lockout. |
68
71
  | `LOCKOUT_DURATION_MINUTES` | `int` | `15` | Lockout duration after max attempts. |
69
72
 
@@ -115,7 +118,6 @@ Pass config inline or as an object:
115
118
 
116
119
  | Option | Type | Default | Description |
117
120
  |--------|------|---------|-------------|
118
- | `OAUTH_PROVIDERS` | `dict` | `{}` | OAuth provider configurations. See [OAuth2](oauth.md). |
119
121
  | `OAUTH_STATE_EXPIRE_SECONDS` | `int` | `300` | OAuth state token TTL (5 min). |
120
122
  | `OAUTH_AUTO_LINK_BY_EMAIL` | `bool` | `True` | Auto-link OAuth accounts to existing users by email. |
121
123
 
@@ -138,10 +138,13 @@ Response:
138
138
  "access_token": "eyJ...",
139
139
  "refresh_token": "eyJ...",
140
140
  "token_type": "bearer",
141
- "expires_in": 1800
141
+ "expires_in": 1800,
142
+ "user": null
142
143
  }
143
144
  ```
144
145
 
146
+ When `INCLUDE_USER_IN_LOGIN=True`, `user` contains the full user object instead of `null`.
147
+
145
148
  **Get current user:**
146
149
 
147
150
  ```bash
@@ -35,7 +35,7 @@ Add a complete authentication and authorization system to your **FastAPI** proje
35
35
  - **Role-based access control** — `CurrentUser`, `VerifiedUser`, `SuperUser`, `require_role()`
36
36
  - **Rate limiting** — per-route auth limits + global middleware (memory or Redis)
37
37
  - **CSRF protection** and **security headers** middleware
38
- - **Pluggable adapters** — SQLModel, SQLAlchemy, or in-memory
38
+ - **Pluggable adapters** — SQLModel or SQLAlchemy
39
39
  - **Generic type parameters** — define your own schemas with full IDE support and type safety
40
40
  - **Composable routers** — include only the route groups you need
41
41
  - **Event hooks** — `after_register`, `after_login`, `send_verification_email`, etc.
@@ -67,12 +67,12 @@ pip install fastapi-fullauth[all]
67
67
  ```python
68
68
  from fastapi import FastAPI
69
69
  from fastapi_fullauth import FullAuth, FullAuthConfig
70
- from fastapi_fullauth.adapters.memory import InMemoryAdapter
70
+ from fastapi_fullauth.adapters.sqlmodel import SQLModelAdapter
71
71
 
72
72
  app = FastAPI()
73
73
 
74
74
  fullauth = FullAuth(
75
- adapter=InMemoryAdapter(),
75
+ adapter=SQLModelAdapter(session_maker=session_maker, user_model=User),
76
76
  config=FullAuthConfig(
77
77
  SECRET_KEY="your-secret-key",
78
78
  ),
@@ -138,6 +138,15 @@ With OAuth enabled, additional routes are registered under `/auth/oauth/`. See [
138
138
 
139
139
  All routes are prefixed with `/api/v1` by default (configurable via `API_PREFIX`).
140
140
 
141
+ ## AI-friendly docs
142
+
143
+ Using an AI coding assistant? Point it at our LLM-optimized docs:
144
+
145
+ - **[llms.txt](llms.txt)** — concise overview with links to all doc pages
146
+ - **[llms-full.txt](llms-full.txt)** — full documentation in a single file
147
+
148
+ Works with Claude, Cursor, Copilot, and any tool that accepts a docs URL.
149
+
141
150
  ## License
142
151
 
143
152
  MIT