From e124a81d58150a94ab083295edd5d7917a136432 Mon Sep 17 00:00:00 2001 From: amir Date: Thu, 17 Jul 2025 17:56:56 +0200 Subject: [PATCH 1/4] addec django configurations --- hydroserver/asgi.py | 5 +- hydroserver/settings.py | 584 +++++++++++++++++++++------------------- hydroserver/wsgi.py | 6 +- manage.py | 6 +- requirements.txt | 1 + 5 files changed, 321 insertions(+), 281 deletions(-) diff --git a/hydroserver/asgi.py b/hydroserver/asgi.py index f3475495..a36a921d 100644 --- a/hydroserver/asgi.py +++ b/hydroserver/asgi.py @@ -9,8 +9,9 @@ import os -from django.core.asgi import get_asgi_application +# from django.core.asgi import get_asgi_application +from configurations.asgi import get_asgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hydroserver.settings") - +os.environ.setdefault("DJANGO_CONFIGURATION", os.getenv("SERVER_ENVIRONMENT", "Base")) application = get_asgi_application() diff --git a/hydroserver/settings.py b/hydroserver/settings.py index 2e4c60a2..54fdb82f 100644 --- a/hydroserver/settings.py +++ b/hydroserver/settings.py @@ -8,321 +8,353 @@ from corsheaders.defaults import default_headers from decouple import config from urllib.parse import urlparse +from configurations import Configuration - -# Build paths inside the project like this: BASE_DIR / "subdir". BASE_DIR = Path(__file__).resolve().parent.parent -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = config( - "SECRET_KEY", - default="django-insecure-zw@4h#ol@0)5fxy=ib6(t&7o4ot9mzvli*d-wd=81kjxqc!5w4", -) - -# SECURITY WARNING: don"t run with debug turned on in production! -DEBUG = config("DEBUG", default=True, cast=bool) -DEPLOYMENT_BACKEND = config("DEPLOYMENT_BACKEND", default="local") - - -# Default Superuser Settings -DEFAULT_SUPERUSER_EMAIL = config( - "DEFAULT_SUPERUSER_EMAIL", default="admin@hydroserver.org" -) -DEFAULT_SUPERUSER_PASSWORD = config("DEFAULT_SUPERUSER_PASSWORD", default="pass") - -# Deployment Settings - -USE_X_FORWARDED_HOST = True -PROXY_BASE_URL = config("PROXY_BASE_URL", "http://localhost") - -hostname = socket.gethostname() -local_ip = socket.gethostbyname(hostname) - -ALLOWED_HOSTS = config("ALLOWED_HOSTS", default=urlparse(PROXY_BASE_URL).netloc).split( - "," -) + [local_ip] - -CORS_ORIGIN_ALLOW_ALL = True -CORS_ALLOW_CREDENTIALS = False -CSRF_TRUSTED_ORIGINS = [PROXY_BASE_URL] - - -# Application definition - -AUTHENTICATION_BACKENDS = [ - "django.contrib.auth.backends.ModelBackend", - "allauth.account.auth_backends.AuthenticationBackend", -] - -INSTALLED_APPS = [ - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.messages", - "django.contrib.staticfiles", - "django.contrib.sites", - "allauth", - "allauth.account", - "allauth.headless", - "allauth.socialaccount", - "allauth.socialaccount.providers.google", - "allauth.socialaccount.providers.orcid", - "allauth.socialaccount.providers.openid_connect", - "iam.auth.providers.hydroshare", - "iam.auth.providers.orcidsandbox", - "corsheaders", - "easyaudit", - "sensorthings", - "storages", - "iam.apps.IamConfig", - "sta.apps.StaConfig", - "etl.apps.EtlConfig", - "django.contrib.admin", -] - -MIDDLEWARE = [ - "django.middleware.security.SecurityMiddleware", - "django.contrib.sessions.middleware.SessionMiddleware", - "corsheaders.middleware.CorsMiddleware", - "hydroserver.middleware.CloudHealthCheckMiddleware", - "django.middleware.common.CommonMiddleware", - "django.middleware.csrf.CsrfViewMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", - "django.contrib.messages.middleware.MessageMiddleware", - "django.middleware.clickjacking.XFrameOptionsMiddleware", - "allauth.account.middleware.AccountMiddleware", - "easyaudit.middleware.easyaudit.EasyAuditMiddleware", - "sensorthings.middleware.SensorThingsMiddleware", -] - -ROOT_URLCONF = "hydroserver.urls" - -TEMPLATES = [ - { - "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [BASE_DIR / "templates"], - "APP_DIRS": True, - "OPTIONS": { - "context_processors": [ - "django.template.context_processors.debug", - "django.template.context_processors.request", - "django.contrib.auth.context_processors.auth", - "django.contrib.messages.context_processors.messages", - ], - }, - }, -] - -WSGI_APPLICATION = "hydroserver.wsgi.application" - - -# Database -# https://docs.djangoproject.com/en/4.1/ref/settings/#databases - -os.environ["DATABASE_URL"] = config( - "DATABASE_URL", default=f"postgresql://hsdbadmin:admin@localhost:5432/hydroserver" -) - -dj_database_config = dj_database_url.config( - engine="django.db.backends.postgresql", - conn_health_checks=config("CONN_HEALTH_CHECKS", default=True, cast=bool), - ssl_require=config("SSL_REQUIRED", default=False, cast=bool), -) - -DATABASES = { - "default": { - **dj_database_config, - "OPTIONS": { - "application_name": "HydroServer", - "pool": { - "min_size": config("DB_POOL_MIN_SIZE", default=5, cast=int), - "max_size": config("DB_POOL_MAX_SIZE", default=10, cast=int), - "timeout": config("DB_POOL_TIMEOUT", default=60, cast=int), +class Base(Configuration): + # Build paths inside the project like this: BASE_DIR / "subdir". + + # SECURITY WARNING: keep the secret key used in production secret! + SECRET_KEY = config( + "SECRET_KEY", + default="django-insecure-zw@4h#ol@0)5fxy=ib6(t&7o4ot9mzvli*d-wd=81kjxqc!5w4", + ) + + # SECURITY WARNING: don"t run with debug turned on in production! + DEBUG = config("DEBUG", default=True, cast=bool) + DEPLOYMENT_BACKEND = config("DEPLOYMENT_BACKEND", default="local") + + # Default Superuser Settings + DEFAULT_SUPERUSER_EMAIL = config( + "DEFAULT_SUPERUSER_EMAIL", default="admin@hydroserver.org" + ) + DEFAULT_SUPERUSER_PASSWORD = config("DEFAULT_SUPERUSER_PASSWORD", default="pass") + + # Deployment Settings + + USE_X_FORWARDED_HOST = True + PROXY_BASE_URL = config("PROXY_BASE_URL", "http://localhost") + + hostname = socket.gethostname() + local_ip = socket.gethostbyname(hostname) + + ALLOWED_HOSTS = config( + "ALLOWED_HOSTS", default=urlparse(PROXY_BASE_URL).netloc + ).split(",") + [local_ip] + + CORS_ORIGIN_ALLOW_ALL = True + CORS_ALLOW_CREDENTIALS = False + CSRF_TRUSTED_ORIGINS = [PROXY_BASE_URL] + + # Application definition + + AUTHENTICATION_BACKENDS = [ + "django.contrib.auth.backends.ModelBackend", + "allauth.account.auth_backends.AuthenticationBackend", + ] + + INSTALLED_APPS = [ + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.sites", + "allauth", + "allauth.account", + "allauth.headless", + "allauth.socialaccount", + "allauth.socialaccount.providers.google", + "allauth.socialaccount.providers.orcid", + "allauth.socialaccount.providers.openid_connect", + "iam.auth.providers.hydroshare", + "iam.auth.providers.orcidsandbox", + "corsheaders", + "easyaudit", + "sensorthings", + "storages", + "iam.apps.IamConfig", + "sta.apps.StaConfig", + "etl.apps.EtlConfig", + "django.contrib.admin", + ] + + MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "corsheaders.middleware.CorsMiddleware", + "hydroserver.middleware.CloudHealthCheckMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "allauth.account.middleware.AccountMiddleware", + "easyaudit.middleware.easyaudit.EasyAuditMiddleware", + "sensorthings.middleware.SensorThingsMiddleware", + ] + + ROOT_URLCONF = "hydroserver.urls" + + TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [BASE_DIR / "templates"], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], }, - **dj_database_config.get("OPTIONS", {}), }, - } -} - - -# Site and Session Settings + ] -SITE_ID = 1 + WSGI_APPLICATION = "hydroserver.wsgi.application" -SESSION_COOKIE_NAME = "hs_session" -SESSION_COOKIE_AGE = 86400 -SESSION_EXPIRE_AT_BROWSER_CLOSE = False + # Database + # https://docs.djangoproject.com/en/4.1/ref/settings/#databases + os.environ["DATABASE_URL"] = config( + "DATABASE_URL", + default=f"postgresql://hsdbadmin:admin@localhost:5432/hydroserver", + ) -# Account and Access Control Settings + dj_database_config = dj_database_url.config( + engine="django.db.backends.postgresql", + conn_health_checks=config("CONN_HEALTH_CHECKS", default=True, cast=bool), + ssl_require=config("SSL_REQUIRED", default=False, cast=bool), + ) -AUTH_USER_MODEL = "iam.User" - -ACCOUNT_SIGNUP_ENABLED = config("ACCOUNT_SIGNUP_ENABLED", default=True, cast=bool) -ACCOUNT_OWNERSHIP_ENABLED = config("ACCOUNT_OWNERSHIP_ENABLED", default=True, cast=bool) - -ACCOUNT_USER_MODEL_USERNAME_FIELD = None -ACCOUNT_USERNAME_REQUIRED = False -ACCOUNT_LOGIN_METHODS = {"email"} -ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED = True -ACCOUNT_EMAIL_REQUIRED = True -ACCOUNT_EMAIL_VERIFICATION = "mandatory" -ACCOUNT_SIGNUP_FORM_CLASS = "iam.auth.forms.UserSignupForm" -ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https" if DEPLOYMENT_BACKEND != "local" else "http" - -ACCOUNT_ADAPTER = "iam.auth.adapters.AccountAdapter" -HEADLESS_ONLY = True + DATABASES = { + "default": { + **dj_database_config, + "OPTIONS": { + "application_name": "HydroServer", + "pool": { + "min_size": config("DB_POOL_MIN_SIZE", default=5, cast=int), + "max_size": config("DB_POOL_MAX_SIZE", default=10, cast=int), + "timeout": config("DB_POOL_TIMEOUT", default=60, cast=int), + }, + **dj_database_config.get("OPTIONS", {}), + }, + } + } -HEADLESS_FRONTEND_URLS = { - "account_confirm_email": f"{PROXY_BASE_URL}/verify-email/{{key}}", - "account_reset_password_from_key": f"{PROXY_BASE_URL}/reset-password/{{key}}", - "account_reset_password": f"{PROXY_BASE_URL}/reset-password", - "account_signup": f"{PROXY_BASE_URL}/sign-up", -} + # Site and Session Settings + SITE_ID = 1 -# Social Account Settings + SESSION_COOKIE_NAME = "hs_session" + SESSION_COOKIE_AGE = 86400 + SESSION_EXPIRE_AT_BROWSER_CLOSE = False -SOCIALACCOUNT_SIGNUP_ONLY = config( - "SOCIALACCOUNT_SIGNUP_ONLY", default=False, cast=bool -) -SOCIALACCOUNT_EMAIL_AUTHENTICATION = True -SOCIALACCOUNT_EMAIL_VERIFICATION = "mandatory" -SOCIALACCOUNT_EMAIL_REQUIRED = True -SOCIALACCOUNT_QUERY_EMAIL = True -SOCIALACCOUNT_AUTO_SIGNUP = False -SOCIALACCOUNT_STORE_TOKENS = True + # Account and Access Control Settings + AUTH_USER_MODEL = "iam.User" -# Email Settings + ACCOUNT_SIGNUP_ENABLED = config("ACCOUNT_SIGNUP_ENABLED", default=True, cast=bool) + ACCOUNT_OWNERSHIP_ENABLED = config( + "ACCOUNT_OWNERSHIP_ENABLED", default=True, cast=bool + ) -EMAIL_CONFIG = dj_email_url.parse(config("SMTP_URL", default="smtp://127.0.0.1:1025")) + ACCOUNT_USER_MODEL_USERNAME_FIELD = None + ACCOUNT_USERNAME_REQUIRED = False + ACCOUNT_LOGIN_METHODS = {"email"} + ACCOUNT_EMAIL_VERIFICATION_BY_CODE_ENABLED = True + ACCOUNT_EMAIL_REQUIRED = True + ACCOUNT_EMAIL_VERIFICATION = "mandatory" + ACCOUNT_SIGNUP_FORM_CLASS = "iam.auth.forms.UserSignupForm" + ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https" if DEPLOYMENT_BACKEND != "local" else "http" -DEFAULT_FROM_EMAIL = config("DEFAULT_FROM_EMAIL", default="webmaster@localhost") -EMAIL_BACKEND = EMAIL_CONFIG["EMAIL_BACKEND"] -EMAIL_HOST = EMAIL_CONFIG["EMAIL_HOST"] -EMAIL_PORT = EMAIL_CONFIG["EMAIL_PORT"] -EMAIL_HOST_USER = EMAIL_CONFIG["EMAIL_HOST_USER"] -EMAIL_HOST_PASSWORD = EMAIL_CONFIG["EMAIL_HOST_PASSWORD"] -EMAIL_USE_TLS = EMAIL_CONFIG["EMAIL_USE_TLS"] -EMAIL_USE_SSL = EMAIL_CONFIG["EMAIL_USE_SSL"] + ACCOUNT_ADAPTER = "iam.auth.adapters.AccountAdapter" + HEADLESS_ONLY = True + HEADLESS_FRONTEND_URLS = { + "account_confirm_email": f"{PROXY_BASE_URL}/verify-email/{{key}}", + "account_reset_password_from_key": f"{PROXY_BASE_URL}/reset-password/{{key}}", + "account_reset_password": f"{PROXY_BASE_URL}/reset-password", + "account_signup": f"{PROXY_BASE_URL}/sign-up", + } -# Audit Settings + # Social Account Settings -ENABLE_AUDITS = config("ENABLE_AUDITS", default=False, cast=bool) + SOCIALACCOUNT_SIGNUP_ONLY = config( + "SOCIALACCOUNT_SIGNUP_ONLY", default=False, cast=bool + ) + SOCIALACCOUNT_EMAIL_AUTHENTICATION = True + SOCIALACCOUNT_EMAIL_VERIFICATION = "mandatory" + SOCIALACCOUNT_EMAIL_REQUIRED = True + SOCIALACCOUNT_QUERY_EMAIL = True + SOCIALACCOUNT_AUTO_SIGNUP = False + SOCIALACCOUNT_STORE_TOKENS = True -DJANGO_EASY_AUDIT_WATCH_MODEL_EVENTS = ENABLE_AUDITS -DJANGO_EASY_AUDIT_WATCH_AUTH_EVENTS = False -DJANGO_EASY_AUDIT_WATCH_REQUEST_EVENTS = False + # Email Settings -DJANGO_EASY_AUDIT_ADMIN_SHOW_MODEL_EVENTS = ENABLE_AUDITS -DJANGO_EASY_AUDIT_ADMIN_SHOW_AUTH_EVENTS = False -DJANGO_EASY_AUDIT_ADMIN_SHOW_REQUEST_EVENTS = False + EMAIL_CONFIG = dj_email_url.parse( + config("SMTP_URL", default="smtp://127.0.0.1:1025") + ) -DJANGO_EASY_AUDIT_UNREGISTERED_CLASSES_EXTRA = ["sta.Observation"] + DEFAULT_FROM_EMAIL = config("DEFAULT_FROM_EMAIL", default="webmaster@localhost") + EMAIL_BACKEND = EMAIL_CONFIG["EMAIL_BACKEND"] + EMAIL_HOST = EMAIL_CONFIG["EMAIL_HOST"] + EMAIL_PORT = EMAIL_CONFIG["EMAIL_PORT"] + EMAIL_HOST_USER = EMAIL_CONFIG["EMAIL_HOST_USER"] + EMAIL_HOST_PASSWORD = EMAIL_CONFIG["EMAIL_HOST_PASSWORD"] + EMAIL_USE_TLS = EMAIL_CONFIG["EMAIL_USE_TLS"] + EMAIL_USE_SSL = EMAIL_CONFIG["EMAIL_USE_SSL"] + # Audit Settings -# Password validation -# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + ENABLE_AUDITS = config("ENABLE_AUDITS", default=False, cast=bool) -AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", - }, -] + DJANGO_EASY_AUDIT_WATCH_MODEL_EVENTS = ENABLE_AUDITS + DJANGO_EASY_AUDIT_WATCH_AUTH_EVENTS = False + DJANGO_EASY_AUDIT_WATCH_REQUEST_EVENTS = False + DJANGO_EASY_AUDIT_ADMIN_SHOW_MODEL_EVENTS = ENABLE_AUDITS + DJANGO_EASY_AUDIT_ADMIN_SHOW_AUTH_EVENTS = False + DJANGO_EASY_AUDIT_ADMIN_SHOW_REQUEST_EVENTS = False -# Storage settings + DJANGO_EASY_AUDIT_UNREGISTERED_CLASSES_EXTRA = ["sta.Observation"] -APP_CLIENT_URL = config("APP_CLIENT_URL", default=PROXY_BASE_URL) -STATIC_URL = "/static/" -MEDIA_URL = "/media/" -SECURE_CROSS_ORIGIN_OPENER_POLICY = None + # Password validation + # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators -if DEPLOYMENT_BACKEND == "aws": - AWS_S3_CUSTOM_DOMAIN = urlparse(PROXY_BASE_URL).hostname - AWS_CLOUDFRONT_KEY = config("AWS_CLOUDFRONT_KEY", default="").encode("ascii") - AWS_CLOUDFRONT_KEY_ID = config("AWS_CLOUDFRONT_KEY_ID", default=None) - STORAGES = { - "default": { - "BACKEND": "storages.backends.s3.S3Storage", - "OPTIONS": { - "bucket_name": config("MEDIA_BUCKET_NAME", default=None), - "location": "media", - "default_acl": "private", - }, + AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, - "staticfiles": { - "BACKEND": "storages.backends.s3boto3.S3StaticStorage", - "OPTIONS": { - "bucket_name": config("STATIC_BUCKET_NAME", default=None), - "location": "static", - "default_acl": None, - }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, - } -elif DEPLOYMENT_BACKEND == "gcp": - GS_PROJECT_ID = config("GS_PROJECT_ID", default=None) - GS_CUSTOM_ENDPOINT = PROXY_BASE_URL - STORAGES = { - "default": { - "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", - "OPTIONS": { - "bucket_name": config("MEDIA_BUCKET_NAME", default=None), - "location": "media", - "default_acl": "publicRead", - }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, - "staticfiles": { - "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", - "OPTIONS": { - "bucket_name": config("STATIC_BUCKET_NAME", default=None), - "location": "static", - "default_acl": "publicRead", - }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, - } -else: - STORAGES = { + ] + + # Storage settings + + APP_CLIENT_URL = config("APP_CLIENT_URL", default=PROXY_BASE_URL) + STATIC_URL = "/static/" + MEDIA_URL = "/media/" + SECURE_CROSS_ORIGIN_OPENER_POLICY = None + + if DEPLOYMENT_BACKEND == "aws": + AWS_S3_CUSTOM_DOMAIN = urlparse(PROXY_BASE_URL).hostname + AWS_CLOUDFRONT_KEY = config("AWS_CLOUDFRONT_KEY", default="").encode("ascii") + AWS_CLOUDFRONT_KEY_ID = config("AWS_CLOUDFRONT_KEY_ID", default=None) + STORAGES = { + "default": { + "BACKEND": "storages.backends.s3.S3Storage", + "OPTIONS": { + "bucket_name": config("MEDIA_BUCKET_NAME", default=None), + "location": "media", + "default_acl": "private", + }, + }, + "staticfiles": { + "BACKEND": "storages.backends.s3boto3.S3StaticStorage", + "OPTIONS": { + "bucket_name": config("STATIC_BUCKET_NAME", default=None), + "location": "static", + "default_acl": None, + }, + }, + } + elif DEPLOYMENT_BACKEND == "gcp": + GS_PROJECT_ID = config("GS_PROJECT_ID", default=None) + GS_CUSTOM_ENDPOINT = PROXY_BASE_URL + STORAGES = { + "default": { + "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", + "OPTIONS": { + "bucket_name": config("MEDIA_BUCKET_NAME", default=None), + "location": "media", + "default_acl": "publicRead", + }, + }, + "staticfiles": { + "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", + "OPTIONS": { + "bucket_name": config("STATIC_BUCKET_NAME", default=None), + "location": "static", + "default_acl": "publicRead", + }, + }, + } + else: + STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + "OPTIONS": {"location": "media"}, + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + "OPTIONS": {"location": "static"}, + }, + } + + # Internationalization + # https://docs.djangoproject.com/en/4.1/topics/i18n/ + + LANGUAGE_CODE = "en-us" + TIME_ZONE = "UTC" + USE_I18N = True + USE_TZ = True + + # Default primary key field type + # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + + DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + + # SensorThings Configuration + + ST_API_PREFIX = "api/sensorthings" + ST_API_ID_QUALIFIER = "'" + ST_API_ID_TYPE: UUID + + +class Minio(Base): + # microk8s cluster dependency minio + MINIO_CONSISTENCY_CHECK_ON_START = False + MINIO_USE_HTTPS = False + MINIO_EXTERNAL_ENDPOINT_USE_HTTPS = False + MINIO_ENDPOINT = "minio.minio-operator.svc.cluster.local" + MINIO_EXTERNAL_ENDPOINT = "localhost:9000" + MINIO_ACCESS_KEY = "NdC3ZRAtzM49PU2P7NZ9" + MINIO_SECRET_KEY = "qxDy3X16uDT3MgZxTqrdgKjliGVmjX2VVrGM9q4t" + INSTALLED_APPS = Base.INSTALLED_APPS + ["django_minio_backend", "api"] + MINIO_PUBLIC_BUCKETS = ["backend", "media", "static"] + MINIO_STATIC_FILES_BUCKET = "static" + MINIO_MEDIA_FILES_BUCKET = "media" + # todo + STORAGES = { # -- ADDED IN Django 5.1 "default": { - "BACKEND": "django.core.files.storage.FileSystemStorage", - "OPTIONS": {"location": "media"}, + "BACKEND": "django_minio_backend.models.MinioBackend", }, - "staticfiles": { - "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", - "OPTIONS": {"location": "static"}, + "staticfiles": { # -- OPTIONAL + # "BACKEND": "django_minio_backend.models.MinioBackendStatic", + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage" }, } -# Internationalization -# https://docs.djangoproject.com/en/4.1/topics/i18n/ - -LANGUAGE_CODE = "en-us" -TIME_ZONE = "UTC" -USE_I18N = True -USE_TZ = True - - -# Default primary key field type -# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field - -DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" - - -# SensorThings Configuration - -ST_API_PREFIX = "api/sensorthings" -ST_API_ID_QUALIFIER = "'" -ST_API_ID_TYPE = UUID +class Postgres(Minio): + DATABASES = { + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": config("POSTGRES_WQDMS_DB", "hydroserver"), + "USER": config("POSTGRES_WQDMS_USER", "postgres"), + "PASSWORD": config("POSTGRES_WQDMS_PASSWORD", "admin1234"), + "HOST": config("POSTGRES_WQDMS_HOST", "ge-postgres.dev.svc.cluster.local"), + "PORT": config("POSTGRES_WQDMS_PORT", "5432"), + } + } diff --git a/hydroserver/wsgi.py b/hydroserver/wsgi.py index 6e4a6029..5527866a 100644 --- a/hydroserver/wsgi.py +++ b/hydroserver/wsgi.py @@ -9,12 +9,14 @@ import os -from django.core.wsgi import get_wsgi_application +# from django.core.wsgi import get_wsgi_application +from configurations.wsgi import get_wsgi_application from django.core.management import call_command from django.db import connection -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hydroserver.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hydroserver.settings") +os.environ.setdefault("DJANGO_CONFIGURATION", os.getenv("SERVER_ENVIRONMENT", "Base")) application = get_wsgi_application() diff --git a/manage.py b/manage.py index 3518cd44..ea82d533 100755 --- a/manage.py +++ b/manage.py @@ -7,8 +7,12 @@ def main(): """Run administrative tasks.""" os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hydroserver.settings") + os.environ.setdefault( + "DJANGO_CONFIGURATION", os.getenv("SERVER_ENVIRONMENT", "Base") + ) try: - from django.core.management import execute_from_command_line + # from django.core.management import execute_from_command_line + from configurations.management import execute_from_command_line except ImportError as exc: raise ImportError( "Couldn't import Django. Are you sure it's installed and " diff --git a/requirements.txt b/requirements.txt index f0066422..636c6b3e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,3 +23,4 @@ country-list==1.1.0 hsclient==1.1.6 boto3==1.36.15 google-cloud-storage==3.0.0 +django-configurations From f55298bf5d597e480e347652a0e3730dbc6e12f0 Mon Sep 17 00:00:00 2001 From: amir Date: Thu, 17 Jul 2025 18:03:03 +0200 Subject: [PATCH 2/4] added minio dependencies --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 636c6b3e..e7439af6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,3 +24,5 @@ hsclient==1.1.6 boto3==1.36.15 google-cloud-storage==3.0.0 django-configurations +django-minio-backend +minio From 61870d90db1e0ec0b0726fc37d4e13cd5c19f1c8 Mon Sep 17 00:00:00 2001 From: amir Date: Thu, 17 Jul 2025 18:34:35 +0200 Subject: [PATCH 3/4] developer settings with sqlite3 --- hydroserver/settings.py | 64 ++++++++++++++++++++--------------------- hydroserver/wsgi.py | 15 ++++++++-- requirements.txt | 3 +- 3 files changed, 45 insertions(+), 37 deletions(-) diff --git a/hydroserver/settings.py b/hydroserver/settings.py index 54fdb82f..5ec35331 100644 --- a/hydroserver/settings.py +++ b/hydroserver/settings.py @@ -9,6 +9,7 @@ from decouple import config from urllib.parse import urlparse from configurations import Configuration +from django.core.management import call_command BASE_DIR = Path(__file__).resolve().parent.parent @@ -322,39 +323,38 @@ class Base(Configuration): ST_API_ID_TYPE: UUID -class Minio(Base): - # microk8s cluster dependency minio - MINIO_CONSISTENCY_CHECK_ON_START = False - MINIO_USE_HTTPS = False - MINIO_EXTERNAL_ENDPOINT_USE_HTTPS = False - MINIO_ENDPOINT = "minio.minio-operator.svc.cluster.local" - MINIO_EXTERNAL_ENDPOINT = "localhost:9000" - MINIO_ACCESS_KEY = "NdC3ZRAtzM49PU2P7NZ9" - MINIO_SECRET_KEY = "qxDy3X16uDT3MgZxTqrdgKjliGVmjX2VVrGM9q4t" - INSTALLED_APPS = Base.INSTALLED_APPS + ["django_minio_backend", "api"] - MINIO_PUBLIC_BUCKETS = ["backend", "media", "static"] - MINIO_STATIC_FILES_BUCKET = "static" - MINIO_MEDIA_FILES_BUCKET = "media" - # todo - STORAGES = { # -- ADDED IN Django 5.1 - "default": { - "BACKEND": "django_minio_backend.models.MinioBackend", - }, - "staticfiles": { # -- OPTIONAL - # "BACKEND": "django_minio_backend.models.MinioBackendStatic", - "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage" - }, - } - - -class Postgres(Minio): +class Development(Base): + # Default Superuser Settings + ALLOWED_HOSTS = ["*"] DATABASES = { "default": { - "ENGINE": "django.db.backends.postgresql", - "NAME": config("POSTGRES_WQDMS_DB", "hydroserver"), - "USER": config("POSTGRES_WQDMS_USER", "postgres"), - "PASSWORD": config("POSTGRES_WQDMS_PASSWORD", "admin1234"), - "HOST": config("POSTGRES_WQDMS_HOST", "ge-postgres.dev.svc.cluster.local"), - "PORT": config("POSTGRES_WQDMS_PORT", "5432"), + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", } } + # dev apps + INSTALLED_APPS = [ + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.sites", + "allauth", + "allauth.account", + "allauth.headless", + "allauth.socialaccount", + # "allauth.socialaccount.providers.google", + # "allauth.socialaccount.providers.orcid", + # "allauth.socialaccount.providers.openid_connect", + "iam.auth.providers.hydroshare", + "iam.auth.providers.orcidsandbox", + "corsheaders", + "easyaudit", + "sensorthings", + "storages", + "iam.apps.IamConfig", + "sta.apps.StaConfig", + "etl.apps.EtlConfig", + "django.contrib.admin", + ] diff --git a/hydroserver/wsgi.py b/hydroserver/wsgi.py index 5527866a..da75d30e 100644 --- a/hydroserver/wsgi.py +++ b/hydroserver/wsgi.py @@ -21,11 +21,20 @@ def is_leader(): - with connection.cursor() as cursor: - cursor.execute("SELECT pg_try_advisory_lock(%s);", [1]) - return cursor.fetchone()[0] + try: + with connection.cursor() as cursor: + cursor.execute("SELECT pg_try_advisory_lock(%s);", [1]) + return cursor.fetchone()[0] + except Exception as e: + print(e) + return False +if os.getenv("DJANGO_CONFIGURATION") in ["Development"]: + call_command("makemigrations") + call_command("migrate") + call_command("setup_admin_user") + if is_leader(): call_command("migrate") call_command("setup_admin_user") diff --git a/requirements.txt b/requirements.txt index e7439af6..6212ed13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,5 +24,4 @@ hsclient==1.1.6 boto3==1.36.15 google-cloud-storage==3.0.0 django-configurations -django-minio-backend -minio + From ff2a707bffd00107b37f1c7a768699c1f0c2c04f Mon Sep 17 00:00:00 2001 From: amir Date: Thu, 17 Jul 2025 19:13:25 +0200 Subject: [PATCH 4/4] review: base path settings --- hydroserver/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hydroserver/settings.py b/hydroserver/settings.py index 5ec35331..f7622b83 100644 --- a/hydroserver/settings.py +++ b/hydroserver/settings.py @@ -16,7 +16,7 @@ class Base(Configuration): # Build paths inside the project like this: BASE_DIR / "subdir". - + BASE_DIR = BASE_DIR # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = config( "SECRET_KEY",