django-whiteneuron 0.2.48.5__tar.gz → 0.3.0.3__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 (191) hide show
  1. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/PKG-INFO +41 -11
  2. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/README.md +38 -8
  3. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/django_whiteneuron.egg-info/PKG-INFO +41 -11
  4. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/django_whiteneuron.egg-info/SOURCES.txt +4 -0
  5. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/django_whiteneuron.egg-info/requires.txt +2 -2
  6. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/pyproject.toml +8 -3
  7. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/urls.py +1 -0
  8. django_whiteneuron-0.3.0.3/whiteneuron/base/utils.py +165 -0
  9. django_whiteneuron-0.3.0.3/whiteneuron/file_management/admin.py +163 -0
  10. django_whiteneuron-0.3.0.3/whiteneuron/file_management/migrations/0004_excelfile_hash_pdffile_hash.py +23 -0
  11. django_whiteneuron-0.3.0.3/whiteneuron/file_management/models.py +121 -0
  12. django_whiteneuron-0.3.0.3/whiteneuron/file_management/urls.py +7 -0
  13. django_whiteneuron-0.3.0.3/whiteneuron/file_management/views.py +50 -0
  14. django_whiteneuron-0.3.0.3/whiteneuron/locale/vi/LC_MESSAGES/django.mo +0 -0
  15. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/locale/vi/LC_MESSAGES/django.po +56 -0
  16. django_whiteneuron-0.3.0.3/whiteneuron/static/base/css/styles.css +2 -0
  17. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/js/loading.js +0 -10
  18. {django_whiteneuron-0.2.48.5/whiteneuron/file_management → django_whiteneuron-0.3.0.3/whiteneuron/synchronization}/views.py +0 -0
  19. django_whiteneuron-0.2.48.5/whiteneuron/base/utils.py → django_whiteneuron-0.3.0.3/whiteneuron/templates/admin/signature.html +15 -158
  20. django_whiteneuron-0.3.0.3/whiteneuron/templates/file_management/widgets/clearable_file_input_no_download.html +20 -0
  21. django_whiteneuron-0.2.48.5/whiteneuron/file_management/admin.py +0 -32
  22. django_whiteneuron-0.2.48.5/whiteneuron/file_management/models.py +0 -65
  23. django_whiteneuron-0.2.48.5/whiteneuron/locale/vi/LC_MESSAGES/django.mo +0 -0
  24. django_whiteneuron-0.2.48.5/whiteneuron/static/base/css/styles.css +0 -2
  25. django_whiteneuron-0.2.48.5/whiteneuron/synchronization/views.py +0 -3
  26. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/LICENSE +0 -0
  27. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/django_whiteneuron.egg-info/dependency_links.txt +0 -0
  28. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/django_whiteneuron.egg-info/top_level.txt +0 -0
  29. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/setup.cfg +0 -0
  30. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/__init__.py +0 -0
  31. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/__init__.py +0 -0
  32. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/admin.py +0 -0
  33. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/apps.py +0 -0
  34. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/asgi.py +0 -0
  35. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/ckeditor.py +0 -0
  36. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/filters.py +0 -0
  37. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/forms.py +0 -0
  38. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/management/__init__.py +0 -0
  39. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/management/commands/__init__.py +0 -0
  40. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/management/commands/init_admin.py +0 -0
  41. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/management/commands/init_groupuser.py +0 -0
  42. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/management/commands/init_guest.py +0 -0
  43. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/middleware.py +0 -0
  44. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0001_initial.py +0 -0
  45. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0002_imagemodel_userprofile_user_avatar_user_biography_and_more.py +0 -0
  46. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0003_notification_obj_link.py +0 -0
  47. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0004_delete_notification.py +0 -0
  48. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0005_user_show_softdelete.py +0 -0
  49. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0006_user_is_bot.py +0 -0
  50. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0007_app.py +0 -0
  51. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0008_app_created_at_app_created_by_app_deleted_at_and_more.py +0 -0
  52. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0009_alter_app_table.py +0 -0
  53. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0010_app_category.py +0 -0
  54. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0011_alter_app_options.py +0 -0
  55. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0012_app_permission.py +0 -0
  56. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0013_app_thumbnail_url.py +0 -0
  57. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0014_alter_app_created_at_alter_app_updated_at_and_more.py +0 -0
  58. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0015_ipblacklist.py +0 -0
  59. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0016_uablacklist.py +0 -0
  60. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/0017_alter_uablacklist_pattern.py +0 -0
  61. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/migrations/__init__.py +0 -0
  62. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/modeladmin.py +0 -0
  63. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/models.py +0 -0
  64. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/resources.py +0 -0
  65. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/settings.py +0 -0
  66. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/sites.py +0 -0
  67. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/tasks.py +0 -0
  68. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/templatetags/__init__.py +0 -0
  69. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/templatetags/unfold_list_custom.py +0 -0
  70. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/templatetags/wn_filters.py +0 -0
  71. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/tests.py +0 -0
  72. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/thread_local.py +0 -0
  73. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/views.py +0 -0
  74. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/base/widgets.py +0 -0
  75. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/__init__.py +0 -0
  76. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_import_export/__init__.py +0 -0
  77. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_import_export/admin.py +0 -0
  78. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_import_export/constants.py +0 -0
  79. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_import_export/mixins.py +0 -0
  80. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_import_export/tasks.py +0 -0
  81. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_import_export/utils.py +0 -0
  82. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_modeltranslation/__init__.py +0 -0
  83. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_modeltranslation/admin.py +0 -0
  84. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/contrib/wn_modeltranslation/utils.py +0 -0
  85. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/dashboard/__init__.py +0 -0
  86. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/dashboard/admin.py +0 -0
  87. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/dashboard/apps.py +0 -0
  88. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/dashboard/migrations/__init__.py +0 -0
  89. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/dashboard/models.py +0 -0
  90. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/dashboard/tests.py +0 -0
  91. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/dashboard/views.py +0 -0
  92. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/__init__.py +0 -0
  93. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/admin.py +0 -0
  94. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/apps.py +0 -0
  95. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/migrations/0001_initial.py +0 -0
  96. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/migrations/0002_feedbackdata_created_by_feedbackdata_deleted_at_and_more.py +0 -0
  97. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/migrations/0003_feedbackdata_note.py +0 -0
  98. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/migrations/0004_alter_feedbackdata_object_id.py +0 -0
  99. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/migrations/0005_feedbackdata_field.py +0 -0
  100. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/migrations/0006_alter_feedbackdata_created_at_and_more.py +0 -0
  101. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/migrations/__init__.py +0 -0
  102. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/models.py +0 -0
  103. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/tests.py +0 -0
  104. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/urls.py +0 -0
  105. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/utils.py +0 -0
  106. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/feedbacks/views.py +0 -0
  107. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/__init__.py +0 -0
  108. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/apps.py +0 -0
  109. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/migrations/0001_initial.py +0 -0
  110. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/migrations/0002_alter_excelfile_options_alter_pdffile_options_and_more.py +0 -0
  111. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/migrations/0003_alter_excelfile_created_at_and_more.py +0 -0
  112. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/migrations/__init__.py +0 -0
  113. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/tests.py +0 -0
  114. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/file_management/utils.py +0 -0
  115. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/manage.py +0 -0
  116. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/__init__.py +0 -0
  117. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/admin.py +0 -0
  118. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/apps.py +0 -0
  119. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/consumers.py +0 -0
  120. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/management/__init__.py +0 -0
  121. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/management/commands/__init__.py +0 -0
  122. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/management/commands/call_demo_noti.py +0 -0
  123. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0001_initial.py +0 -0
  124. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0002_alter_notificationconfig_event_type.py +0 -0
  125. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0003_notification.py +0 -0
  126. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0004_alter_notification_flag.py +0 -0
  127. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0005_notification_keywords.py +0 -0
  128. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0006_remove_notification_keywords.py +0 -0
  129. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0007_notification_changed_data.py +0 -0
  130. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0008_alter_notification_changed_data.py +0 -0
  131. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0009_notification_action_by_alter_notification_user.py +0 -0
  132. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0010_alter_notification_user.py +0 -0
  133. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0011_alter_notification_user.py +0 -0
  134. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/0012_alter_notification_action_and_more.py +0 -0
  135. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/migrations/__init__.py +0 -0
  136. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/models.py +0 -0
  137. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/routing.py +0 -0
  138. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/tests.py +0 -0
  139. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/utils.py +0 -0
  140. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/notification/views.py +0 -0
  141. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/css/btn-styles.css +0 -0
  142. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/css/ckeditor5.css +0 -0
  143. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/css/loading.css +0 -0
  144. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/forms/css/html-editor.css +0 -0
  145. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/forms/js/format.html.js +0 -0
  146. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/forms/js/trix.config.js +0 -0
  147. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/images/delete.svg +0 -0
  148. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/images/edit.svg +0 -0
  149. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/images/icon-viewlink.svg +0 -0
  150. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/images/loading.gif +0 -0
  151. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/images/login-bg.jpg +0 -0
  152. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/images/login_bg.jpg +0 -0
  153. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/images/logo/WhiteNeuron.png +0 -0
  154. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/js/chart.min.js +0 -0
  155. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/js/d3.v7.min.js +0 -0
  156. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/static/base/js/whiteneuron.js +0 -0
  157. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/synchronization/__init__.py +0 -0
  158. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/synchronization/admin.py +0 -0
  159. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/synchronization/apps.py +0 -0
  160. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/synchronization/migrations/__init__.py +0 -0
  161. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/synchronization/models.py +0 -0
  162. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/synchronization/tests.py +0 -0
  163. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/400.html +0 -0
  164. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/403.html +0 -0
  165. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/404.html +0 -0
  166. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/429.html +0 -0
  167. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/500.html +0 -0
  168. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/auth/user/add_form.html +0 -0
  169. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/base/app_change_list.html +0 -0
  170. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/base/image_change_form.html +0 -0
  171. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/base/userprofile_change_form.html +0 -0
  172. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/base.html +0 -0
  173. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/change_list.html +0 -0
  174. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/feedbacks/feedback_change_form.html +0 -0
  175. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/grid_view_results.html +0 -0
  176. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/header.html +0 -0
  177. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/index.html +0 -0
  178. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/login.html +0 -0
  179. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/login_after.html +0 -0
  180. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/search_form.html +0 -0
  181. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/submit_line.html +0 -0
  182. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/wn_change_form.html +0 -0
  183. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/admin/wn_history_panel.html +0 -0
  184. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/base/forms/helpers/toolbar.html +0 -0
  185. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/base/forms/wysiwyg.html +0 -0
  186. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/base.html +0 -0
  187. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/unfold/helpers/account_links.html +0 -0
  188. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/unfold/helpers/app_list_badge.html +0 -0
  189. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/unfold/helpers/field_password.html +0 -0
  190. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/unfold/helpers/navigation_user.html +0 -0
  191. {django_whiteneuron-0.2.48.5 → django_whiteneuron-0.3.0.3}/whiteneuron/templates/unfold/helpers/pagination.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-whiteneuron
3
- Version: 0.2.48.5
3
+ Version: 0.3.0.3
4
4
  Summary: A modern Django Admin extension with enhanced UI/UX, dashboard, feedback, file management, rate limiting, IP blacklisting, and advanced admin integrations built on django-unfold.
5
5
  Author-email: White Neuron <anhnt@whiteneuron.ai>
6
6
  License: MIT License
@@ -58,7 +58,7 @@ Requires-Dist: markdown>=3.7
58
58
  Requires-Dist: openai>=1.58.1
59
59
  Requires-Dist: openpyxl>=3.1.5
60
60
  Requires-Dist: pandas>=2.2.3
61
- Requires-Dist: pillow>=12.1.1
61
+ Requires-Dist: pillow>=12.2.0
62
62
  Requires-Dist: python-dotenv>=1.0.1
63
63
  Requires-Dist: redis>=5.2.1
64
64
  Requires-Dist: sentry-sdk==2.28.0
@@ -74,7 +74,7 @@ Requires-Dist: django-ckeditor-5>=0.2.18
74
74
  Requires-Dist: django-cors-headers>=4.3.0
75
75
  Requires-Dist: django-unfold>=0.85.0
76
76
  Requires-Dist: djangoql>=0.18.1
77
- Requires-Dist: cryptography>=46.0.5
77
+ Requires-Dist: cryptography>=46.0.7
78
78
  Requires-Dist: pyopenssl==26.0.0
79
79
  Provides-Extra: dev
80
80
  Requires-Dist: pytest; extra == "dev"
@@ -96,7 +96,7 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
96
96
 
97
97
  ## Current Version
98
98
 
99
- - 0.2.48.3
99
+ - 0.3.0.2
100
100
 
101
101
  ## Compatibility
102
102
 
@@ -107,10 +107,40 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
107
107
 
108
108
  ## Changelog
109
109
 
110
- ### v0.2.48.4 (2026-04-11) — latest
111
- **Security: Nâng cấp cbor2 5.9.0 và ujson 5.12.0**
112
- - **Security**: `cbor2` nâng từ `v5.8.0` lên `v5.9.0` — bản vá lỗi và cải thiện encoding/decoding CBOR.
113
- - **Security**: `ujson` nâng từ `v5.11.0` lên `v5.12.0` — bản vá bảo mật và cải thiện hiệu suất JSON serialization.
110
+ ### v0.3.0.3 (2026-04-14) — latest
111
+ **Dependency: Upgrade pillow ≥12.2.0, cryptography ≥46.0.7**
112
+ - **Updated**: `pillow` minimum version bumped from `12.1.1` to `12.2.0` — latest upstream patch.
113
+ - **Updated**: `cryptography` minimum version bumped from `46.0.5` to `46.0.7` — security and bug-fix release.
114
+
115
+ ### v0.3.0.2 (2026-04-13)
116
+ **Hotfix: Loading overlay no longer auto-hides after timeout**
117
+ - **Fixed**: `loading.js` — removed the auto-hide logic that dismissed the overlay after 45 seconds. The overlay now only hides when the server sends back the `wn_loading_done` cookie, or via `pageshow`/`visibilitychange`/`focus` events.
118
+
119
+ ### v0.3.0.1 (2026-04-13)
120
+ **Hotfix: Email signature extracted to standalone file; exclude signature_ceo.html from build**
121
+ - **Fixed**: `TEMPLATE` in `base/utils.py` — replaced hardcoded inline HTML signature with a `{signature}` placeholder; content is now read from `templates/admin/signature.html` at the time `send_email_login` is called.
122
+ - **Added**: `_load_signature()` helper — reads `signature.html` relative to `utils.py`.
123
+ - **Added**: `templates/admin/signature.html` — standalone HTML email signature (CTO).
124
+ - **Added**: `templates/admin/signature_ceo.html` — CEO email signature (local-only, excluded from package build).
125
+ - **Config**: `pyproject.toml` — added `[tool.setuptools.exclude-package-data]` to exclude `signature_ceo.html` from wheel/sdist.
126
+
127
+ ### v0.3.0 (2026-04-13)
128
+ **Feature: File integrity protection — SHA-256 hash verification for ExcelFile & PDFFile**
129
+ - **Added**: `compute_file_hash()` function — computes SHA-256 of a `FieldFile` via direct `storage.open()` to avoid Django internal state issues (works for both in-memory uploads and committed storage files).
130
+ - **Added**: `BaseFile.save()` override — automatically computes and stores SHA-256 hash on every new upload; resets `status='done'` when file is replaced after an error; backfills hash for existing files with no hash.
131
+ - **Added**: `BaseFile.verify_integrity()` — compares live storage hash against stored hash; returns `False` if missing or mismatched.
132
+ - **Added**: `download_file` view — `@login_required` endpoint at `file-management/download/<type>/<pk>/`; enrolls legacy records on first download, blocks tampered files with `403 Forbidden`, marks them `status='error'`.
133
+ - **Added**: `file_management/urls.py` — wired into `base/urls.py`.
134
+ - **Added**: `FileInputNoDownload` widget — extends `UnfoldAdminFileFieldWidget` with a custom template that removes the direct download button; adds `accepted_file_types` support per admin subclass (`.xlsx,.xls,.csv` for Excel; `.pdf` for PDF).
135
+ - **Added**: `BaseFileAdmin` enhancements — `integrity_status`, `hash_display`, `current_hash_display` readonly fields; `verified_download` smart button (primary button when OK, error badge when tampered/missing); `change_view` shows Django error message banner on integrity failure; `get_fieldsets` context-aware layout (auto/upload/new).
136
+ - **Fixed**: `status_view` / `method_view` XSS — replaced f-string + `format_html` pattern with proper `format_html(template, *args)` escaping.
137
+ - **Fixed**: `file.delete(save=False)` in `BaseFile.delete()` — prevents extra `save()` call after file deletion.
138
+ - **Improved**: `accepted_file_types` class attribute on admin subclasses — browser-level file type filtering in upload dialog.
139
+
140
+ ### v0.2.48.4 (2026-04-11)
141
+ **Security: Upgrade cbor2 5.9.0 and ujson 5.12.0**
142
+ - **Security**: `cbor2` upgraded from `v5.8.0` to `v5.9.0` — patch release with bug fixes and improved CBOR encoding/decoding.
143
+ - **Security**: `ujson` upgraded from `v5.11.0` to `v5.12.0` — security patch and improved JSON serialization performance.
114
144
 
115
145
  ### v0.2.48.3 (2026-04-10)
116
146
  **Improve: Notification list — DaisyUI badge display, search field verbose names**
@@ -119,9 +149,9 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
119
149
  - **Fixed**: `get_verbose_name_field` now traverses `__`-separated lookup paths (e.g. `user__username`) to resolve proper verbose names for all search fields in `search_help_text`.
120
150
 
121
151
  ### v0.2.48.2 (2026-04-10)
122
- **Security: Nâng cấp django 5.2.13 và thêm pyOpenSSL 26.0.0**
123
- - **Security**: `django` lower bound nâng từ `>=5.2.12` lên `>=5.2.13` — bản vá bảo mật mới nhất của Django.
124
- - **Security**: `pyopenssl==26.0.0` thêm vào explicit dependencies — đảm bảo phiên bản mới nhất của pyOpenSSL được sử dụng, vá các lỗ hổng tiềm ẩn trong TLS/SSL handling.
152
+ **Security: Upgrade django 5.2.13 and add pyOpenSSL 26.0.0**
153
+ - **Security**: `django` lower bound raised from `>=5.2.12` to `>=5.2.13` — latest Django security patch.
154
+ - **Security**: `pyopenssl==26.0.0` added as an explicit dependency — ensures the latest version of pyOpenSSL is used, patching potential vulnerabilities in TLS/SSL handling.
125
155
 
126
156
  ### v0.2.48.1 (2026-04-06)
127
157
  **Fix: Duplicate history entries in change history panel**
@@ -11,7 +11,7 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
11
11
 
12
12
  ## Current Version
13
13
 
14
- - 0.2.48.3
14
+ - 0.3.0.2
15
15
 
16
16
  ## Compatibility
17
17
 
@@ -22,10 +22,40 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
22
22
 
23
23
  ## Changelog
24
24
 
25
- ### v0.2.48.4 (2026-04-11) — latest
26
- **Security: Nâng cấp cbor2 5.9.0 và ujson 5.12.0**
27
- - **Security**: `cbor2` nâng từ `v5.8.0` lên `v5.9.0` — bản vá lỗi và cải thiện encoding/decoding CBOR.
28
- - **Security**: `ujson` nâng từ `v5.11.0` lên `v5.12.0` — bản vá bảo mật và cải thiện hiệu suất JSON serialization.
25
+ ### v0.3.0.3 (2026-04-14) — latest
26
+ **Dependency: Upgrade pillow ≥12.2.0, cryptography ≥46.0.7**
27
+ - **Updated**: `pillow` minimum version bumped from `12.1.1` to `12.2.0` — latest upstream patch.
28
+ - **Updated**: `cryptography` minimum version bumped from `46.0.5` to `46.0.7` — security and bug-fix release.
29
+
30
+ ### v0.3.0.2 (2026-04-13)
31
+ **Hotfix: Loading overlay no longer auto-hides after timeout**
32
+ - **Fixed**: `loading.js` — removed the auto-hide logic that dismissed the overlay after 45 seconds. The overlay now only hides when the server sends back the `wn_loading_done` cookie, or via `pageshow`/`visibilitychange`/`focus` events.
33
+
34
+ ### v0.3.0.1 (2026-04-13)
35
+ **Hotfix: Email signature extracted to standalone file; exclude signature_ceo.html from build**
36
+ - **Fixed**: `TEMPLATE` in `base/utils.py` — replaced hardcoded inline HTML signature with a `{signature}` placeholder; content is now read from `templates/admin/signature.html` at the time `send_email_login` is called.
37
+ - **Added**: `_load_signature()` helper — reads `signature.html` relative to `utils.py`.
38
+ - **Added**: `templates/admin/signature.html` — standalone HTML email signature (CTO).
39
+ - **Added**: `templates/admin/signature_ceo.html` — CEO email signature (local-only, excluded from package build).
40
+ - **Config**: `pyproject.toml` — added `[tool.setuptools.exclude-package-data]` to exclude `signature_ceo.html` from wheel/sdist.
41
+
42
+ ### v0.3.0 (2026-04-13)
43
+ **Feature: File integrity protection — SHA-256 hash verification for ExcelFile & PDFFile**
44
+ - **Added**: `compute_file_hash()` function — computes SHA-256 of a `FieldFile` via direct `storage.open()` to avoid Django internal state issues (works for both in-memory uploads and committed storage files).
45
+ - **Added**: `BaseFile.save()` override — automatically computes and stores SHA-256 hash on every new upload; resets `status='done'` when file is replaced after an error; backfills hash for existing files with no hash.
46
+ - **Added**: `BaseFile.verify_integrity()` — compares live storage hash against stored hash; returns `False` if missing or mismatched.
47
+ - **Added**: `download_file` view — `@login_required` endpoint at `file-management/download/<type>/<pk>/`; enrolls legacy records on first download, blocks tampered files with `403 Forbidden`, marks them `status='error'`.
48
+ - **Added**: `file_management/urls.py` — wired into `base/urls.py`.
49
+ - **Added**: `FileInputNoDownload` widget — extends `UnfoldAdminFileFieldWidget` with a custom template that removes the direct download button; adds `accepted_file_types` support per admin subclass (`.xlsx,.xls,.csv` for Excel; `.pdf` for PDF).
50
+ - **Added**: `BaseFileAdmin` enhancements — `integrity_status`, `hash_display`, `current_hash_display` readonly fields; `verified_download` smart button (primary button when OK, error badge when tampered/missing); `change_view` shows Django error message banner on integrity failure; `get_fieldsets` context-aware layout (auto/upload/new).
51
+ - **Fixed**: `status_view` / `method_view` XSS — replaced f-string + `format_html` pattern with proper `format_html(template, *args)` escaping.
52
+ - **Fixed**: `file.delete(save=False)` in `BaseFile.delete()` — prevents extra `save()` call after file deletion.
53
+ - **Improved**: `accepted_file_types` class attribute on admin subclasses — browser-level file type filtering in upload dialog.
54
+
55
+ ### v0.2.48.4 (2026-04-11)
56
+ **Security: Upgrade cbor2 5.9.0 and ujson 5.12.0**
57
+ - **Security**: `cbor2` upgraded from `v5.8.0` to `v5.9.0` — patch release with bug fixes and improved CBOR encoding/decoding.
58
+ - **Security**: `ujson` upgraded from `v5.11.0` to `v5.12.0` — security patch and improved JSON serialization performance.
29
59
 
30
60
  ### v0.2.48.3 (2026-04-10)
31
61
  **Improve: Notification list — DaisyUI badge display, search field verbose names**
@@ -34,9 +64,9 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
34
64
  - **Fixed**: `get_verbose_name_field` now traverses `__`-separated lookup paths (e.g. `user__username`) to resolve proper verbose names for all search fields in `search_help_text`.
35
65
 
36
66
  ### v0.2.48.2 (2026-04-10)
37
- **Security: Nâng cấp django 5.2.13 và thêm pyOpenSSL 26.0.0**
38
- - **Security**: `django` lower bound nâng từ `>=5.2.12` lên `>=5.2.13` — bản vá bảo mật mới nhất của Django.
39
- - **Security**: `pyopenssl==26.0.0` thêm vào explicit dependencies — đảm bảo phiên bản mới nhất của pyOpenSSL được sử dụng, vá các lỗ hổng tiềm ẩn trong TLS/SSL handling.
67
+ **Security: Upgrade django 5.2.13 and add pyOpenSSL 26.0.0**
68
+ - **Security**: `django` lower bound raised from `>=5.2.12` to `>=5.2.13` — latest Django security patch.
69
+ - **Security**: `pyopenssl==26.0.0` added as an explicit dependency — ensures the latest version of pyOpenSSL is used, patching potential vulnerabilities in TLS/SSL handling.
40
70
 
41
71
  ### v0.2.48.1 (2026-04-06)
42
72
  **Fix: Duplicate history entries in change history panel**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-whiteneuron
3
- Version: 0.2.48.5
3
+ Version: 0.3.0.3
4
4
  Summary: A modern Django Admin extension with enhanced UI/UX, dashboard, feedback, file management, rate limiting, IP blacklisting, and advanced admin integrations built on django-unfold.
5
5
  Author-email: White Neuron <anhnt@whiteneuron.ai>
6
6
  License: MIT License
@@ -58,7 +58,7 @@ Requires-Dist: markdown>=3.7
58
58
  Requires-Dist: openai>=1.58.1
59
59
  Requires-Dist: openpyxl>=3.1.5
60
60
  Requires-Dist: pandas>=2.2.3
61
- Requires-Dist: pillow>=12.1.1
61
+ Requires-Dist: pillow>=12.2.0
62
62
  Requires-Dist: python-dotenv>=1.0.1
63
63
  Requires-Dist: redis>=5.2.1
64
64
  Requires-Dist: sentry-sdk==2.28.0
@@ -74,7 +74,7 @@ Requires-Dist: django-ckeditor-5>=0.2.18
74
74
  Requires-Dist: django-cors-headers>=4.3.0
75
75
  Requires-Dist: django-unfold>=0.85.0
76
76
  Requires-Dist: djangoql>=0.18.1
77
- Requires-Dist: cryptography>=46.0.5
77
+ Requires-Dist: cryptography>=46.0.7
78
78
  Requires-Dist: pyopenssl==26.0.0
79
79
  Provides-Extra: dev
80
80
  Requires-Dist: pytest; extra == "dev"
@@ -96,7 +96,7 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
96
96
 
97
97
  ## Current Version
98
98
 
99
- - 0.2.48.3
99
+ - 0.3.0.2
100
100
 
101
101
  ## Compatibility
102
102
 
@@ -107,10 +107,40 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
107
107
 
108
108
  ## Changelog
109
109
 
110
- ### v0.2.48.4 (2026-04-11) — latest
111
- **Security: Nâng cấp cbor2 5.9.0 và ujson 5.12.0**
112
- - **Security**: `cbor2` nâng từ `v5.8.0` lên `v5.9.0` — bản vá lỗi và cải thiện encoding/decoding CBOR.
113
- - **Security**: `ujson` nâng từ `v5.11.0` lên `v5.12.0` — bản vá bảo mật và cải thiện hiệu suất JSON serialization.
110
+ ### v0.3.0.3 (2026-04-14) — latest
111
+ **Dependency: Upgrade pillow ≥12.2.0, cryptography ≥46.0.7**
112
+ - **Updated**: `pillow` minimum version bumped from `12.1.1` to `12.2.0` — latest upstream patch.
113
+ - **Updated**: `cryptography` minimum version bumped from `46.0.5` to `46.0.7` — security and bug-fix release.
114
+
115
+ ### v0.3.0.2 (2026-04-13)
116
+ **Hotfix: Loading overlay no longer auto-hides after timeout**
117
+ - **Fixed**: `loading.js` — removed the auto-hide logic that dismissed the overlay after 45 seconds. The overlay now only hides when the server sends back the `wn_loading_done` cookie, or via `pageshow`/`visibilitychange`/`focus` events.
118
+
119
+ ### v0.3.0.1 (2026-04-13)
120
+ **Hotfix: Email signature extracted to standalone file; exclude signature_ceo.html from build**
121
+ - **Fixed**: `TEMPLATE` in `base/utils.py` — replaced hardcoded inline HTML signature with a `{signature}` placeholder; content is now read from `templates/admin/signature.html` at the time `send_email_login` is called.
122
+ - **Added**: `_load_signature()` helper — reads `signature.html` relative to `utils.py`.
123
+ - **Added**: `templates/admin/signature.html` — standalone HTML email signature (CTO).
124
+ - **Added**: `templates/admin/signature_ceo.html` — CEO email signature (local-only, excluded from package build).
125
+ - **Config**: `pyproject.toml` — added `[tool.setuptools.exclude-package-data]` to exclude `signature_ceo.html` from wheel/sdist.
126
+
127
+ ### v0.3.0 (2026-04-13)
128
+ **Feature: File integrity protection — SHA-256 hash verification for ExcelFile & PDFFile**
129
+ - **Added**: `compute_file_hash()` function — computes SHA-256 of a `FieldFile` via direct `storage.open()` to avoid Django internal state issues (works for both in-memory uploads and committed storage files).
130
+ - **Added**: `BaseFile.save()` override — automatically computes and stores SHA-256 hash on every new upload; resets `status='done'` when file is replaced after an error; backfills hash for existing files with no hash.
131
+ - **Added**: `BaseFile.verify_integrity()` — compares live storage hash against stored hash; returns `False` if missing or mismatched.
132
+ - **Added**: `download_file` view — `@login_required` endpoint at `file-management/download/<type>/<pk>/`; enrolls legacy records on first download, blocks tampered files with `403 Forbidden`, marks them `status='error'`.
133
+ - **Added**: `file_management/urls.py` — wired into `base/urls.py`.
134
+ - **Added**: `FileInputNoDownload` widget — extends `UnfoldAdminFileFieldWidget` with a custom template that removes the direct download button; adds `accepted_file_types` support per admin subclass (`.xlsx,.xls,.csv` for Excel; `.pdf` for PDF).
135
+ - **Added**: `BaseFileAdmin` enhancements — `integrity_status`, `hash_display`, `current_hash_display` readonly fields; `verified_download` smart button (primary button when OK, error badge when tampered/missing); `change_view` shows Django error message banner on integrity failure; `get_fieldsets` context-aware layout (auto/upload/new).
136
+ - **Fixed**: `status_view` / `method_view` XSS — replaced f-string + `format_html` pattern with proper `format_html(template, *args)` escaping.
137
+ - **Fixed**: `file.delete(save=False)` in `BaseFile.delete()` — prevents extra `save()` call after file deletion.
138
+ - **Improved**: `accepted_file_types` class attribute on admin subclasses — browser-level file type filtering in upload dialog.
139
+
140
+ ### v0.2.48.4 (2026-04-11)
141
+ **Security: Upgrade cbor2 5.9.0 and ujson 5.12.0**
142
+ - **Security**: `cbor2` upgraded from `v5.8.0` to `v5.9.0` — patch release with bug fixes and improved CBOR encoding/decoding.
143
+ - **Security**: `ujson` upgraded from `v5.11.0` to `v5.12.0` — security patch and improved JSON serialization performance.
114
144
 
115
145
  ### v0.2.48.3 (2026-04-10)
116
146
  **Improve: Notification list — DaisyUI badge display, search field verbose names**
@@ -119,9 +149,9 @@ A modern Django Admin extension focused on UI/UX, dashboard, feedback, file mana
119
149
  - **Fixed**: `get_verbose_name_field` now traverses `__`-separated lookup paths (e.g. `user__username`) to resolve proper verbose names for all search fields in `search_help_text`.
120
150
 
121
151
  ### v0.2.48.2 (2026-04-10)
122
- **Security: Nâng cấp django 5.2.13 và thêm pyOpenSSL 26.0.0**
123
- - **Security**: `django` lower bound nâng từ `>=5.2.12` lên `>=5.2.13` — bản vá bảo mật mới nhất của Django.
124
- - **Security**: `pyopenssl==26.0.0` thêm vào explicit dependencies — đảm bảo phiên bản mới nhất của pyOpenSSL được sử dụng, vá các lỗ hổng tiềm ẩn trong TLS/SSL handling.
152
+ **Security: Upgrade django 5.2.13 and add pyOpenSSL 26.0.0**
153
+ - **Security**: `django` lower bound raised from `>=5.2.12` to `>=5.2.13` — latest Django security patch.
154
+ - **Security**: `pyopenssl==26.0.0` added as an explicit dependency — ensures the latest version of pyOpenSSL is used, patching potential vulnerabilities in TLS/SSL handling.
125
155
 
126
156
  ### v0.2.48.1 (2026-04-06)
127
157
  **Fix: Duplicate history entries in change history panel**
@@ -91,11 +91,13 @@ whiteneuron/file_management/admin.py
91
91
  whiteneuron/file_management/apps.py
92
92
  whiteneuron/file_management/models.py
93
93
  whiteneuron/file_management/tests.py
94
+ whiteneuron/file_management/urls.py
94
95
  whiteneuron/file_management/utils.py
95
96
  whiteneuron/file_management/views.py
96
97
  whiteneuron/file_management/migrations/0001_initial.py
97
98
  whiteneuron/file_management/migrations/0002_alter_excelfile_options_alter_pdffile_options_and_more.py
98
99
  whiteneuron/file_management/migrations/0003_alter_excelfile_created_at_and_more.py
100
+ whiteneuron/file_management/migrations/0004_excelfile_hash_pdffile_hash.py
99
101
  whiteneuron/file_management/migrations/__init__.py
100
102
  whiteneuron/locale/vi/LC_MESSAGES/django.mo
101
103
  whiteneuron/locale/vi/LC_MESSAGES/django.po
@@ -163,6 +165,7 @@ whiteneuron/templates/admin/index.html
163
165
  whiteneuron/templates/admin/login.html
164
166
  whiteneuron/templates/admin/login_after.html
165
167
  whiteneuron/templates/admin/search_form.html
168
+ whiteneuron/templates/admin/signature.html
166
169
  whiteneuron/templates/admin/submit_line.html
167
170
  whiteneuron/templates/admin/wn_change_form.html
168
171
  whiteneuron/templates/admin/wn_history_panel.html
@@ -173,6 +176,7 @@ whiteneuron/templates/admin/base/userprofile_change_form.html
173
176
  whiteneuron/templates/admin/feedbacks/feedback_change_form.html
174
177
  whiteneuron/templates/base/forms/wysiwyg.html
175
178
  whiteneuron/templates/base/forms/helpers/toolbar.html
179
+ whiteneuron/templates/file_management/widgets/clearable_file_input_no_download.html
176
180
  whiteneuron/templates/unfold/helpers/account_links.html
177
181
  whiteneuron/templates/unfold/helpers/app_list_badge.html
178
182
  whiteneuron/templates/unfold/helpers/field_password.html
@@ -13,7 +13,7 @@ markdown>=3.7
13
13
  openai>=1.58.1
14
14
  openpyxl>=3.1.5
15
15
  pandas>=2.2.3
16
- pillow>=12.1.1
16
+ pillow>=12.2.0
17
17
  python-dotenv>=1.0.1
18
18
  redis>=5.2.1
19
19
  sentry-sdk==2.28.0
@@ -29,7 +29,7 @@ django-ckeditor-5>=0.2.18
29
29
  django-cors-headers>=4.3.0
30
30
  django-unfold>=0.85.0
31
31
  djangoql>=0.18.1
32
- cryptography>=46.0.5
32
+ cryptography>=46.0.7
33
33
  pyopenssl==26.0.0
34
34
 
35
35
  [dev]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "django-whiteneuron"
3
- version = "0.2.48.5"
3
+ version = "0.3.0.3"
4
4
  description = "A modern Django Admin extension with enhanced UI/UX, dashboard, feedback, file management, rate limiting, IP blacklisting, and advanced admin integrations built on django-unfold."
5
5
  authors = [
6
6
  {name = "White Neuron", email = "anhnt@whiteneuron.ai"}
@@ -24,7 +24,7 @@ dependencies = [
24
24
  "openai>=1.58.1",
25
25
  "openpyxl>=3.1.5",
26
26
  "pandas>=2.2.3",
27
- "pillow>=12.1.1",
27
+ "pillow>=12.2.0",
28
28
  "python-dotenv>=1.0.1",
29
29
  "redis>=5.2.1",
30
30
  "sentry-sdk==2.28.0",
@@ -40,7 +40,7 @@ dependencies = [
40
40
  'django-cors-headers>=4.3.0',
41
41
  "django-unfold>=0.85.0",
42
42
  "djangoql>=0.18.1",
43
- "cryptography>=46.0.5",
43
+ "cryptography>=46.0.7",
44
44
  "pyopenssl==26.0.0",
45
45
  ]
46
46
  requires-python = ">=3.11"
@@ -75,6 +75,11 @@ include = ["whiteneuron*"]
75
75
  "locale/**/*",
76
76
  ]
77
77
 
78
+ [tool.setuptools.exclude-package-data]
79
+ "whiteneuron" = [
80
+ "templates/admin/signature_ceo.html",
81
+ ]
82
+
78
83
  [project.optional-dependencies]
79
84
  dev = ["pytest", "black", "flake8", "pre-commit"]
80
85
 
@@ -24,4 +24,5 @@ urlpatterns += [
24
24
  path("base/guest-login/", GuestLoginView.as_view(), name="guest_login"),
25
25
  # path("i18n/", include("django.conf.urls.i18n")),
26
26
  path("ckeditor5/", include('django_ckeditor_5.urls')),
27
+ path("file-management/", include('whiteneuron.file_management.urls')),
27
28
  ]
@@ -0,0 +1,165 @@
1
+ from django.utils import timezone
2
+ from .models import User, UserActivity
3
+ from django.contrib.auth.models import Group
4
+
5
+ # count time run function
6
+ def timeit(func):
7
+ import time
8
+ def wrapper(*args, **kwargs):
9
+ start = time.time()
10
+ result = func(*args, **kwargs)
11
+ # print(f"{func.__name__} run in {time.time()-start} seconds")
12
+ return result
13
+ return wrapper
14
+
15
+ from django.utils import timezone
16
+ from django.core.exceptions import FieldDoesNotExist
17
+
18
+ def base_badge_callback(request, model, filter_kwargs=None):
19
+ today = timezone.localtime().replace(hour=0, minute=0, second=0, microsecond=0)
20
+
21
+ # try:
22
+ # model._meta.get_field("is_deleted")
23
+ # model._meta.get_field("deleted_at")
24
+ # has_soft_delete = True
25
+ # except FieldDoesNotExist:
26
+ # has_soft_delete = False
27
+
28
+ # if has_soft_delete:
29
+ # number_update = model.objects.filter(
30
+ # is_deleted=False,
31
+ # updated_at__gte=today,
32
+ # ).count()
33
+
34
+ # number_delete= getattr(model, 'objects_all', model.objects).filter(is_deleted=True,deleted_at__gte= timezone.localtime().replace(hour=0, minute=0, second=0, microsecond=0)).count()
35
+ # print("model:",model.__name__,"number_delete:",number_delete)
36
+
37
+ # c = number_update - number_delete
38
+ # else:
39
+ # c = model.objects.filter(
40
+ # updated_at__gte=today,
41
+ # ).count()
42
+
43
+ c = getattr(model, 'objects_all', model.objects)
44
+ if hasattr(model, 'updated_at'):
45
+ c = c.filter(
46
+ updated_at__gte=today,
47
+ )
48
+ elif hasattr(model, 'created_at'):
49
+ c = c.filter(
50
+ created_at__gte=today,
51
+ )
52
+
53
+ if filter_kwargs:
54
+ c = c.filter(**filter_kwargs).count()
55
+ else:
56
+ c = c.count()
57
+ return c
58
+
59
+
60
+ def user_badge_callback(request):
61
+ return base_badge_callback(request, User)
62
+
63
+ def useractivity_badge_callback(request):
64
+ c= UserActivity.objects.filter(timestamp__gte= timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)).count()
65
+ if c==0:
66
+ return ''
67
+ return f"{c}"
68
+
69
+ def user_badge_callback(request):
70
+ return base_badge_callback(request, User)
71
+
72
+ def group_badge_callback(request):
73
+ return 0
74
+
75
+ def app_badge_callback(request):
76
+ from django.conf import settings
77
+ try:
78
+ navigation = settings.UNFOLD.get('SIDEBAR', {}).get('navigation', [])
79
+ return sum(
80
+ 1 for section in navigation for item in section.get('items', [])
81
+ if item.get('title') and item.get('link') and '/base/app/' not in str(item.get('link'))
82
+ )
83
+ except Exception:
84
+ return 0
85
+
86
+ def is_guest_user(user):
87
+ if not user or not user.is_authenticated:
88
+ return True
89
+ if user.username.lower() == "guest":
90
+ return True
91
+ return user.groups.filter(name__in=["Khách thăm", "Guest", "guest"]).exists()
92
+
93
+
94
+ def permission_callback(request):
95
+ return False
96
+
97
+ def permission_superuser_callback(request):
98
+ return request.user.is_superuser
99
+
100
+ def permission_admin_callback(request):
101
+ if request.user.is_superuser:
102
+ return True
103
+ return request.user.groups.filter(name='Quản trị viên').exists()
104
+
105
+ def permission_non_guest_callback(request):
106
+ return not is_guest_user(request.user)
107
+
108
+ def permission_viewer_callback(request):
109
+ return True
110
+
111
+
112
+ import os as _os
113
+
114
+ def _load_signature():
115
+ sig_path = _os.path.normpath(
116
+ _os.path.join(_os.path.dirname(__file__), '..', 'templates', 'admin', 'signature.html')
117
+ )
118
+ with open(sig_path, 'r', encoding='utf-8') as f:
119
+ return f.read()
120
+
121
+
122
+ TEMPLATE="""
123
+ Chào {username},
124
+ <br />
125
+ Bạn đã được cấp quyền truy cập vào <b>{system_name}</b>. Dưới đây là thông tin
126
+ đăng nhập của bạn:
127
+ <br />
128
+ <b> Tên đăng nhập: {username} </b>
129
+ <br />
130
+ <b> Mật khẩu tạm thời: {password} </b>
131
+ <br />
132
+ <b> Lưu ý: </b> Bạn sẽ được yêu cầu thay đổi mật khẩu sau lần đăng nhập đầu tiên
133
+ để đảm bảo an toàn cho thông tin cá nhân và tài khoản của bạn.
134
+ <br />
135
+ <br />
136
+ Để đăng nhập, vui lòng truy cập <a href="{url}">đường dẫn trang đăng nhập</a> và
137
+ nhập thông tin trên.
138
+ <br />
139
+ Nếu bạn gặp bất kỳ vấn đề nào trong quá trình đăng nhập, đừng ngần ngại liên hệ
140
+ với bộ phận hỗ trợ kỹ thuật của chúng tôi.
141
+ <br />
142
+ Trân trọng,
143
+ <br />
144
+ {signature}
145
+ """
146
+
147
+ from django.conf import settings
148
+ from .models import Mail
149
+ def send_email_login(username, password, receiver, is_reset=False):
150
+ global TEMPLATE
151
+ SUBJECT = "Đặt lại mật khẩu hệ thống" if is_reset else "Thông tin đăng nhập hệ thống"
152
+ SYSTEM_NAME= settings.NAME
153
+ URL= settings.URL
154
+ subject= SUBJECT
155
+ template= TEMPLATE
156
+ system_name= SYSTEM_NAME
157
+ context= template.format(username= username, password= password, url= URL, system_name= system_name, signature= _load_signature())
158
+ mail= Mail.objects.create(subject= subject, content= context, receiver= receiver)
159
+ mail.send()
160
+ return mail.is_sent()
161
+
162
+ def make_random_password():
163
+ import random
164
+ import string
165
+ return ''.join(random.choices(string.ascii_letters + string.digits, k=8))