From 743c23e7eca479530b31ae1ce88ae938e9dde0a8 Mon Sep 17 00:00:00 2001 From: Domenico DiNicola Date: Thu, 2 May 2024 17:23:32 +0200 Subject: [PATCH] fragments --- src/aurora/config/fragments/__init__.py | 26 + src/aurora/config/fragments/ad.py | 4 + src/aurora/config/fragments/admin_sync.py | 9 + src/aurora/config/fragments/anymail.py | 3 + .../config/fragments/azure_graph_api.py | 4 + src/aurora/config/fragments/capcha.py | 10 + src/aurora/config/fragments/channels.py | 10 + src/aurora/config/fragments/concurrency.py | 1 + src/aurora/config/fragments/constance.py | 40 ++ src/aurora/config/fragments/cors.py | 12 + src/aurora/config/fragments/csp.py | 62 +++ src/aurora/config/fragments/dbtemplate.py | 2 + src/aurora/config/fragments/django_toolbar.py | 38 ++ src/aurora/config/fragments/flags.py | 10 + src/aurora/config/fragments/front_door.py | 22 + src/aurora/config/fragments/hijack.py | 1 + src/aurora/config/fragments/json_editor.py | 4 + src/aurora/config/fragments/matomo.py | 4 + src/aurora/config/fragments/mdeditor.py | 64 +++ src/aurora/config/fragments/rest_framework.py | 19 + src/aurora/config/fragments/reversion.py | 5 + src/aurora/config/fragments/sentry.py | 27 ++ src/aurora/config/fragments/smart_admin.py | 19 + src/aurora/config/fragments/social_auth.py | 43 ++ src/aurora/config/fragments/strategy.py | 1 + src/aurora/config/fragments/sysinfo.py | 27 ++ src/aurora/config/fragments/translator.py | 5 + src/aurora/config/settings.py | 449 +----------------- src/dbtemplates/admin.py | 20 +- src/dbtemplates/conf.py | 3 +- src/dbtemplates/loader.py | 7 +- src/dbtemplates/models.py | 3 +- src/dbtemplates/test_cases.py | 7 +- tests/browser/conftest.py | 1 + tests/browser/test_f_register.py | 4 +- tests/conftest.py | 1 + tests/extras/testutils/factories.py | 6 +- tests/extras/testutils/perms.py | 1 + tests/test_admin.py | 10 +- tests/test_api.py | 4 +- tests/test_crypt.py | 3 +- tests/test_custom.py | 1 + tests/test_i18n.py | 1 + tests/test_panels.py | 1 + tests/test_security.py | 1 + tests/test_sync.py | 1 + tests/test_utils.py | 10 +- tests/test_validators.py | 2 +- tests/test_views.py | 3 +- 49 files changed, 524 insertions(+), 487 deletions(-) create mode 100644 src/aurora/config/fragments/__init__.py create mode 100644 src/aurora/config/fragments/ad.py create mode 100644 src/aurora/config/fragments/admin_sync.py create mode 100644 src/aurora/config/fragments/anymail.py create mode 100644 src/aurora/config/fragments/azure_graph_api.py create mode 100644 src/aurora/config/fragments/capcha.py create mode 100644 src/aurora/config/fragments/channels.py create mode 100644 src/aurora/config/fragments/concurrency.py create mode 100644 src/aurora/config/fragments/constance.py create mode 100644 src/aurora/config/fragments/cors.py create mode 100644 src/aurora/config/fragments/csp.py create mode 100644 src/aurora/config/fragments/dbtemplate.py create mode 100644 src/aurora/config/fragments/django_toolbar.py create mode 100644 src/aurora/config/fragments/flags.py create mode 100644 src/aurora/config/fragments/front_door.py create mode 100644 src/aurora/config/fragments/hijack.py create mode 100644 src/aurora/config/fragments/json_editor.py create mode 100644 src/aurora/config/fragments/matomo.py create mode 100644 src/aurora/config/fragments/mdeditor.py create mode 100644 src/aurora/config/fragments/rest_framework.py create mode 100644 src/aurora/config/fragments/reversion.py create mode 100644 src/aurora/config/fragments/sentry.py create mode 100644 src/aurora/config/fragments/smart_admin.py create mode 100644 src/aurora/config/fragments/social_auth.py create mode 100644 src/aurora/config/fragments/strategy.py create mode 100644 src/aurora/config/fragments/sysinfo.py create mode 100644 src/aurora/config/fragments/translator.py diff --git a/src/aurora/config/fragments/__init__.py b/src/aurora/config/fragments/__init__.py new file mode 100644 index 00000000..7048ab40 --- /dev/null +++ b/src/aurora/config/fragments/__init__.py @@ -0,0 +1,26 @@ +from .ad import * +from .admin_sync import * +from .anymail import * +from .azure_graph_api import * +from .capcha import * +from .channels import * +from .concurrency import * +from .constance import * +from .cors import * +from .csp import * +from .dbtemplate import * +from .django_toolbar import * +from .flags import * +from .front_door import * +from .hijack import * +from .json_editor import * +from .matomo import * +from .mdeditor import * +from .rest_framework import * +from .reversion import * +from .sentry import * +from .smart_admin import * +from .social_auth import * +from .strategy import * +from .sysinfo import * +from .translator import * diff --git a/src/aurora/config/fragments/ad.py b/src/aurora/config/fragments/ad.py new file mode 100644 index 00000000..17588069 --- /dev/null +++ b/src/aurora/config/fragments/ad.py @@ -0,0 +1,4 @@ +from .. import env + +AZURE_CLIENT_ID = env("AZURE_CLIENT_ID") +AZURE_CLIENT_SECRET = env("AZURE_CLIENT_SECRET") diff --git a/src/aurora/config/fragments/admin_sync.py b/src/aurora/config/fragments/admin_sync.py new file mode 100644 index 00000000..cfd8ba72 --- /dev/null +++ b/src/aurora/config/fragments/admin_sync.py @@ -0,0 +1,9 @@ +from .. import env + +ADMIN_SYNC_CONFIG = env("ADMIN_SYNC_CONFIG") +ADMIN_SYNC_RESPONSE_HEADER = None +# these are actually used only in local development +ADMIN_SYNC_REMOTE_SERVER = env("ADMIN_SYNC_REMOTE_SERVER", default="") +ADMIN_SYNC_REMOTE_ADMIN_URL = env("ADMIN_SYNC_REMOTE_ADMIN_URL", default="") +ADMIN_SYNC_LOCAL_ADMIN_URL = env("ADMIN_SYNC_LOCAL_ADMIN_URL", default="") +# ADMIN_SYNC_USE_REVERSION= diff --git a/src/aurora/config/fragments/anymail.py b/src/aurora/config/fragments/anymail.py new file mode 100644 index 00000000..93676b81 --- /dev/null +++ b/src/aurora/config/fragments/anymail.py @@ -0,0 +1,3 @@ +from .. import env + +ANYMAIL = {"MAILJET_API_KEY": env("MAILJET_API_KEY"), "MAILJET_SECRET_KEY": env("MAILJET_SECRET_KEY")} diff --git a/src/aurora/config/fragments/azure_graph_api.py b/src/aurora/config/fragments/azure_graph_api.py new file mode 100644 index 00000000..99873568 --- /dev/null +++ b/src/aurora/config/fragments/azure_graph_api.py @@ -0,0 +1,4 @@ +# Graph API +AZURE_GRAPH_API_BASE_URL = "https://graph.microsoft.com" +AZURE_GRAPH_API_VERSION = "v1.0" +AZURE_TOKEN_URL = "https://login.microsoftonline.com/unicef.org/oauth2/token" diff --git a/src/aurora/config/fragments/capcha.py b/src/aurora/config/fragments/capcha.py new file mode 100644 index 00000000..81238f57 --- /dev/null +++ b/src/aurora/config/fragments/capcha.py @@ -0,0 +1,10 @@ +from .. import env + +# CAPTCHA_IMAGE_SIZE = 300,200 +CAPTCHA_FONT_SIZE = 40 +CAPTCHA_CHALLENGE_FUNCT = "captcha.helpers.random_char_challenge" +CAPTCHA_TEST_MODE = env("CAPTCHA_TEST_MODE") +CAPTCHA_GET_FROM_POOL = True + + +# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge' diff --git a/src/aurora/config/fragments/channels.py b/src/aurora/config/fragments/channels.py new file mode 100644 index 00000000..a40a369f --- /dev/null +++ b/src/aurora/config/fragments/channels.py @@ -0,0 +1,10 @@ +from .. import env + +CHANNEL_LAYERS = { + "default": { + "BACKEND": "channels_redis.core.RedisChannelLayer", + "CONFIG": { + "hosts": [env("CHANNEL_LAYER")], + }, + }, +} diff --git a/src/aurora/config/fragments/concurrency.py b/src/aurora/config/fragments/concurrency.py new file mode 100644 index 00000000..c3713e6c --- /dev/null +++ b/src/aurora/config/fragments/concurrency.py @@ -0,0 +1 @@ +CONCURRENCY_ENABLED = False diff --git a/src/aurora/config/fragments/constance.py b/src/aurora/config/fragments/constance.py new file mode 100644 index 00000000..78636b82 --- /dev/null +++ b/src/aurora/config/fragments/constance.py @@ -0,0 +1,40 @@ +from collections import OrderedDict + +from .. import env + +CONSTANCE_ADDITIONAL_FIELDS = { + "html_minify_select": [ + "bitfield.forms.BitFormField", + {"initial": 0, "required": False, "choices": (("html", "HTML"), ("line", "NEWLINE"), ("space", "SPACES"))}, + ], +} +CONSTANCE_BACKEND = "constance.backends.database.DatabaseBackend" +CONSTANCE_DATABASE_CACHE_BACKEND = env("CONSTANCE_DATABASE_CACHE_BACKEND") +CONSTANCE_CONFIG = OrderedDict( + { + "CACHE_FORMS": (False, "", bool), + "CACHE_VERSION": (1, "", int), + "HOME_PAGE_REGISTRATIONS": ("", "", str), + "SMART_ADMIN_BOOKMARKS": ( + "", + "", + str, + ), + "LOGIN_LOCAL": (True, "Enable local accounts login", bool), + "LOGIN_SSO": (True, "Enable SSO logon", bool), + "ADMIN_SYNC_REMOTE_SERVER": ("", "production server url", str), + "ADMIN_SYNC_REMOTE_ADMIN_URL": ("/admin/", "", str), + "ADMIN_SYNC_LOCAL_ADMIN_URL": ("/admin/", "", str), + "ADMIN_SYNC_USE_REVERSION": (False, "", bool), + "LOG_POST_ERRORS": (False, "", bool), + "MINIFY_RESPONSE": (0, "select yes or no", "html_minify_select"), + "MINIFY_IGNORE_PATH": (r"", "regex for ignored path", str), + "BASE_TEMPLATE": ("base_lean.html", "Default base template", str), + "HOME_TEMPLATE": ("home.html", "Default home.html", str), + "QRCODE": (True, "Enable QRCode generation", bool), + "SHOW_REGISTER_ANOTHER": (True, "Enable QRCode generation", bool), + "MAINTENANCE_MODE": (False, "set maintenance mode On/Off", bool), + "WAF_REGISTRATION_ALLOWED_HOSTNAMES": (".*", "public website hostname (regex)", str), + "WAF_ADMIN_ALLOWED_HOSTNAMES": ("", "admin website hostname (regex)", str), + } +) diff --git a/src/aurora/config/fragments/cors.py b/src/aurora/config/fragments/cors.py new file mode 100644 index 00000000..eb992d2c --- /dev/null +++ b/src/aurora/config/fragments/cors.py @@ -0,0 +1,12 @@ +from .. import env + +CORS_ALLOWED_ORIGINS = [ + "https://excubo.unicef.io", + "http://localhost:8000", + "https://browser.sentry-cdn.com", + "https://cdnjs.cloudflare.com", + "https://login.microsoftonline.com", +] + env("CORS_ALLOWED_ORIGINS") + +CORS_ORIGIN_ALLOW_ALL = True +CORS_ALLOW_CREDENTIALS = True diff --git a/src/aurora/config/fragments/csp.py b/src/aurora/config/fragments/csp.py new file mode 100644 index 00000000..9370ede6 --- /dev/null +++ b/src/aurora/config/fragments/csp.py @@ -0,0 +1,62 @@ +SOURCES = ( + "'self'", + "inline", + "unsafe-inline", + "data:", + "blob:", + "'unsafe-inline'", + "localhost:8000", + "unpkg.com", + "browser.sentry-cdn.com", + "cdnjs.cloudflare.com", + "unisitetracker.unicef.io", + "cdn.jsdelivr.net", + "register.unicef.org", + "uni-hope-ukr-sr.azurefd.net", + "uni-hope-ukr-sr-dev.azurefd.net", + "uni-hope-ukr-sr-dev.unitst.org", +) + +CSP_DEFAULT_SRC = SOURCES +CSP_FRAME_ANCESTORS = ("'self'",) +# CSP_SCRIPT_SRC = SOURCES +# CSP_STYLE_SRC = ( +# "'self'", +# "'data'", +# "'unsafe-inline'", +# "https://unpkg.com", +# "http://localhost:8000", +# "https://cdnjs.cloudflare.com", +# "http://cdnjs.cloudflare.com", +# +# ) +# CSP_OBJECT_SRC = ("self",) +# CSP_BASE_URI = ("self", "http://localhost:8000",) +# CSP_CONNECT_SRC = ("self",) +# CSP_FONT_SRC = ("self",) +# CSP_FRAME_SRC = ("self",) +# CSP_IMG_SRC = ("self", "data") +# CSP_MANIFEST_SRC = ("self",) +# CSP_MEDIA_SRC = ("self",) +# CSP_REPORT_URI = ("https://624948b721ea44ac2a6b4de4.endpoint.csper.io/?v=0;",) +# CSP_WORKER_SRC = ("self",) +# """default-src 'self'; +# script-src 'report-sample' 'self'; +# style-src 'report-sample' 'self'; +# object-src 'none'; +# +# base-uri 'self'; +# connect-src 'self'; +# font-src 'self'; +# frame-src 'self'; +# img-src 'self'; +# manifest-src 'self'; +# media-src 'self'; +# report-uri https://624948b721ea44ac2a6b4de4.endpoint.csper.io/?v=0; +# worker-src 'none'; +# """ + +# CSP_INCLUDE_NONCE_IN = env("CSP_INCLUDE_NONCE_IN") +# CSP_REPORT_ONLY = env("CSP_REPORT_ONLY") +# CSP_DEFAULT_SRC = env("CSP_DEFAULT_SRC") +# CSP_SCRIPT_SRC = env("CSP_SCRIPT_SRC") diff --git a/src/aurora/config/fragments/dbtemplate.py b/src/aurora/config/fragments/dbtemplate.py new file mode 100644 index 00000000..7954a380 --- /dev/null +++ b/src/aurora/config/fragments/dbtemplate.py @@ -0,0 +1,2 @@ +DBTEMPLATES_USE_REVERSION = True +DBTEMPLATES_USE_CODEMIRROR = True diff --git a/src/aurora/config/fragments/django_toolbar.py b/src/aurora/config/fragments/django_toolbar.py new file mode 100644 index 00000000..217f6c02 --- /dev/null +++ b/src/aurora/config/fragments/django_toolbar.py @@ -0,0 +1,38 @@ +from django_regex.utils import RegexList + + +def show_ddt(request): # pragma: no-cover + from flags.state import flag_enabled + + if request.path in RegexList(("/tpl/.*", "/api/.*", "/dal/.*")): # pragma: no cache + return False + return flag_enabled("DEVELOP_DEBUG_TOOLBAR", request=request) + + +DEBUG_TOOLBAR_CONFIG = { + "SHOW_TOOLBAR_CALLBACK": show_ddt, + "JQUERY_URL": "", + "INSERT_BEFORE": "", + "SHOW_TEMPLATE_CONTEXT": True, +} + +DEBUG_TOOLBAR_PANELS = [ + "debug_toolbar.panels.history.HistoryPanel", + # "debug_toolbar.panels.versions.VersionsPanel", + "aurora.ddt_panels.StatePanel", + "aurora.ddt_panels.MigrationPanel", + "debug_toolbar.panels.timer.TimerPanel", + "flags.panels.FlagsPanel", + "flags.panels.FlagChecksPanel", + "debug_toolbar.panels.settings.SettingsPanel", + "debug_toolbar.panels.headers.HeadersPanel", + "debug_toolbar.panels.request.RequestPanel", + "debug_toolbar.panels.sql.SQLPanel", + "debug_toolbar.panels.staticfiles.StaticFilesPanel", + "debug_toolbar.panels.templates.TemplatesPanel", + "debug_toolbar.panels.cache.CachePanel", + "debug_toolbar.panels.signals.SignalsPanel", + "debug_toolbar.panels.logging.LoggingPanel", + "debug_toolbar.panels.redirects.RedirectsPanel", + "debug_toolbar.panels.profiling.ProfilingPanel", +] diff --git a/src/aurora/config/fragments/flags.py b/src/aurora/config/fragments/flags.py new file mode 100644 index 00000000..42e9dc5c --- /dev/null +++ b/src/aurora/config/fragments/flags.py @@ -0,0 +1,10 @@ +from ..settings import DEBUG + +FLAGS_STATE_LOGGING = DEBUG + +FLAGS = { + "DEVELOP_DEVELOPER": [], + "DEVELOP_DEBUG_TOOLBAR": [], + "SENTRY_JAVASCRIPT": [], + "I18N_COLLECT_MESSAGES": [], +} diff --git a/src/aurora/config/fragments/front_door.py b/src/aurora/config/fragments/front_door.py new file mode 100644 index 00000000..278122e5 --- /dev/null +++ b/src/aurora/config/fragments/front_door.py @@ -0,0 +1,22 @@ +from .. import env + +FRONT_DOOR_CONFIG = "front_door.conf.DjangoConstance" +FRONT_DOOR_ENABLED = env("FRONT_DOOR_ENABLED") +FRONT_DOOR_ALLOWED_PATHS = env("FRONT_DOOR_ALLOWED_PATHS") +FRONT_DOOR_TOKEN = env("FRONT_DOOR_TOKEN") +FRONT_DOOR_HEADER = "x-aurora" +FRONT_DOOR_COOKIE_NAME = "x-aurora" +FRONT_DOOR_COOKIE_PATTERN = ".*" +# FRONT_DOOR_ERROR_CODE = 404 +# FRONT_DOOR_REDIR_URL = "https://www.sosbob.com/" +FRONT_DOOR_LOG_LEVEL = env("FRONT_DOOR_LOG_LEVEL") # LOG_RULE_FAIL +FRONT_DOOR_RULES = [ + # "front_door.rules.internal_ip", # grant access to settings.INTERNAL_IPS + # "front_door.rules.forbidden_path", # DENY access to FORBIDDEN_PATHS + "front_door.rules.allowed_path", # grant access to ALLOWED_PATHS + "front_door.rules.allowed_ip", # grant access to ALLOWED_IPS + "front_door.rules.special_header", # grant access if request has Header[HEADER] == TOKEN + # "front_door.rules.has_header", # grant access if request has HEADER + "front_door.rules.cookie_value", # grant access if request.COOKIES[COOKIE_NAME] + # "front_door.rules.cookie_exists", # grant access ir COOKIE_NAME in request.COOKIES +] diff --git a/src/aurora/config/fragments/hijack.py b/src/aurora/config/fragments/hijack.py new file mode 100644 index 00000000..05fb48ba --- /dev/null +++ b/src/aurora/config/fragments/hijack.py @@ -0,0 +1 @@ +HIJACK_PERMISSION_CHECK = "aurora.administration.hijack.can_impersonate" diff --git a/src/aurora/config/fragments/json_editor.py b/src/aurora/config/fragments/json_editor.py new file mode 100644 index 00000000..68785470 --- /dev/null +++ b/src/aurora/config/fragments/json_editor.py @@ -0,0 +1,4 @@ +JSON_EDITOR_JS = "https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/8.6.4/jsoneditor.js" +JSON_EDITOR_CSS = "https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/8.6.4/jsoneditor.css" +JSON_EDITOR_INIT_JS = "django-jsoneditor/jsoneditor-init.min.js" +JSON_EDITOR_ACE_OPTIONS_JS = "django-jsoneditor/ace_options.min.js" diff --git a/src/aurora/config/fragments/matomo.py b/src/aurora/config/fragments/matomo.py new file mode 100644 index 00000000..bb11d9e6 --- /dev/null +++ b/src/aurora/config/fragments/matomo.py @@ -0,0 +1,4 @@ +from .. import env + +MATOMO_SITE = env("MATOMO_SITE", default="https://unisitetracker.unicef.io/") +MATOMO_ID = env("MATOMO_ID", default="N/A") diff --git a/src/aurora/config/fragments/mdeditor.py b/src/aurora/config/fragments/mdeditor.py new file mode 100644 index 00000000..8db66468 --- /dev/null +++ b/src/aurora/config/fragments/mdeditor.py @@ -0,0 +1,64 @@ +MDEDITOR_CONFIGS = { + "default": { + "width": "100% ", # Custom edit box width + "height": 200, # Custom edit box height + "toolbar": [ + "undo", + "redo", + "|", + "bold", + "del", + "italic", + "quote", + "ucwords", + "uppercase", + "lowercase", + "|", + "h1", + "h2", + "h3", + "h5", + "h6", + "|", + "list-ul", + "list-ol", + "hr", + "|", + "link", + "reference-link", + "image", + "code", + "preformatted-text", + "code-block", + "table", + "datetime", + "emoji", + "html-entities", + "pagebreak", + "goto-line", + "|", + "help", + "info", + "||", + "preview", + "watch", + "fullscreen", + ], # custom edit box toolbar + # image upload format type + # 'upload_image_formats': ["jpg", "jpeg", "gif", "png", "bmp", "webp", "svg"], + # 'image_folder': 'editor', # image save the folder name + "theme": "default", # edit box theme, dark / default + "preview_theme": "default", # Preview area theme, dark / default + "editor_theme": "default", # edit area theme, pastel-on-dark / default + "toolbar_autofixed": False, # Whether the toolbar capitals + "search_replace": True, # Whether to open the search for replacement + "emoji": True, # whether to open the expression function + "tex": True, # whether to open the tex chart function + "flow_chart": True, # whether to open the flow chart function + "sequence": True, # Whether to open the sequence diagram function + "watch": True, # Live preview + "lineWrapping": True, # lineWrapping + "lineNumbers": True, # lineNumbers + "language": "en", # zh / en / es + } +} diff --git a/src/aurora/config/fragments/rest_framework.py b/src/aurora/config/fragments/rest_framework.py new file mode 100644 index 00000000..2480396f --- /dev/null +++ b/src/aurora/config/fragments/rest_framework.py @@ -0,0 +1,19 @@ +REST_FRAMEWORK = { + "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", + "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.NamespaceVersioning", + "DEFAULT_FILTER_BACKENDS": ("django_filters.rest_framework.DjangoFilterBackend",), + "DEFAULT_RENDERER_CLASSES": ( + "rest_framework.renderers.JSONRenderer", + "rest_framework.renderers.BrowsableAPIRenderer", + "rest_framework_datatables.renderers.DatatablesRenderer", + ), + "PAGE_SIZE": 30, + "DEFAULT_AUTHENTICATION_CLASSES": [ + "rest_framework.authentication.BasicAuthentication", + "rest_framework.authentication.SessionAuthentication", + "rest_framework.authentication.TokenAuthentication", + ], + "DEFAULT_PERMISSION_CLASSES": [ + "rest_framework.permissions.DjangoModelPermissions", + ], +} diff --git a/src/aurora/config/fragments/reversion.py b/src/aurora/config/fragments/reversion.py new file mode 100644 index 00000000..c51220de --- /dev/null +++ b/src/aurora/config/fragments/reversion.py @@ -0,0 +1,5 @@ +# Add reversion models to admin interface: +ADD_REVERSION_ADMIN = True +# optional settings: +REVERSION_COMPARE_FOREIGN_OBJECTS_AS_ID = False +REVERSION_COMPARE_IGNORE_NOT_REGISTERED = False diff --git a/src/aurora/config/fragments/sentry.py b/src/aurora/config/fragments/sentry.py new file mode 100644 index 00000000..87d8bfe9 --- /dev/null +++ b/src/aurora/config/fragments/sentry.py @@ -0,0 +1,27 @@ +import logging + +import aurora + +from .. import env + +SENTRY_DSN = env("SENTRY_DSN") +SENTRY_PROJECT = env("SENTRY_PROJECT") +if SENTRY_DSN: + import sentry_sdk + from sentry_sdk.integrations.django import DjangoIntegration + from sentry_sdk.integrations.logging import LoggingIntegration + + sentry_logging = LoggingIntegration( + level=logging.INFO, # Capture info and above as breadcrumbs + event_level=logging.ERROR, # Send errors as events + ) + sentry_sdk.init( + dsn=SENTRY_DSN, + environment=env("SENTRY_ENVIRONMENT", default=None), + integrations=[ + DjangoIntegration(transaction_style="url"), + sentry_logging, + ], + release=aurora.VERSION, + send_default_pii=True, + ) diff --git a/src/aurora/config/fragments/smart_admin.py b/src/aurora/config/fragments/smart_admin.py new file mode 100644 index 00000000..ed42ca4e --- /dev/null +++ b/src/aurora/config/fragments/smart_admin.py @@ -0,0 +1,19 @@ +from .. import env + +SMART_ADMIN_SECTIONS = { + "Registration": ["registration", "dbtemplates", "flatpages"], + "Security": ["social_auth", "security"], + "Form Builder": ["core"], + "Organization": ["core.Organization", "core.Project"], + "Configuration": ["constance", "flags"], + "i18N": [ + "i18n", + ], + "Other": [], + "_hidden_": [], +} +SMART_ADMIN_TITLE = "=" +SMART_ADMIN_HEADER = env("DJANGO_ADMIN_TITLE") +SMART_ADMIN_BOOKMARKS = "aurora.core.utils.get_bookmarks" + +SMART_ADMIN_PROFILE_LINK = True diff --git a/src/aurora/config/fragments/social_auth.py b/src/aurora/config/fragments/social_auth.py new file mode 100644 index 00000000..a9ff2736 --- /dev/null +++ b/src/aurora/config/fragments/social_auth.py @@ -0,0 +1,43 @@ +from .. import env + +SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = env.str("AZURE_CLIENT_SECRET") +SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = env("AZURE_TENANT_ID") +SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = env.str("AZURE_CLIENT_KEY") +SOCIAL_AUTH_RESOURCE = "https://graph.microsoft.com/" +# SOCIAL_AUTH_POLICY = env("AZURE_POLICY_NAME") +# SOCIAL_AUTH_AUTHORITY_HOST = env("AZURE_AUTHORITY_HOST") +SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = [ + "username", + "first_name", + "last_name", + "email", +] + +SOCIAL_AUTH_JSONFIELD_ENABLED = True +SOCIAL_AUTH_PIPELINE = ( + "aurora.core.authentication.social_details", + "social_core.pipeline.social_auth.social_uid", + "social_core.pipeline.social_auth.auth_allowed", + "social_core.pipeline.social_auth.social_user", + "social_core.pipeline.user.get_username", + "aurora.core.authentication.require_email", + "social_core.pipeline.social_auth.associate_by_email", + "aurora.core.authentication.create_user", + "social_core.pipeline.social_auth.associate_user", + "social_core.pipeline.social_auth.load_extra_data", + "aurora.core.authentication.user_details", + "aurora.core.authentication.redir_to_form", +) +SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_USER_FIELDS = [ + "email", + "fullname", +] + +SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_SCOPE = [ + "openid", + "email", + "profile", +] + +SOCIAL_AUTH_SANITIZE_REDIRECTS = True +SOCIAL_AUTH_JWT_LEEWAY = env.int("JWT_LEEWAY", 0) diff --git a/src/aurora/config/fragments/strategy.py b/src/aurora/config/fragments/strategy.py new file mode 100644 index 00000000..fa68e7f9 --- /dev/null +++ b/src/aurora/config/fragments/strategy.py @@ -0,0 +1 @@ +STRATEGY_CLASSLOADER = "aurora.core.registry.classloader" diff --git a/src/aurora/config/fragments/sysinfo.py b/src/aurora/config/fragments/sysinfo.py new file mode 100644 index 00000000..7d3cce96 --- /dev/null +++ b/src/aurora/config/fragments/sysinfo.py @@ -0,0 +1,27 @@ +def masker(key, value, config, request): + from django_sysinfo.utils import cleanse_setting + + from aurora.core.utils import is_root + + if is_root(request): + return value + return cleanse_setting(key, value, config, request) + + +SYSINFO = { + "host": True, + "os": True, + "python": True, + "modules": True, + "masker": "aurora.config.settings.masker", + "masked_environment": "API|TOKEN|KEY|SECRET|PASS|SIGNATURE|AUTH|_ID|SID|DATABASE_URL", + # "project": { + # "mail": False, + # "installed_apps": False, + # "databases": False, + # "MEDIA_ROOT": False, + # "STATIC_ROOT": False, + # "CACHES": False + # }, + # "checks": None, +} diff --git a/src/aurora/config/fragments/translator.py b/src/aurora/config/fragments/translator.py new file mode 100644 index 00000000..94b974e4 --- /dev/null +++ b/src/aurora/config/fragments/translator.py @@ -0,0 +1,5 @@ +from .. import env + +TRANSLATOR_SERVICE = env("TRANSLATOR_SERVICE") +AZURE_TRANSLATOR_KEY = env("AZURE_TRANSLATOR_KEY") +AZURE_TRANSLATOR_LOCATION = env("AZURE_TRANSLATOR_LOCATION") diff --git a/src/aurora/config/settings.py b/src/aurora/config/settings.py index b3a8e66f..a9ad70fb 100644 --- a/src/aurora/config/settings.py +++ b/src/aurora/config/settings.py @@ -1,13 +1,8 @@ import logging import mimetypes import os -from collections import OrderedDict from pathlib import Path -from django_regex.utils import RegexList - -import aurora - from . import env BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) @@ -113,6 +108,7 @@ # "django.middleware.cache.FetchFromCacheMiddleware", "debug_toolbar.middleware.DebugToolbarMiddleware", "hijack.middleware.HijackUserMiddleware", + "csp.middleware.CSPMiddleware", ] X_FRAME_OPTIONS = "SAMEORIGIN" @@ -249,6 +245,7 @@ SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" SESSION_COOKIE_HTTPONLY = True SESSION_EXPIRE_AT_BROWSER_CLOSE = True +SESSION_COOKIE_HTTPONLY = False # for offline forms TIME_ZONE = "UTC" @@ -369,92 +366,7 @@ ] MAX_OBSERVED = 1 -SENTRY_DSN = env("SENTRY_DSN") -SENTRY_PROJECT = env("SENTRY_PROJECT") -if SENTRY_DSN: - import sentry_sdk - from sentry_sdk.integrations.django import DjangoIntegration - from sentry_sdk.integrations.logging import LoggingIntegration - - sentry_logging = LoggingIntegration( - level=logging.INFO, # Capture info and above as breadcrumbs - event_level=logging.ERROR, # Send errors as events - ) - sentry_sdk.init( - dsn=SENTRY_DSN, - environment=env("SENTRY_ENVIRONMENT", default=None), - integrations=[ - DjangoIntegration(transaction_style="url"), - sentry_logging, - ], - release=aurora.VERSION, - send_default_pii=True, - ) -CORS_ALLOWED_ORIGINS = [ - "https://excubo.unicef.io", - "http://localhost:8000", - "https://browser.sentry-cdn.com", - "https://cdnjs.cloudflare.com", - "https://login.microsoftonline.com", -] + env("CORS_ALLOWED_ORIGINS") - -CONSTANCE_ADDITIONAL_FIELDS = { - "html_minify_select": [ - "bitfield.forms.BitFormField", - {"initial": 0, "required": False, "choices": (("html", "HTML"), ("line", "NEWLINE"), ("space", "SPACES"))}, - ], -} -CONSTANCE_BACKEND = "constance.backends.database.DatabaseBackend" -CONSTANCE_DATABASE_CACHE_BACKEND = env("CONSTANCE_DATABASE_CACHE_BACKEND") -CONSTANCE_CONFIG = OrderedDict( - { - "CACHE_FORMS": (False, "", bool), - "CACHE_VERSION": (1, "", int), - "HOME_PAGE_REGISTRATIONS": ("", "", str), - "SMART_ADMIN_BOOKMARKS": ( - "", - "", - str, - ), - "LOGIN_LOCAL": (True, "Enable local accounts login", bool), - "LOGIN_SSO": (True, "Enable SSO logon", bool), - "ADMIN_SYNC_REMOTE_SERVER": ("", "production server url", str), - "ADMIN_SYNC_REMOTE_ADMIN_URL": ("/admin/", "", str), - "ADMIN_SYNC_LOCAL_ADMIN_URL": ("/admin/", "", str), - "ADMIN_SYNC_USE_REVERSION": (False, "", bool), - "LOG_POST_ERRORS": (False, "", bool), - "MINIFY_RESPONSE": (0, "select yes or no", "html_minify_select"), - "MINIFY_IGNORE_PATH": (r"", "regex for ignored path", str), - "BASE_TEMPLATE": ("base_lean.html", "Default base template", str), - "HOME_TEMPLATE": ("home.html", "Default home.html", str), - "QRCODE": (True, "Enable QRCode generation", bool), - "SHOW_REGISTER_ANOTHER": (True, "Enable QRCode generation", bool), - "MAINTENANCE_MODE": (False, "set maintenance mode On/Off", bool), - "WAF_REGISTRATION_ALLOWED_HOSTNAMES": (".*", "public website hostname (regex)", str), - "WAF_ADMIN_ALLOWED_HOSTNAMES": ("", "admin website hostname (regex)", str), - } -) -SMART_ADMIN_SECTIONS = { - "Registration": ["registration", "dbtemplates", "flatpages"], - "Security": ["social_auth", "security"], - "Form Builder": ["core"], - "Organization": ["core.Organization", "core.Project"], - "Configuration": ["constance", "flags"], - "i18N": [ - "i18n", - ], - "Other": [], - "_hidden_": [], -} -SMART_ADMIN_TITLE = "=" -SMART_ADMIN_HEADER = env("DJANGO_ADMIN_TITLE") -SMART_ADMIN_BOOKMARKS = "aurora.core.utils.get_bookmarks" - -SMART_ADMIN_PROFILE_LINK = True - -CORS_ORIGIN_ALLOW_ALL = True -CORS_ALLOW_CREDENTIALS = True RATELIMIT = { "PERIODS": { @@ -470,95 +382,8 @@ AA_PERMISSION_HANDLER = 3 # AA_PERMISSION_CREATE_USE_APPCONFIG - -def masker(key, value, config, request): - from django_sysinfo.utils import cleanse_setting - - from aurora.core.utils import is_root - - if is_root(request): - return value - return cleanse_setting(key, value, config, request) - - -SYSINFO = { - "host": True, - "os": True, - "python": True, - "modules": True, - "masker": "aurora.config.settings.masker", - "masked_environment": "API|TOKEN|KEY|SECRET|PASS|SIGNATURE|AUTH|_ID|SID|DATABASE_URL", - # "project": { - # "mail": False, - # "installed_apps": False, - # "databases": False, - # "MEDIA_ROOT": False, - # "STATIC_ROOT": False, - # "CACHES": False - # }, - # "checks": None, -} - -FLAGS_STATE_LOGGING = DEBUG - -FLAGS = { - "DEVELOP_DEVELOPER": [], - "DEVELOP_DEBUG_TOOLBAR": [], - "SENTRY_JAVASCRIPT": [], - "I18N_COLLECT_MESSAGES": [], -} - -JSON_EDITOR_JS = "https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/8.6.4/jsoneditor.js" -JSON_EDITOR_CSS = "https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/8.6.4/jsoneditor.css" -JSON_EDITOR_INIT_JS = "django-jsoneditor/jsoneditor-init.min.js" -JSON_EDITOR_ACE_OPTIONS_JS = "django-jsoneditor/ace_options.min.js" - -# CAPTCHA_IMAGE_SIZE = 300,200 -CAPTCHA_FONT_SIZE = 40 -CAPTCHA_CHALLENGE_FUNCT = "captcha.helpers.random_char_challenge" -CAPTCHA_TEST_MODE = env("CAPTCHA_TEST_MODE") -CAPTCHA_GET_FROM_POOL = True - - -# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge' - - -# DEBUG TOOLBAR -def show_ddt(request): # pragma: no-cover - from flags.state import flag_enabled - - if request.path in RegexList(("/tpl/.*", "/api/.*", "/dal/.*")): # pragma: no cache - return False - return flag_enabled("DEVELOP_DEBUG_TOOLBAR", request=request) - - -DEBUG_TOOLBAR_CONFIG = { - "SHOW_TOOLBAR_CALLBACK": show_ddt, - "JQUERY_URL": "", - "INSERT_BEFORE": "", - "SHOW_TEMPLATE_CONTEXT": True, -} INTERNAL_IPS = env.list("INTERNAL_IPS") -DEBUG_TOOLBAR_PANELS = [ - "debug_toolbar.panels.history.HistoryPanel", - # "debug_toolbar.panels.versions.VersionsPanel", - "aurora.ddt_panels.StatePanel", - "aurora.ddt_panels.MigrationPanel", - "debug_toolbar.panels.timer.TimerPanel", - "flags.panels.FlagsPanel", - "flags.panels.FlagChecksPanel", - "debug_toolbar.panels.settings.SettingsPanel", - "debug_toolbar.panels.headers.HeadersPanel", - "debug_toolbar.panels.request.RequestPanel", - "debug_toolbar.panels.sql.SQLPanel", - "debug_toolbar.panels.staticfiles.StaticFilesPanel", - "debug_toolbar.panels.templates.TemplatesPanel", - "debug_toolbar.panels.cache.CachePanel", - "debug_toolbar.panels.signals.SignalsPanel", - "debug_toolbar.panels.logging.LoggingPanel", - "debug_toolbar.panels.redirects.RedirectsPanel", - "debug_toolbar.panels.profiling.ProfilingPanel", -] + ROOT_TOKEN = env("ROOT_TOKEN") CSRF_FAILURE_VIEW = "aurora.web.views.site.error_csrf" @@ -567,55 +392,6 @@ def show_ddt(request): # pragma: no-cover AUTH_USER_MODEL = "auth.User" # AUTH_USER_MODEL = "security.AuroraUser" -# Graph API -AZURE_GRAPH_API_BASE_URL = "https://graph.microsoft.com" -AZURE_GRAPH_API_VERSION = "v1.0" -AZURE_TOKEN_URL = "https://login.microsoftonline.com/unicef.org/oauth2/token" - -# Social Auth settings. -SOCIAL_AUTH_BACKEND_NAME = "macioce" -SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = env.str("AZURE_CLIENT_SECRET") -SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = env("AZURE_TENANT_ID") -SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = env.str("AZURE_CLIENT_KEY") -SOCIAL_AUTH_RESOURCE = "https://graph.microsoft.com/" -# SOCIAL_AUTH_POLICY = env("AZURE_POLICY_NAME") -# SOCIAL_AUTH_AUTHORITY_HOST = env("AZURE_AUTHORITY_HOST") -SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = [ - "username", - "first_name", - "last_name", - "email", -] - -SOCIAL_AUTH_JSONFIELD_ENABLED = True -SOCIAL_AUTH_PIPELINE = ( - "aurora.core.authentication.social_details", - "social_core.pipeline.social_auth.social_uid", - "social_core.pipeline.social_auth.auth_allowed", - "social_core.pipeline.social_auth.social_user", - "social_core.pipeline.user.get_username", - "aurora.core.authentication.require_email", - "social_core.pipeline.social_auth.associate_by_email", - "aurora.core.authentication.create_user", - "social_core.pipeline.social_auth.associate_user", - "social_core.pipeline.social_auth.load_extra_data", - "aurora.core.authentication.user_details", - "aurora.core.authentication.redir_to_form", -) -SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_USER_FIELDS = [ - "email", - "fullname", -] - -SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_SCOPE = [ - "openid", - "email", - "profile", -] - -SOCIAL_AUTH_SANITIZE_REDIRECTS = True -SOCIAL_AUTH_JWT_LEEWAY = env.int("JWT_LEEWAY", 0) - # fix admin name LOGIN_URL = "/login" LOGIN_REDIRECT_URL = "/logged-in/" @@ -627,230 +403,13 @@ def show_ddt(request): # pragma: no-cover HTTP2_PRELOAD_HEADERS = True HTTP2_PRESEND_CACHED_HEADERS = True HTTP2_SERVER_PUSH = False -# CSP -SOURCES = ( - "'self'", - "inline", - "unsafe-inline", - "data:", - "blob:", - "'unsafe-inline'", - "localhost:8000", - "unpkg.com", - "browser.sentry-cdn.com", - "cdnjs.cloudflare.com", - "unisitetracker.unicef.io", - "cdn.jsdelivr.net", - "register.unicef.org", - "uni-hope-ukr-sr.azurefd.net", - "uni-hope-ukr-sr-dev.azurefd.net", - "uni-hope-ukr-sr-dev.unitst.org", -) -MIDDLEWARE += [ - "csp.middleware.CSPMiddleware", -] -CSP_DEFAULT_SRC = SOURCES -CSP_FRAME_ANCESTORS = ("'self'",) -# CSP_SCRIPT_SRC = SOURCES -# CSP_STYLE_SRC = ( -# "'self'", -# "'data'", -# "'unsafe-inline'", -# "https://unpkg.com", -# "http://localhost:8000", -# "https://cdnjs.cloudflare.com", -# "http://cdnjs.cloudflare.com", -# -# ) -# CSP_OBJECT_SRC = ("self",) -# CSP_BASE_URI = ("self", "http://localhost:8000",) -# CSP_CONNECT_SRC = ("self",) -# CSP_FONT_SRC = ("self",) -# CSP_FRAME_SRC = ("self",) -# CSP_IMG_SRC = ("self", "data") -# CSP_MANIFEST_SRC = ("self",) -# CSP_MEDIA_SRC = ("self",) -# CSP_REPORT_URI = ("https://624948b721ea44ac2a6b4de4.endpoint.csper.io/?v=0;",) -# CSP_WORKER_SRC = ("self",) -# """default-src 'self'; -# script-src 'report-sample' 'self'; -# style-src 'report-sample' 'self'; -# object-src 'none'; -# -# base-uri 'self'; -# connect-src 'self'; -# font-src 'self'; -# frame-src 'self'; -# img-src 'self'; -# manifest-src 'self'; -# media-src 'self'; -# report-uri https://624948b721ea44ac2a6b4de4.endpoint.csper.io/?v=0; -# worker-src 'none'; -# """ - -# CSP_INCLUDE_NONCE_IN = env("CSP_INCLUDE_NONCE_IN") -# CSP_REPORT_ONLY = env("CSP_REPORT_ONLY") -# CSP_DEFAULT_SRC = env("CSP_DEFAULT_SRC") -# CSP_SCRIPT_SRC = env("CSP_SCRIPT_SRC") SECURE_HSTS_SECONDS = 60 SECURE_HSTS_INCLUDE_SUBDOMAINS = True -# Add reversion models to admin interface: -ADD_REVERSION_ADMIN = True -# optional settings: -REVERSION_COMPARE_FOREIGN_OBJECTS_AS_ID = False -REVERSION_COMPARE_IGNORE_NOT_REGISTERED = False - -ADMIN_SYNC_CONFIG = env("ADMIN_SYNC_CONFIG") -ADMIN_SYNC_RESPONSE_HEADER = None -# these are actually used only in local development -ADMIN_SYNC_REMOTE_SERVER = env("ADMIN_SYNC_REMOTE_SERVER", default="") -ADMIN_SYNC_REMOTE_ADMIN_URL = env("ADMIN_SYNC_REMOTE_ADMIN_URL", default="") -ADMIN_SYNC_LOCAL_ADMIN_URL = env("ADMIN_SYNC_LOCAL_ADMIN_URL", default="") -# ADMIN_SYNC_USE_REVERSION= - SILENCED_SYSTEM_CHECKS = ["debug_toolbar.W006", "urls.W005", "admin_extra_buttons.PERM"] -DBTEMPLATES_USE_REVERSION = True -DBTEMPLATES_USE_CODEMIRROR = True -CONCURRENCY_ENABLED = False - -STRATEGY_CLASSLOADER = "aurora.core.registry.classloader" MIGRATION_LOCK_KEY = env("MIGRATION_LOCK_KEY") -# for offline forms -DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 10 -SESSION_COOKIE_HTTPONLY = False - -HIJACK_PERMISSION_CHECK = "aurora.administration.hijack.can_impersonate" - -CHANNEL_LAYERS = { - "default": { - "BACKEND": "channels_redis.core.RedisChannelLayer", - "CONFIG": { - "hosts": [env("CHANNEL_LAYER")], - }, - }, -} - -MDEDITOR_CONFIGS = { - "default": { - "width": "100% ", # Custom edit box width - "height": 200, # Custom edit box height - "toolbar": [ - "undo", - "redo", - "|", - "bold", - "del", - "italic", - "quote", - "ucwords", - "uppercase", - "lowercase", - "|", - "h1", - "h2", - "h3", - "h5", - "h6", - "|", - "list-ul", - "list-ol", - "hr", - "|", - "link", - "reference-link", - "image", - "code", - "preformatted-text", - "code-block", - "table", - "datetime", - "emoji", - "html-entities", - "pagebreak", - "goto-line", - "|", - "help", - "info", - "||", - "preview", - "watch", - "fullscreen", - ], # custom edit box toolbar - # image upload format type - # 'upload_image_formats': ["jpg", "jpeg", "gif", "png", "bmp", "webp", "svg"], - # 'image_folder': 'editor', # image save the folder name - "theme": "default", # edit box theme, dark / default - "preview_theme": "default", # Preview area theme, dark / default - "editor_theme": "default", # edit area theme, pastel-on-dark / default - "toolbar_autofixed": False, # Whether the toolbar capitals - "search_replace": True, # Whether to open the search for replacement - "emoji": True, # whether to open the expression function - "tex": True, # whether to open the tex chart function - "flow_chart": True, # whether to open the flow chart function - "sequence": True, # Whether to open the sequence diagram function - "watch": True, # Live preview - "lineWrapping": True, # lineWrapping - "lineNumbers": True, # lineNumbers - "language": "en", # zh / en / es - } -} - -REST_FRAMEWORK = { - "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", - "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.NamespaceVersioning", - "DEFAULT_FILTER_BACKENDS": ("django_filters.rest_framework.DjangoFilterBackend",), - "DEFAULT_RENDERER_CLASSES": ( - "rest_framework.renderers.JSONRenderer", - "rest_framework.renderers.BrowsableAPIRenderer", - "rest_framework_datatables.renderers.DatatablesRenderer", - ), - "PAGE_SIZE": 30, - "DEFAULT_AUTHENTICATION_CLASSES": [ - "rest_framework.authentication.BasicAuthentication", - "rest_framework.authentication.SessionAuthentication", - "rest_framework.authentication.TokenAuthentication", - ], - "DEFAULT_PERMISSION_CLASSES": [ - "rest_framework.permissions.DjangoModelPermissions", - ], -} - -FRONT_DOOR_CONFIG = "front_door.conf.DjangoConstance" -FRONT_DOOR_ENABLED = env("FRONT_DOOR_ENABLED") -FRONT_DOOR_ALLOWED_PATHS = env("FRONT_DOOR_ALLOWED_PATHS") -FRONT_DOOR_TOKEN = env("FRONT_DOOR_TOKEN") -FRONT_DOOR_HEADER = "x-aurora" -FRONT_DOOR_COOKIE_NAME = "x-aurora" -FRONT_DOOR_COOKIE_PATTERN = ".*" -# FRONT_DOOR_ERROR_CODE = 404 -# FRONT_DOOR_REDIR_URL = "https://www.sosbob.com/" -FRONT_DOOR_LOG_LEVEL = env("FRONT_DOOR_LOG_LEVEL") # LOG_RULE_FAIL -FRONT_DOOR_RULES = [ - # "front_door.rules.internal_ip", # grant access to settings.INTERNAL_IPS - # "front_door.rules.forbidden_path", # DENY access to FORBIDDEN_PATHS - "front_door.rules.allowed_path", # grant access to ALLOWED_PATHS - "front_door.rules.allowed_ip", # grant access to ALLOWED_IPS - "front_door.rules.special_header", # grant access if request has Header[HEADER] == TOKEN - # "front_door.rules.has_header", # grant access if request has HEADER - "front_door.rules.cookie_value", # grant access if request.COOKIES[COOKIE_NAME] - # "front_door.rules.cookie_exists", # grant access ir COOKIE_NAME in request.COOKIES -] - -TRANSLATOR_SERVICE = env("TRANSLATOR_SERVICE") -AZURE_TRANSLATOR_KEY = env("AZURE_TRANSLATOR_KEY") -AZURE_TRANSLATOR_LOCATION = env("AZURE_TRANSLATOR_LOCATION") - -AZURE_CLIENT_ID = env("AZURE_CLIENT_ID") -AZURE_CLIENT_SECRET = env("AZURE_CLIENT_SECRET") - -MATOMO_SITE = env("MATOMO_SITE", default="https://unisitetracker.unicef.io/") -MATOMO_ID = env("MATOMO_ID", default="N/A") -ANYMAIL = { - "MAILJET_API_KEY": env("MAILJET_API_KEY"), - "MAILJET_SECRET_KEY": env("MAILJET_SECRET_KEY") -} +from .fragments import * # noqa diff --git a/src/dbtemplates/admin.py b/src/dbtemplates/admin.py index 9dfb0eb4..7f7bd3ca 100644 --- a/src/dbtemplates/admin.py +++ b/src/dbtemplates/admin.py @@ -1,26 +1,26 @@ import logging import posixpath -from admin_extra_buttons.decorators import button, view - -# Check if django-reversion is installed and use reversions' VersionAdmin -# as the base admin class if yes -from admin_sync.mixin import PublishMixin, SyncMixin -from adminfilters.mixin import AdminFiltersMixin -from adminfilters.value import ValueFilter from django import forms from django.contrib import admin from django.core.exceptions import ImproperlyConfigured from django.http import HttpResponse from django.shortcuts import render from django.utils.safestring import mark_safe -from django.utils.translation import gettext_lazy as _ -from django.utils.translation import ngettext +from django.utils.translation import gettext_lazy as _, ngettext from dbtemplates.conf import settings -from dbtemplates.models import Template, add_template_to_cache, remove_cached_template +from dbtemplates.models import add_template_to_cache, remove_cached_template, Template from dbtemplates.utils.template import check_template_syntax +from admin_extra_buttons.decorators import button, view + +# Check if django-reversion is installed and use reversions' VersionAdmin +# as the base admin class if yes +from admin_sync.mixin import PublishMixin, SyncMixin +from adminfilters.mixin import AdminFiltersMixin +from adminfilters.value import ValueFilter + if settings.DBTEMPLATES_USE_REVERSION: from reversion.admin import VersionAdmin as TemplateModelAdmin else: diff --git a/src/dbtemplates/conf.py b/src/dbtemplates/conf.py index 825678fb..9db392ea 100644 --- a/src/dbtemplates/conf.py +++ b/src/dbtemplates/conf.py @@ -1,9 +1,10 @@ import posixpath -from appconf import AppConf from django.conf import settings from django.core.exceptions import ImproperlyConfigured +from appconf import AppConf + class DbTemplatesConf(AppConf): USE_CODEMIRROR = False diff --git a/src/dbtemplates/loader.py b/src/dbtemplates/loader.py index 96e1b7b0..86255790 100644 --- a/src/dbtemplates/loader.py +++ b/src/dbtemplates/loader.py @@ -4,12 +4,7 @@ from django.template.loaders.base import Loader as BaseLoader from dbtemplates.models import Template -from dbtemplates.utils.cache import ( - cache, - get_cache_key, - get_cache_notfound_key, - set_and_return, -) +from dbtemplates.utils.cache import cache, get_cache_key, get_cache_notfound_key, set_and_return class Loader(BaseLoader): diff --git a/src/dbtemplates/models.py b/src/dbtemplates/models.py index f6dd3d10..b4c8ddb8 100644 --- a/src/dbtemplates/models.py +++ b/src/dbtemplates/models.py @@ -6,12 +6,13 @@ from django.template import TemplateDoesNotExist from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ -from natural_keys import NaturalKeyModel, NaturalKeyModelManager from dbtemplates.conf import settings from dbtemplates.utils.cache import add_template_to_cache, remove_cached_template from dbtemplates.utils.template import get_template_source +from natural_keys import NaturalKeyModel, NaturalKeyModelManager + class Template(NaturalKeyModel, models.Model): """ diff --git a/src/dbtemplates/test_cases.py b/src/dbtemplates/test_cases.py index 49605a38..d6da8341 100644 --- a/src/dbtemplates/test_cases.py +++ b/src/dbtemplates/test_cases.py @@ -7,14 +7,11 @@ from django.contrib.sites.models import Site from django.core.cache.backends.base import BaseCache from django.core.management import call_command -from django.template import TemplateDoesNotExist, loader +from django.template import loader, TemplateDoesNotExist from django.test import TestCase from dbtemplates.conf import settings -from dbtemplates.management.commands.sync_templates import ( - DATABASE_TO_FILES, - FILES_TO_DATABASE, -) +from dbtemplates.management.commands.sync_templates import DATABASE_TO_FILES, FILES_TO_DATABASE from dbtemplates.models import Template from dbtemplates.utils.cache import get_cache_backend, get_cache_key from dbtemplates.utils.template import check_template_syntax, get_template_source diff --git a/tests/browser/conftest.py b/tests/browser/conftest.py index 802fd3a1..59d2f801 100644 --- a/tests/browser/conftest.py +++ b/tests/browser/conftest.py @@ -2,6 +2,7 @@ from collections import namedtuple import pytest + from selenium.webdriver.common.by import By from testutils.utils import wait_for diff --git a/tests/browser/test_f_register.py b/tests/browser/test_f_register.py index 67f2a30c..23c7a90c 100644 --- a/tests/browser/test_f_register.py +++ b/tests/browser/test_f_register.py @@ -2,9 +2,11 @@ from pathlib import Path import pytest -from concurrency.api import disable_concurrency + from django.core.management import call_command from django.utils import translation + +from concurrency.api import disable_concurrency from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.select import Select diff --git a/tests/conftest.py b/tests/conftest.py index 7544a382..707f5a8f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ import os import pytest + from django import forms from django.core.files.storage import get_storage_class diff --git a/tests/extras/testutils/factories.py b/tests/extras/testutils/factories.py index 6ce0cedc..29cb4e6e 100644 --- a/tests/extras/testutils/factories.py +++ b/tests/extras/testutils/factories.py @@ -1,14 +1,16 @@ -import factory.fuzzy from django import forms from django.contrib.admin.models import LogEntry from django.contrib.auth.models import Group, User from django.utils import timezone + +import dbtemplates.models as dbtemplates + +import factory.fuzzy from factory.base import FactoryMetaClass from rest_framework.authtoken.models import TokenProxy from social_django.models import Association, Nonce, UserSocialAuth from strategy_field.utils import fqn -import dbtemplates.models as dbtemplates from aurora.core.models import ( CustomFieldType, FlexForm, diff --git a/tests/extras/testutils/perms.py b/tests/extras/testutils/perms.py index 06fd065d..3a972839 100644 --- a/tests/extras/testutils/perms.py +++ b/tests/extras/testutils/perms.py @@ -2,6 +2,7 @@ from random import choice from django.contrib.auth.models import Permission + from faker import Faker from aurora.core.models import Organization diff --git a/tests/test_admin.py b/tests/test_admin.py index 0df57c1b..30467b3b 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -1,14 +1,16 @@ from typing import List -from unittest.mock import Mock import pytest -from _pytest.mark import Mark -from _pytest.python import Metafunc -from admin_extra_buttons.handlers import ChoiceHandler +from unittest.mock import Mock + from django.contrib.admin.sites import site from django.contrib.admin.templatetags.admin_urls import admin_urlname from django.db.models.options import Options from django.urls import reverse + +from _pytest.mark import Mark +from _pytest.python import Metafunc +from admin_extra_buttons.handlers import ChoiceHandler from django_regex.utils import RegexList as _RegexList diff --git a/tests/test_api.py b/tests/test_api.py index 36433f33..6b2676fb 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -2,9 +2,11 @@ import time import pytest -from Crypto.PublicKey import RSA + from django.urls import reverse +from Crypto.PublicKey import RSA + from aurora.core.crypto import decrypt PUBLIC = b"""-----BEGIN PUBLIC KEY----- diff --git a/tests/test_crypt.py b/tests/test_crypt.py index dd65a785..8d11bbf0 100644 --- a/tests/test_crypt.py +++ b/tests/test_crypt.py @@ -1,9 +1,10 @@ import json import pytest + from Crypto.PublicKey import RSA -from aurora.core.crypto import RSACrypto, crypt, decrypt +from aurora.core.crypto import crypt, decrypt, RSACrypto LANGUAGES = { "english": "first", diff --git a/tests/test_custom.py b/tests/test_custom.py index f725a9dc..3124f153 100644 --- a/tests/test_custom.py +++ b/tests/test_custom.py @@ -1,4 +1,5 @@ import pytest + from django import forms from aurora.core.models import CustomFieldType diff --git a/tests/test_i18n.py b/tests/test_i18n.py index 4ab6f548..fb5d6b7f 100644 --- a/tests/test_i18n.py +++ b/tests/test_i18n.py @@ -1,4 +1,5 @@ import pytest + from django.urls import reverse diff --git a/tests/test_panels.py b/tests/test_panels.py index 3fcac387..f90b5231 100644 --- a/tests/test_panels.py +++ b/tests/test_panels.py @@ -1,4 +1,5 @@ import pytest + from django.contrib.admin.sites import site from django.urls import reverse diff --git a/tests/test_security.py b/tests/test_security.py index 3a36dc77..cb0a2851 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -1,4 +1,5 @@ import pytest + from testutils.perms import user_grant_permissions from aurora.registration.models import Registration diff --git a/tests/test_sync.py b/tests/test_sync.py index f866db3b..a4c0c8ce 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -3,6 +3,7 @@ from pathlib import Path import pytest + from django.core.management import call_command diff --git a/tests/test_utils.py b/tests/test_utils.py index 0ee07250..8aeaf055 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,16 +1,10 @@ import base64 import pytest + from django.core.files.uploadedfile import SimpleUploadedFile -from aurora.core.utils import ( - apply_nested, - extract_content, - flatten_dict, - merge_data, - namify, - underscore_to_camelcase, -) +from aurora.core.utils import apply_nested, extract_content, flatten_dict, merge_data, namify, underscore_to_camelcase from aurora.registration.storage import Router diff --git a/tests/test_validators.py b/tests/test_validators.py index eccb77dd..37f214b2 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -1,6 +1,6 @@ +import pytest from unittest.mock import Mock -import pytest from django.core.exceptions import ValidationError from aurora.core.models import Validator diff --git a/tests/test_views.py b/tests/test_views.py index efee6fe3..b7acc3b2 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,9 +1,10 @@ import base64 import json from pathlib import Path -from unittest.mock import Mock import pytest +from unittest.mock import Mock + from webtest import Upload LANGUAGES = {