Files
RasadDam_Backend/Rasaddam_Backend/settings.py

495 lines
16 KiB
Python

"""
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 sentry_sdk
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/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-@0apn-lk85pfw=z00x2ib$w9#rwz8%2v4i_n^^9jz-m9b+y55*'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
sentry_sdk.init(
dsn="https://e8d8ff4f1bf729370af00b7775be441c@o4509597964697600.ingest.us.sentry.io/4509597966073856",
# Add data like request headers and IP for users,
# see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
send_default_pii=True,
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for tracing.
traces_sample_rate=1.0,
# Set profile_session_sample_rate to 1.0 to profile 100%
# of profile sessions.
profile_session_sample_rate=1.0,
# Set profile_lifecycle to "trace" to automatically
# run the profiler on when there is an active transaction
profile_lifecycle="trace",
)
ASGI_APPLICATION = "Rasaddam_Backend.asgi.application" # noqa
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'https://rasadyar.net/',
'https://localhost:9200',
'https://api.rasadyaar.net',
'https://api.dam.rasadyaar.net',
'https://dam.rasadyar.net'
'http://localhost:3000',
'http://192.168.88.130:3000',
'https://rasaddam-front.liara.run'
]
# 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',
'rest_captcha',
'captcha',
'drf_yasg',
"django_celery_results",
"django_celery_beat",
]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
'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',
'apps.log.middlewares.SaveLog'
]
ROOT_URLCONF = 'Rasaddam_Backend.urls'
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'
},
}
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 <token>"',
},
'basic': { # <<-- is for djagno authentication
'type': 'basic'
},
},
'USE_SESSION_AUTH': False,
"DEFAULT_AUTO_SCHEMA_CLASS": "drf_yasg.inspectors.SwaggerAutoSchema"
}
CELERY_BROKER_URL = "redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0" # Requires Redis server
accept_content = ["application/json"]
result_serializer = "json"
task_serializer = "json"
timezone = "UTC"
CELERY_RESULT_BACKEND = "redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0"
CELERY_CACHE_BACKEND = 'default'
# 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")],
},
},
}
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",
"http_auth": ("elastic", "uYkiQ860vLW8DIbWpNjqtz2B"),
}
}
# 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 = (
'http://localhost:8080',
'http://127.0.0.1:8080',
'http://127.0.0.1:3000',
'http://localhost:3000',
'http://192.168.88.130:3000',
'https://rasadyar.net',
'https://rasaddam-front.liara.run',
'https://dam.rasadyar.net'
)
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = False
SESSION_COOKIE_SECURE = False
CSRF_COOKIE_SECURE = False
JAZZMIN_SETTINGS = {
# 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 search from the search bar, search bar omitted if excluded
# If you want to use a single search 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"]
}]
},
# Custom icons for side menu apps/models See https://fontawesome.com/icons?d=gallery&m=free&v=5.0.0,5.0.1,5.0.10,5.0.11,5.0.12,5.0.13,5.0.2,5.0.3,5.0.4,5.0.5,5.0.6,5.0.7,5.0.8,5.0.9,5.1.0,5.1.1,5.2.0,5.3.0,5.3.1,5.4.0,5.4.1,5.4.2,5.13.0,5.12.0,5.11.2,5.11.1,5.10.0,5.9.0,5.8.2,5.8.1,5.7.2,5.7.1,5.7.0,5.6.3,5.5.0,5.4.2
# 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,
}