uchill/chatnext/backend/config/settings/development.py

453 lines
14 KiB
Python

# /home/ram/aparsoft/backend/config/settings/development.py
# config/settings/development.py
from .base import *
import os
from decouple import config
from datetime import timedelta
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# Create logs directory if it doesn't exist
LOGS_DIR = BASE_DIR / "logs"
if not LOGS_DIR.exists():
os.makedirs(LOGS_DIR, exist_ok=True)
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"corsheaders.middleware.CorsMiddleware",
"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",
# Add the account middleware:
"allauth.account.middleware.AccountMiddleware",
]
AUTHENTICATION_BACKENDS = (
# 'users.backends.EmailBackend',
# 'social_core.backends.google.GoogleOAuth2',
# Needed to login by username in Django admin, regardless of `allauth`
"django.contrib.auth.backends.ModelBackend",
# `allauth` specific authentication methods, such as login by email
"allauth.account.auth_backends.AuthenticationBackend",
)
# Postgres
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": config("DB_NAME", default="chatbotdb"),
"USER": config("DB_USER", default="chatbot_user"),
"PASSWORD": config("DB_PASSWORD", default="chatbot_pass"),
"HOST": config("DB_HOST", default="localhost"),
"PORT": config("DB_PORT", default="5432"),
"OPTIONS": {
"sslmode": "disable", # Disables SSL for local development
},
}
}
PGVECTOR_CONNECTION_STRING = config("PGVECTOR_CONNECTION_STRING")
PG_CHECKPOINT_URI = config("PG_CHECKPOINT_URI")
# Fix the encoding issue - add these lines
if "\\x3a" in PGVECTOR_CONNECTION_STRING:
PGVECTOR_CONNECTION_STRING = PGVECTOR_CONNECTION_STRING.replace("\\x3a", ":")
if "\\x3a" in PG_CHECKPOINT_URI:
PG_CHECKPOINT_URI = PG_CHECKPOINT_URI.replace("\\x3a", ":")
STATIC_URL = "/static/"
STATICFILES_DIRS = [
BASE_DIR / "static",
]
# Ensure static files directory exists
STATIC_ROOT = BASE_DIR / "staticfiles"
STATIC_ROOT.mkdir(exist_ok=True)
if STATIC_ROOT.exists():
os.chmod(STATIC_ROOT, 0o755)
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
MEDIA_ROOT.mkdir(exist_ok=True)
if MEDIA_ROOT.exists():
os.chmod(MEDIA_ROOT, 0o755)
# File upload configurations
FILE_UPLOAD_PERMISSIONS = 0o644
FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755
FILE_UPLOAD_MAX_MEMORY_SIZE = 5242880 # 5 MB
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.StaticFilesStorage"
STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
ALLOWED_HOSTS = [
"127.0.0.1",
"localhost",
]
# Custom admin URL
ADMIN_URL = config("DJANGO_ADMIN_URL", default="chatbot-admin/")
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config(
"DJANGO_SECRET_KEY",
"django-insecure-p!1w7j+^j5v8y-@$_9j*8mr-)l#$u=08=c)!=(b1dleci18$7+",
)
# Password validation
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
"OPTIONS": {
"min_length": 8,
},
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
DJANGO_PUBLIC_BASE_URL = config(
"DJANGO_PUBLIC_BASE_URL", default="http://localhost:8000"
)
DJANGO_PUBLIC_API_URL = config(
"DJANGO_PUBLIC_API_URL", default="http://localhost:8000/api/v1"
)
# API Keys with defaults (for build process)
OPENAI_API_KEY = config("OPENAI_API_KEY")
TAVILY_API_KEY = config("TAVILY_API_KEY")
ANTHROPIC_API_KEY = config("ANTHROPIC_API_KEY")
# If you need separate keys for dev and prod, you can set them here
DEFAULT_LLM_PROVIDER = "openai"
DEFAULT_LLM_MODEL = "gpt-4o-mini"
DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small"
REQUEST_GPT_TIMEOUT = 30
CORS_ALLOW_CREDENTIALS = True
# CORS settings
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000", # Next.js development server
"http://127.0.0.1:3000",
"http://localhost:8000",
"http://docserve.localhost:8000",
]
# CSRF Trusted Origins
CSRF_TRUSTED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000",
"http://localhost:8000",
"http://docserve.localhost:8000",
]
CSRF_COOKIE_SECURE = False # Set to True in production with HTTPS
CSRF_COOKIE_HTTPONLY = False # Set to True in production
CSRF_COOKIE_SAMESITE = "Lax"
CSRF_USE_SESSIONS = False
CSRF_COOKIE_NAME = "csrftoken"
SESSION_COOKIE_SECURE = False # Set to True in production with HTTPS
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Lax"
CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
]
CORS_ALLOW_HEADERS = [
"accept",
"accept-encoding",
"authorization",
"content-type",
"dnt",
"origin",
"user-agent",
"x-csrftoken",
"x-csrf-token",
"csrf-token",
"csrftoken",
"x-requested-with",
"cache-control",
"pragma",
"expires",
]
# Redis and Celery Configuration
REDIS_URL = config("REDIS_URL", default="redis://localhost:6379/0")
# Celery Settings
CELERY_BROKER_URL = config("CELERY_BROKER_URL", default="redis://localhost:6379/1")
CELERY_RESULT_BACKEND = config("CELERY_RESULT_BACKEND", default="redis://localhost:6379/2")
# Celery Configuration Options
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60
CELERY_ACCEPT_CONTENT = ["json"]
CELERY_TASK_SERIALIZER = "json"
CELERY_RESULT_SERIALIZER = "json"
CELERY_TIMEZONE = "UTC"
# Broker and Result Backend Transport Options
CELERY_BROKER_TRANSPORT_OPTIONS = {
"visibility_timeout": 3600, # 1 hour
"max_retries": 3,
}
CELERY_RESULT_BACKEND_TRANSPORT_OPTIONS = {
"retry_policy": {
"timeout": 5.0,
"max_retries": 3,
}
}
# Channel Layers Configuration (for Django Channels)
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [REDIS_URL],
"capacity": 1500,
"expiry": 20,
},
},
}
# Cache Configuration
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": REDIS_URL,
"OPTIONS": {
"db": "1",
"pool_class": "redis.connection.ConnectionPool",
"socket_timeout": 5,
"socket_connect_timeout": 5,
"retry_on_timeout": True,
"max_connections": 100,
},
"KEY_PREFIX": "nlp_playground",
}
}
# Base REST_FRAMEWORK settings (can be extended in environment settings)
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
"PAGE_SIZE": int(config("DJANGO_PAGINATION_LIMIT", 18)),
"DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend",
"rest_framework.filters.OrderingFilter",
],
"DEFAULT_AUTHENTICATION_CLASSES": [
# "accounts.services.CustomJWTCookieAuthentication",
"rest_framework_simplejwt.authentication.JWTAuthentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.BasicAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_THROTTLE_CLASSES": [
"rest_framework.throttling.AnonRateThrottle",
"rest_framework.throttling.UserRateThrottle",
"rest_framework.throttling.ScopedRateThrottle",
],
"DEFAULT_THROTTLE_RATES": {
"anon": "100/minute",
"user": "200/minute",
"login": "30/minute",
},
}
# Security headers
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = "DENY"
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SIMPLE_JWT = {
# Token lifetimes
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=60),
"REFRESH_TOKEN_LIFETIME": timedelta(days=7),
# Token rotation settings
# Disable token rotation to prevent blacklisting issues
"ROTATE_REFRESH_TOKENS": True, # Enable rotation
"BLACKLIST_AFTER_ROTATION": True, # Enable blacklisting
"UPDATE_LAST_LOGIN": False, # Reduce DB hits
"AUTH_HEADER_TYPES": ("Bearer",),
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
# Signing settings
# 'ALGORITHM': 'HS256',
# 'SIGNING_KEY': SECRET_KEY,
# 'VERIFYING_KEY': None,
# Token validation settings
# 'AUDIENCE': None,
# 'ISSUER': None,
# Header settings
# 'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
# User settings
# 'USER_ID_FIELD': 'id',
# 'USER_ID_CLAIM': 'user_id',
# Token classes and claims
# 'TOKEN_TYPE_CLAIM': 'token_type',
# 'JTI_CLAIM': 'jti',
# Additional security settings
# 'TOKEN_USER_CLASS': 'django.contrib.auth.models.User',
# Use them if required: sliding token settings
# 'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
# 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=30),
# 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
# Frontend URL for email links
FRONTEND_URL = config("NEXTAUTH_URL", default="http://localhost:3000")
# Newsletter email settings for development
CONTACT_EMAIL = config("CONTACT_EMAIL", default="contact@aparsoft.com")
AI_TEAM_EMAIL = config("AI_TEAM_EMAIL", default="ai@aparsoft.com")
ENTERPRISE_TEAM_EMAIL = config(
"ENTERPRISE_TEAM_EMAIL", default="enterprise@aparsoft.com"
)
CONSULTING_TEAM_EMAIL = config(
"CONSULTING_TEAM_EMAIL", default="consulting@aparsoft.com"
)
PARTNERSHIPS_EMAIL = config("PARTNERSHIPS_EMAIL", default="partnerships@aparsoft.com")
HR_EMAIL = config("HR_EMAIL", default="hr@aparsoft.com")
SUPPORT_EMAIL = config("SUPPORT_EMAIL", default="support@aparsoft.com")
# Email configuration for development (optional)
# Print emails to console
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
DEFAULT_FROM_EMAIL = config("DEFAULT_FROM_EMAIL", default="noreply@aparsoft.com")
# OAuth settings
OAUTH = {
"GOOGLE": {
"CLIENT_ID": "your-google-client-id",
"CLIENT_SECRET": "your-google-client-secret",
"REDIRECT_URI": "https://aparsoft.com/auth/callback/google",
},
"GITHUB": {
"CLIENT_ID": "your-github-client-id",
"CLIENT_SECRET": "your-github-client-secret",
"REDIRECT_URI": "https://aparsoft.com/auth/callback/github",
},
# Add other OAuth providers as needed
}
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"verbose": {
# Added {name}
"format": "[{asctime}] {levelname} [{name}] {message}",
"style": "{",
"datefmt": "%Y-%m-%d %H:%M:%S",
},
"simple": {
"format": "[{levelname}] {message}",
"style": "{",
},
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "simple",
"level": "INFO",
},
"file": {
"class": "logging.handlers.RotatingFileHandler", # Changed to RotatingFileHandler
"filename": BASE_DIR / "logs" / "dev-debug.log",
"formatter": "verbose",
"level": "INFO",
"maxBytes": 1024 * 1024 * 5, # 5 MB
"backupCount": 5,
"delay": True, # Delay creation until first log record is written
},
},
"loggers": {
"": { # Root logger
"handlers": ["console", "file"],
"level": "INFO",
"propagate": True,
},
"django": {
"handlers": ["console", "file"],
"level": "WARNING",
"propagate": False,
},
"django.server": {
"handlers": ["console"],
"level": "INFO",
"propagate": False,
},
"accounts": { # Your app logger
"handlers": ["console", "file"],
"level": "INFO",
"propagate": False,
},
"jazzmin": {
"handlers": ["console", "file"],
"level": "ERROR", # Change to ERROR to suppress warnings
"propagate": False,
},
},
}
JAZZMIN_UI_TWEAKS = {
"navbar_small_text": False,
"footer_small_text": False,
"body_small_text": False,
"brand_small_text": False,
"brand_colour": False,
"accent": "accent-primary",
"navbar": "navbar-white navbar-light",
"no_navbar_border": False,
"navbar_fixed": False,
"layout_boxed": False,
"footer_fixed": False,
"sidebar_fixed": False,
"sidebar": "sidebar-dark-primary",
"sidebar_nav_small_text": False,
"sidebar_disable_expand": False,
"sidebar_nav_child_indent": False,
"sidebar_nav_compact_style": False,
"sidebar_nav_legacy_style": False,
"sidebar_nav_flat_style": False,
"theme": "cerulean",
"dark_mode_theme": None,
"button_classes": {
"primary": "btn-outline-primary",
"secondary": "btn-outline-secondary",
"info": "btn-info",
"warning": "btn-warning",
"danger": "btn-danger",
"success": "btn-success",
},
}