bustapi 0.13.5__tar.gz → 0.13.8__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 (261) hide show
  1. {bustapi-0.13.5 → bustapi-0.13.8}/CHANGELOG.md +20 -0
  2. {bustapi-0.13.5 → bustapi-0.13.8}/Cargo.lock +28 -29
  3. {bustapi-0.13.5 → bustapi-0.13.8}/Cargo.toml +1 -1
  4. {bustapi-0.13.5 → bustapi-0.13.8}/PKG-INFO +1 -1
  5. {bustapi-0.13.5 → bustapi-0.13.8}/docs/changelog.md +20 -0
  6. {bustapi-0.13.5 → bustapi-0.13.8}/pyproject.toml +1 -1
  7. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/__init__.py +1 -1
  8. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/auth/decorators.py +47 -28
  9. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/auth/login.py +13 -3
  10. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/core/helpers.py +1 -3
  11. bustapi-0.13.8/tests/test_discussion_28.py +87 -0
  12. {bustapi-0.13.5 → bustapi-0.13.8}/- +0 -0
  13. {bustapi-0.13.5 → bustapi-0.13.8}/.github/FUNDING.yml +0 -0
  14. {bustapi-0.13.5 → bustapi-0.13.8}/.github/workflows/ci-multiplatform.yml +0 -0
  15. {bustapi-0.13.5 → bustapi-0.13.8}/.github/workflows/ci.yml +0 -0
  16. {bustapi-0.13.5 → bustapi-0.13.8}/.github/workflows/docs.yml +0 -0
  17. {bustapi-0.13.5 → bustapi-0.13.8}/.github/workflows/manual-publish.yml +0 -0
  18. {bustapi-0.13.5 → bustapi-0.13.8}/.gitignore +0 -0
  19. {bustapi-0.13.5 → bustapi-0.13.8}/.python-version +0 -0
  20. {bustapi-0.13.5 → bustapi-0.13.8}/AGENT_KNOWLEDGE.md +0 -0
  21. {bustapi-0.13.5 → bustapi-0.13.8}/Dockerfile +0 -0
  22. {bustapi-0.13.5 → bustapi-0.13.8}/LICENSE +0 -0
  23. {bustapi-0.13.5 → bustapi-0.13.8}/README.md +0 -0
  24. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/CACHE_BENCHMARK.md +0 -0
  25. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/README.md +0 -0
  26. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/app.py +0 -0
  27. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/benchmark_all.py +0 -0
  28. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/benchmark_avg.py +0 -0
  29. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/benchmark_cache.py +0 -0
  30. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/benchmark_combined.png +0 -0
  31. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/bustapi.md +0 -0
  32. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/bustapi_bench.py +0 -0
  33. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/bustapi_internal.py +0 -0
  34. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/comparison_bench.py +0 -0
  35. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/comprehensive_benchmark.py +0 -0
  36. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/gen_graph.py +0 -0
  37. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/quick_bench.py +0 -0
  38. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/resource_bench.py +0 -0
  39. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/rps_comparison.png +0 -0
  40. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/run_comparison_auto.py +0 -0
  41. {bustapi-0.13.5 → bustapi-0.13.8}/benchmarks/ws_benchmark.py +0 -0
  42. {bustapi-0.13.5 → bustapi-0.13.8}/docs/advanced/async.md +0 -0
  43. {bustapi-0.13.5 → bustapi-0.13.8}/docs/advanced/blueprints.md +0 -0
  44. {bustapi-0.13.5 → bustapi-0.13.8}/docs/advanced/dependency_injection.md +0 -0
  45. {bustapi-0.13.5 → bustapi-0.13.8}/docs/advanced/deployment.md +0 -0
  46. {bustapi-0.13.5 → bustapi-0.13.8}/docs/advanced/middleware.md +0 -0
  47. {bustapi-0.13.5 → bustapi-0.13.8}/docs/advanced/security.md +0 -0
  48. {bustapi-0.13.5 → bustapi-0.13.8}/docs/advanced/validation.md +0 -0
  49. {bustapi-0.13.5 → bustapi-0.13.8}/docs/api-reference.md +0 -0
  50. {bustapi-0.13.5 → bustapi-0.13.8}/docs/assets/logo.png +0 -0
  51. {bustapi-0.13.5 → bustapi-0.13.8}/docs/complete-api-reference.md +0 -0
  52. {bustapi-0.13.5 → bustapi-0.13.8}/docs/deployment-performance-guide.md +0 -0
  53. {bustapi-0.13.5 → bustapi-0.13.8}/docs/deployment.md +0 -0
  54. {bustapi-0.13.5 → bustapi-0.13.8}/docs/examples-guide.md +0 -0
  55. {bustapi-0.13.5 → bustapi-0.13.8}/docs/index.md +0 -0
  56. {bustapi-0.13.5 → bustapi-0.13.8}/docs/installation.md +0 -0
  57. {bustapi-0.13.5 → bustapi-0.13.8}/docs/overrides/.gitkeep +0 -0
  58. {bustapi-0.13.5 → bustapi-0.13.8}/docs/quickstart.md +0 -0
  59. {bustapi-0.13.5 → bustapi-0.13.8}/docs/release_track.md +0 -0
  60. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/advanced/async_support.html +0 -0
  61. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/advanced/blueprints.html +0 -0
  62. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/advanced/dependency_injection.html +0 -0
  63. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/advanced/middleware.html +0 -0
  64. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/advanced/validation.html +0 -0
  65. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/api/all.html +0 -0
  66. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/api/app.html +0 -0
  67. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/api/context.html +0 -0
  68. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/api/utilities.html +0 -0
  69. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/assets/logo.png +0 -0
  70. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/changelog.html +0 -0
  71. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/core_concepts/request_data.html +0 -0
  72. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/core_concepts/responses.html +0 -0
  73. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/core_concepts/routing.html +0 -0
  74. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/core_concepts/templates.html +0 -0
  75. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/examples/index.html +0 -0
  76. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/getting_started/index.html +0 -0
  77. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/getting_started/quickstart.html +0 -0
  78. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/index.html +0 -0
  79. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/script.js +0 -0
  80. {bustapi-0.13.5 → bustapi-0.13.8}/docs/site/style.css +0 -0
  81. {bustapi-0.13.5 → bustapi-0.13.8}/docs/stylesheets/extra.css +0 -0
  82. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/authentication.md +0 -0
  83. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/caching.md +0 -0
  84. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/cli.md +0 -0
  85. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/database.md +0 -0
  86. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/documentation.md +0 -0
  87. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/error_handling.md +0 -0
  88. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/jwt.md +0 -0
  89. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/logging.md +0 -0
  90. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/multiprocessing.md +0 -0
  91. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/request_data.md +0 -0
  92. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/responses.md +0 -0
  93. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/routing.md +0 -0
  94. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/sessions.md +0 -0
  95. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/static_files.md +0 -0
  96. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/templates.md +0 -0
  97. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/turbo-routes.md +0 -0
  98. {bustapi-0.13.5 → bustapi-0.13.8}/docs/user-guide/video-streaming.md +0 -0
  99. {bustapi-0.13.5 → bustapi-0.13.8}/docs/websockets.md +0 -0
  100. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/08_auto_docs.py +0 -0
  101. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/12_test_modes.py +0 -0
  102. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/13_error_handling.py +0 -0
  103. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/14_middleware.py +0 -0
  104. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/16_middleware_session.py +0 -0
  105. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/20_file_uploads.py +0 -0
  106. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/24_body_and_depends.py +0 -0
  107. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/27_video_stream.py +0 -0
  108. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/28_websocket.py +0 -0
  109. {bustapi-0.13.5 → bustapi-0.13.8}/examples/advanced/29_turbo_websocket.py +0 -0
  110. {bustapi-0.13.5 → bustapi-0.13.8}/examples/basics/01_hello_world.py +0 -0
  111. {bustapi-0.13.5 → bustapi-0.13.8}/examples/basics/02_parameters.py +0 -0
  112. {bustapi-0.13.5 → bustapi-0.13.8}/examples/basics/03_async.py +0 -0
  113. {bustapi-0.13.5 → bustapi-0.13.8}/examples/basics/04_request_data.py +0 -0
  114. {bustapi-0.13.5 → bustapi-0.13.8}/examples/basics/19_all_types.py +0 -0
  115. {bustapi-0.13.5 → bustapi-0.13.8}/examples/database/07_database_raw.py +0 -0
  116. {bustapi-0.13.5 → bustapi-0.13.8}/examples/database/10_database_sqlmodel.py +0 -0
  117. {bustapi-0.13.5 → bustapi-0.13.8}/examples/routing/06_blueprints.py +0 -0
  118. {bustapi-0.13.5 → bustapi-0.13.8}/examples/routing/09_complex_routing.py +0 -0
  119. {bustapi-0.13.5 → bustapi-0.13.8}/examples/routing/21_path_validation.py +0 -0
  120. {bustapi-0.13.5 → bustapi-0.13.8}/examples/routing/22_path_docs.py +0 -0
  121. {bustapi-0.13.5 → bustapi-0.13.8}/examples/routing/23_query_validation.py +0 -0
  122. {bustapi-0.13.5 → bustapi-0.13.8}/examples/routing/blueprint_with_jwt.py +0 -0
  123. {bustapi-0.13.5 → bustapi-0.13.8}/examples/security/10_rate_limit_demo.py +0 -0
  124. {bustapi-0.13.5 → bustapi-0.13.8}/examples/security/11_security_demo.py +0 -0
  125. {bustapi-0.13.5 → bustapi-0.13.8}/examples/security/17_jwt_auth.py +0 -0
  126. {bustapi-0.13.5 → bustapi-0.13.8}/examples/security/17_safe_features.py +0 -0
  127. {bustapi-0.13.5 → bustapi-0.13.8}/examples/security/18_jwt_cookies.py +0 -0
  128. {bustapi-0.13.5 → bustapi-0.13.8}/examples/security/18_safe_advanced.py +0 -0
  129. {bustapi-0.13.5 → bustapi-0.13.8}/examples/security/18_session_login.py +0 -0
  130. {bustapi-0.13.5 → bustapi-0.13.8}/examples/templates/05_templates.py +0 -0
  131. {bustapi-0.13.5 → bustapi-0.13.8}/examples/templates/26_complex_template.py +0 -0
  132. {bustapi-0.13.5 → bustapi-0.13.8}/examples/templates/templates/index.html +0 -0
  133. {bustapi-0.13.5 → bustapi-0.13.8}/examples/turbo/cache_test.py +0 -0
  134. {bustapi-0.13.5 → bustapi-0.13.8}/examples/turbo/fair_benchmark.py +0 -0
  135. {bustapi-0.13.5 → bustapi-0.13.8}/examples/turbo/typed_turbo_example.py +0 -0
  136. {bustapi-0.13.5 → bustapi-0.13.8}/examples/ws/app.py +0 -0
  137. {bustapi-0.13.5 → bustapi-0.13.8}/examples/ws/templates/index.html +0 -0
  138. {bustapi-0.13.5 → bustapi-0.13.8}/examples/ws/websockets_demo.py +0 -0
  139. {bustapi-0.13.5 → bustapi-0.13.8}/examples/ws/ws_limit.py +0 -0
  140. {bustapi-0.13.5 → bustapi-0.13.8}/mkdocs.yml +0 -0
  141. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/app.py +0 -0
  142. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/auth/__init__.py +0 -0
  143. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/auth/csrf.py +0 -0
  144. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/auth/password.py +0 -0
  145. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/auth/tokens.py +0 -0
  146. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/auth/user.py +0 -0
  147. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/cli/__init__.py +0 -0
  148. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/cli/main.py +0 -0
  149. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/context.py +0 -0
  150. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/core/__init__.py +0 -0
  151. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/core/asgi.py +0 -0
  152. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/core/exceptions.py +0 -0
  153. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/core/logging.py +0 -0
  154. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/dependencies.py +0 -0
  155. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/dispatch.py +0 -0
  156. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/documentation/__init__.py +0 -0
  157. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/documentation/generator.py +0 -0
  158. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/extraction.py +0 -0
  159. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/fastapi_compat.py +0 -0
  160. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/hooks.py +0 -0
  161. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/http/__init__.py +0 -0
  162. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/http/request.py +0 -0
  163. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/http/response.py +0 -0
  164. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/jwt.py +0 -0
  165. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/logging.py +0 -0
  166. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/middleware.py +0 -0
  167. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/multiprocess.py +0 -0
  168. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/params.py +0 -0
  169. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/py.typed +0 -0
  170. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/responses.py +0 -0
  171. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/routing/__init__.py +0 -0
  172. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/routing/blueprints.py +0 -0
  173. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/routing/decorators.py +0 -0
  174. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/safe/__init__.py +0 -0
  175. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/safe/concurrency.py +0 -0
  176. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/safe/types.py +0 -0
  177. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/security/__init__.py +0 -0
  178. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/security/extension.py +0 -0
  179. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/security/rate_limit.py +0 -0
  180. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/server/__init__.py +0 -0
  181. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/server/runner.py +0 -0
  182. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/server/wsgi.py +0 -0
  183. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/sessions.py +0 -0
  184. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/templating/__init__.py +0 -0
  185. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/templating/engine.py +0 -0
  186. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/templating/mixin.py +0 -0
  187. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/testing/__init__.py +0 -0
  188. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/testing/client.py +0 -0
  189. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/utils.py +0 -0
  190. {bustapi-0.13.5 → bustapi-0.13.8}/python/bustapi/websocket.py +0 -0
  191. {bustapi-0.13.5 → bustapi-0.13.8}/run_all_examples.py +0 -0
  192. {bustapi-0.13.5 → bustapi-0.13.8}/scratch/test_abort.py +0 -0
  193. {bustapi-0.13.5 → bustapi-0.13.8}/scratch/test_headers.py +0 -0
  194. {bustapi-0.13.5 → bustapi-0.13.8}/src/bindings/app.rs +0 -0
  195. {bustapi-0.13.5 → bustapi-0.13.8}/src/bindings/converters.rs +0 -0
  196. {bustapi-0.13.5 → bustapi-0.13.8}/src/bindings/handlers.rs +0 -0
  197. {bustapi-0.13.5 → bustapi-0.13.8}/src/bindings/mod.rs +0 -0
  198. {bustapi-0.13.5 → bustapi-0.13.8}/src/bindings/request.rs +0 -0
  199. {bustapi-0.13.5 → bustapi-0.13.8}/src/bindings/typed_turbo.rs +0 -0
  200. {bustapi-0.13.5 → bustapi-0.13.8}/src/bindings/websocket.rs +0 -0
  201. {bustapi-0.13.5 → bustapi-0.13.8}/src/crypto.rs +0 -0
  202. {bustapi-0.13.5 → bustapi-0.13.8}/src/jwt.rs +0 -0
  203. {bustapi-0.13.5 → bustapi-0.13.8}/src/lib.rs +0 -0
  204. {bustapi-0.13.5 → bustapi-0.13.8}/src/logger.rs +0 -0
  205. {bustapi-0.13.5 → bustapi-0.13.8}/src/rate_limiter.rs +0 -0
  206. {bustapi-0.13.5 → bustapi-0.13.8}/src/request/methods.rs +0 -0
  207. {bustapi-0.13.5 → bustapi-0.13.8}/src/request/mod.rs +0 -0
  208. {bustapi-0.13.5 → bustapi-0.13.8}/src/request/tests.rs +0 -0
  209. {bustapi-0.13.5 → bustapi-0.13.8}/src/response/builders.rs +0 -0
  210. {bustapi-0.13.5 → bustapi-0.13.8}/src/response/methods.rs +0 -0
  211. {bustapi-0.13.5 → bustapi-0.13.8}/src/response/mod.rs +0 -0
  212. {bustapi-0.13.5 → bustapi-0.13.8}/src/router/handlers.rs +0 -0
  213. {bustapi-0.13.5 → bustapi-0.13.8}/src/router/matching.rs +0 -0
  214. {bustapi-0.13.5 → bustapi-0.13.8}/src/router/middleware.rs +0 -0
  215. {bustapi-0.13.5 → bustapi-0.13.8}/src/router/mod.rs +0 -0
  216. {bustapi-0.13.5 → bustapi-0.13.8}/src/router/tests.rs +0 -0
  217. {bustapi-0.13.5 → bustapi-0.13.8}/src/server/handlers.rs +0 -0
  218. {bustapi-0.13.5 → bustapi-0.13.8}/src/server/mod.rs +0 -0
  219. {bustapi-0.13.5 → bustapi-0.13.8}/src/server/startup.rs +0 -0
  220. {bustapi-0.13.5 → bustapi-0.13.8}/src/server/stream.rs +0 -0
  221. {bustapi-0.13.5 → bustapi-0.13.8}/src/static_files.rs +0 -0
  222. {bustapi-0.13.5 → bustapi-0.13.8}/src/templating.rs +0 -0
  223. {bustapi-0.13.5 → bustapi-0.13.8}/src/watcher.rs +0 -0
  224. {bustapi-0.13.5 → bustapi-0.13.8}/src/websocket/config.rs +0 -0
  225. {bustapi-0.13.5 → bustapi-0.13.8}/src/websocket/mod.rs +0 -0
  226. {bustapi-0.13.5 → bustapi-0.13.8}/src/websocket/session.rs +0 -0
  227. {bustapi-0.13.5 → bustapi-0.13.8}/src/websocket/turbo.rs +0 -0
  228. {bustapi-0.13.5 → bustapi-0.13.8}/static/style.css +0 -0
  229. {bustapi-0.13.5 → bustapi-0.13.8}/templates/base.html +0 -0
  230. {bustapi-0.13.5 → bustapi-0.13.8}/templates/complex.html +0 -0
  231. {bustapi-0.13.5 → bustapi-0.13.8}/tests/docs_test_all.py +0 -0
  232. {bustapi-0.13.5 → bustapi-0.13.8}/tests/docs_test_api_reference.py +0 -0
  233. {bustapi-0.13.5 → bustapi-0.13.8}/tests/docs_test_installation.py +0 -0
  234. {bustapi-0.13.5 → bustapi-0.13.8}/tests/docs_test_quickstart.py +0 -0
  235. {bustapi-0.13.5 → bustapi-0.13.8}/tests/docs_test_simple.py +0 -0
  236. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_050_features.py +0 -0
  237. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_async_hooks.py +0 -0
  238. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_async_login.py +0 -0
  239. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_auth.py +0 -0
  240. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_discussion_21.py +0 -0
  241. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_discussion_22.py +0 -0
  242. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_examples.py +0 -0
  243. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_hot_reload.py +0 -0
  244. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_issue_18.py +0 -0
  245. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_issue_23.py +0 -0
  246. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_issue_24.py +0 -0
  247. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_jwt.py +0 -0
  248. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_jwt_cookies.py +0 -0
  249. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_login_manager.py +0 -0
  250. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_middleware.py +0 -0
  251. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_multiprocess_stability.py +0 -0
  252. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_new_examples.py +0 -0
  253. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_orm_conflict.py +0 -0
  254. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_path_standalone.py +0 -0
  255. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_path_validation.py +0 -0
  256. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_rate_limit_rust.py +0 -0
  257. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_safe.py +0 -0
  258. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_security_unit.py +0 -0
  259. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_sessions.py +0 -0
  260. {bustapi-0.13.5 → bustapi-0.13.8}/tests/test_zero_copy.py +0 -0
  261. {bustapi-0.13.5 → bustapi-0.13.8}/tests/verify_router.py +0 -0
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to this project will be documented here.
4
4
 
5
+ ## [0.13.8] - 2026-06-11
6
+
7
+ ### Added
8
+ - **Auth Decorators**: Added a `require_all` flag to `@roles_required` and `@permission_required` decorators, enabling explicit AND/OR logic for multi-role/permission checks.
9
+
10
+ ### Fixed
11
+ - **Auth Async Support**: Fixed a critical bug where `@roles_required` and `@permission_required` decorators failed to support `async def` routes.
12
+
13
+ ## [0.13.7] - 2026-06-10
14
+
15
+ ### Fixed
16
+ - **Login Manager ID Resolution**: Improved `login_user()` to gracefully handle non-string `get_id()` returns (e.g. integer IDs from Peewee ORM) and added support for a conflict-free `get_login_id()` method to prevent overriding built-in ORM properties.
17
+ - **Version Sync**: Synchronized package version in `__init__.py` which was previously out of sync with the package configuration.
18
+
19
+ ## [0.13.6] - 2026-06-08
20
+
21
+ ### Fixed
22
+ - **Auth Login Context**: Fixed `login_manager` extraction by correcting the attribute check on the request from `_app` to `app` ([#26](https://github.com/RUSTxPY/BustAPI/issues/26)).
23
+ - **Template Directory Handling**: Resolved duplicated fallback logic for template directories in `core/helpers.py` by streamlining the lookup against `current_app.template_folder` ([#25](https://github.com/RUSTxPY/BustAPI/issues/25)).
24
+
5
25
  ## [0.13.5] - 2026-06-04
6
26
 
7
27
  ### Added
@@ -372,9 +372,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
372
372
 
373
373
  [[package]]
374
374
  name = "bitflags"
375
- version = "2.12.1"
375
+ version = "2.13.0"
376
376
  source = "registry+https://github.com/rust-lang/crates.io-index"
377
- checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
377
+ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
378
378
 
379
379
  [[package]]
380
380
  name = "blake2"
@@ -396,9 +396,9 @@ dependencies = [
396
396
 
397
397
  [[package]]
398
398
  name = "block-buffer"
399
- version = "0.12.0"
399
+ version = "0.12.1"
400
400
  source = "registry+https://github.com/rust-lang/crates.io-index"
401
- checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be"
401
+ checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
402
402
  dependencies = [
403
403
  "hybrid-array",
404
404
  ]
@@ -432,7 +432,7 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
432
432
 
433
433
  [[package]]
434
434
  name = "bustapi_core"
435
- version = "0.13.5"
435
+ version = "0.13.8"
436
436
  dependencies = [
437
437
  "actix-files",
438
438
  "actix-http",
@@ -526,9 +526,9 @@ dependencies = [
526
526
 
527
527
  [[package]]
528
528
  name = "chrono"
529
- version = "0.4.44"
529
+ version = "0.4.45"
530
530
  source = "registry+https://github.com/rust-lang/crates.io-index"
531
- checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
531
+ checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
532
532
  dependencies = [
533
533
  "iana-time-zone",
534
534
  "js-sys",
@@ -779,7 +779,7 @@ version = "0.11.3"
779
779
  source = "registry+https://github.com/rust-lang/crates.io-index"
780
780
  checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
781
781
  dependencies = [
782
- "block-buffer 0.12.0",
782
+ "block-buffer 0.12.1",
783
783
  "const-oid",
784
784
  "crypto-common 0.2.2",
785
785
  ]
@@ -1329,13 +1329,12 @@ dependencies = [
1329
1329
 
1330
1330
  [[package]]
1331
1331
  name = "js-sys"
1332
- version = "0.3.99"
1332
+ version = "0.3.100"
1333
1333
  source = "registry+https://github.com/rust-lang/crates.io-index"
1334
- checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
1334
+ checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162"
1335
1335
  dependencies = [
1336
1336
  "cfg-if",
1337
1337
  "futures-util",
1338
- "once_cell",
1339
1338
  "wasm-bindgen",
1340
1339
  ]
1341
1340
 
@@ -1432,9 +1431,9 @@ dependencies = [
1432
1431
 
1433
1432
  [[package]]
1434
1433
  name = "log"
1435
- version = "0.4.31"
1434
+ version = "0.4.32"
1436
1435
  source = "registry+https://github.com/rust-lang/crates.io-index"
1437
- checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f"
1436
+ checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
1438
1437
 
1439
1438
  [[package]]
1440
1439
  name = "matchers"
@@ -1876,9 +1875,9 @@ dependencies = [
1876
1875
 
1877
1876
  [[package]]
1878
1877
  name = "regex"
1879
- version = "1.12.3"
1878
+ version = "1.12.4"
1880
1879
  source = "registry+https://github.com/rust-lang/crates.io-index"
1881
- checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
1880
+ checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
1882
1881
  dependencies = [
1883
1882
  "aho-corasick",
1884
1883
  "memchr",
@@ -1905,9 +1904,9 @@ checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973"
1905
1904
 
1906
1905
  [[package]]
1907
1906
  name = "regex-syntax"
1908
- version = "0.8.10"
1907
+ version = "0.8.11"
1909
1908
  source = "registry+https://github.com/rust-lang/crates.io-index"
1910
- checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
1909
+ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
1911
1910
 
1912
1911
  [[package]]
1913
1912
  name = "rustc_version"
@@ -2457,9 +2456,9 @@ dependencies = [
2457
2456
 
2458
2457
  [[package]]
2459
2458
  name = "wasm-bindgen"
2460
- version = "0.2.122"
2459
+ version = "0.2.123"
2461
2460
  source = "registry+https://github.com/rust-lang/crates.io-index"
2462
- checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
2461
+ checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563"
2463
2462
  dependencies = [
2464
2463
  "cfg-if",
2465
2464
  "once_cell",
@@ -2470,9 +2469,9 @@ dependencies = [
2470
2469
 
2471
2470
  [[package]]
2472
2471
  name = "wasm-bindgen-macro"
2473
- version = "0.2.122"
2472
+ version = "0.2.123"
2474
2473
  source = "registry+https://github.com/rust-lang/crates.io-index"
2475
- checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
2474
+ checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc"
2476
2475
  dependencies = [
2477
2476
  "quote",
2478
2477
  "wasm-bindgen-macro-support",
@@ -2480,9 +2479,9 @@ dependencies = [
2480
2479
 
2481
2480
  [[package]]
2482
2481
  name = "wasm-bindgen-macro-support"
2483
- version = "0.2.122"
2482
+ version = "0.2.123"
2484
2483
  source = "registry+https://github.com/rust-lang/crates.io-index"
2485
- checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
2484
+ checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b"
2486
2485
  dependencies = [
2487
2486
  "bumpalo",
2488
2487
  "proc-macro2",
@@ -2493,9 +2492,9 @@ dependencies = [
2493
2492
 
2494
2493
  [[package]]
2495
2494
  name = "wasm-bindgen-shared"
2496
- version = "0.2.122"
2495
+ version = "0.2.123"
2497
2496
  source = "registry+https://github.com/rust-lang/crates.io-index"
2498
- checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
2497
+ checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92"
2499
2498
  dependencies = [
2500
2499
  "unicode-ident",
2501
2500
  ]
@@ -2892,18 +2891,18 @@ dependencies = [
2892
2891
 
2893
2892
  [[package]]
2894
2893
  name = "zerocopy"
2895
- version = "0.8.50"
2894
+ version = "0.8.52"
2896
2895
  source = "registry+https://github.com/rust-lang/crates.io-index"
2897
- checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1"
2896
+ checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
2898
2897
  dependencies = [
2899
2898
  "zerocopy-derive",
2900
2899
  ]
2901
2900
 
2902
2901
  [[package]]
2903
2902
  name = "zerocopy-derive"
2904
- version = "0.8.50"
2903
+ version = "0.8.52"
2905
2904
  source = "registry+https://github.com/rust-lang/crates.io-index"
2906
- checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639"
2905
+ checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
2907
2906
  dependencies = [
2908
2907
  "proc-macro2",
2909
2908
  "quote",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "bustapi_core"
3
- version = "0.13.5"
3
+ version = "0.13.8"
4
4
  edition = "2021"
5
5
  readme = "README.md"
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bustapi
3
- Version: 0.13.5
3
+ Version: 0.13.8
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to this project will be documented here.
4
4
 
5
+ ## [0.13.8] - 2026-06-11
6
+
7
+ ### Added
8
+ - **Auth Decorators**: Added a `require_all` flag to `@roles_required` and `@permission_required` decorators, enabling explicit AND/OR logic for multi-role/permission checks.
9
+
10
+ ### Fixed
11
+ - **Auth Async Support**: Fixed a critical bug where `@roles_required` and `@permission_required` decorators failed to support `async def` routes.
12
+
13
+ ## [0.13.7] - 2026-06-10
14
+
15
+ ### Fixed
16
+ - **Login Manager ID Resolution**: Improved `login_user()` to gracefully handle non-string `get_id()` returns (e.g. integer IDs from Peewee ORM) and added support for a conflict-free `get_login_id()` method to prevent overriding built-in ORM properties.
17
+ - **Version Sync**: Synchronized package version in `__init__.py` which was previously out of sync with the package configuration.
18
+
19
+ ## [0.13.6] - 2026-06-08
20
+
21
+ ### Fixed
22
+ - **Auth Login Context**: Fixed `login_manager` extraction by correcting the attribute check on the request from `_app` to `app` ([#26](https://github.com/RUSTxPY/BustAPI/issues/26)).
23
+ - **Template Directory Handling**: Resolved duplicated fallback logic for template directories in `core/helpers.py` by streamlining the lookup against `current_app.template_folder` ([#25](https://github.com/RUSTxPY/BustAPI/issues/25)).
24
+
5
25
  ## [0.13.5] - 2026-06-04
6
26
 
7
27
  ### Added
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "bustapi"
7
- version = "0.13.5"
7
+ version = "0.13.8"
8
8
  description = "High-performance Python web framework with Rust backend"
9
9
  authors = [
10
10
  {name = "GrandpaEJ", email = ""}
@@ -22,7 +22,7 @@ import platform
22
22
  import sys
23
23
  from http import HTTPStatus
24
24
 
25
- __version__ = "0.13.5"
25
+ __version__ = "0.13.8"
26
26
  __author__ = "BustAPI" # with GrandpaEJ
27
27
  __email__ = ""
28
28
 
@@ -89,25 +89,17 @@ def fresh_login_required(fn: Callable) -> Callable:
89
89
  return wrapper
90
90
 
91
91
 
92
- def roles_required(*roles: str) -> Callable:
92
+ def roles_required(*roles: str, require_all: bool = False) -> Callable:
93
93
  """
94
94
  Require user to have specific role(s).
95
95
 
96
- Usage:
97
- @app.get("/admin")
98
- @roles_required("admin")
99
- def admin_panel():
100
- ...
101
-
102
- @app.get("/moderator")
103
- @roles_required("admin", "moderator")
104
- def mod_panel():
105
- ...
96
+ Args:
97
+ roles: The roles to check.
98
+ require_all: If True, user must have ALL specified roles (AND). If False, ANY role is sufficient (OR).
106
99
  """
107
100
 
108
101
  def decorator(fn: Callable) -> Callable:
109
- @wraps(fn)
110
- def wrapper(*args, **kwargs):
102
+ def check_roles():
111
103
  from ..core.exceptions import abort
112
104
  from .login import current_user
113
105
 
@@ -123,10 +115,25 @@ def roles_required(*roles: str) -> Callable:
123
115
  else:
124
116
  user_roles = []
125
117
 
126
- # Check if user has any required role
127
- if not any(r in user_roles for r in roles):
128
- abort(403, f"Role required: {', '.join(roles)}")
118
+ if require_all:
119
+ if not all(r in user_roles for r in roles):
120
+ abort(403, f"Roles required: {', '.join(roles)}")
121
+ else:
122
+ if not any(r in user_roles for r in roles):
123
+ abort(403, f"Role required: {', '.join(roles)}")
124
+
125
+ if inspect.iscoroutinefunction(fn):
129
126
 
127
+ @wraps(fn)
128
+ async def async_wrapper(*args, **kwargs):
129
+ check_roles()
130
+ return await fn(*args, **kwargs)
131
+
132
+ return async_wrapper
133
+
134
+ @wraps(fn)
135
+ def wrapper(*args, **kwargs):
136
+ check_roles()
130
137
  return fn(*args, **kwargs)
131
138
 
132
139
  return wrapper
@@ -134,20 +141,17 @@ def roles_required(*roles: str) -> Callable:
134
141
  return decorator
135
142
 
136
143
 
137
- def permission_required(*permissions: str) -> Callable:
144
+ def permission_required(*permissions: str, require_all: bool = True) -> Callable:
138
145
  """
139
146
  Require user to have specific permission(s).
140
147
 
141
- Usage:
142
- @app.post("/delete")
143
- @permission_required("delete_posts")
144
- def delete_post():
145
- ...
148
+ Args:
149
+ permissions: The permissions to check.
150
+ require_all: If True, user must have ALL permissions (AND). If False, ANY permission is sufficient (OR).
146
151
  """
147
152
 
148
153
  def decorator(fn: Callable) -> Callable:
149
- @wraps(fn)
150
- def wrapper(*args, **kwargs):
154
+ def check_permissions():
151
155
  from ..core.exceptions import abort
152
156
  from .login import current_user
153
157
 
@@ -159,11 +163,26 @@ def permission_required(*permissions: str) -> Callable:
159
163
  if callable(user_perms):
160
164
  user_perms = user_perms()
161
165
 
162
- # Check all required permissions
163
- for perm in permissions:
164
- if perm not in user_perms:
165
- abort(403, f"Permission required: {perm}")
166
+ if require_all:
167
+ for perm in permissions:
168
+ if perm not in user_perms:
169
+ abort(403, f"Permission required: {perm}")
170
+ else:
171
+ if not any(perm in user_perms for perm in permissions):
172
+ abort(403, f"Permission required: {', '.join(permissions)}")
173
+
174
+ if inspect.iscoroutinefunction(fn):
166
175
 
176
+ @wraps(fn)
177
+ async def async_wrapper(*args, **kwargs):
178
+ check_permissions()
179
+ return await fn(*args, **kwargs)
180
+
181
+ return async_wrapper
182
+
183
+ @wraps(fn)
184
+ def wrapper(*args, **kwargs):
185
+ check_permissions()
167
186
  return fn(*args, **kwargs)
168
187
 
169
188
  return wrapper
@@ -107,15 +107,25 @@ def login_user(user, remember: bool = False, fresh: bool = True) -> bool:
107
107
  return False
108
108
 
109
109
  # Get user ID
110
- user_id = getattr(user, "get_id", lambda: None)()
110
+ # 1. Support custom conflict-free get_login_id() first
111
+ user_id = getattr(user, "get_login_id", lambda: None)()
112
+
113
+ # 2. Fallback to standard get_id()
111
114
  if user_id is None:
115
+ user_id = getattr(user, "get_id", lambda: None)()
116
+
117
+ # 3. Ensure string conversion (e.g., Peewee get_id() returns int)
118
+ if user_id is not None:
119
+ user_id = str(user_id)
120
+ else:
121
+ # 4. Final fallback to .id attribute
112
122
  try:
113
123
  user_id = str(user.id)
114
124
  except AttributeError:
115
125
  return False
116
126
 
117
127
  # Get login manager config
118
- login_manager = getattr(request, "_app", None)
128
+ login_manager = getattr(request, "app", None)
119
129
  if login_manager:
120
130
  login_manager = getattr(login_manager, "login_manager", None)
121
131
 
@@ -153,7 +163,7 @@ def logout_user() -> bool:
153
163
  return False
154
164
 
155
165
  # Get login manager config
156
- login_manager = getattr(request, "_app", None)
166
+ login_manager = getattr(request, "app", None)
157
167
  if login_manager:
158
168
  login_manager = getattr(login_manager, "login_manager", None)
159
169
 
@@ -307,9 +307,7 @@ def render_template(template_name: str, **context) -> Response:
307
307
  if template_dir is None:
308
308
  try:
309
309
  current_app = _get_current_object()
310
- template_dir = (
311
- getattr(current_app, "template_folder", None) or "templates"
312
- )
310
+ template_dir = getattr(current_app, "template_folder", "templates")
313
311
  except RuntimeError:
314
312
  # No app context, use default
315
313
  template_dir = "templates"
@@ -0,0 +1,87 @@
1
+ from dataclasses import dataclass
2
+ from unittest.mock import patch
3
+
4
+ import pytest
5
+ from bustapi import BustAPI
6
+ from bustapi.auth.decorators import permission_required, roles_required
7
+ from bustapi.testing import BustTestClient
8
+
9
+ app = BustAPI()
10
+ app.secret_key = "test_secret"
11
+
12
+
13
+ @dataclass
14
+ class MockUser:
15
+ is_authenticated: bool = True
16
+ roles: list = None
17
+ permissions: list = None
18
+
19
+ def get_id(self):
20
+ return "123"
21
+
22
+
23
+ # Setup routes
24
+ @app.route("/sync-role-or")
25
+ @roles_required("admin", "editor")
26
+ def sync_role_or():
27
+ return "ok"
28
+
29
+
30
+ @app.route("/sync-role-and")
31
+ @roles_required("admin", "editor", require_all=True)
32
+ def sync_role_and():
33
+ return "ok"
34
+
35
+
36
+ @app.route("/async-perm-and")
37
+ @permission_required("read", "write")
38
+ async def async_perm_and():
39
+ return "ok"
40
+
41
+
42
+ @app.route("/async-perm-or")
43
+ @permission_required("read", "write", require_all=False)
44
+ async def async_perm_or():
45
+ return "ok"
46
+
47
+
48
+ def test_roles_or():
49
+ with patch("bustapi.auth.login.current_user", MockUser(roles=["editor"])):
50
+ with BustTestClient(app) as client:
51
+ assert client.get("/sync-role-or").status_code == 200
52
+
53
+ with patch("bustapi.auth.login.current_user", MockUser(roles=["user"])):
54
+ with BustTestClient(app) as client:
55
+ assert client.get("/sync-role-or").status_code == 403
56
+
57
+
58
+ def test_roles_and():
59
+ with patch("bustapi.auth.login.current_user", MockUser(roles=["admin", "editor"])):
60
+ with BustTestClient(app) as client:
61
+ assert client.get("/sync-role-and").status_code == 200
62
+
63
+ with patch("bustapi.auth.login.current_user", MockUser(roles=["admin"])):
64
+ with BustTestClient(app) as client:
65
+ assert client.get("/sync-role-and").status_code == 403
66
+
67
+
68
+ def test_perms_and():
69
+ with patch(
70
+ "bustapi.auth.login.current_user", MockUser(permissions=["read", "write"])
71
+ ):
72
+ with BustTestClient(app) as client:
73
+ assert client.get("/async-perm-and").status_code == 200
74
+
75
+ with patch("bustapi.auth.login.current_user", MockUser(permissions=["read"])):
76
+ with BustTestClient(app) as client:
77
+ assert client.get("/async-perm-and").status_code == 403
78
+
79
+
80
+ def test_perms_or():
81
+ with patch("bustapi.auth.login.current_user", MockUser(permissions=["read"])):
82
+ with BustTestClient(app) as client:
83
+ assert client.get("/async-perm-or").status_code == 200
84
+
85
+ with patch("bustapi.auth.login.current_user", MockUser(permissions=["delete"])):
86
+ with BustTestClient(app) as client:
87
+ assert client.get("/async-perm-or").status_code == 403
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes