""" Django settings for Rasaddam_Backend project. Generated by 'django-admin startproject' using Django 5.2. For more information on this file, see https://docs.djangoproject.com/en/5.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/5.2/ref/settings/ """ import os.path from datetime import timedelta from pathlib import Path import os from dotenv import load_dotenv from django.conf import settings # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ if not os.getenv("RUNNING_IN_DOCKER"): dotenv_path = BASE_DIR / ".env.local" load_dotenv(dotenv_path) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get("SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! DEBUG = bool(os.environ.get("DEBUG", default=0)) ASGI_APPLICATION = "Rasaddam_Backend.asgi.application" # noqa ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS").split(",") # Application definition INSTALLED_APPS = [ 'jazzmin', # noqa 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_elasticsearch_dsl', 'django_elasticsearch_dsl_drf', 'rest_framework', "corsheaders", 'rest_framework_simplejwt', 'rest_framework_simplejwt.token_blacklist', 'apps.authentication.apps.AuthenticationConfig', 'apps.authorization.apps.AuthorizationConfig', 'apps.captcha_app.apps.CaptchaAppConfig', 'apps.core.apps.CoreConfig', 'apps.herd.apps.HerdAppConfig', 'apps.livestock.apps.LivestockConfig', 'apps.pos_device.apps.PosDeviceConfig', 'apps.tag.apps.TagConfig', 'apps.warehouse.apps.WarehouseConfig', 'apps.search.apps.SearchConfig', 'apps.log.apps.LogConfig', 'apps.product.apps.ProductConfig', 'apps.notification.apps.NotificationConfig', 'rest_captcha', 'captcha', 'drf_yasg', "django_celery_results", "django_celery_beat", # "elasticapm.contrib.django", ] MIDDLEWARE = [ # 'elasticapm.contrib.django.middleware.TracingMiddleware', 'apps.core.middlewares.Json500Middleware', 'corsheaders.middleware.CorsMiddleware', # noqa 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'apps.authentication.middlewares.BlockedTokenMiddleware', 'crum.CurrentRequestUserMiddleware', # noqa 'apps.log.middlewares.SaveLog', 'apps.pos_device.middlewares.PosDeviceValidationMiddleware', ] ROOT_URLCONF = 'Rasaddam_Backend.urls' # noqa TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'Rasaddam_Backend.wsgi.application' # Database # https://docs.djangoproject.com/en/5.2/ref/settings/#databases MONGODB_DATABASES = { "default": { "name": 'mongodb', "host": "", "tz_aware": True, # if you using timezones in django (USE_TZ = True) # noqa }, } DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.postgresql_psycopg2', # 'NAME': "postgres", # 'HOST': "monte-rosa.liara.cloud", # 'USER': "root", # 'PASSWORD': "aFC3hqbxxR0SeBPZ6TCZ37my", # 'PORT': '32718' # }, 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': os.environ.get("DB_NAME"), 'HOST': os.environ.get("DB_HOST"), 'USER': os.environ.get("DB_USERNAME"), 'PASSWORD': os.environ.get("DB_PASSWORD"), 'PORT': os.environ.get("DB_PORT"), }, } AUTH_USER_MODEL = 'authentication.User' SWAGGER_SETTINGS = { 'SECURITY_DEFINITIONS': { "bearer": { "type": "apiKey", "name": "Authorization", "in": "header", "description": 'JWT Authorization header using the Bearer scheme. Example: "Authorization: Bearer "', }, 'basic': { # <<-- is for djagno authentication 'type': 'basic' }, }, 'USE_SESSION_AUTH': False, "DEFAULT_AUTO_SCHEMA_CLASS": "drf_yasg.inspectors.SwaggerAutoSchema" } CELERY_BROKER_URL = os.environ.get("CELERY_BROKER_URL") accept_content = ["application/json"] result_serializer = "json" task_serializer = "json" timezone = "UTC" CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND") CELERY_CACHE_BACKEND = os.environ.get("CELERY_CACHE_BACKEND") # Celery Beat settings CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" LOGIN_URL = 'rest_framework:login' LOGOUT_URL = 'rest_framework:logout' REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ), 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), 'DEFAULT_FILTER_BACKENDS': [ 'django_filters.rest_framework.DjangoFilterBackend', 'rest_framework.filters.SearchFilter', ], 'EXCEPTION_HANDLER': 'apps.core.error_handler.custom_exception_handler', "DEFAULT_PAGINATION_CLASS": 'apps.core.pagination.CustomPageNumberPagination', "PAGE_SIZE": 20, 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' } SIMPLE_JWT = { "ACCESS_TOKEN_LIFETIME": timedelta(days=1), "REFRESH_TOKEN_LIFETIME": timedelta(days=1), "ROTATE_REFRESH_TOKENS": False, "BLACKLIST_AFTER_ROTATION": False, "UPDATE_LAST_LOGIN": False, "ALGORITHM": "HS256", "SIGNING_KEY": 'django-insecure-@0apn-lk85pfw=z00x2ib$w9#rwz8%2v4i_n^^9jz-m9b+y55*', "VERIFYING_KEY": "", "AUDIENCE": None, "ISSUER": None, "JSON_ENCODER": None, "JWK_URL": None, "LEEWAY": 0, "AUTH_HEADER_TYPES": ("Bearer",), "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", "USER_ID_FIELD": "id", "USER_ID_CLAIM": "user_id", "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule", "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",), "TOKEN_TYPE_CLAIM": "token_type", "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser", "JTI_CLAIM": "jti", "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp", "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5), "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1), "TOKEN_OBTAIN_SERIALIZER": 'apps.authentication.api.v1.jwt_serializer.CustomizedTokenObtainPairSerializer', "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer", "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer", "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer", "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer", "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer", } CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", }, "KEY_PREFIX": "You have successfully set up a key-value pair!" }, 'memcache': { "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache", "LOCATION": "127.0.0.1:11211", } } CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": { "hosts": [("redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0")], # noqa }, }, } REST_CAPTCHA = { 'CAPTCHA_CACHE': 'default', 'CAPTCHA_TIMEOUT': 300, # 5 minutes 'CAPTCHA_LENGTH': 6, 'CAPTCHA_FONT_SIZE': 35, 'CAPTCHA_IMAGE_SIZE': (90, 20), 'CAPTCHA_LETTER_ROTATION': (-35, 35), 'CAPTCHA_FOREGROUND_COLOR': '#000000', 'CAPTCHA_BACKGROUND_COLOR': '#ffffff', # 'CAPTCHA_FONT_PATH': 'CAPTCHA_CACHE_KEY': 'rest_captcha_{key}.{version}', 'FILTER_FUNCTION': 'rest_captcha.captcha.filter_default', 'NOISE_FUNCTION': 'apps.captcha_app.api.v1.serializers.noise_default' } ELASTICSEARCH_DSL = { # elastic HSA256 finger print f7d94c1da0668ba7874e5e09c3b1b91284fcdda97c361e0165401dc9375531b0 # noqa # liara elastic password uYkiQ860vLW8DIbWpNjqtz2B # noqa # local system password =z66+LCIebq4NQRR_+=R # noqa "default": { "hosts": "http://monte-rosa.liara.cloud:31157", # noqa "http_auth": ("elastic", "uYkiQ860vLW8DIbWpNjqtz2B"), # noqa } } # ELASTIC_APM = { # 'SERVICE_NAME': 'rasaddam-backend', # noqa # # 'SECRET_TOKEN': 'T1hTTnZwa0JJbFhUVTBsQVRnbTc6cHpWVUloSklUaXViYllCdE9IQkFYQQ==', # noqa # # 'SERVER_URL': 'http://apm.rasadyar.com', # noqa # # 'ENVIRONMENT': 'production', # noqa # # 'DEBUG': True, # # 'ELASTIC_APM_LOG_LEVEL': 'trace' # } # Password validation # https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators 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', }, ] # Internationalization # https://docs.djangoproject.com/en/5.2/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.2/howto/static-files/ STATIC_URL = 'static/' # Default primary key field type # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DATA_UPLOAD_MAX_MEMORY_SIZE = 50242880 CORS_ORIGIN_ALLOW_ALL = False CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINS = os.environ.get("CORS_ALLOWED_ORIGINS").split(",") SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_SSL_REDIRECT = False SESSION_COOKIE_SECURE = False CSRF_COOKIE_SECURE = False JAZZMIN_SETTINGS = { # noqa # title of the window (Will default to current_admin_site.site_title if absent or None) "site_title": "Library Admin", # Title on the login screen (19 chars max) (defaults to current_admin_site.site_header if absent or None) "site_header": "Library", # Title on the brand (19 chars max) (defaults to current_admin_site.site_header if absent or None) "site_brand": "Library", # Logo to use for your site, must be present in static files, used for brand on top left "site_logo": "books/img/logo.png", # Logo to use for your site, must be present in static files, used for login form logo (defaults to site_logo) "login_logo": None, # Logo to use for login form in dark themes (defaults to login_logo) "login_logo_dark": None, # CSS classes that are applied to the logo above "site_logo_classes": "img-circle", # Relative path to a favicon for your site, will default to site_logo if absent (ideally 32x32 px) "site_icon": None, # Welcome text on the login screen "welcome_sign": "Welcome to the library", # Copyright on the footer "copyright": "Acme Library Ltd", # List of model admins to filter from the filter bar, filter bar omitted if excluded # If you want to use a single filter field you dont need to use a list, you can use a simple string "search_model": ["auth.User", "auth.Group"], # Field name on user model that contains avatar ImageField/URLField/Charfield or a callable that receives the user "user_avatar": None, ############ # Top Menu # ############ # Links to put along the top menu "topmenu_links": [ # Url that gets reversed (Permissions can be added) {"name": "Home", "url": "admin:index", "permissions": ["auth.view_user"]}, # external url that opens in a new window (Permissions can be added) {"name": "Support", "url": "https://github.com/farridav/django-jazzmin/issues", "new_window": True}, # model admin to link to (Permissions checked against model) {"model": "auth.User"}, # App with dropdown menu to all its models pages (Permissions checked against models) {"app": "books"}, ], ############# # User Menu # ############# # Additional links to include in the user menu on the top right ("app" url type is not allowed) "usermenu_links": [ {"name": "Support", "url": "https://github.com/farridav/django-jazzmin/issues", "new_window": True}, {"model": "auth.user"} ], ############# # Side Menu # ############# # Whether to display the side menu "show_sidebar": True, # Whether to aut expand the menu "navigation_expanded": True, # Hide these apps when generating side menu e.g (auth) "hide_apps": [], # Hide these models when generating side menu (e.g auth.user) "hide_models": [], # List of apps (and/or models) to base side menu ordering off of (does not need to contain all apps/models) "order_with_respect_to": ["auth", "books", "books.author", "books.book"], # Custom links to append to app groups, keyed on app name "custom_links": { "books": [{ "name": "Make Messages", "url": "make_messages", "icon": "fas fa-comments", "permissions": ["books.view_book"] }] }, # for the full list of 5.13.0 free icon classes "icons": { "auth": "fas fa-users-cog", "auth.user": "fas fa-user", "auth.Group": "fas fa-users", }, # Icons that are used when one is not manually specified "default_icon_parents": "fas fa-chevron-circle-right", "default_icon_children": "fas fa-circle", ################# # Related Modal # ################# # Use modals instead of popups "related_modal_active": False, ############# # UI Tweaks # ############# # Relative paths to custom CSS/JS scripts (must be present in static files) "custom_css": None, "custom_js": None, # Whether to link font from fonts.googleapis.com (use custom_css to supply font otherwise) "use_google_fonts_cdn": True, # Whether to show the UI customizer on the sidebar "show_ui_builder": False, ############### # Change view # ############### # Render out the change view as a single form, or in tabs, current options are # - single # - horizontal_tabs (default) # - vertical_tabs # - collapsible # - carousel "changeform_format": "horizontal_tabs", # override change forms on a per modeladmin basis "changeform_format_overrides": {"auth.user": "collapsible", "auth.group": "vertical_tabs"}, # Add a language dropdown into the admin # "language_chooser": True, }