django-spire 0.23.7__py3-none-any.whl → 0.23.8__py3-none-any.whl
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_spire/ai/admin.py +11 -11
- django_spire/ai/chat/apps.py +1 -0
- django_spire/ai/chat/templates/django_spire/ai/chat/widget/dialog_widget.html +1 -1
- django_spire/ai/chat/tests/factories.py +15 -0
- django_spire/ai/chat/tests/test_controller.py +45 -0
- django_spire/ai/chat/tests/test_models.py +301 -0
- django_spire/ai/chat/tests/test_prompts.py +48 -0
- django_spire/ai/chat/tests/test_responses.py +208 -0
- django_spire/ai/chat/tests/test_router/test_base_chat_router.py +66 -6
- django_spire/ai/chat/tests/test_router/test_chat_workflow.py +73 -3
- django_spire/ai/chat/tests/test_router/test_integration.py +86 -6
- django_spire/ai/chat/tests/test_router/test_intent_decoder.py +93 -1
- django_spire/ai/chat/tests/test_router/test_message_intel.py +60 -1
- django_spire/ai/chat/tests/test_router/test_spire_chat_router.py +110 -0
- django_spire/ai/chat/tests/test_urls/test_json_urls.py +202 -1
- django_spire/ai/context/tests/__init__.py +0 -0
- django_spire/ai/context/tests/test_context.py +188 -0
- django_spire/ai/decorators.py +7 -6
- django_spire/ai/prompt/tests/test_bots.py +100 -10
- django_spire/ai/prompt/tests/test_prompt_intel.py +83 -0
- django_spire/ai/prompt/tests/test_prompt_tuning.py +126 -0
- django_spire/ai/sms/decorators.py +8 -2
- django_spire/ai/sms/tests/test_sms.py +240 -16
- django_spire/ai/sms/tests/test_sms_intel.py +42 -0
- django_spire/ai/sms/tests/test_webhook.py +155 -7
- django_spire/ai/sms/views.py +23 -24
- django_spire/ai/tests/test_ai.py +131 -7
- django_spire/auth/apps.py +4 -2
- django_spire/auth/controller/controller.py +36 -23
- django_spire/auth/controller/exceptions.py +9 -0
- django_spire/auth/group/admin.py +1 -0
- django_spire/auth/group/apps.py +2 -0
- django_spire/auth/group/factories.py +17 -8
- django_spire/auth/group/forms.py +7 -0
- django_spire/auth/group/tests/test_factories.py +146 -0
- django_spire/auth/group/tests/test_forms.py +282 -0
- django_spire/auth/group/tests/test_models.py +192 -0
- django_spire/auth/group/tests/test_querysets.py +98 -0
- django_spire/auth/group/tests/test_utils.py +341 -0
- django_spire/auth/group/tests/test_views.py +377 -0
- django_spire/auth/group/urls/__init__.py +3 -1
- django_spire/auth/group/urls/form_urls.py +2 -0
- django_spire/auth/group/urls/json_urls.py +3 -0
- django_spire/auth/group/urls/page_urls.py +2 -0
- django_spire/auth/group/utils.py +6 -2
- django_spire/auth/group/views/form_views.py +6 -3
- django_spire/auth/group/views/json_views.py +6 -2
- django_spire/auth/mfa/admin.py +2 -0
- django_spire/auth/mfa/apps.py +2 -0
- django_spire/auth/mfa/forms.py +1 -0
- django_spire/auth/mfa/querysets.py +9 -2
- django_spire/auth/mfa/tests/test_models.py +233 -0
- django_spire/auth/mfa/tests/test_utils.py +106 -0
- django_spire/auth/mfa/urls/__init__.py +2 -0
- django_spire/auth/mfa/urls/page_urls.py +2 -0
- django_spire/auth/mfa/urls/redirect_urls.py +2 -0
- django_spire/auth/mfa/views/page_views.py +2 -1
- django_spire/auth/permissions/consts.py +2 -2
- django_spire/auth/permissions/decorators.py +8 -8
- django_spire/auth/permissions/permissions.py +28 -35
- django_spire/auth/permissions/tests/test_decorators.py +333 -0
- django_spire/auth/permissions/tests/test_permissions.py +337 -0
- django_spire/auth/permissions/tests/test_tools.py +305 -0
- django_spire/auth/permissions/tools.py +21 -15
- django_spire/auth/seeding/seed.py +3 -0
- django_spire/auth/seeding/seeder.py +2 -0
- django_spire/auth/tests/test_controller.py +323 -0
- django_spire/auth/tests/test_url_endpoints.py +9 -9
- django_spire/auth/tests/test_views.py +406 -0
- django_spire/auth/urls/admin_urls.py +2 -0
- django_spire/auth/urls/redirect_urls.py +2 -0
- django_spire/auth/user/apps.py +2 -0
- django_spire/auth/user/forms.py +9 -0
- django_spire/auth/user/models.py +1 -1
- django_spire/auth/user/services/services.py +1 -0
- django_spire/auth/user/tests/factories.py +14 -13
- django_spire/auth/user/tests/test_factories.py +166 -2
- django_spire/auth/user/tests/test_forms.py +573 -0
- django_spire/auth/user/tests/test_models.py +257 -0
- django_spire/auth/user/tests/test_services.py +200 -0
- django_spire/auth/user/tests/test_tools.py +153 -0
- django_spire/auth/user/tests/test_user_factories.py +139 -0
- django_spire/auth/user/tests/test_views.py +363 -0
- django_spire/auth/user/tools.py +7 -1
- django_spire/auth/user/urls/form_urls.py +3 -0
- django_spire/auth/user/urls/page_urls.py +3 -0
- django_spire/auth/user/views/form_views.py +19 -10
- django_spire/auth/user/views/page_views.py +8 -2
- django_spire/auth/views/redirect_views.py +14 -9
- django_spire/comment/admin.py +2 -0
- django_spire/comment/apps.py +2 -0
- django_spire/comment/templatetags/comment_tags.py +1 -0
- django_spire/comment/tests/test_forms.py +27 -0
- django_spire/comment/tests/test_models.py +215 -0
- django_spire/comment/tests/test_querysets.py +101 -0
- django_spire/comment/tests/test_utils.py +90 -0
- django_spire/comment/urls.py +2 -0
- django_spire/comment/utils.py +22 -13
- django_spire/comment/views.py +1 -1
- django_spire/conf.py +8 -6
- django_spire/consts.py +1 -1
- django_spire/contrib/breadcrumb/apps.py +2 -0
- django_spire/contrib/breadcrumb/breadcrumbs.py +18 -18
- django_spire/contrib/breadcrumb/tests/test_breadcrumbs.py +198 -0
- django_spire/contrib/constructor/__init__.py +3 -3
- django_spire/contrib/constructor/constructor.py +15 -15
- django_spire/contrib/constructor/django_model_constructor.py +5 -4
- django_spire/contrib/constructor/exceptions.py +5 -3
- django_spire/contrib/constructor/tests/__init__.py +0 -0
- django_spire/contrib/constructor/tests/test_constructor.py +193 -0
- django_spire/contrib/form/tests/__init__.py +0 -0
- django_spire/contrib/form/tests/test_forms.py +203 -0
- django_spire/contrib/generic_views/modal_views.py +2 -1
- django_spire/contrib/generic_views/portal_views.py +20 -19
- django_spire/contrib/generic_views/tests/__init__.py +0 -0
- django_spire/contrib/generic_views/tests/test_views.py +459 -0
- django_spire/contrib/help/apps.py +2 -0
- django_spire/contrib/help/templatetags/help.py +1 -0
- django_spire/contrib/help/tests/__init__.py +0 -0
- django_spire/contrib/help/tests/test_templatetags.py +100 -0
- django_spire/contrib/options/mixins.py +6 -5
- django_spire/contrib/options/tests/factories.py +5 -1
- django_spire/contrib/options/tests/test_options.py +234 -0
- django_spire/contrib/ordering/exceptions.py +7 -3
- django_spire/contrib/ordering/mixins.py +2 -0
- django_spire/contrib/ordering/querysets.py +3 -1
- django_spire/contrib/ordering/services/processor_service.py +8 -4
- django_spire/contrib/ordering/services/service.py +1 -2
- django_spire/contrib/ordering/tests/__init__.py +0 -0
- django_spire/contrib/ordering/tests/test_ordering.py +165 -0
- django_spire/contrib/ordering/validators.py +6 -6
- django_spire/contrib/pagination/templatetags/pagination_tags.py +12 -5
- django_spire/contrib/pagination/tests/__init__.py +0 -0
- django_spire/contrib/pagination/tests/test_pagination.py +179 -0
- django_spire/contrib/performance/decorators.py +16 -6
- django_spire/contrib/performance/tests/__init__.py +0 -0
- django_spire/contrib/performance/tests/test_performance.py +107 -0
- django_spire/contrib/queryset/enums.py +3 -1
- django_spire/contrib/queryset/filter_tools.py +10 -5
- django_spire/contrib/queryset/mixins.py +16 -16
- django_spire/contrib/queryset/tests/__init__.py +0 -0
- django_spire/contrib/queryset/tests/test_queryset.py +137 -0
- django_spire/contrib/seeding/field/base.py +13 -7
- django_spire/contrib/seeding/field/callable.py +8 -1
- django_spire/contrib/seeding/field/cleaners.py +5 -5
- django_spire/contrib/seeding/field/custom.py +20 -10
- django_spire/contrib/seeding/field/django/seeder.py +8 -6
- django_spire/contrib/seeding/field/enums.py +7 -5
- django_spire/contrib/seeding/field/override.py +16 -6
- django_spire/contrib/seeding/field/static.py +9 -2
- django_spire/contrib/seeding/field/tests/test_base.py +18 -14
- django_spire/contrib/seeding/field/tests/test_callable.py +13 -9
- django_spire/contrib/seeding/field/tests/test_cleaners.py +51 -38
- django_spire/contrib/seeding/field/tests/test_static.py +13 -9
- django_spire/contrib/seeding/intelligence/bots/seeder_generator_bot.py +2 -0
- django_spire/contrib/seeding/intelligence/intel.py +5 -1
- django_spire/contrib/seeding/intelligence/prompts/factory.py +6 -1
- django_spire/contrib/seeding/intelligence/prompts/foreign_key_selection_prompt.py +6 -1
- django_spire/contrib/seeding/intelligence/prompts/generate_django_model_seeder_prompts.py +2 -0
- django_spire/contrib/seeding/intelligence/prompts/generic_relationship_selection_prompt.py +7 -1
- django_spire/contrib/seeding/intelligence/prompts/hierarchical_selection_prompt.py +6 -2
- django_spire/contrib/seeding/intelligence/prompts/model_field_choices_prompt.py +8 -2
- django_spire/contrib/seeding/intelligence/prompts/negation_prompt.py +2 -0
- django_spire/contrib/seeding/intelligence/prompts/objective_prompt.py +6 -1
- django_spire/contrib/seeding/management/commands/seeding.py +9 -3
- django_spire/contrib/seeding/management/example.py +2 -0
- django_spire/contrib/seeding/model/base.py +16 -7
- django_spire/contrib/seeding/model/config.py +31 -15
- django_spire/contrib/seeding/model/django/config.py +13 -13
- django_spire/contrib/seeding/model/django/seeder.py +4 -4
- django_spire/contrib/seeding/model/django/tests/test_seeder.py +34 -23
- django_spire/contrib/seeding/model/enums.py +2 -0
- django_spire/contrib/seeding/tests/test_config.py +71 -0
- django_spire/contrib/seeding/tests/test_custom.py +35 -0
- django_spire/contrib/seeding/tests/test_enums.py +40 -0
- django_spire/contrib/seeding/tests/test_intel.py +32 -0
- django_spire/contrib/seeding/tests/test_override.py +63 -0
- django_spire/contrib/service/__init__.py +2 -2
- django_spire/contrib/service/django_model_service.py +16 -15
- django_spire/contrib/service/exceptions.py +5 -3
- django_spire/contrib/service/tests/__init__.py +0 -0
- django_spire/contrib/service/tests/test_service.py +153 -0
- django_spire/contrib/session/apps.py +2 -0
- django_spire/contrib/session/controller.py +48 -42
- django_spire/contrib/session/templatetags/session_tags.py +11 -2
- django_spire/contrib/session/tests/test_session_controller.py +117 -53
- django_spire/contrib/tests/__init__.py +0 -0
- django_spire/contrib/tests/test_utils.py +37 -0
- django_spire/contrib/utils.py +4 -1
- django_spire/core/apps.py +2 -0
- django_spire/core/converters/tests/test_to_data.py +353 -0
- django_spire/core/converters/tests/test_to_enums.py +61 -41
- django_spire/core/converters/tests/test_to_pydantic.py +138 -109
- django_spire/core/converters/to_data.py +29 -10
- django_spire/core/converters/to_enums.py +4 -2
- django_spire/core/converters/to_pydantic.py +22 -22
- django_spire/core/decorators.py +19 -6
- django_spire/core/forms/widgets.py +4 -0
- django_spire/core/maps.py +3 -1
- django_spire/core/middleware/maintenance.py +3 -3
- django_spire/core/middleware.py +8 -6
- django_spire/core/redirect/__init__.py +5 -0
- django_spire/core/redirect/generic_redirect.py +1 -2
- django_spire/core/redirect/tests/__init__.py +0 -0
- django_spire/core/redirect/tests/test_generic_redirect.py +34 -0
- django_spire/core/{tests/tests_redirect.py → redirect/tests/test_safe_redirect.py} +55 -81
- django_spire/core/shortcuts.py +3 -3
- django_spire/core/static/django_spire/css/app-layout.css +1 -1
- django_spire/core/static/django_spire/css/app-navigation.css +3 -3
- django_spire/core/static/django_spire/css/bootstrap-override.css +4 -0
- django_spire/core/tag/admin.py +12 -0
- django_spire/core/tag/intelligence/tag_set_bot.py +2 -0
- django_spire/core/tag/mixins.py +2 -0
- django_spire/core/tag/models.py +2 -0
- django_spire/core/tag/querysets.py +2 -0
- django_spire/core/tag/service/tag_service.py +6 -3
- django_spire/core/tag/tests/test_intelligence.py +9 -9
- django_spire/core/tag/tests/test_tags.py +44 -54
- django_spire/core/tag/tests/test_tools.py +191 -0
- django_spire/core/tag/tools.py +3 -0
- django_spire/core/templates/django_spire/card/card.html +5 -2
- django_spire/core/templates/django_spire/card/title_card.html +9 -4
- django_spire/core/templates/django_spire/infinite_scroll/base.html +1 -0
- django_spire/core/templates/django_spire/navigation/side_navigation.html +19 -24
- django_spire/core/templates/django_spire/page/full_page.html +46 -16
- django_spire/core/templates/django_spire/table/base.html +4 -2
- django_spire/core/templatetags/json.py +6 -2
- django_spire/core/templatetags/message.py +13 -8
- django_spire/core/templatetags/string_formating.py +8 -5
- django_spire/core/templatetags/tests/__init__.py +0 -0
- django_spire/core/templatetags/tests/test_templatetags.py +427 -0
- django_spire/core/templatetags/variable_types.py +17 -9
- django_spire/core/tests/test_cases.py +1 -1
- django_spire/core/tests/test_conf.py +43 -0
- django_spire/core/tests/test_consts.py +28 -0
- django_spire/core/tests/test_context_processors.py +93 -0
- django_spire/core/tests/test_decorators.py +95 -0
- django_spire/core/tests/test_django_spire_utils.py +56 -0
- django_spire/core/tests/test_exceptions.py +37 -0
- django_spire/core/tests/test_models.py +54 -0
- django_spire/core/tests/test_settings.py +45 -0
- django_spire/core/tests/test_shortcuts.py +74 -0
- django_spire/core/tests/test_urls.py +16 -0
- django_spire/core/tests/test_utils.py +58 -0
- django_spire/core/urls.py +4 -1
- django_spire/core/utils.py +12 -8
- django_spire/exceptions.py +16 -1
- django_spire/file/admin.py +4 -2
- django_spire/file/apps.py +8 -10
- django_spire/file/fields.py +7 -7
- django_spire/file/forms.py +1 -1
- django_spire/file/interfaces.py +15 -15
- django_spire/file/mixins.py +1 -4
- django_spire/file/models.py +3 -5
- django_spire/file/tests/factories.py +59 -0
- django_spire/file/tests/test_admin.py +69 -0
- django_spire/file/tests/test_apps.py +24 -0
- django_spire/file/tests/test_fields.py +114 -0
- django_spire/file/tests/test_forms.py +20 -0
- django_spire/file/tests/test_interfaces.py +183 -0
- django_spire/file/tests/test_models.py +82 -0
- django_spire/file/tests/test_querysets.py +102 -0
- django_spire/file/tests/test_utils.py +32 -0
- django_spire/file/tests/test_views.py +145 -0
- django_spire/file/tests/test_widgets.py +82 -0
- django_spire/file/tools.py +8 -2
- django_spire/file/views.py +7 -3
- django_spire/file/widgets.py +12 -12
- django_spire/help_desk/admin.py +15 -0
- django_spire/help_desk/apps.py +2 -0
- django_spire/help_desk/auth/controller.py +2 -0
- django_spire/help_desk/choices.py +2 -0
- django_spire/help_desk/enums.py +2 -0
- django_spire/help_desk/exceptions.py +31 -3
- django_spire/help_desk/forms.py +2 -0
- django_spire/help_desk/models.py +2 -0
- django_spire/help_desk/querysets.py +4 -1
- django_spire/help_desk/services/notification_service.py +26 -27
- django_spire/help_desk/services/service.py +2 -3
- django_spire/help_desk/tests/factories.py +8 -3
- django_spire/help_desk/tests/test_admin.py +41 -0
- django_spire/help_desk/tests/test_apps.py +41 -0
- django_spire/help_desk/tests/test_choices.py +50 -0
- django_spire/help_desk/tests/test_controller.py +87 -0
- django_spire/help_desk/tests/test_enums.py +18 -0
- django_spire/help_desk/tests/test_exceptions.py +37 -0
- django_spire/help_desk/tests/test_forms.py +89 -0
- django_spire/help_desk/tests/test_models.py +59 -0
- django_spire/help_desk/tests/test_querysets.py +38 -0
- django_spire/help_desk/tests/test_services/test_notification_service.py +15 -8
- django_spire/help_desk/tests/test_services/test_service.py +92 -0
- django_spire/help_desk/tests/test_urls/test_form_urls.py +6 -6
- django_spire/help_desk/tests/test_urls/test_page_urls.py +8 -9
- django_spire/help_desk/tests/test_views/test_form_views.py +46 -19
- django_spire/help_desk/tests/test_views/test_page_views.py +32 -9
- django_spire/help_desk/urls/__init__.py +4 -1
- django_spire/help_desk/urls/form_urls.py +3 -0
- django_spire/help_desk/urls/page_urls.py +3 -0
- django_spire/help_desk/views/form_views.py +13 -5
- django_spire/help_desk/views/page_views.py +11 -3
- django_spire/history/activity/admin.py +2 -0
- django_spire/history/activity/apps.py +3 -1
- django_spire/history/activity/mixins.py +13 -7
- django_spire/history/activity/models.py +6 -5
- django_spire/history/activity/querysets.py +2 -0
- django_spire/history/activity/tests/__init__.py +0 -0
- django_spire/history/activity/tests/test_activity.py +176 -0
- django_spire/history/admin.py +9 -2
- django_spire/history/choices.py +3 -0
- django_spire/history/models.py +5 -5
- django_spire/history/tests/test_admin.py +93 -0
- django_spire/history/tests/test_history.py +101 -0
- django_spire/history/tests/test_mixins.py +84 -0
- django_spire/history/viewed/admin.py +3 -1
- django_spire/history/viewed/apps.py +3 -1
- django_spire/history/viewed/models.py +2 -0
- django_spire/history/viewed/tests/__init__.py +0 -0
- django_spire/history/viewed/tests/test_viewed.py +46 -0
- django_spire/knowledge/auth/tests/__init__.py +0 -0
- django_spire/knowledge/auth/tests/test_controller.py +116 -0
- django_spire/knowledge/collection/admin.py +5 -1
- django_spire/knowledge/collection/models.py +3 -1
- django_spire/knowledge/collection/seeding/seed.py +1 -0
- django_spire/knowledge/collection/services/factory_service.py +10 -11
- django_spire/knowledge/collection/services/ordering_service.py +1 -2
- django_spire/knowledge/collection/services/service.py +5 -10
- django_spire/knowledge/collection/services/tag_service.py +5 -2
- django_spire/knowledge/collection/tests/factories.py +28 -1
- django_spire/knowledge/collection/tests/test_models.py +48 -0
- django_spire/knowledge/collection/tests/test_querysets.py +93 -0
- django_spire/knowledge/collection/tests/test_services/test_factory_service.py +100 -0
- django_spire/knowledge/collection/tests/test_services/test_services.py +160 -0
- django_spire/knowledge/collection/tests/test_urls/test_form_urls.py +21 -3
- django_spire/knowledge/collection/tests/test_urls/test_json_urls.py +39 -1
- django_spire/knowledge/collection/tests/test_urls/test_page_urls.py +12 -4
- django_spire/knowledge/collection/urls/__init__.py +3 -0
- django_spire/knowledge/collection/urls/form_urls.py +2 -0
- django_spire/knowledge/collection/urls/json_urls.py +2 -0
- django_spire/knowledge/collection/urls/page_urls.py +2 -0
- django_spire/knowledge/collection/views/form_views.py +4 -4
- django_spire/knowledge/collection/views/json_views.py +5 -1
- django_spire/knowledge/collection/views/page_views.py +5 -2
- django_spire/knowledge/entry/admin.py +7 -1
- django_spire/knowledge/entry/forms.py +2 -0
- django_spire/knowledge/entry/models.py +2 -0
- django_spire/knowledge/entry/seeding/seed.py +3 -0
- django_spire/knowledge/entry/services/automation_service.py +5 -4
- django_spire/knowledge/entry/services/factory_service.py +7 -5
- django_spire/knowledge/entry/services/service.py +4 -7
- django_spire/knowledge/entry/services/tag_service.py +0 -1
- django_spire/knowledge/entry/services/tool_service.py +1 -0
- django_spire/knowledge/entry/services/transformation_services.py +1 -5
- django_spire/knowledge/entry/tests/factories.py +1 -2
- django_spire/knowledge/entry/tests/test_factory_service.py +20 -0
- django_spire/knowledge/entry/tests/test_models.py +41 -0
- django_spire/knowledge/entry/tests/test_querysets.py +71 -0
- django_spire/knowledge/entry/tests/test_services.py +94 -0
- django_spire/knowledge/entry/tests/test_urls/test_form_urls.py +9 -14
- django_spire/knowledge/entry/tests/test_urls/test_json_urls.py +48 -5
- django_spire/knowledge/entry/tests/test_urls/test_page_urls.py +6 -8
- django_spire/knowledge/entry/tests/test_urls/test_template_urls.py +40 -0
- django_spire/knowledge/entry/urls/form_urls.py +2 -0
- django_spire/knowledge/entry/urls/json_urls.py +2 -0
- django_spire/knowledge/entry/urls/page_urls.py +2 -0
- django_spire/knowledge/entry/urls/template_urls.py +2 -0
- django_spire/knowledge/entry/version/block/choices.py +2 -0
- django_spire/knowledge/entry/version/block/data/data.py +1 -0
- django_spire/knowledge/entry/version/block/data/list/data.py +8 -13
- django_spire/knowledge/entry/version/block/data/list/maps.py +3 -0
- django_spire/knowledge/entry/version/block/data/list/meta.py +1 -2
- django_spire/knowledge/entry/version/block/data/list/tests/__init__.py +0 -0
- django_spire/knowledge/entry/version/block/data/list/tests/test_maps.py +32 -0
- django_spire/knowledge/entry/version/block/data/list/tests/test_meta.py +58 -0
- django_spire/knowledge/entry/version/block/data/maps.py +3 -6
- django_spire/knowledge/entry/version/block/models.py +7 -5
- django_spire/knowledge/entry/version/block/seeding/constants.py +5 -4
- django_spire/knowledge/entry/version/block/services/service.py +2 -3
- django_spire/knowledge/entry/version/block/tests/factories.py +4 -10
- django_spire/knowledge/entry/version/block/tests/test_choices.py +56 -0
- django_spire/knowledge/entry/version/block/tests/test_data.py +90 -0
- django_spire/knowledge/entry/version/block/tests/test_maps.py +37 -0
- django_spire/knowledge/entry/version/block/tests/test_models.py +55 -0
- django_spire/knowledge/entry/version/block/tests/test_querysets.py +35 -0
- django_spire/knowledge/entry/version/block/tests/test_services.py +65 -0
- django_spire/knowledge/entry/version/choices.py +2 -0
- django_spire/knowledge/entry/version/converters/converter.py +1 -1
- django_spire/knowledge/entry/version/converters/docx_converter.py +4 -7
- django_spire/knowledge/entry/version/converters/markdown_converter.py +20 -20
- django_spire/knowledge/entry/version/maps.py +4 -5
- django_spire/knowledge/entry/version/querysets.py +1 -1
- django_spire/knowledge/entry/version/seeding/seeder.py +1 -2
- django_spire/knowledge/entry/version/services/processor_service.py +5 -4
- django_spire/knowledge/entry/version/services/service.py +1 -2
- django_spire/knowledge/entry/version/tests/factories.py +2 -2
- django_spire/knowledge/entry/version/tests/test_choices.py +18 -0
- django_spire/knowledge/entry/version/tests/test_converters/test_docx_converter.py +56 -8
- django_spire/knowledge/entry/version/tests/test_converters/test_markdown_converter.py +78 -0
- django_spire/knowledge/entry/version/tests/test_maps.py +58 -0
- django_spire/knowledge/entry/version/tests/test_models.py +23 -0
- django_spire/knowledge/entry/version/tests/test_querysets.py +26 -0
- django_spire/knowledge/entry/version/tests/test_services.py +62 -0
- django_spire/knowledge/entry/version/tests/test_urls/test_json_urls.py +27 -8
- django_spire/knowledge/entry/version/tests/test_urls/test_page_urls.py +15 -8
- django_spire/knowledge/entry/version/tests/test_urls/test_redirect_urls.py +38 -0
- django_spire/knowledge/entry/version/urls/__init__.py +3 -0
- django_spire/knowledge/entry/version/urls/json_urls.py +2 -1
- django_spire/knowledge/entry/version/urls/page_urls.py +2 -0
- django_spire/knowledge/entry/version/urls/redirect_urls.py +2 -0
- django_spire/knowledge/entry/version/views/json_views.py +5 -1
- django_spire/knowledge/entry/version/views/page_views.py +10 -3
- django_spire/knowledge/entry/version/views/redirect_views.py +5 -1
- django_spire/knowledge/entry/views/form_views.py +16 -8
- django_spire/knowledge/entry/views/json_views.py +3 -1
- django_spire/knowledge/entry/views/page_views.py +8 -2
- django_spire/knowledge/entry/views/template_views.py +7 -1
- django_spire/knowledge/exceptions.py +2 -1
- django_spire/knowledge/intelligence/intel/answer_intel.py +2 -1
- django_spire/knowledge/intelligence/intel/entry_intel.py +0 -1
- django_spire/knowledge/intelligence/workflows/knowledge_workflow.py +4 -5
- django_spire/knowledge/models.py +1 -2
- django_spire/knowledge/tests/__init__.py +0 -0
- django_spire/knowledge/tests/test_templatetags.py +40 -0
- django_spire/knowledge/tests/test_urls/__init__.py +0 -0
- django_spire/knowledge/tests/test_urls/test_page_urls.py +24 -0
- django_spire/knowledge/urls/__init__.py +2 -0
- django_spire/knowledge/urls/page_urls.py +2 -0
- django_spire/knowledge/views/page_views.py +8 -3
- django_spire/notification/admin.py +3 -1
- django_spire/notification/app/admin.py +2 -0
- django_spire/notification/app/apps.py +3 -1
- django_spire/notification/app/exceptions.py +9 -2
- django_spire/notification/app/models.py +8 -4
- django_spire/notification/app/processor.py +22 -26
- django_spire/notification/app/querysets.py +2 -0
- django_spire/notification/app/tests/__init__.py +0 -0
- django_spire/notification/app/tests/factories.py +34 -0
- django_spire/notification/app/tests/test_apps.py +24 -0
- django_spire/notification/app/tests/test_models.py +72 -0
- django_spire/notification/app/tests/test_processor.py +111 -0
- django_spire/notification/app/tests/test_querysets.py +90 -0
- django_spire/notification/app/tests/test_views/__init__.py +0 -0
- django_spire/notification/app/tests/test_views/test_json_views.py +48 -0
- django_spire/notification/app/tests/test_views/test_page_views.py +19 -0
- django_spire/notification/app/urls/__init__.py +3 -1
- django_spire/notification/app/urls/json_urls.py +6 -4
- django_spire/notification/app/urls/page_urls.py +4 -3
- django_spire/notification/app/urls/template_urls.py +4 -2
- django_spire/notification/apps.py +4 -1
- django_spire/notification/email/admin.py +5 -1
- django_spire/notification/email/apps.py +3 -1
- django_spire/notification/email/exceptions.py +4 -2
- django_spire/notification/email/helper.py +5 -3
- django_spire/notification/email/models.py +4 -0
- django_spire/notification/email/processor.py +19 -15
- django_spire/notification/email/querysets.py +3 -0
- django_spire/notification/email/tests/__init__.py +0 -0
- django_spire/notification/email/tests/factories.py +35 -0
- django_spire/notification/email/tests/test_apps.py +24 -0
- django_spire/notification/email/tests/test_models.py +52 -0
- django_spire/notification/email/tests/test_processor.py +92 -0
- django_spire/notification/email/tests/test_querysets.py +43 -0
- django_spire/notification/exceptions.py +17 -2
- django_spire/notification/managers.py +7 -1
- django_spire/notification/maps.py +4 -1
- django_spire/notification/mixins.py +2 -0
- django_spire/notification/models.py +3 -1
- django_spire/notification/processors/notification.py +12 -5
- django_spire/notification/processors/processor.py +2 -0
- django_spire/notification/processors/tests/__init__.py +0 -0
- django_spire/notification/processors/tests/test_notification.py +106 -0
- django_spire/notification/push/admin.py +10 -1
- django_spire/notification/push/apps.py +3 -1
- django_spire/notification/push/models.py +2 -3
- django_spire/notification/push/tests/__init__.py +0 -0
- django_spire/notification/push/tests/test_apps.py +24 -0
- django_spire/notification/push/tests/test_models.py +28 -0
- django_spire/notification/querysets.py +7 -1
- django_spire/notification/sms/admin.py +2 -0
- django_spire/notification/sms/apps.py +4 -1
- django_spire/notification/sms/automations.py +2 -0
- django_spire/notification/sms/choices.py +2 -0
- django_spire/notification/sms/exceptions.py +19 -5
- django_spire/notification/sms/helper.py +33 -23
- django_spire/notification/sms/models.py +5 -1
- django_spire/notification/sms/processor.py +20 -20
- django_spire/notification/sms/querysets.py +2 -0
- django_spire/notification/sms/tests/factories.py +33 -0
- django_spire/notification/sms/tests/test_apps.py +24 -0
- django_spire/notification/sms/tests/test_automation.py +38 -0
- django_spire/notification/sms/tests/test_choices.py +15 -0
- django_spire/notification/sms/tests/test_consts.py +17 -0
- django_spire/notification/sms/tests/test_exceptions.py +27 -0
- django_spire/notification/sms/tests/test_helper.py +50 -0
- django_spire/notification/sms/tests/test_models.py +81 -0
- django_spire/notification/sms/tests/test_processor.py +107 -0
- django_spire/notification/sms/tests/test_tools.py +25 -11
- django_spire/notification/sms/tools.py +16 -5
- django_spire/notification/sms/urls/__init__.py +3 -1
- django_spire/notification/sms/urls/media_urls.py +2 -0
- django_spire/notification/sms/views/media_views.py +14 -4
- django_spire/notification/tests/__init__.py +0 -0
- django_spire/notification/tests/factories.py +26 -0
- django_spire/notification/tests/test_admin.py +55 -0
- django_spire/notification/tests/test_apps.py +30 -0
- django_spire/notification/tests/test_automation.py +18 -0
- django_spire/notification/tests/test_choices.py +59 -0
- django_spire/notification/tests/test_exceptions.py +58 -0
- django_spire/notification/tests/test_managers.py +100 -0
- django_spire/notification/tests/test_maps.py +31 -0
- django_spire/notification/tests/test_models.py +76 -0
- django_spire/notification/tests/test_querysets.py +184 -0
- django_spire/notification/tests/test_utils.py +23 -0
- django_spire/notification/urls.py +3 -1
- django_spire/notification/utils.py +3 -1
- django_spire/settings.py +3 -0
- django_spire/theme/tests/test_context_processor.py +15 -13
- django_spire/theme/tests/test_enums.py +2 -2
- django_spire/theme/tests/test_filesystem.py +2 -5
- django_spire/theme/tests/test_integration.py +12 -12
- django_spire/theme/tests/test_model.py +40 -38
- django_spire/theme/tests/test_views/test_json_views.py +33 -33
- django_spire/theme/urls/json_urls.py +3 -0
- django_spire/theme/urls/page_urls.py +3 -0
- django_spire/urls.py +19 -15
- django_spire/utils.py +13 -4
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/METADATA +1 -1
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/RECORD +530 -358
- django_spire/contrib/options/tests/test_unit.py +0 -148
- django_spire/contrib/seeding/tests/test_seeding.py +0 -25
- django_spire/core/tests/test_templatetags.py +0 -117
- django_spire/core/tests/tests_shortcuts.py +0 -73
- django_spire/history/activity/tests.py +0 -3
- django_spire/history/activity/views.py +0 -3
- django_spire/knowledge/collection/tests/test_services/test_transformation_service.py +0 -71
- django_spire/notification/app/tests.py +0 -3
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/WHEEL +0 -0
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/licenses/LICENSE.md +0 -0
- {django_spire-0.23.7.dist-info → django_spire-0.23.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from django_spire.auth.group.models import AuthGroup
|
|
6
|
+
from django_spire.auth.group.utils import (
|
|
7
|
+
codename_list_to_perm_level,
|
|
8
|
+
codename_to_perm_level,
|
|
9
|
+
has_app_permission,
|
|
10
|
+
has_app_permission_or_404,
|
|
11
|
+
perm_level_to_django_permission,
|
|
12
|
+
perm_level_to_int,
|
|
13
|
+
perm_level_to_string,
|
|
14
|
+
set_group_users,
|
|
15
|
+
)
|
|
16
|
+
from django_spire.auth.user.tests.factories import create_super_user, create_user
|
|
17
|
+
from django_spire.core.tests.test_cases import BaseTestCase
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SetGroupUsersTestCase(BaseTestCase):
|
|
21
|
+
def setUp(self) -> None:
|
|
22
|
+
super().setUp()
|
|
23
|
+
|
|
24
|
+
self.group = AuthGroup.objects.create(name='Test Group')
|
|
25
|
+
self.user1 = create_user(username='user1')
|
|
26
|
+
self.user2 = create_user(username='user2')
|
|
27
|
+
self.user3 = create_user(username='user3')
|
|
28
|
+
|
|
29
|
+
def test_set_group_users(self) -> None:
|
|
30
|
+
set_group_users(self.group, [self.user1, self.user2])
|
|
31
|
+
assert self.group.user_set.count() == 2
|
|
32
|
+
|
|
33
|
+
def test_set_group_users_empty(self) -> None:
|
|
34
|
+
self.group.user_set.add(self.user1)
|
|
35
|
+
set_group_users(self.group, [])
|
|
36
|
+
assert self.group.user_set.count() == 0
|
|
37
|
+
|
|
38
|
+
def test_set_group_users_replaces_existing(self) -> None:
|
|
39
|
+
self.group.user_set.add(self.user1)
|
|
40
|
+
set_group_users(self.group, [self.user2])
|
|
41
|
+
assert self.group.user_set.count() == 1
|
|
42
|
+
assert self.user2 in self.group.user_set.all()
|
|
43
|
+
assert self.user1 not in self.group.user_set.all()
|
|
44
|
+
|
|
45
|
+
def test_set_group_users_multiple(self) -> None:
|
|
46
|
+
set_group_users(self.group, [self.user1, self.user2, self.user3])
|
|
47
|
+
assert self.group.user_set.count() == 3
|
|
48
|
+
|
|
49
|
+
def test_set_group_users_idempotent(self) -> None:
|
|
50
|
+
set_group_users(self.group, [self.user1])
|
|
51
|
+
set_group_users(self.group, [self.user1])
|
|
52
|
+
assert self.group.user_set.count() == 1
|
|
53
|
+
|
|
54
|
+
def test_set_group_users_preserves_user_in_other_groups(self) -> None:
|
|
55
|
+
other_group = AuthGroup.objects.create(name='Other Group')
|
|
56
|
+
other_group.user_set.add(self.user1)
|
|
57
|
+
set_group_users(self.group, [self.user1])
|
|
58
|
+
assert self.user1 in other_group.user_set.all()
|
|
59
|
+
assert self.user1 in self.group.user_set.all()
|
|
60
|
+
|
|
61
|
+
def test_set_group_users_with_queryset(self) -> None:
|
|
62
|
+
from django_spire.auth.user.models import AuthUser
|
|
63
|
+
users = AuthUser.objects.filter(pk__in=[self.user1.pk, self.user2.pk])
|
|
64
|
+
set_group_users(self.group, list(users))
|
|
65
|
+
assert self.group.user_set.count() == 2
|
|
66
|
+
|
|
67
|
+
def test_set_group_users_clears_all_then_sets(self) -> None:
|
|
68
|
+
self.group.user_set.add(self.user1, self.user2, self.user3)
|
|
69
|
+
set_group_users(self.group, [self.user1])
|
|
70
|
+
assert self.group.user_set.count() == 1
|
|
71
|
+
assert self.user1 in self.group.user_set.all()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class CodenameToPermLevelTestCase(BaseTestCase):
|
|
75
|
+
def test_view_codename(self) -> None:
|
|
76
|
+
assert codename_to_perm_level('view_model') == 1
|
|
77
|
+
|
|
78
|
+
def test_add_codename(self) -> None:
|
|
79
|
+
assert codename_to_perm_level('add_model') == 2
|
|
80
|
+
|
|
81
|
+
def test_change_codename(self) -> None:
|
|
82
|
+
assert codename_to_perm_level('change_model') == 3
|
|
83
|
+
|
|
84
|
+
def test_delete_codename(self) -> None:
|
|
85
|
+
assert codename_to_perm_level('delete_model') == 4
|
|
86
|
+
|
|
87
|
+
def test_none_codename(self) -> None:
|
|
88
|
+
assert codename_to_perm_level('none_model') == 0
|
|
89
|
+
|
|
90
|
+
def test_unknown_prefix(self) -> None:
|
|
91
|
+
assert codename_to_perm_level('unknown_model') == 0
|
|
92
|
+
|
|
93
|
+
def test_complex_model_name(self) -> None:
|
|
94
|
+
assert codename_to_perm_level('view_my_complex_model') == 1
|
|
95
|
+
assert codename_to_perm_level('delete_my_complex_model') == 4
|
|
96
|
+
|
|
97
|
+
def test_uppercase_prefix(self) -> None:
|
|
98
|
+
assert codename_to_perm_level('VIEW_model') == 1
|
|
99
|
+
|
|
100
|
+
def test_mixed_case_prefix(self) -> None:
|
|
101
|
+
assert codename_to_perm_level('View_model') == 1
|
|
102
|
+
|
|
103
|
+
def test_empty_codename(self) -> None:
|
|
104
|
+
assert codename_to_perm_level('') == 0
|
|
105
|
+
|
|
106
|
+
def test_underscore_only(self) -> None:
|
|
107
|
+
assert codename_to_perm_level('_') == 0
|
|
108
|
+
|
|
109
|
+
def test_no_underscore(self) -> None:
|
|
110
|
+
assert codename_to_perm_level('viewmodel') == 0
|
|
111
|
+
|
|
112
|
+
def test_multiple_underscores(self) -> None:
|
|
113
|
+
assert codename_to_perm_level('view_my_model_name') == 1
|
|
114
|
+
|
|
115
|
+
def test_special_characters(self) -> None:
|
|
116
|
+
assert codename_to_perm_level('view_model@special') == 1
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class CodenameListToPermLevelTestCase(BaseTestCase):
|
|
120
|
+
def test_empty_list(self) -> None:
|
|
121
|
+
assert codename_list_to_perm_level([]) == 0
|
|
122
|
+
|
|
123
|
+
def test_single_codename(self) -> None:
|
|
124
|
+
assert codename_list_to_perm_level(['view_model']) == 1
|
|
125
|
+
|
|
126
|
+
def test_multiple_codenames_returns_highest(self) -> None:
|
|
127
|
+
codenames = ['view_model', 'add_model', 'change_model']
|
|
128
|
+
assert codename_list_to_perm_level(codenames) == 3
|
|
129
|
+
|
|
130
|
+
def test_all_permissions(self) -> None:
|
|
131
|
+
codenames = ['view_model', 'add_model', 'change_model', 'delete_model']
|
|
132
|
+
assert codename_list_to_perm_level(codenames) == 4
|
|
133
|
+
|
|
134
|
+
def test_unordered_codenames(self) -> None:
|
|
135
|
+
codenames = ['delete_model', 'view_model', 'add_model']
|
|
136
|
+
assert codename_list_to_perm_level(codenames) == 4
|
|
137
|
+
|
|
138
|
+
def test_duplicate_codenames(self) -> None:
|
|
139
|
+
codenames = ['view_model', 'view_model', 'view_model']
|
|
140
|
+
assert codename_list_to_perm_level(codenames) == 1
|
|
141
|
+
|
|
142
|
+
def test_mixed_valid_invalid(self) -> None:
|
|
143
|
+
codenames = ['view_model', 'invalid_model', 'delete_model']
|
|
144
|
+
assert codename_list_to_perm_level(codenames) == 4
|
|
145
|
+
|
|
146
|
+
def test_all_invalid(self) -> None:
|
|
147
|
+
codenames = ['invalid_model', 'unknown_model', 'fake_model']
|
|
148
|
+
assert codename_list_to_perm_level(codenames) == 0
|
|
149
|
+
|
|
150
|
+
def test_single_delete(self) -> None:
|
|
151
|
+
assert codename_list_to_perm_level(['delete_model']) == 4
|
|
152
|
+
|
|
153
|
+
def test_view_and_add(self) -> None:
|
|
154
|
+
codenames = ['view_model', 'add_model']
|
|
155
|
+
assert codename_list_to_perm_level(codenames) == 2
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class PermLevelToIntTestCase(BaseTestCase):
|
|
159
|
+
def test_integer_zero(self) -> None:
|
|
160
|
+
assert perm_level_to_int(0) == 0
|
|
161
|
+
|
|
162
|
+
def test_integer_valid_range(self) -> None:
|
|
163
|
+
for i in range(5):
|
|
164
|
+
assert perm_level_to_int(i) == i
|
|
165
|
+
|
|
166
|
+
def test_integer_out_of_range_high(self) -> None:
|
|
167
|
+
assert perm_level_to_int(5) == 0
|
|
168
|
+
assert perm_level_to_int(100) == 0
|
|
169
|
+
|
|
170
|
+
def test_integer_out_of_range_low(self) -> None:
|
|
171
|
+
assert perm_level_to_int(-1) == 0
|
|
172
|
+
assert perm_level_to_int(-100) == 0
|
|
173
|
+
|
|
174
|
+
def test_string_none(self) -> None:
|
|
175
|
+
assert perm_level_to_int('none') == 0
|
|
176
|
+
assert perm_level_to_int('None') == 0
|
|
177
|
+
assert perm_level_to_int('NONE') == 0
|
|
178
|
+
|
|
179
|
+
def test_string_view(self) -> None:
|
|
180
|
+
assert perm_level_to_int('view') == 1
|
|
181
|
+
assert perm_level_to_int('View') == 1
|
|
182
|
+
assert perm_level_to_int('VIEW') == 1
|
|
183
|
+
|
|
184
|
+
def test_string_add(self) -> None:
|
|
185
|
+
assert perm_level_to_int('add') == 2
|
|
186
|
+
assert perm_level_to_int('Add') == 2
|
|
187
|
+
assert perm_level_to_int('ADD') == 2
|
|
188
|
+
|
|
189
|
+
def test_string_change(self) -> None:
|
|
190
|
+
assert perm_level_to_int('change') == 3
|
|
191
|
+
assert perm_level_to_int('Change') == 3
|
|
192
|
+
assert perm_level_to_int('CHANGE') == 3
|
|
193
|
+
|
|
194
|
+
def test_string_delete(self) -> None:
|
|
195
|
+
assert perm_level_to_int('delete') == 4
|
|
196
|
+
assert perm_level_to_int('Delete') == 4
|
|
197
|
+
assert perm_level_to_int('DELETE') == 4
|
|
198
|
+
|
|
199
|
+
def test_invalid_string(self) -> None:
|
|
200
|
+
assert perm_level_to_int('invalid') == 0
|
|
201
|
+
assert perm_level_to_int('') == 0
|
|
202
|
+
assert perm_level_to_int('random') == 0
|
|
203
|
+
|
|
204
|
+
def test_whitespace_string(self) -> None:
|
|
205
|
+
assert perm_level_to_int(' view ') == 0
|
|
206
|
+
|
|
207
|
+
def test_string_with_numbers(self) -> None:
|
|
208
|
+
assert perm_level_to_int('view1') == 0
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class PermLevelToStringTestCase(BaseTestCase):
|
|
212
|
+
def test_level_zero(self) -> None:
|
|
213
|
+
assert perm_level_to_string(0) == 'None'
|
|
214
|
+
|
|
215
|
+
def test_level_one(self) -> None:
|
|
216
|
+
assert perm_level_to_string(1) == 'View'
|
|
217
|
+
|
|
218
|
+
def test_level_two(self) -> None:
|
|
219
|
+
assert perm_level_to_string(2) == 'Add'
|
|
220
|
+
|
|
221
|
+
def test_level_three(self) -> None:
|
|
222
|
+
assert perm_level_to_string(3) == 'Change'
|
|
223
|
+
|
|
224
|
+
def test_level_four(self) -> None:
|
|
225
|
+
assert perm_level_to_string(4) == 'Delete'
|
|
226
|
+
|
|
227
|
+
def test_string_input(self) -> None:
|
|
228
|
+
assert perm_level_to_string('view') == 'View'
|
|
229
|
+
assert perm_level_to_string('delete') == 'Delete'
|
|
230
|
+
|
|
231
|
+
def test_invalid_level_returns_none(self) -> None:
|
|
232
|
+
assert perm_level_to_string(5) == 'None'
|
|
233
|
+
assert perm_level_to_string(-1) == 'None'
|
|
234
|
+
|
|
235
|
+
def test_all_string_inputs(self) -> None:
|
|
236
|
+
assert perm_level_to_string('none') == 'None'
|
|
237
|
+
assert perm_level_to_string('view') == 'View'
|
|
238
|
+
assert perm_level_to_string('add') == 'Add'
|
|
239
|
+
assert perm_level_to_string('change') == 'Change'
|
|
240
|
+
assert perm_level_to_string('delete') == 'Delete'
|
|
241
|
+
|
|
242
|
+
def test_very_high_number(self) -> None:
|
|
243
|
+
assert perm_level_to_string(999) == 'None'
|
|
244
|
+
|
|
245
|
+
def test_very_low_number(self) -> None:
|
|
246
|
+
assert perm_level_to_string(-999) == 'None'
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class PermLevelToDjangoPermissionTestCase(BaseTestCase):
|
|
250
|
+
def test_view_permission(self) -> None:
|
|
251
|
+
result = perm_level_to_django_permission(1, 'app_label', 'model')
|
|
252
|
+
assert result == 'app_label.view_model'
|
|
253
|
+
|
|
254
|
+
def test_add_permission(self) -> None:
|
|
255
|
+
result = perm_level_to_django_permission(2, 'app_label', 'model')
|
|
256
|
+
assert result == 'app_label.add_model'
|
|
257
|
+
|
|
258
|
+
def test_change_permission(self) -> None:
|
|
259
|
+
result = perm_level_to_django_permission(3, 'app_label', 'model')
|
|
260
|
+
assert result == 'app_label.change_model'
|
|
261
|
+
|
|
262
|
+
def test_delete_permission(self) -> None:
|
|
263
|
+
result = perm_level_to_django_permission(4, 'app_label', 'model')
|
|
264
|
+
assert result == 'app_label.delete_model'
|
|
265
|
+
|
|
266
|
+
def test_none_permission(self) -> None:
|
|
267
|
+
result = perm_level_to_django_permission(0, 'app_label', 'model')
|
|
268
|
+
assert result == 'app_label.none_model'
|
|
269
|
+
|
|
270
|
+
def test_complex_app_label(self) -> None:
|
|
271
|
+
result = perm_level_to_django_permission(1, 'my_app_label', 'model')
|
|
272
|
+
assert result == 'my_app_label.view_model'
|
|
273
|
+
|
|
274
|
+
def test_complex_model_name(self) -> None:
|
|
275
|
+
result = perm_level_to_django_permission(1, 'app', 'my_model_name')
|
|
276
|
+
assert result == 'app.view_my_model_name'
|
|
277
|
+
|
|
278
|
+
def test_string_perm_level(self) -> None:
|
|
279
|
+
result = perm_level_to_django_permission('view', 'app', 'model')
|
|
280
|
+
assert result == 'app.view_model'
|
|
281
|
+
|
|
282
|
+
def test_uppercase_string_perm_level(self) -> None:
|
|
283
|
+
result = perm_level_to_django_permission('DELETE', 'app', 'model')
|
|
284
|
+
assert result == 'app.delete_model'
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class HasAppPermissionTestCase(BaseTestCase):
|
|
288
|
+
def setUp(self) -> None:
|
|
289
|
+
super().setUp()
|
|
290
|
+
|
|
291
|
+
self.user = create_user(username='testuser')
|
|
292
|
+
|
|
293
|
+
def test_user_without_permission(self) -> None:
|
|
294
|
+
result = has_app_permission(self.user, 'app_label', 'model', 'view')
|
|
295
|
+
assert result is False
|
|
296
|
+
|
|
297
|
+
def test_superuser_has_permission(self) -> None:
|
|
298
|
+
superuser = create_super_user()
|
|
299
|
+
result = has_app_permission(superuser, 'any_app', 'any_model', 'delete')
|
|
300
|
+
assert result is True
|
|
301
|
+
|
|
302
|
+
def test_various_actions(self) -> None:
|
|
303
|
+
for action in ['view', 'add', 'change', 'delete']:
|
|
304
|
+
result = has_app_permission(self.user, 'app', 'model', action)
|
|
305
|
+
assert result is False
|
|
306
|
+
|
|
307
|
+
def test_superuser_all_actions(self) -> None:
|
|
308
|
+
superuser = create_super_user()
|
|
309
|
+
for action in ['view', 'add', 'change', 'delete']:
|
|
310
|
+
result = has_app_permission(superuser, 'app', 'model', action)
|
|
311
|
+
assert result is True
|
|
312
|
+
|
|
313
|
+
def test_invalid_action(self) -> None:
|
|
314
|
+
result = has_app_permission(self.user, 'app', 'model', 'invalid')
|
|
315
|
+
assert result is False
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class HasAppPermissionOr404TestCase(BaseTestCase):
|
|
319
|
+
def setUp(self) -> None:
|
|
320
|
+
super().setUp()
|
|
321
|
+
self.user = create_user(username='testuser')
|
|
322
|
+
|
|
323
|
+
def test_raises_permission_error(self) -> None:
|
|
324
|
+
with pytest.raises(PermissionError):
|
|
325
|
+
has_app_permission_or_404(self.user, 'app', 'model', 'view')
|
|
326
|
+
|
|
327
|
+
def test_superuser_returns_true(self) -> None:
|
|
328
|
+
superuser = create_super_user()
|
|
329
|
+
result = has_app_permission_or_404(superuser, 'any_app', 'any_model', 'delete')
|
|
330
|
+
assert result is True
|
|
331
|
+
|
|
332
|
+
def test_raises_for_all_actions(self) -> None:
|
|
333
|
+
for action in ['view', 'add', 'change', 'delete']:
|
|
334
|
+
with pytest.raises(PermissionError):
|
|
335
|
+
has_app_permission_or_404(self.user, 'app', 'model', action)
|
|
336
|
+
|
|
337
|
+
def test_superuser_all_actions_pass(self) -> None:
|
|
338
|
+
superuser = create_super_user()
|
|
339
|
+
for action in ['view', 'add', 'change', 'delete']:
|
|
340
|
+
result = has_app_permission_or_404(superuser, 'app', 'model', action)
|
|
341
|
+
assert result is True
|