django-chassis 1.0.1__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 (351) hide show
  1. django_chassis-1.0.1/LICENSE +21 -0
  2. django_chassis-1.0.1/MANIFEST.in +3 -0
  3. django_chassis-1.0.1/PKG-INFO +175 -0
  4. django_chassis-1.0.1/README.md +134 -0
  5. django_chassis-1.0.1/django_chassis/__init__.py +1 -0
  6. django_chassis-1.0.1/django_chassis/admins/__init__.py +15 -0
  7. django_chassis-1.0.1/django_chassis/admins/admin_audit_log.py +107 -0
  8. django_chassis-1.0.1/django_chassis/admins/group.py +56 -0
  9. django_chassis-1.0.1/django_chassis/admins/login_attempt.py +69 -0
  10. django_chassis-1.0.1/django_chassis/admins/login_attempt_schedule.py +44 -0
  11. django_chassis-1.0.1/django_chassis/admins/user.py +52 -0
  12. django_chassis-1.0.1/django_chassis/admins/user_session.py +100 -0
  13. django_chassis-1.0.1/django_chassis/apps.py +18 -0
  14. django_chassis-1.0.1/django_chassis/components/__init__.py +22 -0
  15. django_chassis-1.0.1/django_chassis/components/actions.py +145 -0
  16. django_chassis-1.0.1/django_chassis/components/alerts.py +80 -0
  17. django_chassis-1.0.1/django_chassis/components/base.py +69 -0
  18. django_chassis-1.0.1/django_chassis/components/charts.py +82 -0
  19. django_chassis-1.0.1/django_chassis/components/geo_ip_database_alert.py +46 -0
  20. django_chassis-1.0.1/django_chassis/components/metrics.py +97 -0
  21. django_chassis-1.0.1/django_chassis/components/navbar.py +101 -0
  22. django_chassis-1.0.1/django_chassis/components/toggle_actions.py +122 -0
  23. django_chassis-1.0.1/django_chassis/conf.py +32 -0
  24. django_chassis-1.0.1/django_chassis/decorators/__init__.py +25 -0
  25. django_chassis-1.0.1/django_chassis/decorators/object_action.py +99 -0
  26. django_chassis-1.0.1/django_chassis/decorators/related_items.py +25 -0
  27. django_chassis-1.0.1/django_chassis/dto/__init__.py +71 -0
  28. django_chassis-1.0.1/django_chassis/dto/admin_information_badge.py +14 -0
  29. django_chassis-1.0.1/django_chassis/dto/admin_information_row.py +21 -0
  30. django_chassis-1.0.1/django_chassis/dto/admin_information_section.py +21 -0
  31. django_chassis-1.0.1/django_chassis/dto/admin_navbar_child_item.py +16 -0
  32. django_chassis-1.0.1/django_chassis/dto/admin_navbar_item.py +21 -0
  33. django_chassis-1.0.1/django_chassis/dto/admin_page_action.py +17 -0
  34. django_chassis-1.0.1/django_chassis/dto/admin_page_alert.py +15 -0
  35. django_chassis-1.0.1/django_chassis/dto/admin_profile.py +22 -0
  36. django_chassis-1.0.1/django_chassis/dto/admin_sidebar_child_item.py +16 -0
  37. django_chassis-1.0.1/django_chassis/dto/admin_sidebar_item.py +28 -0
  38. django_chassis-1.0.1/django_chassis/dto/admin_timeline.py +14 -0
  39. django_chassis-1.0.1/django_chassis/dto/admin_timeline_group.py +14 -0
  40. django_chassis-1.0.1/django_chassis/dto/admin_timeline_item.py +17 -0
  41. django_chassis-1.0.1/django_chassis/dto/brand.py +13 -0
  42. django_chassis-1.0.1/django_chassis/dto/brand_badge.py +14 -0
  43. django_chassis-1.0.1/django_chassis/dto/client_device.py +13 -0
  44. django_chassis-1.0.1/django_chassis/dto/dashboard_action.py +23 -0
  45. django_chassis-1.0.1/django_chassis/dto/dashboard_action_variant.py +18 -0
  46. django_chassis-1.0.1/django_chassis/dto/dashboard_alert.py +20 -0
  47. django_chassis-1.0.1/django_chassis/dto/dashboard_block.py +21 -0
  48. django_chassis-1.0.1/django_chassis/dto/dashboard_chart.py +29 -0
  49. django_chassis-1.0.1/django_chassis/dto/dashboard_chart_data.py +15 -0
  50. django_chassis-1.0.1/django_chassis/dto/dashboard_chart_point.py +12 -0
  51. django_chassis-1.0.1/django_chassis/dto/dashboard_chart_series.py +15 -0
  52. django_chassis-1.0.1/django_chassis/dto/dashboard_metric.py +23 -0
  53. django_chassis-1.0.1/django_chassis/dto/dashboard_stacked_item.py +16 -0
  54. django_chassis-1.0.1/django_chassis/dto/export_field.py +16 -0
  55. django_chassis-1.0.1/django_chassis/dto/export_filter.py +17 -0
  56. django_chassis-1.0.1/django_chassis/dto/import_field.py +16 -0
  57. django_chassis-1.0.1/django_chassis/dto/import_preview.py +34 -0
  58. django_chassis-1.0.1/django_chassis/dto/login_attempt_availability.py +14 -0
  59. django_chassis-1.0.1/django_chassis/dto/request_client_metadata.py +17 -0
  60. django_chassis-1.0.1/django_chassis/dto/user_profile_activity.py +14 -0
  61. django_chassis-1.0.1/django_chassis/enums/__init__.py +57 -0
  62. django_chassis-1.0.1/django_chassis/enums/admin_audit_action.py +40 -0
  63. django_chassis-1.0.1/django_chassis/enums/admin_audit_result.py +30 -0
  64. django_chassis-1.0.1/django_chassis/enums/admin_error_status.py +73 -0
  65. django_chassis-1.0.1/django_chassis/enums/admin_navbar_item_type.py +11 -0
  66. django_chassis-1.0.1/django_chassis/enums/button_color.py +14 -0
  67. django_chassis-1.0.1/django_chassis/enums/choices_enum.py +36 -0
  68. django_chassis-1.0.1/django_chassis/enums/dashboard_alert_style.py +22 -0
  69. django_chassis-1.0.1/django_chassis/enums/dashboard_block_type.py +13 -0
  70. django_chassis-1.0.1/django_chassis/enums/dashboard_chart_color.py +11 -0
  71. django_chassis-1.0.1/django_chassis/enums/dashboard_chart_type.py +11 -0
  72. django_chassis-1.0.1/django_chassis/enums/dashboard_component_status.py +12 -0
  73. django_chassis-1.0.1/django_chassis/enums/dashboard_live_widget_type.py +12 -0
  74. django_chassis-1.0.1/django_chassis/enums/dashboard_metric_result_type.py +11 -0
  75. django_chassis-1.0.1/django_chassis/enums/dashboard_stacked_item_tone.py +12 -0
  76. django_chassis-1.0.1/django_chassis/enums/export_backend.py +22 -0
  77. django_chassis-1.0.1/django_chassis/enums/export_format.py +42 -0
  78. django_chassis-1.0.1/django_chassis/enums/export_status.py +28 -0
  79. django_chassis-1.0.1/django_chassis/enums/import_backend.py +22 -0
  80. django_chassis-1.0.1/django_chassis/enums/import_format.py +35 -0
  81. django_chassis-1.0.1/django_chassis/enums/import_status.py +30 -0
  82. django_chassis-1.0.1/django_chassis/enums/permission_check.py +10 -0
  83. django_chassis-1.0.1/django_chassis/enums/permission_name_language.py +9 -0
  84. django_chassis-1.0.1/django_chassis/enums/row_action_display.py +10 -0
  85. django_chassis-1.0.1/django_chassis/enums/row_action_type.py +12 -0
  86. django_chassis-1.0.1/django_chassis/enums/sidebar_icon_color.py +33 -0
  87. django_chassis-1.0.1/django_chassis/enums/tab_display.py +10 -0
  88. django_chassis-1.0.1/django_chassis/enums/user_session_end_reason.py +28 -0
  89. django_chassis-1.0.1/django_chassis/exceptions.py +33 -0
  90. django_chassis-1.0.1/django_chassis/filters/__init__.py +0 -0
  91. django_chassis-1.0.1/django_chassis/filters/user_session_state.py +42 -0
  92. django_chassis-1.0.1/django_chassis/forms/__init__.py +13 -0
  93. django_chassis-1.0.1/django_chassis/forms/admin_authentication.py +87 -0
  94. django_chassis-1.0.1/django_chassis/forms/confirmed_action.py +11 -0
  95. django_chassis-1.0.1/django_chassis/forms/export_form.py +103 -0
  96. django_chassis-1.0.1/django_chassis/forms/import_export_base.py +92 -0
  97. django_chassis-1.0.1/django_chassis/forms/import_form.py +65 -0
  98. django_chassis-1.0.1/django_chassis/forms/self_password_change.py +19 -0
  99. django_chassis-1.0.1/django_chassis/management/__init__.py +0 -0
  100. django_chassis-1.0.1/django_chassis/management/commands/__init__.py +0 -0
  101. django_chassis-1.0.1/django_chassis/management/commands/run_gunicorn.py +91 -0
  102. django_chassis-1.0.1/django_chassis/middlewares/__init__.py +5 -0
  103. django_chassis-1.0.1/django_chassis/middlewares/admin_audit.py +43 -0
  104. django_chassis-1.0.1/django_chassis/middlewares/admin_error_page.py +66 -0
  105. django_chassis-1.0.1/django_chassis/middlewares/user_session.py +46 -0
  106. django_chassis-1.0.1/django_chassis/migrations/0001_initial.py +217 -0
  107. django_chassis-1.0.1/django_chassis/migrations/__init__.py +0 -0
  108. django_chassis-1.0.1/django_chassis/mixins/__init__.py +6 -0
  109. django_chassis-1.0.1/django_chassis/mixins/admin.py +300 -0
  110. django_chassis-1.0.1/django_chassis/mixins/admin_site.py +355 -0
  111. django_chassis-1.0.1/django_chassis/mixins/core/__init__.py +3 -0
  112. django_chassis-1.0.1/django_chassis/mixins/core/actions.py +164 -0
  113. django_chassis-1.0.1/django_chassis/mixins/core/audit.py +68 -0
  114. django_chassis-1.0.1/django_chassis/mixins/core/base.py +73 -0
  115. django_chassis-1.0.1/django_chassis/mixins/core/changelist.py +207 -0
  116. django_chassis-1.0.1/django_chassis/mixins/core/import_export.py +193 -0
  117. django_chassis-1.0.1/django_chassis/mixins/core/object_page.py +306 -0
  118. django_chassis-1.0.1/django_chassis/mixins/core/permissions.py +75 -0
  119. django_chassis-1.0.1/django_chassis/mixins/core/presentation.py +395 -0
  120. django_chassis-1.0.1/django_chassis/mixins/no_delete_admin.py +14 -0
  121. django_chassis-1.0.1/django_chassis/mixins/read_only_admin.py +29 -0
  122. django_chassis-1.0.1/django_chassis/models/__init__.py +17 -0
  123. django_chassis-1.0.1/django_chassis/models/admin_audit_log.py +105 -0
  124. django_chassis-1.0.1/django_chassis/models/export_history.py +93 -0
  125. django_chassis-1.0.1/django_chassis/models/history_storage.py +32 -0
  126. django_chassis-1.0.1/django_chassis/models/import_history.py +93 -0
  127. django_chassis-1.0.1/django_chassis/models/login_attempt.py +52 -0
  128. django_chassis-1.0.1/django_chassis/models/login_attempt_schedule.py +39 -0
  129. django_chassis-1.0.1/django_chassis/models/managers.py +43 -0
  130. django_chassis-1.0.1/django_chassis/models/user_profile.py +58 -0
  131. django_chassis-1.0.1/django_chassis/models/user_session.py +99 -0
  132. django_chassis-1.0.1/django_chassis/navbar/__init__.py +3 -0
  133. django_chassis-1.0.1/django_chassis/navbar/admin_profile.py +40 -0
  134. django_chassis-1.0.1/django_chassis/navbar/password_change.py +40 -0
  135. django_chassis-1.0.1/django_chassis/navbar/theme.py +24 -0
  136. django_chassis-1.0.1/django_chassis/options/__init__.py +82 -0
  137. django_chassis-1.0.1/django_chassis/options/admin_page_group.py +15 -0
  138. django_chassis-1.0.1/django_chassis/options/badge_fields.py +14 -0
  139. django_chassis-1.0.1/django_chassis/options/date_hierarchy.py +15 -0
  140. django_chassis-1.0.1/django_chassis/options/decimal_amount.py +17 -0
  141. django_chassis-1.0.1/django_chassis/options/export.py +39 -0
  142. django_chassis-1.0.1/django_chassis/options/field_tabs.py +21 -0
  143. django_chassis-1.0.1/django_chassis/options/filters.py +16 -0
  144. django_chassis-1.0.1/django_chassis/options/foreign_key_tab_group.py +18 -0
  145. django_chassis-1.0.1/django_chassis/options/foreign_key_tabs.py +23 -0
  146. django_chassis-1.0.1/django_chassis/options/import_option.py +35 -0
  147. django_chassis-1.0.1/django_chassis/options/list_action.py +19 -0
  148. django_chassis-1.0.1/django_chassis/options/list_actions.py +12 -0
  149. django_chassis-1.0.1/django_chassis/options/object_actions.py +17 -0
  150. django_chassis-1.0.1/django_chassis/options/permission.py +35 -0
  151. django_chassis-1.0.1/django_chassis/options/pretty_json.py +10 -0
  152. django_chassis-1.0.1/django_chassis/options/related_entities.py +21 -0
  153. django_chassis-1.0.1/django_chassis/options/related_entity.py +23 -0
  154. django_chassis-1.0.1/django_chassis/options/row_action.py +19 -0
  155. django_chassis-1.0.1/django_chassis/options/row_actions.py +30 -0
  156. django_chassis-1.0.1/django_chassis/options/search.py +16 -0
  157. django_chassis-1.0.1/django_chassis/options/settings.py +13 -0
  158. django_chassis-1.0.1/django_chassis/options/sidebar_link.py +15 -0
  159. django_chassis-1.0.1/django_chassis/options/sidebar_model_item.py +14 -0
  160. django_chassis-1.0.1/django_chassis/options/sidebar_page_item.py +14 -0
  161. django_chassis-1.0.1/django_chassis/options/sidebar_section.py +22 -0
  162. django_chassis-1.0.1/django_chassis/options/table.py +21 -0
  163. django_chassis-1.0.1/django_chassis/options/table_action.py +24 -0
  164. django_chassis-1.0.1/django_chassis/options/table_action_url_kwarg.py +11 -0
  165. django_chassis-1.0.1/django_chassis/options/table_column.py +13 -0
  166. django_chassis-1.0.1/django_chassis/permissions.py +53 -0
  167. django_chassis-1.0.1/django_chassis/protocols.py +40 -0
  168. django_chassis-1.0.1/django_chassis/py.typed +0 -0
  169. django_chassis-1.0.1/django_chassis/registries/__init__.py +3 -0
  170. django_chassis-1.0.1/django_chassis/registries/permission_registry.py +33 -0
  171. django_chassis-1.0.1/django_chassis/renderers/__init__.py +3 -0
  172. django_chassis-1.0.1/django_chassis/renderers/admin_error_page_renderer.py +167 -0
  173. django_chassis-1.0.1/django_chassis/services/__init__.py +65 -0
  174. django_chassis-1.0.1/django_chassis/services/action_permission_validation_service.py +50 -0
  175. django_chassis-1.0.1/django_chassis/services/admin_audit_log_service.py +155 -0
  176. django_chassis-1.0.1/django_chassis/services/admin_navbar_service.py +118 -0
  177. django_chassis-1.0.1/django_chassis/services/admin_page_service.py +108 -0
  178. django_chassis-1.0.1/django_chassis/services/admin_permission_service.py +24 -0
  179. django_chassis-1.0.1/django_chassis/services/admin_profile_service.py +54 -0
  180. django_chassis-1.0.1/django_chassis/services/admin_sidebar_service.py +304 -0
  181. django_chassis-1.0.1/django_chassis/services/celery_availability_service.py +25 -0
  182. django_chassis-1.0.1/django_chassis/services/client_device_service.py +193 -0
  183. django_chassis-1.0.1/django_chassis/services/client_geo_ip_service.py +158 -0
  184. django_chassis-1.0.1/django_chassis/services/client_ip_service.py +56 -0
  185. django_chassis-1.0.1/django_chassis/services/confirmed_action_service.py +46 -0
  186. django_chassis-1.0.1/django_chassis/services/dashboard_analytics_cache_service.py +28 -0
  187. django_chassis-1.0.1/django_chassis/services/dashboard_live_serialization_service.py +68 -0
  188. django_chassis-1.0.1/django_chassis/services/dashboard_service.py +379 -0
  189. django_chassis-1.0.1/django_chassis/services/deleted_objects_service.py +164 -0
  190. django_chassis-1.0.1/django_chassis/services/import_apply_service.py +262 -0
  191. django_chassis-1.0.1/django_chassis/services/import_export_dispatch_service.py +146 -0
  192. django_chassis-1.0.1/django_chassis/services/import_export_field_service.py +157 -0
  193. django_chassis-1.0.1/django_chassis/services/import_export_filter_service.py +183 -0
  194. django_chassis-1.0.1/django_chassis/services/import_export_process_service.py +226 -0
  195. django_chassis-1.0.1/django_chassis/services/import_export_python_queue_service.py +91 -0
  196. django_chassis-1.0.1/django_chassis/services/import_export_serialization_service.py +493 -0
  197. django_chassis-1.0.1/django_chassis/services/login_attempt_limit_service.py +341 -0
  198. django_chassis-1.0.1/django_chassis/services/pagination_service.py +61 -0
  199. django_chassis-1.0.1/django_chassis/services/permission_initialization_service.py +35 -0
  200. django_chassis-1.0.1/django_chassis/services/permission_name_normalization_service.py +125 -0
  201. django_chassis-1.0.1/django_chassis/services/session_key_crypto_service.py +26 -0
  202. django_chassis-1.0.1/django_chassis/services/table_service.py +135 -0
  203. django_chassis-1.0.1/django_chassis/services/user_profile_service.py +117 -0
  204. django_chassis-1.0.1/django_chassis/services/user_session_service.py +266 -0
  205. django_chassis-1.0.1/django_chassis/signals/__init__.py +10 -0
  206. django_chassis-1.0.1/django_chassis/signals/initialize_permissions.py +15 -0
  207. django_chassis-1.0.1/django_chassis/signals/normalize_default_permission_names.py +13 -0
  208. django_chassis-1.0.1/django_chassis/signals/user_profile.py +42 -0
  209. django_chassis-1.0.1/django_chassis/singleton.py +17 -0
  210. django_chassis-1.0.1/django_chassis/static/admin/chassis/admin.css +1815 -0
  211. django_chassis-1.0.1/django_chassis/static/admin/chassis/alerts.css +264 -0
  212. django_chassis-1.0.1/django_chassis/static/admin/chassis/alerts.js +46 -0
  213. django_chassis-1.0.1/django_chassis/static/admin/chassis/apexcharts/apexcharts.css +1203 -0
  214. django_chassis-1.0.1/django_chassis/static/admin/chassis/apexcharts/apexcharts.min.js +5 -0
  215. django_chassis-1.0.1/django_chassis/static/admin/chassis/auth.css +311 -0
  216. django_chassis-1.0.1/django_chassis/static/admin/chassis/collapsibles.js +46 -0
  217. django_chassis-1.0.1/django_chassis/static/admin/chassis/dashboard.css +854 -0
  218. django_chassis-1.0.1/django_chassis/static/admin/chassis/dashboard_charts.js +234 -0
  219. django_chassis-1.0.1/django_chassis/static/admin/chassis/dashboard_live.js +332 -0
  220. django_chassis-1.0.1/django_chassis/static/admin/chassis/date_input_mask.js +237 -0
  221. django_chassis-1.0.1/django_chassis/static/admin/chassis/error_page.css +116 -0
  222. django_chassis-1.0.1/django_chassis/static/admin/chassis/filters.js +19 -0
  223. django_chassis-1.0.1/django_chassis/static/admin/chassis/fontawesome/css/all.min.css +9 -0
  224. django_chassis-1.0.1/django_chassis/static/admin/chassis/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  225. django_chassis-1.0.1/django_chassis/static/admin/chassis/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  226. django_chassis-1.0.1/django_chassis/static/admin/chassis/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  227. django_chassis-1.0.1/django_chassis/static/admin/chassis/fontawesome/webfonts/fa-v4compatibility.woff2 +0 -0
  228. django_chassis-1.0.1/django_chassis/static/admin/chassis/icon.svg +7 -0
  229. django_chassis-1.0.1/django_chassis/static/admin/chassis/navbar.css +374 -0
  230. django_chassis-1.0.1/django_chassis/static/admin/chassis/navbar_dropdown.js +29 -0
  231. django_chassis-1.0.1/django_chassis/static/admin/chassis/related_pagination.js +176 -0
  232. django_chassis-1.0.1/django_chassis/static/admin/chassis/secret_field.js +105 -0
  233. django_chassis-1.0.1/django_chassis/static/admin/chassis/sidebar.css +765 -0
  234. django_chassis-1.0.1/django_chassis/static/admin/chassis/sidebar.js +63 -0
  235. django_chassis-1.0.1/django_chassis/static/admin/chassis/table_selection.js +22 -0
  236. django_chassis-1.0.1/django_chassis/tasks/__init__.py +3 -0
  237. django_chassis-1.0.1/django_chassis/tasks/process_import_export.py +26 -0
  238. django_chassis-1.0.1/django_chassis/templates/admin/base.html +328 -0
  239. django_chassis-1.0.1/django_chassis/templates/admin/change_form.html +35 -0
  240. django_chassis-1.0.1/django_chassis/templates/admin/chassis/auth_alert.html +9 -0
  241. django_chassis-1.0.1/django_chassis/templates/admin/chassis/auth_alerts.html +40 -0
  242. django_chassis-1.0.1/django_chassis/templates/admin/chassis/blocked_profiles.html +80 -0
  243. django_chassis-1.0.1/django_chassis/templates/admin/chassis/brand.html +16 -0
  244. django_chassis-1.0.1/django_chassis/templates/admin/chassis/change_form.html +63 -0
  245. django_chassis-1.0.1/django_chassis/templates/admin/chassis/change_list.html +141 -0
  246. django_chassis-1.0.1/django_chassis/templates/admin/chassis/confirmed_action.html +29 -0
  247. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/actions/base.html +21 -0
  248. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/actions/toggle.html +45 -0
  249. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/index.html +113 -0
  250. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/actions.html +14 -0
  251. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/alerts.html +27 -0
  252. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/chart.html +40 -0
  253. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/items/action.html +29 -0
  254. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/items/metric.html +75 -0
  255. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/metrics.html +14 -0
  256. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/metrics_and_actions.html +18 -0
  257. django_chassis-1.0.1/django_chassis/templates/admin/chassis/dashboard/sections/panel_heading.html +12 -0
  258. django_chassis-1.0.1/django_chassis/templates/admin/chassis/date_hierarchy.html +23 -0
  259. django_chassis-1.0.1/django_chassis/templates/admin/chassis/filters.html +49 -0
  260. django_chassis-1.0.1/django_chassis/templates/admin/chassis/form_rows.html +44 -0
  261. django_chassis-1.0.1/django_chassis/templates/admin/chassis/import_export_form.html +128 -0
  262. django_chassis-1.0.1/django_chassis/templates/admin/chassis/import_export_landing.html +42 -0
  263. django_chassis-1.0.1/django_chassis/templates/admin/chassis/import_export_preview.html +113 -0
  264. django_chassis-1.0.1/django_chassis/templates/admin/chassis/information_alert.html +7 -0
  265. django_chassis-1.0.1/django_chassis/templates/admin/chassis/information_page.html +24 -0
  266. django_chassis-1.0.1/django_chassis/templates/admin/chassis/information_sections.html +108 -0
  267. django_chassis-1.0.1/django_chassis/templates/admin/chassis/object_page.html +26 -0
  268. django_chassis-1.0.1/django_chassis/templates/admin/chassis/page.html +21 -0
  269. django_chassis-1.0.1/django_chassis/templates/admin/chassis/pagination.html +18 -0
  270. django_chassis-1.0.1/django_chassis/templates/admin/chassis/related_entities.html +41 -0
  271. django_chassis-1.0.1/django_chassis/templates/admin/chassis/row_actions.html +19 -0
  272. django_chassis-1.0.1/django_chassis/templates/admin/chassis/search.html +29 -0
  273. django_chassis-1.0.1/django_chassis/templates/admin/chassis/self_password_change.html +34 -0
  274. django_chassis-1.0.1/django_chassis/templates/admin/chassis/sidebar.html +74 -0
  275. django_chassis-1.0.1/django_chassis/templates/admin/chassis/table.html +54 -0
  276. django_chassis-1.0.1/django_chassis/templates/admin/chassis/timeline.html +37 -0
  277. django_chassis-1.0.1/django_chassis/templates/admin/chassis/widgets/date.html +1 -0
  278. django_chassis-1.0.1/django_chassis/templates/admin/chassis/widgets/split_datetime.html +16 -0
  279. django_chassis-1.0.1/django_chassis/templates/admin/chassis/widgets/time.html +1 -0
  280. django_chassis-1.0.1/django_chassis/templates/admin/error.html +37 -0
  281. django_chassis-1.0.1/django_chassis/templates/admin/footer.html +15 -0
  282. django_chassis-1.0.1/django_chassis/templates/admin/login.html +86 -0
  283. django_chassis-1.0.1/django_chassis/templates/admin/object_actions/base_action_view.html +18 -0
  284. django_chassis-1.0.1/django_chassis/templatetags/__init__.py +1 -0
  285. django_chassis-1.0.1/django_chassis/templatetags/admin_footer.py +15 -0
  286. django_chassis-1.0.1/django_chassis/templatetags/chassis_admin.py +95 -0
  287. django_chassis-1.0.1/django_chassis/type_aliases.py +5 -0
  288. django_chassis-1.0.1/django_chassis/utils/__init__.py +8 -0
  289. django_chassis-1.0.1/django_chassis/utils/fixed_point_decimal.py +39 -0
  290. django_chassis-1.0.1/django_chassis/utils/table_exists.py +8 -0
  291. django_chassis-1.0.1/django_chassis/validators/__init__.py +0 -0
  292. django_chassis-1.0.1/django_chassis/validators/login_attempt_unlock.py +16 -0
  293. django_chassis-1.0.1/django_chassis/validators/object_action_condition.py +23 -0
  294. django_chassis-1.0.1/django_chassis/validators/translation_management.py +15 -0
  295. django_chassis-1.0.1/django_chassis/validators/user_session_termination.py +20 -0
  296. django_chassis-1.0.1/django_chassis/views/__init__.py +19 -0
  297. django_chassis-1.0.1/django_chassis/views/admin_information_page.py +44 -0
  298. django_chassis-1.0.1/django_chassis/views/admin_object_page.py +214 -0
  299. django_chassis-1.0.1/django_chassis/views/admin_page.py +113 -0
  300. django_chassis-1.0.1/django_chassis/views/admin_profile.py +232 -0
  301. django_chassis-1.0.1/django_chassis/views/import_export.py +575 -0
  302. django_chassis-1.0.1/django_chassis/views/permission_admin_page.py +29 -0
  303. django_chassis-1.0.1/django_chassis/views/personal_admin_page.py +22 -0
  304. django_chassis-1.0.1/django_chassis/views/self_password_change.py +54 -0
  305. django_chassis-1.0.1/django_chassis/views/superuser_admin_page.py +24 -0
  306. django_chassis-1.0.1/django_chassis/widgets/__init__.py +33 -0
  307. django_chassis-1.0.1/django_chassis/widgets/date_input.py +33 -0
  308. django_chassis-1.0.1/django_chassis/widgets/date_time_input.py +27 -0
  309. django_chassis-1.0.1/django_chassis/widgets/execution_backend_select.py +35 -0
  310. django_chassis-1.0.1/django_chassis/widgets/input_mask.py +35 -0
  311. django_chassis-1.0.1/django_chassis/widgets/split_date_time.py +19 -0
  312. django_chassis-1.0.1/django_chassis/widgets/time_input.py +33 -0
  313. django_chassis-1.0.1/django_chassis.egg-info/PKG-INFO +175 -0
  314. django_chassis-1.0.1/django_chassis.egg-info/SOURCES.txt +349 -0
  315. django_chassis-1.0.1/django_chassis.egg-info/dependency_links.txt +1 -0
  316. django_chassis-1.0.1/django_chassis.egg-info/requires.txt +10 -0
  317. django_chassis-1.0.1/django_chassis.egg-info/top_level.txt +1 -0
  318. django_chassis-1.0.1/pyproject.toml +109 -0
  319. django_chassis-1.0.1/setup.cfg +4 -0
  320. django_chassis-1.0.1/tests/test_admin_mro.py +57 -0
  321. django_chassis-1.0.1/tests/test_admin_object_page.py +100 -0
  322. django_chassis-1.0.1/tests/test_admin_permissions.py +139 -0
  323. django_chassis-1.0.1/tests/test_admin_site.py +272 -0
  324. django_chassis-1.0.1/tests/test_badge_fields.py +75 -0
  325. django_chassis-1.0.1/tests/test_client_metadata.py +103 -0
  326. django_chassis-1.0.1/tests/test_collapsible_state.py +173 -0
  327. django_chassis-1.0.1/tests/test_custom_permissions.py +86 -0
  328. django_chassis-1.0.1/tests/test_dashboard_analytics_cache_service.py +58 -0
  329. django_chassis-1.0.1/tests/test_dashboard_live.py +356 -0
  330. django_chassis-1.0.1/tests/test_date_hierarchy.py +46 -0
  331. django_chassis-1.0.1/tests/test_date_input_mask.py +188 -0
  332. django_chassis-1.0.1/tests/test_decimal_amount.py +178 -0
  333. django_chassis-1.0.1/tests/test_deleted_objects.py +89 -0
  334. django_chassis-1.0.1/tests/test_error_pages.py +256 -0
  335. django_chassis-1.0.1/tests/test_import_export.py +1023 -0
  336. django_chassis-1.0.1/tests/test_list_actions.py +221 -0
  337. django_chassis-1.0.1/tests/test_model_table_names.py +29 -0
  338. django_chassis-1.0.1/tests/test_navbar.py +504 -0
  339. django_chassis-1.0.1/tests/test_object_actions.py +119 -0
  340. django_chassis-1.0.1/tests/test_pagination_service.py +71 -0
  341. django_chassis-1.0.1/tests/test_permission_mixins.py +49 -0
  342. django_chassis-1.0.1/tests/test_permission_name_normalization.py +112 -0
  343. django_chassis-1.0.1/tests/test_permissions.py +106 -0
  344. django_chassis-1.0.1/tests/test_related_entities.py +143 -0
  345. django_chassis-1.0.1/tests/test_row_actions.py +57 -0
  346. django_chassis-1.0.1/tests/test_service_exports.py +10 -0
  347. django_chassis-1.0.1/tests/test_singleton.py +74 -0
  348. django_chassis-1.0.1/tests/test_source_conventions.py +261 -0
  349. django_chassis-1.0.1/tests/test_table_service.py +196 -0
  350. django_chassis-1.0.1/tests/test_timeline.py +142 -0
  351. django_chassis-1.0.1/tests/test_users_module.py +194 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RDD Lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ recursive-include django_chassis/templates *
2
+ recursive-include django_chassis/static *
3
+ include django_chassis/py.typed
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-chassis
3
+ Version: 1.0.1
4
+ Summary: Declarative Django Admin chassis: mixin, site, options, pages, and dashboard
5
+ Author-email: Raman Marozau <r.morozov@rdd-lab.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://django-chassis.rdd-lab.com/
8
+ Project-URL: Documentation, https://django-chassis.rdd-lab.com/
9
+ Project-URL: Issues, https://github.com/RDDLab/Django-Chassis/issues
10
+ Project-URL: Repository, https://github.com/RDDLab/Django-Chassis
11
+ Project-URL: Changelog, https://github.com/RDDLab/Django-Chassis/blob/main/CHANGELOG.md
12
+ Keywords: django,admin,dashboard,chassis
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Framework :: Django
18
+ Classifier: Framework :: Django :: 6.0
19
+ Classifier: Framework :: Django :: 6.1
20
+ Classifier: Programming Language :: Python
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Internet :: WWW/HTTP
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: <3.15,>=3.13
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: django>=6.0
32
+ Requires-Dist: pygments>=2.18
33
+ Requires-Dist: openpyxl>=3.1
34
+ Requires-Dist: geoip2>=4.8
35
+ Requires-Dist: netaddr>=1.3.0
36
+ Requires-Dist: device-detector>=6.4.0
37
+ Requires-Dist: gunicorn>=26.1.0
38
+ Provides-Extra: celery
39
+ Requires-Dist: celery>=5.3; extra == "celery"
40
+ Dynamic: license-file
41
+
42
+ <div align="center">
43
+ <img src="https://github.com/RDDLab/Django-Chassis/raw/main/docs/static/img/logo.svg" alt="Django-Chassis" width="560">
44
+
45
+ <p><strong>A declarative, fully typed chassis for building polished Django Admin applications.</strong></p>
46
+
47
+ <p>
48
+ <a href="https://django-chassis.rdd-lab.com/">Documentation</a> ·
49
+ <a href="https://django-chassis.rdd-lab.com/getting-started">Quick start</a> ·
50
+ <a href="https://django-chassis.rdd-lab.com/api-reference">API reference</a> ·
51
+ <a href="https://github.com/RDDLab/Django-Chassis/blob/main/CHANGELOG.md">Changelog</a>
52
+ </p>
53
+
54
+ <p>
55
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/badge/release-1.0.1-0f766e?style=flat-square" alt="Django-Chassis 1.0.1"></a>
56
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/pypi/pyversions/django-chassis.svg?style=flat-square" alt="Supported Python versions"></a>
57
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/pypi/djversions/django-chassis.svg?style=flat-square" alt="Supported Django versions"></a>
58
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/pypi/types/django-chassis.svg?style=flat-square" alt="Typed package"></a>
59
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="MIT license"></a>
60
+ </p>
61
+
62
+ <p>
63
+ <a href="https://github.com/RDDLab/Django-Chassis/actions/workflows/testing.yml"><img src="https://img.shields.io/github/actions/workflow/status/RDDLab/Django-Chassis/testing.yml?branch=main&amp;label=tests&amp;style=flat-square" alt="Test status"></a>
64
+ <a href="https://results.pre-commit.ci/latest/github/RDDLab/Django-Chassis/main"><img src="https://results.pre-commit.ci/badge/github/RDDLab/Django-Chassis/main.svg" alt="pre-commit.ci status"></a>
65
+ </p>
66
+ </div>
67
+
68
+ ---
69
+
70
+ Django-Chassis gives a project a structured `AdminSite`, composable
71
+ `ModelAdmin` options, custom pages, dashboard contracts, and a complete template
72
+ overlay. Domain models and business rules stay in the project; Chassis provides
73
+ the reusable Admin application layer around them.
74
+
75
+ ## Features
76
+
77
+ - **Declarative configuration** — compose the Admin with
78
+ `ChassisAdminSiteMixin`, `ChassisAdminMixin`, and immutable `options`.
79
+ - **A polished changelist** — search, filters, date hierarchy, tabs, badges,
80
+ pretty JSON, and decimal-amount presentation without ad-hoc template forks.
81
+ - **Row, list, and object actions** — permission-aware buttons, confirmation, and condition methods.
82
+ - **Related entities and generic tables** — independently paginated tables with `TableOption`.
83
+ - **Custom pages** — permission-aware pages, personal pages, information pages, and timelines.
84
+ - **Dashboard contracts** — metrics, charts, alerts, actions, a four-column grid, and live refresh at `dashboard/live/`.
85
+ - **Import/export** — JSON/XML in, JSON/XML/CSV/XLSX out, preview/apply, history, optional Celery.
86
+ - **Users and security** — profiles, sessions, login-attempt limits, GeoIP country detection, and an Admin audit journal.
87
+ - **Fully typed** — ships `py.typed` and is checked with Pyrefly in strict mode.
88
+
89
+ ## Installation
90
+
91
+ ```bash
92
+ pip install django-chassis
93
+ ```
94
+
95
+ Version `1.0.1` requires Python 3.13 or 3.14 and Django 6.0+.
96
+
97
+ Put `'django_chassis'` **before** `'django.contrib.admin'` so package templates overlay the stock Admin:
98
+
99
+ ```python
100
+ INSTALLED_APPS = [
101
+ 'django_chassis',
102
+ 'django.contrib.admin',
103
+ # ...
104
+ ]
105
+ ```
106
+
107
+ Background import/export is optional:
108
+
109
+ ```bash
110
+ pip install 'django-chassis[celery]'
111
+ ```
112
+
113
+ For a production HTTP server, Chassis also provides a Gunicorn management
114
+ command:
115
+
116
+ ```bash
117
+ python manage.py run_gunicorn --port=8000 --workers=2
118
+ ```
119
+
120
+ ## Quick start
121
+
122
+ Create a Chassis `AdminSite`, register a model, and mount the site in `urls.py`:
123
+
124
+ ```python
125
+ from django.contrib.admin import AdminSite, ModelAdmin
126
+ from django.urls import path
127
+ from django.utils.translation import gettext_lazy as _
128
+
129
+ from django_chassis.mixins import ChassisAdminMixin, ChassisAdminSiteMixin
130
+ from django_chassis.options import RowActionsOption, SearchOption
131
+
132
+ from catalog.models import Book
133
+
134
+
135
+ class CustomAdminSite(ChassisAdminSiteMixin, AdminSite):
136
+ chassis_brand_name = _('My project')
137
+ chassis_brand_logo_static_path = 'img/logo.png'
138
+
139
+
140
+ admin_site = CustomAdminSite(name='admin')
141
+
142
+
143
+ class BookAdmin(ChassisAdminMixin, ModelAdmin):
144
+ options = [SearchOption(fields=['title', 'isbn']), RowActionsOption()]
145
+
146
+
147
+ admin_site.register(Book, BookAdmin)
148
+
149
+ urlpatterns = [path('admin/', admin_site.urls)]
150
+ ```
151
+
152
+ > `ChassisAdminSiteMixin` and `ChassisAdminMixin` must come before their Django
153
+ > classes in the MRO.
154
+
155
+ ## Documentation
156
+
157
+ Read the full guides, architecture notes, option reference, and dashboard
158
+ contracts at **[django-chassis.rdd-lab.com](https://django-chassis.rdd-lab.com/)**.
159
+
160
+ ## Testing
161
+
162
+ ```bash
163
+ uv sync --group dev
164
+ uv run pytest
165
+ ```
166
+
167
+ ## License
168
+
169
+ Distributed under the [MIT License](https://opensource.org/licenses/MIT).
170
+
171
+ ## Support the project
172
+
173
+ <a href="https://nowpayments.io/donation?api_key=7664bfa5-ea12-4ded-9c3b-8a498d437114" target="_blank" rel="noreferrer noopener">
174
+ <img src="https://nowpayments.io/images/embeds/donation-button-white.svg" alt="Cryptocurrency & Bitcoin donation button by NOWPayments">
175
+ </a>
@@ -0,0 +1,134 @@
1
+ <div align="center">
2
+ <img src="https://github.com/RDDLab/Django-Chassis/raw/main/docs/static/img/logo.svg" alt="Django-Chassis" width="560">
3
+
4
+ <p><strong>A declarative, fully typed chassis for building polished Django Admin applications.</strong></p>
5
+
6
+ <p>
7
+ <a href="https://django-chassis.rdd-lab.com/">Documentation</a> ·
8
+ <a href="https://django-chassis.rdd-lab.com/getting-started">Quick start</a> ·
9
+ <a href="https://django-chassis.rdd-lab.com/api-reference">API reference</a> ·
10
+ <a href="https://github.com/RDDLab/Django-Chassis/blob/main/CHANGELOG.md">Changelog</a>
11
+ </p>
12
+
13
+ <p>
14
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/badge/release-1.0.1-0f766e?style=flat-square" alt="Django-Chassis 1.0.1"></a>
15
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/pypi/pyversions/django-chassis.svg?style=flat-square" alt="Supported Python versions"></a>
16
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/pypi/djversions/django-chassis.svg?style=flat-square" alt="Supported Django versions"></a>
17
+ <a href="https://pypi.org/project/django-chassis/"><img src="https://img.shields.io/pypi/types/django-chassis.svg?style=flat-square" alt="Typed package"></a>
18
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="MIT license"></a>
19
+ </p>
20
+
21
+ <p>
22
+ <a href="https://github.com/RDDLab/Django-Chassis/actions/workflows/testing.yml"><img src="https://img.shields.io/github/actions/workflow/status/RDDLab/Django-Chassis/testing.yml?branch=main&amp;label=tests&amp;style=flat-square" alt="Test status"></a>
23
+ <a href="https://results.pre-commit.ci/latest/github/RDDLab/Django-Chassis/main"><img src="https://results.pre-commit.ci/badge/github/RDDLab/Django-Chassis/main.svg" alt="pre-commit.ci status"></a>
24
+ </p>
25
+ </div>
26
+
27
+ ---
28
+
29
+ Django-Chassis gives a project a structured `AdminSite`, composable
30
+ `ModelAdmin` options, custom pages, dashboard contracts, and a complete template
31
+ overlay. Domain models and business rules stay in the project; Chassis provides
32
+ the reusable Admin application layer around them.
33
+
34
+ ## Features
35
+
36
+ - **Declarative configuration** — compose the Admin with
37
+ `ChassisAdminSiteMixin`, `ChassisAdminMixin`, and immutable `options`.
38
+ - **A polished changelist** — search, filters, date hierarchy, tabs, badges,
39
+ pretty JSON, and decimal-amount presentation without ad-hoc template forks.
40
+ - **Row, list, and object actions** — permission-aware buttons, confirmation, and condition methods.
41
+ - **Related entities and generic tables** — independently paginated tables with `TableOption`.
42
+ - **Custom pages** — permission-aware pages, personal pages, information pages, and timelines.
43
+ - **Dashboard contracts** — metrics, charts, alerts, actions, a four-column grid, and live refresh at `dashboard/live/`.
44
+ - **Import/export** — JSON/XML in, JSON/XML/CSV/XLSX out, preview/apply, history, optional Celery.
45
+ - **Users and security** — profiles, sessions, login-attempt limits, GeoIP country detection, and an Admin audit journal.
46
+ - **Fully typed** — ships `py.typed` and is checked with Pyrefly in strict mode.
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ pip install django-chassis
52
+ ```
53
+
54
+ Version `1.0.1` requires Python 3.13 or 3.14 and Django 6.0+.
55
+
56
+ Put `'django_chassis'` **before** `'django.contrib.admin'` so package templates overlay the stock Admin:
57
+
58
+ ```python
59
+ INSTALLED_APPS = [
60
+ 'django_chassis',
61
+ 'django.contrib.admin',
62
+ # ...
63
+ ]
64
+ ```
65
+
66
+ Background import/export is optional:
67
+
68
+ ```bash
69
+ pip install 'django-chassis[celery]'
70
+ ```
71
+
72
+ For a production HTTP server, Chassis also provides a Gunicorn management
73
+ command:
74
+
75
+ ```bash
76
+ python manage.py run_gunicorn --port=8000 --workers=2
77
+ ```
78
+
79
+ ## Quick start
80
+
81
+ Create a Chassis `AdminSite`, register a model, and mount the site in `urls.py`:
82
+
83
+ ```python
84
+ from django.contrib.admin import AdminSite, ModelAdmin
85
+ from django.urls import path
86
+ from django.utils.translation import gettext_lazy as _
87
+
88
+ from django_chassis.mixins import ChassisAdminMixin, ChassisAdminSiteMixin
89
+ from django_chassis.options import RowActionsOption, SearchOption
90
+
91
+ from catalog.models import Book
92
+
93
+
94
+ class CustomAdminSite(ChassisAdminSiteMixin, AdminSite):
95
+ chassis_brand_name = _('My project')
96
+ chassis_brand_logo_static_path = 'img/logo.png'
97
+
98
+
99
+ admin_site = CustomAdminSite(name='admin')
100
+
101
+
102
+ class BookAdmin(ChassisAdminMixin, ModelAdmin):
103
+ options = [SearchOption(fields=['title', 'isbn']), RowActionsOption()]
104
+
105
+
106
+ admin_site.register(Book, BookAdmin)
107
+
108
+ urlpatterns = [path('admin/', admin_site.urls)]
109
+ ```
110
+
111
+ > `ChassisAdminSiteMixin` and `ChassisAdminMixin` must come before their Django
112
+ > classes in the MRO.
113
+
114
+ ## Documentation
115
+
116
+ Read the full guides, architecture notes, option reference, and dashboard
117
+ contracts at **[django-chassis.rdd-lab.com](https://django-chassis.rdd-lab.com/)**.
118
+
119
+ ## Testing
120
+
121
+ ```bash
122
+ uv sync --group dev
123
+ uv run pytest
124
+ ```
125
+
126
+ ## License
127
+
128
+ Distributed under the [MIT License](https://opensource.org/licenses/MIT).
129
+
130
+ ## Support the project
131
+
132
+ <a href="https://nowpayments.io/donation?api_key=7664bfa5-ea12-4ded-9c3b-8a498d437114" target="_blank" rel="noreferrer noopener">
133
+ <img src="https://nowpayments.io/images/embeds/donation-button-white.svg" alt="Cryptocurrency & Bitcoin donation button by NOWPayments">
134
+ </a>
@@ -0,0 +1,15 @@
1
+ from django_chassis.admins.admin_audit_log import AdminAuditLogAdmin
2
+ from django_chassis.admins.group import GroupAdmin
3
+ from django_chassis.admins.login_attempt import LoginAttemptAdmin
4
+ from django_chassis.admins.login_attempt_schedule import LoginAttemptScheduleAdmin
5
+ from django_chassis.admins.user import UserAdmin
6
+ from django_chassis.admins.user_session import UserSessionAdmin
7
+
8
+ __all__ = [
9
+ 'AdminAuditLogAdmin',
10
+ 'GroupAdmin',
11
+ 'LoginAttemptAdmin',
12
+ 'LoginAttemptScheduleAdmin',
13
+ 'UserAdmin',
14
+ 'UserSessionAdmin'
15
+ ]
@@ -0,0 +1,107 @@
1
+ from django.contrib import admin
2
+ from django.db.models import Model
3
+ from django.http import HttpRequest
4
+ from django.utils.translation import gettext_lazy as _
5
+
6
+ from django_chassis.mixins.admin import ChassisAdminMixin
7
+ from django_chassis.mixins.read_only_admin import ReadOnlyAdminMixin
8
+ from django_chassis.options import FiltersOption, SearchOption
9
+
10
+
11
+ class AdminAuditLogAdmin(ChassisAdminMixin, ReadOnlyAdminMixin, admin.ModelAdmin):
12
+ """
13
+ Просматривать журнал HTTP-действий Django Admin.
14
+ """
15
+
16
+ options = [
17
+ SearchOption(fields=['username', 'path', 'object_repr', 'client_ip']),
18
+ FiltersOption(fields=['action', 'result', 'is_superuser'])
19
+ ]
20
+ fieldsets = [
21
+ (
22
+ _('Действие'),
23
+ {
24
+ 'classes': ['wide'],
25
+ 'fields': [
26
+ 'id',
27
+ 'user',
28
+ 'username',
29
+ 'is_superuser',
30
+ 'action',
31
+ 'result',
32
+ 'action_name',
33
+ 'created_at',
34
+ 'completed_at',
35
+ 'status_code',
36
+ 'response_time_ms'
37
+ ]
38
+ }
39
+ ),
40
+ (
41
+ _('Объект'),
42
+ {
43
+ 'classes': ['wide'],
44
+ 'fields': ['app_label', 'model_name', 'object_id', 'object_repr', 'object_count', 'changes']
45
+ }
46
+ ),
47
+ (
48
+ _('Запрос'),
49
+ {
50
+ 'classes': ['wide'],
51
+ 'fields': [
52
+ 'method',
53
+ 'path',
54
+ 'route_name',
55
+ 'query_params',
56
+ 'client_ip',
57
+ 'remote_ip',
58
+ 'forwarded_for',
59
+ 'user_agent',
60
+ 'browser',
61
+ 'operating_system',
62
+ 'is_mobile',
63
+ 'referer',
64
+ 'session_hash'
65
+ ]
66
+ }
67
+ )
68
+ ]
69
+ readonly_fields = [
70
+ 'id',
71
+ 'user',
72
+ 'username',
73
+ 'is_superuser',
74
+ 'action',
75
+ 'result',
76
+ 'action_name',
77
+ 'created_at',
78
+ 'completed_at',
79
+ 'status_code',
80
+ 'response_time_ms',
81
+ 'app_label',
82
+ 'model_name',
83
+ 'object_id',
84
+ 'object_repr',
85
+ 'object_count',
86
+ 'changes',
87
+ 'method',
88
+ 'path',
89
+ 'route_name',
90
+ 'query_params',
91
+ 'client_ip',
92
+ 'remote_ip',
93
+ 'forwarded_for',
94
+ 'user_agent',
95
+ 'browser',
96
+ 'operating_system',
97
+ 'is_mobile',
98
+ 'referer',
99
+ 'session_hash'
100
+ ]
101
+
102
+ def has_view_permission(self, request: HttpRequest, obj: Model | None = None) -> bool:
103
+ """
104
+ Сохранить стандартную проверку view журнала.
105
+ """
106
+ del obj
107
+ return getattr(request.user, 'has_perm')('django_chassis.view_adminauditlog')
@@ -0,0 +1,56 @@
1
+ from django.contrib.auth.admin import GroupAdmin as DjangoGroupAdmin
2
+ from django.db.models import Model
3
+ from django.http import HttpRequest
4
+
5
+ from django_chassis.mixins.admin import ChassisAdminMixin
6
+ from django_chassis.options import SearchOption
7
+ from django_chassis.protocols import cast_admin_user
8
+
9
+
10
+ class GroupAdmin(ChassisAdminMixin, DjangoGroupAdmin):
11
+ """
12
+ Управлять стандартными группами Django через Chassis Admin.
13
+ """
14
+
15
+ options = [SearchOption(fields=['name'])]
16
+
17
+ @classmethod
18
+ def _is_active_staff_superuser(cls, request: HttpRequest) -> bool:
19
+ """
20
+ Разрешить управление группами только полному суперпользователю.
21
+ """
22
+ user = cast_admin_user(request.user)
23
+ return user.is_authenticated and user.is_active and user.is_staff and user.is_superuser
24
+
25
+ def has_module_permission(self, request: HttpRequest) -> bool:
26
+ """
27
+ Скрыть раздел групп от несуперпользователей.
28
+ """
29
+ return self._is_active_staff_superuser(request)
30
+
31
+ def has_view_permission(self, request: HttpRequest, obj: Model | None = None) -> bool:
32
+ """
33
+ Закрыть список, карточку и прямые URL групп.
34
+ """
35
+ del obj
36
+ return self._is_active_staff_superuser(request)
37
+
38
+ def has_add_permission(self, request: HttpRequest) -> bool:
39
+ """
40
+ Запретить создание групп несуперпользователям.
41
+ """
42
+ return self._is_active_staff_superuser(request)
43
+
44
+ def has_change_permission(self, request: HttpRequest, obj: Model | None = None) -> bool:
45
+ """
46
+ Запретить изменение группы несуперпользователям.
47
+ """
48
+ del obj
49
+ return self._is_active_staff_superuser(request)
50
+
51
+ def has_delete_permission(self, request: HttpRequest, obj: Model | None = None) -> bool:
52
+ """
53
+ Запретить удаление группы несуперпользователям.
54
+ """
55
+ del obj
56
+ return self._is_active_staff_superuser(request)
@@ -0,0 +1,69 @@
1
+ from django.contrib import admin, messages
2
+ from django.contrib.auth.base_user import AbstractBaseUser
3
+ from django.db.models import Model
4
+ from django.http import HttpRequest, HttpResponse
5
+ from django.utils.translation import gettext_lazy as _
6
+
7
+ from django_chassis.decorators import object_action
8
+ from django_chassis.enums import ButtonColor
9
+ from django_chassis.mixins.admin import ChassisAdminMixin
10
+ from django_chassis.mixins.read_only_admin import ReadOnlyAdminMixin
11
+ from django_chassis.models.login_attempt import LoginAttempt
12
+ from django_chassis.options import ObjectActionsOption, SearchOption
13
+ from django_chassis.services.login_attempt_limit_service import LoginAttemptLimitService
14
+ from django_chassis.validators.login_attempt_unlock import can_unlock_login_attempt
15
+
16
+ class LoginAttemptAdmin(ChassisAdminMixin, ReadOnlyAdminMixin, admin.ModelAdmin):
17
+ """
18
+ Просматривать журнал попыток входа и снимать блокировку области.
19
+ """
20
+
21
+ options = [SearchOption(fields=['username', 'client_ip', 'browser']), ObjectActionsOption(actions=['unlock_scope'])]
22
+ fieldsets = [
23
+ (_('Попытка'), {'classes': ['wide'], 'fields': [
24
+ 'id',
25
+ 'username',
26
+ 'user',
27
+ 'client_ip',
28
+ 'browser',
29
+ 'attempt_number',
30
+ 'is_successful',
31
+ 'is_unlock',
32
+ 'created_at'
33
+ ]})
34
+ ]
35
+ readonly_fields = [
36
+ 'id',
37
+ 'username',
38
+ 'user',
39
+ 'client_ip',
40
+ 'browser',
41
+ 'attempt_number',
42
+ 'is_successful',
43
+ 'is_unlock',
44
+ 'created_at'
45
+ ]
46
+
47
+ @object_action(
48
+ description=_('Снять блокировку'),
49
+ permission='unlock_loginattempt',
50
+ confirmation=_('Снять блокировку входа для этой области логин/IP/браузер?'),
51
+ color=ButtonColor.WARNING,
52
+ condition=can_unlock_login_attempt
53
+ )
54
+ def unlock_scope(self, request: HttpRequest, obj: LoginAttempt) -> HttpResponse | None:
55
+ """
56
+ Начать новый цикл ограничений для области этой записи.
57
+ """
58
+ if not isinstance(request.user, AbstractBaseUser):
59
+ return None
60
+ LoginAttemptLimitService().unlock(username=obj.username, client_ip=obj.client_ip, browser=obj.browser)
61
+ messages.success(request, _('Блокировка входа снята.'))
62
+ return None
63
+
64
+ def has_view_permission(self, request: HttpRequest, obj: Model | None = None) -> bool:
65
+ """
66
+ Сохранить стандартную проверку view журнала попыток.
67
+ """
68
+ del obj
69
+ return getattr(request.user, 'has_perm')('django_chassis.view_loginattempt')
@@ -0,0 +1,44 @@
1
+ from django.contrib import admin
2
+ from django.db.models import Model
3
+ from django.http import HttpRequest
4
+ from django.utils.translation import gettext_lazy as _
5
+
6
+ from django_chassis.mixins.admin import ChassisAdminMixin
7
+ from django_chassis.mixins.no_delete_admin import NoDeleteAdminMixin
8
+ from django_chassis.models.login_attempt_schedule import LoginAttemptSchedule
9
+ from django_chassis.options import SearchOption
10
+ from django_chassis.protocols import cast_admin_user
11
+
12
+ class LoginAttemptScheduleAdmin(ChassisAdminMixin, NoDeleteAdminMixin, admin.ModelAdmin):
13
+ """
14
+ Настраивать задержки между попытками локального входа.
15
+ """
16
+
17
+ options = [SearchOption(fields=['attempt_number'])]
18
+ fieldsets = [(_('Правило'), {'classes': ['wide'], 'fields': ['attempt_number', 'delay_seconds', 'is_active']})]
19
+
20
+ def has_module_permission(self, request: HttpRequest) -> bool:
21
+ """
22
+ Показать расписание только суперпользователю.
23
+ """
24
+ return bool(cast_admin_user(request.user).is_superuser)
25
+
26
+ def has_view_permission(self, request: HttpRequest, obj: Model | None = None) -> bool:
27
+ """
28
+ Закрыть карточку расписания от несуперпользователей.
29
+ """
30
+ del obj
31
+ return bool(cast_admin_user(request.user).is_superuser)
32
+
33
+ def has_add_permission(self, request: HttpRequest) -> bool:
34
+ """
35
+ Разрешить создание правил только суперпользователю.
36
+ """
37
+ return bool(cast_admin_user(request.user).is_superuser)
38
+
39
+ def has_change_permission(self, request: HttpRequest, obj: Model | None = None) -> bool:
40
+ """
41
+ Разрешить изменение правил только суперпользователю.
42
+ """
43
+ del obj
44
+ return bool(cast_admin_user(request.user).is_superuser)