django-whiteneuron 0.2.36__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.
- django_whiteneuron-0.2.36/LICENSE +21 -0
- django_whiteneuron-0.2.36/PKG-INFO +382 -0
- django_whiteneuron-0.2.36/README.md +302 -0
- django_whiteneuron-0.2.36/django_whiteneuron.egg-info/PKG-INFO +382 -0
- django_whiteneuron-0.2.36/django_whiteneuron.egg-info/SOURCES.txt +175 -0
- django_whiteneuron-0.2.36/django_whiteneuron.egg-info/dependency_links.txt +1 -0
- django_whiteneuron-0.2.36/django_whiteneuron.egg-info/requires.txt +37 -0
- django_whiteneuron-0.2.36/django_whiteneuron.egg-info/top_level.txt +1 -0
- django_whiteneuron-0.2.36/pyproject.toml +92 -0
- django_whiteneuron-0.2.36/setup.cfg +4 -0
- django_whiteneuron-0.2.36/whiteneuron/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/base/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/base/admin.py +751 -0
- django_whiteneuron-0.2.36/whiteneuron/base/apps.py +8 -0
- django_whiteneuron-0.2.36/whiteneuron/base/asgi.py +33 -0
- django_whiteneuron-0.2.36/whiteneuron/base/ckeditor.py +12 -0
- django_whiteneuron-0.2.36/whiteneuron/base/filters.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/base/forms.py +12 -0
- django_whiteneuron-0.2.36/whiteneuron/base/management/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/base/management/commands/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/base/management/commands/init_admin.py +106 -0
- django_whiteneuron-0.2.36/whiteneuron/base/management/commands/init_groupuser.py +83 -0
- django_whiteneuron-0.2.36/whiteneuron/base/management/commands/init_guest.py +32 -0
- django_whiteneuron-0.2.36/whiteneuron/base/middleware.py +371 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0001_initial.py +132 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0002_imagemodel_userprofile_user_avatar_user_biography_and_more.py +421 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0003_notification_obj_link.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0004_delete_notification.py +16 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0005_user_show_softdelete.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0006_user_is_bot.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0007_app.py +28 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0008_app_created_at_app_created_by_app_deleted_at_and_more.py +56 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0009_alter_app_table.py +17 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0010_app_category.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0011_alter_app_options.py +17 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0012_app_permission.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0013_app_thumbnail_url.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0014_alter_app_created_at_alter_app_updated_at_and_more.py +44 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/0015_ipblacklist.py +33 -0
- django_whiteneuron-0.2.36/whiteneuron/base/migrations/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/base/modeladmin.py +478 -0
- django_whiteneuron-0.2.36/whiteneuron/base/models.py +868 -0
- django_whiteneuron-0.2.36/whiteneuron/base/resources.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/base/settings.py +832 -0
- django_whiteneuron-0.2.36/whiteneuron/base/sites.py +13 -0
- django_whiteneuron-0.2.36/whiteneuron/base/tasks.py +4 -0
- django_whiteneuron-0.2.36/whiteneuron/base/templatetags/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/base/templatetags/unfold_list_custom.py +10 -0
- django_whiteneuron-0.2.36/whiteneuron/base/templatetags/wn_filters.py +8 -0
- django_whiteneuron-0.2.36/whiteneuron/base/tests.py +46 -0
- django_whiteneuron-0.2.36/whiteneuron/base/thread_local.py +2 -0
- django_whiteneuron-0.2.36/whiteneuron/base/urls.py +26 -0
- django_whiteneuron-0.2.36/whiteneuron/base/utils.py +360 -0
- django_whiteneuron-0.2.36/whiteneuron/base/views.py +13 -0
- django_whiteneuron-0.2.36/whiteneuron/base/widgets.py +29 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_import_export/__init__.py +14 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_import_export/admin.py +67 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_import_export/constants.py +1 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_import_export/mixins.py +2 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_import_export/tasks.py +40 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_import_export/utils.py +16 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_modeltranslation/__init__.py +8 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_modeltranslation/admin.py +48 -0
- django_whiteneuron-0.2.36/whiteneuron/contrib/wn_modeltranslation/utils.py +81 -0
- django_whiteneuron-0.2.36/whiteneuron/dashboard/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/dashboard/admin.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/dashboard/apps.py +8 -0
- django_whiteneuron-0.2.36/whiteneuron/dashboard/migrations/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/dashboard/models.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/dashboard/tests.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/dashboard/views.py +304 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/admin.py +127 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/apps.py +8 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/migrations/0001_initial.py +79 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/migrations/0002_feedbackdata_created_by_feedbackdata_deleted_at_and_more.py +81 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/migrations/0003_feedbackdata_note.py +23 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/migrations/0004_alter_feedbackdata_object_id.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/migrations/0005_feedbackdata_field.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/migrations/0006_alter_feedbackdata_created_at_and_more.py +24 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/migrations/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/models.py +72 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/tests.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/urls.py +69 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/utils.py +5 -0
- django_whiteneuron-0.2.36/whiteneuron/feedbacks/views.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/admin.py +32 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/apps.py +7 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/migrations/0001_initial.py +198 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/migrations/0002_alter_excelfile_options_alter_pdffile_options_and_more.py +74 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/migrations/0003_alter_excelfile_created_at_and_more.py +34 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/migrations/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/models.py +65 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/tests.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/utils.py +8 -0
- django_whiteneuron-0.2.36/whiteneuron/file_management/views.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/locale/vi/LC_MESSAGES/django.mo +0 -0
- django_whiteneuron-0.2.36/whiteneuron/locale/vi/LC_MESSAGES/django.po +1038 -0
- django_whiteneuron-0.2.36/whiteneuron/manage.py +22 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/admin.py +205 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/apps.py +7 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/consumers.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/management/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/management/commands/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/management/commands/call_demo_noti.py +11 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0001_initial.py +93 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0002_alter_notificationconfig_event_type.py +27 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0003_notification.py +73 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0004_alter_notification_flag.py +27 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0005_notification_keywords.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0006_remove_notification_keywords.py +17 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0007_notification_changed_data.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0008_alter_notification_changed_data.py +18 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0009_notification_action_by_alter_notification_user.py +26 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0010_alter_notification_user.py +21 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0011_alter_notification_user.py +21 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/0012_alter_notification_action_and_more.py +73 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/migrations/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/models.py +118 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/routing.py +6 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/tests.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/utils.py +11 -0
- django_whiteneuron-0.2.36/whiteneuron/notification/views.py +23 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/css/btn-styles.css +62 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/css/ckeditor5.css +550 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/css/loading.css +18 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/css/styles.css +2 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/forms/css/html-editor.css +89 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/forms/js/format.html.js +171 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/forms/js/trix.config.js +257 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/images/delete.svg +1 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/images/edit.svg +3 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/images/icon-viewlink.svg +3 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/images/loading.gif +0 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/images/login-bg.jpg +0 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/images/login_bg.jpg +0 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/images/logo/WhiteNeuron.png +0 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/js/chart.min.js +19 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/js/d3.v7.min.js +2 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/js/loading.js +179 -0
- django_whiteneuron-0.2.36/whiteneuron/static/base/js/whiteneuron.js +39 -0
- django_whiteneuron-0.2.36/whiteneuron/synchronization/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/synchronization/admin.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/synchronization/apps.py +6 -0
- django_whiteneuron-0.2.36/whiteneuron/synchronization/migrations/__init__.py +0 -0
- django_whiteneuron-0.2.36/whiteneuron/synchronization/models.py +29 -0
- django_whiteneuron-0.2.36/whiteneuron/synchronization/tests.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/synchronization/views.py +3 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/400.html +72 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/403.html +72 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/404.html +76 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/429.html +77 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/500.html +74 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/auth/user/add_form.html +5 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/base/image_change_form.html +30 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/base/userprofile_change_form.html +11 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/base.html +15 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/change_list.html +59 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/feedbacks/feedback_change_form.html +41 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/grid_view_results.html +139 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/header.html +32 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/index.html +97 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/login.html +56 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/login_after.html +21 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/search_form.html +60 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/admin/submit_line.html +67 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/base/forms/helpers/toolbar.html +108 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/base/forms/wysiwyg.html +15 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/base.html +81 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/unfold/helpers/account_links.html +126 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/unfold/helpers/app_list_badge.html +53 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/unfold/helpers/field_password.html +26 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/unfold/helpers/navigation_user.html +41 -0
- django_whiteneuron-0.2.36/whiteneuron/templates/unfold/helpers/pagination.html +14 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Nguyễn Tú Anh
|
|
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,382 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-whiteneuron
|
|
3
|
+
Version: 0.2.36
|
|
4
|
+
Summary: django-whiteneuron là một gói mở rộng giúp nâng cấp giao diện và chức năng Django Admin, mang đến trải nghiệm quản trị hiện đại, trực quan và tối ưu hiệu suất. 🚀
|
|
5
|
+
Author-email: White Neuron <anhnt@whiteneuron.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Nguyễn Tú Anh
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: homepage, https://github.com/White-Neuron/django-whiteneuron
|
|
29
|
+
Project-URL: repository, https://github.com/White-Neuron/django-whiteneuron
|
|
30
|
+
Keywords: django,plugin,admin,dashboard,whiteneuron
|
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: Framework :: Django
|
|
34
|
+
Classifier: Framework :: Django :: 5.0
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Requires-Python: >=3.11
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: django-debug-toolbar>=5.0.1
|
|
44
|
+
Requires-Dist: django>=5.1.6
|
|
45
|
+
Requires-Dist: django-celery-beat>=2.7.0
|
|
46
|
+
Requires-Dist: django-guardian>=2.4.0
|
|
47
|
+
Requires-Dist: django-imagekit>=5.0.0
|
|
48
|
+
Requires-Dist: django-import-export>=4.3.3
|
|
49
|
+
Requires-Dist: django-modeltranslation>=0.19.11
|
|
50
|
+
Requires-Dist: django-ninja>=1.3.0
|
|
51
|
+
Requires-Dist: django-simple-history>=3.8.0
|
|
52
|
+
Requires-Dist: gunicorn>=23.0.0
|
|
53
|
+
Requires-Dist: hiredis>=3.1.0
|
|
54
|
+
Requires-Dist: markdown>=3.7
|
|
55
|
+
Requires-Dist: openai>=1.58.1
|
|
56
|
+
Requires-Dist: openpyxl>=3.1.5
|
|
57
|
+
Requires-Dist: pandas>=2.2.3
|
|
58
|
+
Requires-Dist: pillow>=11.0.0
|
|
59
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
60
|
+
Requires-Dist: redis>=5.2.1
|
|
61
|
+
Requires-Dist: sentry-sdk==2.28.0
|
|
62
|
+
Requires-Dist: django-browser-reload>=1.18.0
|
|
63
|
+
Requires-Dist: whitenoise>=6.9.0
|
|
64
|
+
Requires-Dist: django-crispy-forms>=2.4
|
|
65
|
+
Requires-Dist: django-colorfield>=0.14.0
|
|
66
|
+
Requires-Dist: channels>=4.2.2
|
|
67
|
+
Requires-Dist: channels-redis>=4.2.1
|
|
68
|
+
Requires-Dist: uvicorn>=0.34.3
|
|
69
|
+
Requires-Dist: daphne>=4.2.0
|
|
70
|
+
Requires-Dist: django-ckeditor-5>=0.2.18
|
|
71
|
+
Requires-Dist: django-cors-headers>=4.3.0
|
|
72
|
+
Requires-Dist: django-unfold>=0.85.0
|
|
73
|
+
Requires-Dist: djangoql>=0.18.1
|
|
74
|
+
Provides-Extra: dev
|
|
75
|
+
Requires-Dist: pytest; extra == "dev"
|
|
76
|
+
Requires-Dist: black; extra == "dev"
|
|
77
|
+
Requires-Dist: flake8; extra == "dev"
|
|
78
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
79
|
+
Dynamic: license-file
|
|
80
|
+
|
|
81
|
+
# django-whiteneuron
|
|
82
|
+
|
|
83
|
+
django-whiteneuron là package mở rộng Django Admin theo hướng hiện đại, tập trung vào UI/UX quản trị, dashboard, feedback, file management và các tích hợp admin nâng cao.
|
|
84
|
+
|
|
85
|
+
## Phiên bản hiện tại
|
|
86
|
+
|
|
87
|
+
- 0.2.36
|
|
88
|
+
|
|
89
|
+
## Tương thích
|
|
90
|
+
|
|
91
|
+
- Python >= 3.11
|
|
92
|
+
- Django >= 5.1.6
|
|
93
|
+
- django-unfold >= 0.85.0
|
|
94
|
+
- Tailwind CSS 4.x + daisyUI 5.x (khi dùng bộ style frontend đi kèm)
|
|
95
|
+
|
|
96
|
+
## Changelog
|
|
97
|
+
|
|
98
|
+
### v0.2.36 (2026-03-30) — latest
|
|
99
|
+
**Security: init_admin — xoá hardcode password, sinh mật khẩu ngẫu nhiên, gửi email tự động**
|
|
100
|
+
- **Security**: Xoá password hardcode `'wnadmin2024&'` khỏi `init_admin.py` — thay bằng `secrets.choice()` (CSPRNG) sinh mật khẩu 20 ký tự (chữ hoa, thường, số, ký tự đặc biệt).
|
|
101
|
+
- **Added**: Hỗ trợ `INIT_ADMIN_PASSWORD` env var — ưu tiên dùng password cố định từ `.env`, nếu không có thì sinh ngẫu nhiên.
|
|
102
|
+
- **Added**: Hỗ trợ `INIT_ADMIN_EMAIL` env var — email nhận mật khẩu tạm thời, bắt buộc phải có (không còn hardcode).
|
|
103
|
+
- **Added**: Tự động gửi email mật khẩu qua `send_email_login()` với template chuẩn (chữ ký công ty, link đăng nhập) khi password là random.
|
|
104
|
+
- **Added**: Flag `--reset-password` cho lệnh `init_admin` — đặt lại mật khẩu admin đã tồn tại mà không ảnh hưởng luồng CI/CD bình thường.
|
|
105
|
+
- **Fixed**: Double DB write khi tạo user mới — chỉ 1 lần `save()` duy nhất.
|
|
106
|
+
- **Fixed**: Validate email trước khi ghi password vào DB — tránh password bị đổi nhưng email gửi thất bại.
|
|
107
|
+
- **Improved**: `send_email_login()` thêm param `is_reset` — subject email thay đổi theo ngữ cảnh (tạo mới vs đặt lại).
|
|
108
|
+
- **Removed**: File `templates/admin/base/email_password.html` không dùng.
|
|
109
|
+
|
|
110
|
+
### v0.2.35 (2026-03-29)
|
|
111
|
+
**Dynamic IP Blacklist: Redis + Model + Admin**
|
|
112
|
+
- **Added**: `IPBlacklist` model (`base/ip_blacklists`) — quản lý IP bị chặn real-time qua Django Admin, hỗ trợ block vĩnh viễn và tạm thời (`blocked_until` với Redis TTL tự expire).
|
|
113
|
+
- **Added**: `IPBlacklistAdmin` — giao diện quản lý IP blacklist với actions Activate/Deactivate, hiện thị trong sidebar System dưới icon `block`, superuser only.
|
|
114
|
+
- **Added**: Action **"Block IP address"** trong `UserActivityAdmin` — chọn bản ghi activity → block IP ngay lập tức vào Redis, không cần restart Daphne.
|
|
115
|
+
- **Improved**: `RateLimitMiddleware._is_blacklisted()` kiểm tra thêm `cache.get('blacklist:dynamic:<ip>')` sau static env blacklist — hybrid hai lớp tĩnh + động.
|
|
116
|
+
- **Added**: Migration `base/0015_ipblacklist.py`.
|
|
117
|
+
|
|
118
|
+
### v0.2.34 (2026-03-29)
|
|
119
|
+
**IP Blacklist: chặn IP/CIDR vĩnh viễn qua `.env`**
|
|
120
|
+
- **Added**: `RateLimitMiddleware` bổ sung `_is_blacklisted()` — kiểm tra IP/CIDR blacklist trước rate limit, trả 403 ngay lập tức cho IP bị block.
|
|
121
|
+
- **Added**: Parse `IP_BLACKLIST` từ settings (comma-separated IPs và/hoặc CIDR), hỗ trợ cả IPv4 và IPv6 — single IP dùng `set` lookup O(1), CIDR range dùng `ip_network` match.
|
|
122
|
+
- **Added**: Setting `IP_BLACKLIST` trong `settings.py` và biến tương ứng trong `env.example`.
|
|
123
|
+
|
|
124
|
+
### v0.2.33 (2026-03-29)
|
|
125
|
+
**Rate Limiting fix cho Docker + Daphne**
|
|
126
|
+
- **Fixed**: `_is_rate_limited()` và `_is_user_rate_limited()` thêm `except Exception: return False` — bắt `ConnectionError` khi Redis không reachable trong Docker (trước đây unhandled exception làm request crash hoặc bypass rate limit).
|
|
127
|
+
- **Fixed**: Default `RATE_LIMIT_REQUESTS` hạ từ 300 → 60 req/60 s, `USER_RATE_LIMIT_REQUESTS` từ 200 → 60 — phù hợp với admin panel.
|
|
128
|
+
- **Fixed**: `User.display_header()` dùng `reverse('admin:base_user_change')` thay vì hardcode `/admin/base/user/` — tránh broken link khi đổi admin prefix.
|
|
129
|
+
- **Fixed**: Default `BEHIND_CLOUDFLARE=True` vì luôn deploy qua Cloudflare Tunnel.
|
|
130
|
+
|
|
131
|
+
### v0.2.32 (2026-03-29)
|
|
132
|
+
**Security hardening & Gunicorn production readiness**
|
|
133
|
+
- **Security**: `get_client_ip()` chỉ tin tưởng `CF-Connecting-IP` / `True-Client-IP` khi `BEHIND_CLOUDFLARE=True` — tránh bypass rate limit qua header giả mạo.
|
|
134
|
+
- **Fixed**: `UserActivityMiddleware.__call__()` cache kết quả `do_not_track()` vào `skip` — tránh gọi 2 lần mỗi request.
|
|
135
|
+
- **Removed**: `import logging` không dùng trong middleware.py.
|
|
136
|
+
|
|
137
|
+
### v0.2.31 (2026-03-29)
|
|
138
|
+
**Rate Limiting, Security Hardening & Error Pages**
|
|
139
|
+
- **Added**: `RateLimitMiddleware` — global IP-based rate limiting (300 req/60 s mặc định) đặt ngay sau `SecurityMiddleware`, hoạt động cả trên API lẫn browser.
|
|
140
|
+
- **Improved**: `UserActivityMiddleware` bổ sung per-user rate limiting (200 req/60 s mặc định).
|
|
141
|
+
- **Added**: `/ws/` vào `exclude_paths` của `UserActivityMiddleware` — WS handshake không bị log và không tính vào rate limit.
|
|
142
|
+
- **Security**: Sanitize `POST` data trước khi ghi vào `UserActivity` — mask các field nhạy cảm (password, token, api_key…).
|
|
143
|
+
- **Security**: Chuyển sang pattern `cache.incr()` first (atomic trên Redis) tránh race condition.
|
|
144
|
+
- **Added**: Template lỗi đầy đủ: `400.html`, `403.html`, `404.html`, `429.html`, `500.html`.
|
|
145
|
+
- **Added**: `base.html` skeleton tối giản cho các trang lỗi — không phụ thuộc file static ngoài.
|
|
146
|
+
- **Added**: Cảnh báo startup khi production chạy không có Redis (rate limit không chính xác trên multi-worker).
|
|
147
|
+
|
|
148
|
+
### v0.2.30 (2026-03-29)
|
|
149
|
+
- **Improved**: `AppAdmin.get_queryset()` chỉ trả về các app active mà user thực sự có quyền truy cập.
|
|
150
|
+
- **Improved**: `superuser` vẫn giữ nguyên quyền nhìn thấy toàn bộ app active.
|
|
151
|
+
|
|
152
|
+
### v0.2.29 (2026-03-28)
|
|
153
|
+
- **Fixed**: `NotificationAdmin` không còn bị lỗi 403 khi bấm `View Linked Object`.
|
|
154
|
+
- **Improved**: Action xem đối tượng liên kết được route riêng qua detail action, tương thích tốt hơn với Unfold.
|
|
155
|
+
- **Improved**: Bổ sung xử lý an toàn khi notification không có `obj_link`.
|
|
156
|
+
|
|
157
|
+
### v0.2.28 (2026-03-28)
|
|
158
|
+
- **Improved**: Giao diện grid view của user/app dùng icon trực quan hơn cho role và trạng thái.
|
|
159
|
+
- **Improved**: Chuẩn hóa `verbose_name` cho nhiều field trong `Notification` và `NotificationConfig`.
|
|
160
|
+
- **Added**: Migration `notification/0012` đồng bộ metadata field-level.
|
|
161
|
+
|
|
162
|
+
### v0.2.27 và trước
|
|
163
|
+
Xem chi tiết tại [releases](https://github.com/White-Neuron/django-whiteneuron/releases).
|
|
164
|
+
|
|
165
|
+
## Cài đặt (ưu tiên uv)
|
|
166
|
+
|
|
167
|
+
Package chưa phát hành lên PyPI.
|
|
168
|
+
|
|
169
|
+
### Cài từ GitHub theo tag
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
uv add "git+https://github.com/White-Neuron/django-whiteneuron.git@v0.2.35"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Cài từ source local
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
uv pip install -e .
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Cấu hình Django cơ bản
|
|
182
|
+
|
|
183
|
+
Thêm các app vào đầu INSTALLED_APPS:
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
INSTALLED_APPS = [
|
|
187
|
+
"whiteneuron",
|
|
188
|
+
"whiteneuron.base",
|
|
189
|
+
"whiteneuron.feedbacks",
|
|
190
|
+
"whiteneuron.file_management",
|
|
191
|
+
"whiteneuron.contrib",
|
|
192
|
+
"whiteneuron.dashboard",
|
|
193
|
+
# ... các app khác
|
|
194
|
+
]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Thêm middleware cần thiết (thứ tự quan trọng):
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
MIDDLEWARE = [
|
|
201
|
+
"django.middleware.security.SecurityMiddleware",
|
|
202
|
+
"whiteneuron.base.middleware.RateLimitMiddleware", # ← ngay sau SecurityMiddleware
|
|
203
|
+
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
204
|
+
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
205
|
+
"django.middleware.common.CommonMiddleware",
|
|
206
|
+
"django.middleware.csrf.CsrfViewMiddleware",
|
|
207
|
+
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
208
|
+
"django.contrib.messages.middleware.MessageMiddleware",
|
|
209
|
+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
210
|
+
"whiteneuron.base.middleware.ReadonlyExceptionHandlerMiddleware",
|
|
211
|
+
"whiteneuron.base.middleware.UserActivityMiddleware", # ← sau AuthenticationMiddleware
|
|
212
|
+
"whiteneuron.base.middleware.ThreadLocalMiddleware",
|
|
213
|
+
]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Thiết lập user model:
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
AUTH_USER_MODEL = "base.User"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Cấu hình UNFOLD mẫu
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
from django.templatetags.static import static
|
|
226
|
+
from django.utils.translation import gettext_lazy as _
|
|
227
|
+
|
|
228
|
+
UNFOLD = {
|
|
229
|
+
"SITE_HEADER": _("White Neuron"),
|
|
230
|
+
"SITE_TITLE": _("White Neuron Admin"),
|
|
231
|
+
"SITE_SUBHEADER": _("Admin panel"),
|
|
232
|
+
# Dùng SITE_ICON thay vì SITE_LOGO để giữ SITE_TITLE hiển thị đúng
|
|
233
|
+
"SITE_ICON": {
|
|
234
|
+
"light": lambda request: static("base/images/logo/WhiteNeuron.png"),
|
|
235
|
+
"dark": lambda request: static("base/images/logo/WhiteNeuron.png"),
|
|
236
|
+
},
|
|
237
|
+
"SITE_FAVICONS": [
|
|
238
|
+
{
|
|
239
|
+
"rel": "icon",
|
|
240
|
+
"sizes": "32x32",
|
|
241
|
+
"type": "image/svg+xml",
|
|
242
|
+
"href": lambda request: static("base/images/logo/WhiteNeuron.png"),
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
"SHOW_HISTORY": False,
|
|
246
|
+
"SHOW_LANGUAGES": True,
|
|
247
|
+
"SHOW_VIEW_ON_SITE": True,
|
|
248
|
+
"SHOW_BACK_BUTTON": True,
|
|
249
|
+
"DASHBOARD_CALLBACK": "whiteneuron.dashboard.views.dashboard_callback",
|
|
250
|
+
"LOGIN": {
|
|
251
|
+
"image": lambda request: static("base/images/login-bg.jpg"),
|
|
252
|
+
},
|
|
253
|
+
"STYLES": [
|
|
254
|
+
lambda request: static("base/css/styles.css"),
|
|
255
|
+
lambda request: static("base/css/btn-styles.css"),
|
|
256
|
+
lambda request: static("base/css/loading.css"),
|
|
257
|
+
],
|
|
258
|
+
"SCRIPTS": [
|
|
259
|
+
lambda request: static("base/js/loading.js"),
|
|
260
|
+
lambda request: static("base/js/whiteneuron.js"),
|
|
261
|
+
],
|
|
262
|
+
"BORDER_RADIUS": "6px",
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Frontend (Tailwind 4 + daisyUI 5)
|
|
267
|
+
|
|
268
|
+
Cài dependencies frontend:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npm install -D @tailwindcss/cli@next daisyui@latest
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Build CSS bằng script có sẵn:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
bash scripts/tailwind.sh
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Hoặc chạy trực tiếp:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
npx @tailwindcss/cli -i styles.css -o whiteneuron/static/base/css/styles.css --minify
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Chạy local package example
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
cd whiteneuron
|
|
290
|
+
python manage.py migrate
|
|
291
|
+
python manage.py runserver
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Truy cập admin tại: http://127.0.0.1:8000/admin/
|
|
295
|
+
|
|
296
|
+
## Build package
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
uv build
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Hoặc dùng script build tổng hợp:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
bash scripts/build.sh
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Rate Limiting
|
|
309
|
+
|
|
310
|
+
`RateLimitMiddleware` giới hạn theo IP, `UserActivityMiddleware` giới hạn theo user đã đăng nhập. Cần Redis để hoạt động chính xác trên môi trường multi-worker.
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
# settings.py (hoặc env)
|
|
314
|
+
RATE_LIMIT_REQUESTS = 60 # số request tối đa / window (theo IP)
|
|
315
|
+
RATE_LIMIT_WINDOW = 60 # tính bằng giây
|
|
316
|
+
|
|
317
|
+
USER_RATE_LIMIT_REQUESTS = 60 # theo user đã đăng nhập
|
|
318
|
+
USER_RATE_LIMIT_WINDOW = 60
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Các biến env tương ứng: `RATE_LIMIT_REQUESTS`, `RATE_LIMIT_WINDOW`, `USER_RATE_LIMIT_REQUESTS`, `USER_RATE_LIMIT_WINDOW`.
|
|
322
|
+
|
|
323
|
+
Khi vượt ngưỡng:
|
|
324
|
+
- Request API (`/api/` hoặc `Accept: application/json`) → JSON `{"detail": "Too many requests."}` với status 429.
|
|
325
|
+
- Request browser → render template `429.html` với header `Retry-After`.
|
|
326
|
+
|
|
327
|
+
## IP Blacklist
|
|
328
|
+
|
|
329
|
+
Hai lớp bảo vệ hoạt động song song. Cả hai đều được kiểm tra trước rate limit, trả 403 ngay lập tức.
|
|
330
|
+
|
|
331
|
+
### Tĩnh — `.env` (CIDR ranges, infra bans)
|
|
332
|
+
|
|
333
|
+
Load lúc khởi động, hỗ trợ IPv4/IPv6 và CIDR:
|
|
334
|
+
|
|
335
|
+
```env
|
|
336
|
+
# .env
|
|
337
|
+
IP_BLACKLIST=185.220.101.5,194.165.16.0/22,2001:db8::/32
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Cần **restart Daphne/Gunicorn** để apply khi thêm entry mới.
|
|
341
|
+
|
|
342
|
+
### Động — Django Admin + Redis (real-time)
|
|
343
|
+
|
|
344
|
+
Quản lý qua **System → IP Blacklist** trong admin panel (superuser only):
|
|
345
|
+
|
|
346
|
+
- **Block vĩnh viễn**: để trống `blocked_until`
|
|
347
|
+
- **Block tạm thời**: set `blocked_until` → Redis TTL tự expire, không cần cron
|
|
348
|
+
- **Block nhanh từ logs**: *User Activity* → chọn records → action **Block IP address** → Redis key set ngay, không restart
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
Request → check static env blacklist (O(1))
|
|
352
|
+
→ check cache.get('blacklist:dynamic:<ip>') (1 Redis GET)
|
|
353
|
+
→ 403 nếu match, không tốn rate limit check
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Error Pages
|
|
357
|
+
|
|
358
|
+
Các template lỗi nằm trong `whiteneuron/templates/` và được Django tự động sử dụng khi `DEBUG=False`:
|
|
359
|
+
|
|
360
|
+
| Template | Lỗi | Ghi chú |
|
|
361
|
+
|---|---|---|
|
|
362
|
+
| `400.html` | Bad Request | |
|
|
363
|
+
| `403.html` | Forbidden | |
|
|
364
|
+
| `404.html` | Not Found | |
|
|
365
|
+
| `429.html` | Too Many Requests | Render thủ công bởi middleware, truyền `{{ retry_after }}` |
|
|
366
|
+
| `500.html` | Server Error | |
|
|
367
|
+
|
|
368
|
+
Không cần đăng ký `handler400/403/404/500` — Django tự tìm template qua `APP_DIRS=True`.
|
|
369
|
+
|
|
370
|
+
## Môi trường cấu hình
|
|
371
|
+
|
|
372
|
+
Copy env.example thành file môi trường phù hợp cho dự án của bạn và cập nhật các biến như DATABASE, REDIS, EMAIL, ALLOWED_HOSTS.
|
|
373
|
+
|
|
374
|
+
## Liên hệ
|
|
375
|
+
|
|
376
|
+
- Email: [anhnt@whiteneuron.com](mailto:anhnt@whiteneuron.com)
|
|
377
|
+
- Website: [https://whiteneuron.ai](https://whiteneuron.ai)
|
|
378
|
+
- GitHub: [https://github.com/White-Neuron/django-whiteneuron](https://github.com/White-Neuron/django-whiteneuron)
|
|
379
|
+
|
|
380
|
+
## License
|
|
381
|
+
|
|
382
|
+
MIT License.
|