djapi-guard 1.0.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 (294) hide show
  1. djapi_guard-1.0.0/.github/FUNDING.yml +5 -0
  2. djapi_guard-1.0.0/.github/ISSUE_TEMPLATE/bug_report.md +78 -0
  3. djapi_guard-1.0.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  4. djapi_guard-1.0.0/.github/ISSUE_TEMPLATE/documentation.md +53 -0
  5. djapi_guard-1.0.0/.github/ISSUE_TEMPLATE/feature_request.md +60 -0
  6. djapi_guard-1.0.0/.github/PULL_REQUEST_TEMPLATE.md +66 -0
  7. djapi_guard-1.0.0/.github/dependabot.yml +17 -0
  8. djapi_guard-1.0.0/.github/scripts/bump_version.py +319 -0
  9. djapi_guard-1.0.0/.github/workflows/ci.yml +174 -0
  10. djapi_guard-1.0.0/.github/workflows/code-ql.yml +129 -0
  11. djapi_guard-1.0.0/.github/workflows/container-release.yml +152 -0
  12. djapi_guard-1.0.0/.github/workflows/docs.yml +193 -0
  13. djapi_guard-1.0.0/.github/workflows/release.yml +154 -0
  14. djapi_guard-1.0.0/.github/workflows/scheduled-lint.yml +201 -0
  15. djapi_guard-1.0.0/.gitignore +226 -0
  16. djapi_guard-1.0.0/.mike.yml +8 -0
  17. djapi_guard-1.0.0/.pre-commit-config.yaml +62 -0
  18. djapi_guard-1.0.0/CHANGELOG.md +29 -0
  19. djapi_guard-1.0.0/CLAUDE.md +94 -0
  20. djapi_guard-1.0.0/CODE_OF_CONDUCT.md +162 -0
  21. djapi_guard-1.0.0/CONTRIBUTING.md +132 -0
  22. djapi_guard-1.0.0/Dockerfile +32 -0
  23. djapi_guard-1.0.0/LICENSE +21 -0
  24. djapi_guard-1.0.0/MANIFEST.in +3 -0
  25. djapi_guard-1.0.0/Makefile +239 -0
  26. djapi_guard-1.0.0/PKG-INFO +805 -0
  27. djapi_guard-1.0.0/README.md +752 -0
  28. djapi_guard-1.0.0/SECURITY.md +114 -0
  29. djapi_guard-1.0.0/compose.yml +54 -0
  30. djapi_guard-1.0.0/djangoapi_guard/__init__.py +42 -0
  31. djapi_guard-1.0.0/djangoapi_guard/core/__init__.py +5 -0
  32. djapi_guard-1.0.0/djangoapi_guard/core/behavioral/__init__.py +6 -0
  33. djapi_guard-1.0.0/djangoapi_guard/core/behavioral/context.py +16 -0
  34. djapi_guard-1.0.0/djangoapi_guard/core/behavioral/processor.py +109 -0
  35. djapi_guard-1.0.0/djangoapi_guard/core/bypass/__init__.py +6 -0
  36. djapi_guard-1.0.0/djangoapi_guard/core/bypass/context.py +20 -0
  37. djapi_guard-1.0.0/djangoapi_guard/core/bypass/handler.py +67 -0
  38. djapi_guard-1.0.0/djangoapi_guard/core/checks/__init__.py +45 -0
  39. djapi_guard-1.0.0/djangoapi_guard/core/checks/base.py +107 -0
  40. djapi_guard-1.0.0/djangoapi_guard/core/checks/helpers.py +331 -0
  41. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/__init__.py +67 -0
  42. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/authentication.py +65 -0
  43. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/cloud_ip_refresh.py +23 -0
  44. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/cloud_provider.py +91 -0
  45. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/custom_request.py +64 -0
  46. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/custom_validators.py +58 -0
  47. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/emergency_mode.py +63 -0
  48. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/https_enforcement.py +77 -0
  49. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/ip_security.py +149 -0
  50. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/rate_limit.py +225 -0
  51. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/referrer.py +99 -0
  52. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/request_logging.py +17 -0
  53. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/request_size_content.py +110 -0
  54. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/required_headers.py +83 -0
  55. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/route_config.py +27 -0
  56. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/suspicious_activity.py +172 -0
  57. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/time_window.py +74 -0
  58. djapi_guard-1.0.0/djangoapi_guard/core/checks/implementations/user_agent.py +91 -0
  59. djapi_guard-1.0.0/djangoapi_guard/core/checks/pipeline.py +131 -0
  60. djapi_guard-1.0.0/djangoapi_guard/core/events/__init__.py +9 -0
  61. djapi_guard-1.0.0/djangoapi_guard/core/events/extension_events.py +164 -0
  62. djapi_guard-1.0.0/djangoapi_guard/core/events/metrics.py +80 -0
  63. djapi_guard-1.0.0/djangoapi_guard/core/initialization/__init__.py +10 -0
  64. djapi_guard-1.0.0/djangoapi_guard/core/initialization/handler_initializer.py +111 -0
  65. djapi_guard-1.0.0/djangoapi_guard/core/responses/__init__.py +6 -0
  66. djapi_guard-1.0.0/djangoapi_guard/core/responses/context.py +24 -0
  67. djapi_guard-1.0.0/djangoapi_guard/core/responses/factory.py +165 -0
  68. djapi_guard-1.0.0/djangoapi_guard/core/routing/__init__.py +6 -0
  69. djapi_guard-1.0.0/djangoapi_guard/core/routing/context.py +20 -0
  70. djapi_guard-1.0.0/djangoapi_guard/core/routing/resolver.py +103 -0
  71. djapi_guard-1.0.0/djangoapi_guard/core/validation/__init__.py +6 -0
  72. djapi_guard-1.0.0/djangoapi_guard/core/validation/context.py +14 -0
  73. djapi_guard-1.0.0/djangoapi_guard/core/validation/validator.py +83 -0
  74. djapi_guard-1.0.0/djangoapi_guard/decorators/__init__.py +59 -0
  75. djapi_guard-1.0.0/djangoapi_guard/decorators/access_control.py +87 -0
  76. djapi_guard-1.0.0/djangoapi_guard/decorators/advanced.py +82 -0
  77. djapi_guard-1.0.0/djangoapi_guard/decorators/authentication.py +65 -0
  78. djapi_guard-1.0.0/djangoapi_guard/decorators/base.py +223 -0
  79. djapi_guard-1.0.0/djangoapi_guard/decorators/behavioral.py +161 -0
  80. djapi_guard-1.0.0/djangoapi_guard/decorators/content_filtering.py +101 -0
  81. djapi_guard-1.0.0/djangoapi_guard/decorators/rate_limiting.py +47 -0
  82. djapi_guard-1.0.0/djangoapi_guard/detection_engine/__init__.py +11 -0
  83. djapi_guard-1.0.0/djangoapi_guard/detection_engine/compiler.py +230 -0
  84. djapi_guard-1.0.0/djangoapi_guard/detection_engine/monitor.py +547 -0
  85. djapi_guard-1.0.0/djangoapi_guard/detection_engine/preprocessor.py +440 -0
  86. djapi_guard-1.0.0/djangoapi_guard/detection_engine/semantic.py +504 -0
  87. djapi_guard-1.0.0/djangoapi_guard/handlers/__init__.py +21 -0
  88. djapi_guard-1.0.0/djangoapi_guard/handlers/behavior_handler.py +377 -0
  89. djapi_guard-1.0.0/djangoapi_guard/handlers/cloud_handler.py +299 -0
  90. djapi_guard-1.0.0/djangoapi_guard/handlers/dynamic_rule_handler.py +345 -0
  91. djapi_guard-1.0.0/djangoapi_guard/handlers/ipban_handler.py +147 -0
  92. djapi_guard-1.0.0/djangoapi_guard/handlers/ipinfo_handler.py +238 -0
  93. djapi_guard-1.0.0/djangoapi_guard/handlers/ratelimit_handler.py +245 -0
  94. djapi_guard-1.0.0/djangoapi_guard/handlers/redis_handler.py +286 -0
  95. djapi_guard-1.0.0/djangoapi_guard/handlers/security_headers_handler.py +552 -0
  96. djapi_guard-1.0.0/djangoapi_guard/handlers/suspatterns_handler.py +997 -0
  97. djapi_guard-1.0.0/djangoapi_guard/middleware.py +491 -0
  98. djapi_guard-1.0.0/djangoapi_guard/models.py +863 -0
  99. djapi_guard-1.0.0/djangoapi_guard/protocols/__init__.py +9 -0
  100. djapi_guard-1.0.0/djangoapi_guard/protocols/agent_protocol.py +76 -0
  101. djapi_guard-1.0.0/djangoapi_guard/protocols/geo_ip_protocol.py +16 -0
  102. djapi_guard-1.0.0/djangoapi_guard/protocols/redis_protocol.py +18 -0
  103. djapi_guard-1.0.0/djangoapi_guard/scripts/__init__.py +0 -0
  104. djapi_guard-1.0.0/djangoapi_guard/scripts/rate_lua.py +23 -0
  105. djapi_guard-1.0.0/djangoapi_guard/utils.py +848 -0
  106. djapi_guard-1.0.0/docs/api/behavior-manager.md +48 -0
  107. djapi_guard-1.0.0/docs/api/cloud-manager.md +38 -0
  108. djapi_guard-1.0.0/docs/api/core-architecture.md +68 -0
  109. djapi_guard-1.0.0/docs/api/decorators.md +106 -0
  110. djapi_guard-1.0.0/docs/api/ipban-manager.md +37 -0
  111. djapi_guard-1.0.0/docs/api/ipinfo-manager.md +39 -0
  112. djapi_guard-1.0.0/docs/api/overview.md +66 -0
  113. djapi_guard-1.0.0/docs/api/ratelimit-manager.md +35 -0
  114. djapi_guard-1.0.0/docs/api/redis-manager.md +45 -0
  115. djapi_guard-1.0.0/docs/api/security-headers.md +60 -0
  116. djapi_guard-1.0.0/docs/api/security-middleware.md +141 -0
  117. djapi_guard-1.0.0/docs/api/sus-patterns.md +59 -0
  118. djapi_guard-1.0.0/docs/api/utilities.md +57 -0
  119. djapi_guard-1.0.0/docs/assets/favicon.png +0 -0
  120. djapi_guard-1.0.0/docs/assets/logo.svg +9 -0
  121. djapi_guard-1.0.0/docs/css/custom.css +94 -0
  122. djapi_guard-1.0.0/docs/index.md +393 -0
  123. djapi_guard-1.0.0/docs/installation.md +87 -0
  124. djapi_guard-1.0.0/docs/overrides/partials/analytics.html +10 -0
  125. djapi_guard-1.0.0/docs/overrides/partials/footer.html +15 -0
  126. djapi_guard-1.0.0/docs/overrides/partials/version-select.html +14 -0
  127. djapi_guard-1.0.0/docs/release-notes.md +29 -0
  128. djapi_guard-1.0.0/docs/tutorial/advanced-customizations.md +238 -0
  129. djapi_guard-1.0.0/docs/tutorial/configuration/cors.md +103 -0
  130. djapi_guard-1.0.0/docs/tutorial/configuration/logging.md +239 -0
  131. djapi_guard-1.0.0/docs/tutorial/configuration/security-config.md +240 -0
  132. djapi_guard-1.0.0/docs/tutorial/decorators/access-control.md +122 -0
  133. djapi_guard-1.0.0/docs/tutorial/decorators/advanced.md +67 -0
  134. djapi_guard-1.0.0/docs/tutorial/decorators/authentication.md +102 -0
  135. djapi_guard-1.0.0/docs/tutorial/decorators/behavioral.md +87 -0
  136. djapi_guard-1.0.0/docs/tutorial/decorators/content-filtering.md +106 -0
  137. djapi_guard-1.0.0/docs/tutorial/decorators/overview.md +217 -0
  138. djapi_guard-1.0.0/docs/tutorial/decorators/rate-limiting.md +89 -0
  139. djapi_guard-1.0.0/docs/tutorial/examples/example-app.md +220 -0
  140. djapi_guard-1.0.0/docs/tutorial/first-steps.md +130 -0
  141. djapi_guard-1.0.0/docs/tutorial/ip-management/banning.md +64 -0
  142. djapi_guard-1.0.0/docs/tutorial/ip-management/cloud-providers.md +80 -0
  143. djapi_guard-1.0.0/docs/tutorial/ip-management/geolocation.md +101 -0
  144. djapi_guard-1.0.0/docs/tutorial/ip-management/rate-limiter.md +96 -0
  145. djapi_guard-1.0.0/docs/tutorial/redis-integration/caching.md +84 -0
  146. djapi_guard-1.0.0/docs/tutorial/security/custom-patterns.md +72 -0
  147. djapi_guard-1.0.0/docs/tutorial/security/detection-engine/architecture.md +54 -0
  148. djapi_guard-1.0.0/docs/tutorial/security/detection-engine/components.md +39 -0
  149. djapi_guard-1.0.0/docs/tutorial/security/detection-engine/configuration.md +65 -0
  150. djapi_guard-1.0.0/docs/tutorial/security/detection-engine/overview.md +51 -0
  151. djapi_guard-1.0.0/docs/tutorial/security/detection-engine/performance-tuning.md +48 -0
  152. djapi_guard-1.0.0/docs/tutorial/security/http-security-headers.md +78 -0
  153. djapi_guard-1.0.0/docs/tutorial/security/monitoring.md +59 -0
  154. djapi_guard-1.0.0/docs/tutorial/security/penetration-detection.md +72 -0
  155. djapi_guard-1.0.0/docs/tutorial/security/proxy-security.md +69 -0
  156. djapi_guard-1.0.0/docs/versions/versions.json +4 -0
  157. djapi_guard-1.0.0/examples/__init__.py +0 -0
  158. djapi_guard-1.0.0/examples/advanced/Dockerfile +40 -0
  159. djapi_guard-1.0.0/examples/advanced/README.md +78 -0
  160. djapi_guard-1.0.0/examples/advanced/advanced_app/__init__.py +0 -0
  161. djapi_guard-1.0.0/examples/advanced/advanced_app/models.py +80 -0
  162. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/__init__.py +25 -0
  163. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/access_control.py +66 -0
  164. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/admin.py +138 -0
  165. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/advanced.py +63 -0
  166. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/auth.py +67 -0
  167. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/basic.py +72 -0
  168. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/behavioral.py +76 -0
  169. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/content.py +87 -0
  170. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/headers.py +201 -0
  171. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/health.py +21 -0
  172. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/rate_limiting.py +53 -0
  173. djapi_guard-1.0.0/examples/advanced/advanced_app/routes/testing.py +98 -0
  174. djapi_guard-1.0.0/examples/advanced/advanced_app/security.py +106 -0
  175. djapi_guard-1.0.0/examples/advanced/advanced_app/views.py +0 -0
  176. djapi_guard-1.0.0/examples/advanced/advanced_project/__init__.py +0 -0
  177. djapi_guard-1.0.0/examples/advanced/advanced_project/settings.py +28 -0
  178. djapi_guard-1.0.0/examples/advanced/advanced_project/urls.py +75 -0
  179. djapi_guard-1.0.0/examples/advanced/advanced_project/wsgi.py +7 -0
  180. djapi_guard-1.0.0/examples/advanced/compose.yml +59 -0
  181. djapi_guard-1.0.0/examples/advanced/gunicorn.conf.py +21 -0
  182. djapi_guard-1.0.0/examples/advanced/manage.py +20 -0
  183. djapi_guard-1.0.0/examples/advanced/nginx/nginx.conf +65 -0
  184. djapi_guard-1.0.0/examples/advanced/pyproject.toml +15 -0
  185. djapi_guard-1.0.0/examples/simple/Dockerfile +17 -0
  186. djapi_guard-1.0.0/examples/simple/README.md +139 -0
  187. djapi_guard-1.0.0/examples/simple/__init__.py +0 -0
  188. djapi_guard-1.0.0/examples/simple/compose.yml +27 -0
  189. djapi_guard-1.0.0/examples/simple/example_app/__init__.py +0 -0
  190. djapi_guard-1.0.0/examples/simple/example_app/views.py +840 -0
  191. djapi_guard-1.0.0/examples/simple/example_project/__init__.py +0 -0
  192. djapi_guard-1.0.0/examples/simple/example_project/settings.py +106 -0
  193. djapi_guard-1.0.0/examples/simple/example_project/urls.py +66 -0
  194. djapi_guard-1.0.0/examples/simple/example_project/wsgi.py +7 -0
  195. djapi_guard-1.0.0/examples/simple/manage.py +20 -0
  196. djapi_guard-1.0.0/examples/simple/requirements.txt +3 -0
  197. djapi_guard-1.0.0/mkdocs.yml +181 -0
  198. djapi_guard-1.0.0/pyproject.toml +246 -0
  199. djapi_guard-1.0.0/setup.py +9 -0
  200. djapi_guard-1.0.0/tests/__init__.py +0 -0
  201. djapi_guard-1.0.0/tests/conftest.py +77 -0
  202. djapi_guard-1.0.0/tests/settings.py +27 -0
  203. djapi_guard-1.0.0/tests/test_agent/__init__.py +1 -0
  204. djapi_guard-1.0.0/tests/test_agent/conftest.py +265 -0
  205. djapi_guard-1.0.0/tests/test_agent/test_behavior_agent_integration.py +120 -0
  206. djapi_guard-1.0.0/tests/test_agent/test_cloud_agent_integration.py +158 -0
  207. djapi_guard-1.0.0/tests/test_agent/test_decorator_agent_integration.py +386 -0
  208. djapi_guard-1.0.0/tests/test_agent/test_drh_agent_integration.py +1322 -0
  209. djapi_guard-1.0.0/tests/test_agent/test_extension_agent_integration.py +888 -0
  210. djapi_guard-1.0.0/tests/test_agent/test_ipban_agent_integration.py +114 -0
  211. djapi_guard-1.0.0/tests/test_agent/test_ipinfo_agent_integration.py +298 -0
  212. djapi_guard-1.0.0/tests/test_agent/test_models_agent_integration.py +134 -0
  213. djapi_guard-1.0.0/tests/test_agent/test_ratelimit_agent_integration.py +218 -0
  214. djapi_guard-1.0.0/tests/test_agent/test_redis_agent_integration.py +192 -0
  215. djapi_guard-1.0.0/tests/test_agent/test_suspatterns_agent_integration.py +142 -0
  216. djapi_guard-1.0.0/tests/test_agent/test_utils_agent_integration.py +95 -0
  217. djapi_guard-1.0.0/tests/test_cloud_ips/__init__.py +0 -0
  218. djapi_guard-1.0.0/tests/test_cloud_ips/test_cloud_ips.py +277 -0
  219. djapi_guard-1.0.0/tests/test_core/__init__.py +0 -0
  220. djapi_guard-1.0.0/tests/test_core/test_behavioral.py +308 -0
  221. djapi_guard-1.0.0/tests/test_core/test_bypass_handler.py +233 -0
  222. djapi_guard-1.0.0/tests/test_core/test_check_implementations.py +838 -0
  223. djapi_guard-1.0.0/tests/test_core/test_checks_base.py +249 -0
  224. djapi_guard-1.0.0/tests/test_core/test_cloud_provider_edge_cases.py +164 -0
  225. djapi_guard-1.0.0/tests/test_core/test_edge_cases.py +419 -0
  226. djapi_guard-1.0.0/tests/test_core/test_https_enforcement_edge_cases.py +530 -0
  227. djapi_guard-1.0.0/tests/test_core/test_initialization.py +466 -0
  228. djapi_guard-1.0.0/tests/test_core/test_ip_security_edge_cases.py +189 -0
  229. djapi_guard-1.0.0/tests/test_core/test_metrics.py +102 -0
  230. djapi_guard-1.0.0/tests/test_core/test_pipeline.py +266 -0
  231. djapi_guard-1.0.0/tests/test_core/test_rate_limit_edge_cases.py +327 -0
  232. djapi_guard-1.0.0/tests/test_core/test_routing_resolver.py +236 -0
  233. djapi_guard-1.0.0/tests/test_core/test_time_window_edge_cases.py +86 -0
  234. djapi_guard-1.0.0/tests/test_core/test_validator.py +276 -0
  235. djapi_guard-1.0.0/tests/test_coverage_gaps.py +1345 -0
  236. djapi_guard-1.0.0/tests/test_decorators/__init__.py +1 -0
  237. djapi_guard-1.0.0/tests/test_decorators/test_access_control.py +178 -0
  238. djapi_guard-1.0.0/tests/test_decorators/test_advanced.py +201 -0
  239. djapi_guard-1.0.0/tests/test_decorators/test_advanced_edge_cases.py +150 -0
  240. djapi_guard-1.0.0/tests/test_decorators/test_authentication.py +274 -0
  241. djapi_guard-1.0.0/tests/test_decorators/test_base.py +163 -0
  242. djapi_guard-1.0.0/tests/test_decorators/test_behavior_handler.py +503 -0
  243. djapi_guard-1.0.0/tests/test_decorators/test_behavior_handler_edge_cases.py +118 -0
  244. djapi_guard-1.0.0/tests/test_decorators/test_behavioral.py +330 -0
  245. djapi_guard-1.0.0/tests/test_decorators/test_content_filtering.py +222 -0
  246. djapi_guard-1.0.0/tests/test_decorators/test_decorator_events.py +230 -0
  247. djapi_guard-1.0.0/tests/test_decorators/test_extension_integration.py +540 -0
  248. djapi_guard-1.0.0/tests/test_decorators/test_rate_limiting.py +137 -0
  249. djapi_guard-1.0.0/tests/test_extension/__init__.py +0 -0
  250. djapi_guard-1.0.0/tests/test_extension/test_security_extension.py +627 -0
  251. djapi_guard-1.0.0/tests/test_features/__init__.py +0 -0
  252. djapi_guard-1.0.0/tests/test_features/test_configurable_cloud_refresh.py +142 -0
  253. djapi_guard-1.0.0/tests/test_features/test_context_aware_detection.py +143 -0
  254. djapi_guard-1.0.0/tests/test_features/test_last_updated_cloud.py +84 -0
  255. djapi_guard-1.0.0/tests/test_features/test_structured_json_logging.py +99 -0
  256. djapi_guard-1.0.0/tests/test_handlers/__init__.py +0 -0
  257. djapi_guard-1.0.0/tests/test_handlers/test_agent_events.py +357 -0
  258. djapi_guard-1.0.0/tests/test_handlers/test_dynamic_rule_handler.py +985 -0
  259. djapi_guard-1.0.0/tests/test_handlers/test_handler_redis_paths.py +750 -0
  260. djapi_guard-1.0.0/tests/test_ipinfo/__init__.py +0 -0
  261. djapi_guard-1.0.0/tests/test_ipinfo/test_ipinfo.py +289 -0
  262. djapi_guard-1.0.0/tests/test_middleware.py +1327 -0
  263. djapi_guard-1.0.0/tests/test_models/__init__.py +0 -0
  264. djapi_guard-1.0.0/tests/test_models/test_models.py +273 -0
  265. djapi_guard-1.0.0/tests/test_models_legacy.py +78 -0
  266. djapi_guard-1.0.0/tests/test_redis/__init__.py +0 -0
  267. djapi_guard-1.0.0/tests/test_redis/test_redis.py +235 -0
  268. djapi_guard-1.0.0/tests/test_security_headers/__init__.py +1 -0
  269. djapi_guard-1.0.0/tests/test_security_headers/test_agent_integration.py +266 -0
  270. djapi_guard-1.0.0/tests/test_security_headers/test_cors_integration.py +259 -0
  271. djapi_guard-1.0.0/tests/test_security_headers/test_csp_validation.py +94 -0
  272. djapi_guard-1.0.0/tests/test_security_headers/test_edge_cases.py +109 -0
  273. djapi_guard-1.0.0/tests/test_security_headers/test_extension_integration.py +96 -0
  274. djapi_guard-1.0.0/tests/test_security_headers/test_headers_core.py +426 -0
  275. djapi_guard-1.0.0/tests/test_security_headers/test_redis_integration.py +315 -0
  276. djapi_guard-1.0.0/tests/test_security_headers/test_security_validation.py +203 -0
  277. djapi_guard-1.0.0/tests/test_sus_patterns/__init__.py +0 -0
  278. djapi_guard-1.0.0/tests/test_sus_patterns/conftest.py +71 -0
  279. djapi_guard-1.0.0/tests/test_sus_patterns/test_compiler.py +317 -0
  280. djapi_guard-1.0.0/tests/test_sus_patterns/test_detection_engine.py +75 -0
  281. djapi_guard-1.0.0/tests/test_sus_patterns/test_extension_integration.py +115 -0
  282. djapi_guard-1.0.0/tests/test_sus_patterns/test_monitor.py +717 -0
  283. djapi_guard-1.0.0/tests/test_sus_patterns/test_preprocessor.py +459 -0
  284. djapi_guard-1.0.0/tests/test_sus_patterns/test_semantic.py +500 -0
  285. djapi_guard-1.0.0/tests/test_sus_patterns/test_sus_patterns.py +714 -0
  286. djapi_guard-1.0.0/tests/test_utils/__init__.py +0 -0
  287. djapi_guard-1.0.0/tests/test_utils/test_ip_ban_manager.py +94 -0
  288. djapi_guard-1.0.0/tests/test_utils/test_logging.py +399 -0
  289. djapi_guard-1.0.0/tests/test_utils/test_proxy_handling.py +154 -0
  290. djapi_guard-1.0.0/tests/test_utils/test_request_checks.py +654 -0
  291. djapi_guard-1.0.0/tests/test_utils/test_utils_edge_cases.py +265 -0
  292. djapi_guard-1.0.0/tests/test_utils_legacy.py +112 -0
  293. djapi_guard-1.0.0/tests/urls.py +21 -0
  294. djapi_guard-1.0.0/vulture_whitelist.py +128 -0
@@ -0,0 +1,5 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: rennf93
4
+ tidelift: pypi/djapi-guard
5
+ custom: ['https://paypal.me/renzof93']
@@ -0,0 +1,78 @@
1
+ ---
2
+
3
+ name: Bug report
4
+ about: Create a report to help us improve DjangoAPI Guard
5
+ title: '[BUG] '
6
+ labels: bug
7
+ assignees: ''
8
+ ---
9
+
10
+ Bug Description
11
+ ===============
12
+
13
+ A clear and concise description of what the bug is.
14
+
15
+ ___
16
+
17
+ Steps To Reproduce
18
+ ------------------
19
+
20
+ Steps to reproduce the behavior:
21
+
22
+ 1. Configure DjangoAPI Guard with '...'
23
+ 2. Make request to endpoint '....'
24
+ 3. See error
25
+
26
+ ___
27
+
28
+ Expected Behavior
29
+ -----------------
30
+
31
+ A clear and concise description of what you expected to happen.
32
+
33
+ ___
34
+
35
+ Actual Behavior
36
+ ---------------
37
+
38
+ What actually happened, including error messages, stack traces, or logs.
39
+
40
+ ___
41
+
42
+ Environment
43
+ -----------
44
+
45
+ - DjangoAPI Guard version: [e.g. 1.0.0]
46
+ - Python version: [e.g. 3.11.10]
47
+ - Django version: [e.g. 5.1.0]
48
+ - OS: [e.g. Ubuntu 22.04, Windows 11, MacOS 15.4]
49
+ - Other relevant dependencies:
50
+
51
+ ___
52
+
53
+ Configuration
54
+ -------------
55
+
56
+ ```python
57
+ # Include your DjangoAPI Guard configuration here
58
+ # settings.py
59
+ MIDDLEWARE = [
60
+ "djangoapi_guard.middleware.DjangoAPIGuardMiddleware",
61
+ # ...
62
+ ]
63
+
64
+ DJANGOAPI_GUARD = {
65
+ # Include your config here
66
+ }
67
+ ```
68
+
69
+ ___
70
+
71
+ Additional Context
72
+ ------------------
73
+
74
+ Add any other context about the problem here. For example:
75
+
76
+ - Is this happening in production or development?
77
+ - Does it happen consistently or intermittently?
78
+ - Have you tried any workarounds?
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Django API Guard Documentation
4
+ url: https://rennf93.github.io/djapi-guard/
5
+ about: Check the documentation for usage information and tutorials
6
+ - name: Usage Questions
7
+ url: https://github.com/rennf93/djapi-guard/discussions
8
+ about: Please ask and answer questions in GitHub Discussions
@@ -0,0 +1,53 @@
1
+ ---
2
+
3
+ name: Documentation
4
+ about: Report issues with the DjangoAPI Guard documentation or suggest improvements
5
+ title: '[DOCS] '
6
+ labels: documentation
7
+ assignees: ''
8
+ ---
9
+
10
+ Documentation Issue
11
+ ===================
12
+
13
+ Describe the issue or improvement needed for the documentation.
14
+
15
+ ___
16
+
17
+ Current Documentation
18
+ ---------------------
19
+
20
+ Link to the current documentation page or section that needs improvement:
21
+ [Link it here](https://example.com)
22
+
23
+ ___
24
+
25
+ Suggested Changes
26
+ -----------------
27
+
28
+ Describe what changes you suggest:
29
+
30
+ - [ ] Clarify existing content
31
+ - [ ] Add missing information
32
+ - [ ] Fix incorrect information
33
+ - [ ] Improve examples
34
+ - [ ] Fix typos/grammar
35
+ - [ ] Other (please specify)
36
+
37
+ ___
38
+
39
+ Proposed Text
40
+ -------------
41
+
42
+ If you have a specific suggestion for new text, please provide it here:
43
+
44
+ ```markdown
45
+ # Your proposed documentation text here
46
+ ```
47
+
48
+ ___
49
+
50
+ Additional Context
51
+ ------------------
52
+
53
+ Any other information or screenshots about the documentation issue.
@@ -0,0 +1,60 @@
1
+ ---
2
+
3
+ name: Feature request
4
+ about: Suggest an idea for DjangoAPI Guard
5
+ title: '[FEATURE] '
6
+ labels: enhancement
7
+ assignees: ''
8
+ ---
9
+
10
+ Is your feature request related to a problem
11
+ =============================================
12
+
13
+ A clear and concise description of what the problem is. Ex. I'm always facing issues when [...]
14
+
15
+ ___
16
+
17
+ Describe the solution you'd like
18
+ ---------------------------------
19
+
20
+ A clear and concise description of what you want to happen. Include any API design ideas or examples of how you'd like to use this feature.
21
+
22
+ ___
23
+
24
+ Describe alternatives you've considered
25
+ ---------------------------------------
26
+
27
+ A clear and concise description of any alternative solutions or features you've considered.
28
+
29
+ ___
30
+
31
+ Example Implementation
32
+ ----------------------
33
+
34
+ If possible, provide a pseudocode example of how this feature might be implemented or used:
35
+
36
+ ```python
37
+ # Example code showing how you'd like to use this feature
38
+ # settings.py
39
+ MIDDLEWARE = [
40
+ "djangoapi_guard.middleware.DjangoAPIGuardMiddleware",
41
+ # ...
42
+ ]
43
+
44
+ DJANGOAPI_GUARD = {
45
+ "new_feature": {
46
+ # Your feature configuration here
47
+ }
48
+ }
49
+ ```
50
+
51
+ ___
52
+
53
+ Additional context
54
+ ------------------
55
+
56
+ Add any other context or screenshots about the feature request here:
57
+
58
+ - How would this benefit the community?
59
+ - Are there similar implementations in other libraries that could be referenced?
60
+ - Would this require changes to existing APIs?
@@ -0,0 +1,66 @@
1
+ Description
2
+ ===========
3
+
4
+ <!--- Describe your changes in detail -->
5
+
6
+ ___
7
+
8
+ Related Issue
9
+ -------------
10
+
11
+ <!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
12
+ <!--- Please link to the issue here: -->
13
+ Fixes #
14
+
15
+ ___
16
+
17
+ Motivation and Context
18
+ ----------------------
19
+
20
+ <!--- Why is this change required? What problem does it solve? -->
21
+ <!--- If adding a new feature, please describe the motivation for it -->
22
+
23
+ ___
24
+
25
+ Type of change
26
+ --------------
27
+
28
+ <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
29
+
30
+ - [ ] Bug fix (non-breaking change which fixes an issue)
31
+ - [ ] New feature (non-breaking change which adds functionality)
32
+ - [ ] Breaking change (fix or feature that would cause existing functionality to change)
33
+ - [ ] Documentation change
34
+ - [ ] Performance improvement
35
+ - [ ] Code cleanup or refactoring
36
+
37
+ ___
38
+
39
+ How Has This Been Tested
40
+ -------------------------
41
+
42
+ <!--- Please describe in detail how you tested your changes. -->
43
+ <!--- Include details of your testing environment, and the tests you ran to -->
44
+ <!--- see how your change affects other areas of the code, etc. -->
45
+
46
+ ___
47
+
48
+ Screenshots (if appropriate)
49
+ -----------------------------
50
+
51
+ ___
52
+
53
+ Checklist
54
+ ---------
55
+
56
+ <!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
57
+ <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
58
+
59
+ - [ ] My code follows the code style of this project (Mypy, Ruff)
60
+ - [ ] I have added tests to cover my changes
61
+ - [ ] All new and existing tests passed
62
+ - [ ] My change requires a change to the documentation
63
+ - [ ] I have updated the documentation accordingly
64
+ - [ ] I have checked that my changes don't introduce any new warnings or errors
65
+ - [ ] I have updated the version number if necessary
66
+ - [ ] I have added any new dependencies to the appropriate requirements file
@@ -0,0 +1,17 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+
8
+ - package-ecosystem: "pip"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
12
+ groups:
13
+ dependencies:
14
+ patterns:
15
+ - "*"
16
+ allow:
17
+ - dependency-type: "all"
@@ -0,0 +1,319 @@
1
+ """
2
+ Version bump helper script for djapi-guard.
3
+
4
+ Updates the version string across all files that reference it:
5
+ - pyproject.toml
6
+ - .mike.yml
7
+ - docs/versions/versions.json
8
+ - docs/index.md
9
+ - CHANGELOG.md
10
+ - docs/release-notes.md
11
+
12
+ Usage:
13
+ python .github/scripts/bump_version.py <version>
14
+ make bump-version VERSION=x.y.z
15
+
16
+ No external dependencies required — stdlib only.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import json
22
+ import re
23
+ import sys
24
+ from collections.abc import Callable
25
+ from datetime import datetime, timezone
26
+ from pathlib import Path
27
+
28
+ # Resolve project root relative to this script's location
29
+ PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
30
+
31
+ VERSION_PATTERN = re.compile(r"^\d+\.\d+\.\d+$")
32
+
33
+
34
+ def parse_semver(version: str) -> tuple[int, ...]:
35
+ """Parse a semver string into a comparable tuple."""
36
+ return tuple(int(part) for part in version.split("."))
37
+
38
+
39
+ def is_latest(new_version: str, existing_versions: list[str]) -> bool:
40
+ """Return True if new_version is >= all existing versions."""
41
+ new_parsed = parse_semver(new_version)
42
+ for v in existing_versions:
43
+ try:
44
+ if parse_semver(v) > new_parsed:
45
+ return False
46
+ except ValueError:
47
+ continue
48
+ return True
49
+
50
+
51
+ def sorted_versions_descending(versions: list[str]) -> list[str]:
52
+ """Sort version strings in descending semver order."""
53
+ semver_versions = []
54
+ non_semver = []
55
+ for v in versions:
56
+ try:
57
+ semver_versions.append((parse_semver(v), v))
58
+ except ValueError:
59
+ non_semver.append(v)
60
+ semver_versions.sort(reverse=True)
61
+ return [v for _, v in semver_versions] + non_semver
62
+
63
+
64
+ def update_pyproject_toml(version: str) -> bool:
65
+ """Update version in pyproject.toml."""
66
+ path = PROJECT_ROOT / "pyproject.toml"
67
+ content = path.read_text()
68
+ pattern = re.compile(r'^(version\s*=\s*)"[^"]*"', re.MULTILINE)
69
+ match = pattern.search(content)
70
+ if not match:
71
+ print(" ERROR: Could not find version field in pyproject.toml")
72
+ return False
73
+ current = re.search(r'"([^"]*)"', match.group(0))
74
+ if current and current.group(1) == version:
75
+ print(f" pyproject.toml: already set to {version}")
76
+ return True
77
+ new_content = pattern.sub(f'{match.group(1)}"{version}"', content)
78
+ path.write_text(new_content)
79
+ print(f" pyproject.toml: updated to {version}")
80
+ return True
81
+
82
+
83
+ def update_mike_yml(version: str) -> bool:
84
+ """Update .mike.yml with new version entry and latest alias."""
85
+ path = PROJECT_ROOT / ".mike.yml"
86
+ content = path.read_text()
87
+ lines = content.splitlines()
88
+
89
+ # Extract existing versions from the versions list
90
+ existing_versions: list[str] = []
91
+ versions_start = -1
92
+ versions_end = -1
93
+ in_versions = False
94
+ for i, line in enumerate(lines):
95
+ if line.startswith("versions:"):
96
+ versions_start = i
97
+ in_versions = True
98
+ continue
99
+ if in_versions:
100
+ stripped = line.strip()
101
+ if stripped.startswith("- "):
102
+ entry = stripped[2:].strip()
103
+ existing_versions.append(entry)
104
+ versions_end = i
105
+ else:
106
+ break
107
+
108
+ if versions_start == -1:
109
+ print(" ERROR: Could not find versions list in .mike.yml")
110
+ return False
111
+
112
+ # Check if version already exists
113
+ if version in existing_versions:
114
+ print(f" .mike.yml: version {version} already present")
115
+ else:
116
+ # Build new versions list: semver versions sorted descending, then "latest"
117
+ semver_versions = [v for v in existing_versions if v != "latest"]
118
+ semver_versions.append(version)
119
+ sorted_versions = sorted_versions_descending(semver_versions)
120
+ if "latest" in existing_versions:
121
+ sorted_versions.append("latest")
122
+
123
+ # Rebuild the versions block
124
+ new_version_lines = [f" - {v}" for v in sorted_versions]
125
+ lines = (
126
+ lines[: versions_start + 1] + new_version_lines + lines[versions_end + 1 :]
127
+ )
128
+ print(f" .mike.yml: added version {version}")
129
+
130
+ # Update the latest alias if this is the newest version
131
+ semver_only = [v for v in existing_versions + [version] if v != "latest"]
132
+ if is_latest(version, semver_only):
133
+ alias_pattern = re.compile(r"^(\s*latest:\s*).+$")
134
+ for i, line in enumerate(lines):
135
+ match = alias_pattern.match(line)
136
+ if match:
137
+ if line.strip() == f"latest: {version}":
138
+ print(f" .mike.yml: latest alias already points to {version}")
139
+ else:
140
+ lines[i] = f" latest: {version}"
141
+ print(f" .mike.yml: updated latest alias to {version}")
142
+ break
143
+
144
+ path.write_text("\n".join(lines) + "\n")
145
+ return True
146
+
147
+
148
+ def update_versions_json(version: str) -> bool:
149
+ """Update docs/versions/versions.json."""
150
+ path = PROJECT_ROOT / "docs" / "versions" / "versions.json"
151
+ data: dict[str, str] = json.loads(path.read_text())
152
+
153
+ if version in data and data.get("latest") == version:
154
+ print(f" versions.json: already contains {version}")
155
+ return True
156
+
157
+ changed = False
158
+ if version not in data:
159
+ data[version] = version
160
+ changed = True
161
+ print(f" versions.json: added {version}")
162
+
163
+ # Determine if this is the latest
164
+ semver_keys = [k for k in data if k != "latest"]
165
+ if is_latest(version, semver_keys):
166
+ if data.get("latest") != version:
167
+ data["latest"] = version
168
+ changed = True
169
+ print(f" versions.json: updated latest to {version}")
170
+
171
+ if not changed:
172
+ print(f" versions.json: already up to date for {version}")
173
+ return True
174
+
175
+ # Sort: semver keys descending, then "latest" at the end
176
+ semver_keys = [k for k in data if k != "latest"]
177
+ sorted_keys = sorted_versions_descending(semver_keys)
178
+ if "latest" in data:
179
+ sorted_keys.append("latest")
180
+
181
+ ordered: dict[str, str] = {k: data[k] for k in sorted_keys}
182
+ path.write_text(json.dumps(ordered, indent=4) + "\n")
183
+ return True
184
+
185
+
186
+ def update_index_md(version: str) -> bool:
187
+ """Update docker pull version tag in docs/index.md."""
188
+ path = PROJECT_ROOT / "docs" / "index.md"
189
+ content = path.read_text()
190
+
191
+ pattern = re.compile(
192
+ r"(docker pull ghcr\.io/rennf93/djapi-guard-example:v)"
193
+ r"[\d]+\.[\d]+\.[\d]+"
194
+ )
195
+ match = pattern.search(content)
196
+ if not match:
197
+ print(" docs/index.md: no docker pull version tag found, skipping")
198
+ return True
199
+
200
+ current_version = match.group(0).split(":v")[-1]
201
+ if current_version == version:
202
+ print(f" docs/index.md: already set to v{version}")
203
+ return True
204
+
205
+ # Only update if this is the latest version
206
+ # We check against pyproject.toml's current version as reference
207
+ pyproject = PROJECT_ROOT / "pyproject.toml"
208
+ pyproject_content = pyproject.read_text()
209
+ pyproject_match = re.search(
210
+ r'^version\s*=\s*"([^"]*)"', pyproject_content, re.MULTILINE
211
+ )
212
+ existing_versions = [pyproject_match.group(1)] if pyproject_match else []
213
+ existing_versions.append(current_version)
214
+
215
+ if not is_latest(version, existing_versions):
216
+ print(f" docs/index.md: {version} is not latest, skipping docker tag update")
217
+ return True
218
+
219
+ new_content = pattern.sub(f"\\g<1>{version}", content)
220
+ path.write_text(new_content)
221
+ print(f" docs/index.md: updated docker tag to v{version}")
222
+ return True
223
+
224
+
225
+ def _insert_changelog_scaffold(path: Path, version: str, label: str) -> bool:
226
+ """Insert a version scaffold block into a changelog file."""
227
+ content = path.read_text()
228
+ today = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d")
229
+ header = f"v{version} ({today})"
230
+
231
+ # Check if this version already has an entry
232
+ if f"v{version} (" in content:
233
+ print(f" {label}: v{version} entry already exists")
234
+ return True
235
+
236
+ scaffold = (
237
+ f"{header}\n"
238
+ f"-------------------\n"
239
+ f"\n"
240
+ f"TITLE (v{version})\n"
241
+ f"------------\n"
242
+ f"\n"
243
+ f"CONTENT\n"
244
+ f"\n"
245
+ f"___\n"
246
+ f"\n"
247
+ )
248
+
249
+ # Find the first existing version entry to insert before it
250
+ version_header_pattern = re.compile(r"^v\d+\.\d+\.\d+ \(", re.MULTILINE)
251
+ match = version_header_pattern.search(content)
252
+ if match:
253
+ insert_pos = match.start()
254
+ new_content = content[:insert_pos] + scaffold + content[insert_pos:]
255
+ else:
256
+ # No existing entries — append at end
257
+ new_content = content.rstrip() + "\n\n" + scaffold
258
+
259
+ path.write_text(new_content)
260
+ print(f" {label}: added v{version} scaffold")
261
+ return True
262
+
263
+
264
+ def update_changelogs(version: str) -> bool:
265
+ """Update CHANGELOG.md and docs/release-notes.md."""
266
+ changelog = PROJECT_ROOT / "CHANGELOG.md"
267
+ release_notes = PROJECT_ROOT / "docs" / "release-notes.md"
268
+
269
+ ok = True
270
+ ok = _insert_changelog_scaffold(changelog, version, "CHANGELOG.md") and ok
271
+ ok = (
272
+ _insert_changelog_scaffold(release_notes, version, "docs/release-notes.md")
273
+ and ok
274
+ )
275
+ return ok
276
+
277
+
278
+ def main() -> int:
279
+ if len(sys.argv) != 2:
280
+ print("Usage: bump_version.py <version>")
281
+ print(" version must be in X.Y.Z format")
282
+ return 1
283
+
284
+ version = sys.argv[1]
285
+
286
+ if not VERSION_PATTERN.match(version):
287
+ print(f"Error: '{version}' is not a valid version. Expected format: X.Y.Z")
288
+ return 1
289
+
290
+ print(f"Bumping version to {version}...\n")
291
+
292
+ updaters: list[tuple[str, Callable[[str], bool]]] = [
293
+ ("pyproject.toml", update_pyproject_toml),
294
+ (".mike.yml", update_mike_yml),
295
+ ("docs/versions/versions.json", update_versions_json),
296
+ ("docs/index.md", update_index_md),
297
+ ("changelogs", update_changelogs),
298
+ ]
299
+
300
+ all_ok = True
301
+ for name, updater in updaters:
302
+ try:
303
+ if not updater(version):
304
+ print(f"\n FAILED: {name}")
305
+ all_ok = False
306
+ except Exception as e:
307
+ print(f"\n ERROR updating {name}: {e}")
308
+ all_ok = False
309
+
310
+ print()
311
+ if all_ok:
312
+ print("Version bump complete.")
313
+ else:
314
+ print("Version bump completed with errors.")
315
+ return 0 if all_ok else 1
316
+
317
+
318
+ if __name__ == "__main__":
319
+ sys.exit(main())