From 91c8b4f9c2b98fde2c19df78c20493c34029cc07 Mon Sep 17 00:00:00 2001 From: ndu Date: Fri, 27 Dec 2024 06:33:08 +0100 Subject: [PATCH] chore(feat): add env handling --- .gitignore | 6 ++- README.md | 24 +++++++++++- server/.env.example | 7 +++- server/core/asgi.py | 5 ++- server/core/config/local.py | 46 ++++++++++++++++++++++- server/core/config/production.py | 64 +++++++++++++++++++------------- server/core/wsgi.py | 5 ++- server/manage.py | 10 +++-- server/requirements.txt | 1 + 9 files changed, 128 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index ae8b10a..78712d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ dumps/ .venv/ .env +.env.local +.env.production __pycache__/ test.py test.json @@ -16,4 +18,6 @@ test.rest db.sqlite3 old-backup-db.sqlite3 dump.rdp -client/ \ No newline at end of file +client/ + +switch-env.sh \ No newline at end of file diff --git a/README.md b/README.md index 432c61d..86c138d 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,29 @@ Before running the application, ensure you have the following: EMAIL_HOST_PASSWORD = 'enter password' #for Gmail, generate app password ``` -5. Run the application in development mode: +5. Environment Switching: Use this script (switch-env.sh) to easily switch between environments: + ```sh + #!/bin/bash + if [ "$1" == "local" ]; then + cp .env.local .env + echo "Switched to local environment" + elif [ "$1" == "prod" ]; then + cp .env.production .env + echo "Switched to production environment" + else + echo "Please specify environment: local or prod" + fi + ``` + Make it executable and use: + + ```sh + chmod +x switch-env.sh + ./switch-env.sh local # Switch to local environment + ./switch-env.sh prod # Switch to production environment + ``` + + +6. Run the application: - Start Server: diff --git a/server/.env.example b/server/.env.example index 7dba888..941a911 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,6 +1,6 @@ # Environment Settings # Use core.config.local for Dev environment and core.config.production for production environment -DJANGO_SETTINGS_MODULE='core.config.local' +DJANGO_SETTINGS_MODULE='core.config.local' # Changes based on environment # Sqlite3 database config SECRET_KEY='paste db.sqlite3 key here' @@ -13,9 +13,12 @@ DB_PASS= DB_HOST=localhost DB_PORT=5432 +# Host Settings +ALLOWED_HOSTS=localhost,127.0.0.1 SITE_URL='http://localhost:8000' -# OpenAI +# API Keys +TINYMCE_API_KEY=xxxxxx OPENAI_API_KEY=xxxxxx # Cloudinary diff --git a/server/core/asgi.py b/server/core/asgi.py index 2aa209a..abb6887 100644 --- a/server/core/asgi.py +++ b/server/core/asgi.py @@ -14,6 +14,7 @@ from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.config.local') +settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', 'core.config.production') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module) -application = get_asgi_application() +application = get_asgi_application() \ No newline at end of file diff --git a/server/core/config/local.py b/server/core/config/local.py index 1d96b34..4be86e2 100644 --- a/server/core/config/local.py +++ b/server/core/config/local.py @@ -1,9 +1,51 @@ from .base import * +# Development-specific settings +DEBUG = True + +# Media settings MEDIA_URL = '/media/' +# Development hosts +ALLOWED_HOSTS = ['localhost', '127.0.0.1'] + +# CSRF settings for local development CSRF_TRUSTED_ORIGINS = [ 'http://127.0.0.1:8000', 'http://localhost:8000', - 'http://localhost:4321', -] \ No newline at end of file +] + +CORS_ALLOW_CREDENTIALS = True + +# Database settings (you might want to use SQLite for local development) +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': config('DB_NAME', default='your_local_db_name'), + 'USER': config('DB_USER', default='your_local_db_user'), + 'PASSWORD': config('DB_PASS', default='your_local_db_password'), + 'HOST': config('DB_HOST', default='localhost'), + 'PORT': config('DB_PORT', default='5432'), + } +} + +# Security settings appropriate for development +CSRF_COOKIE_SECURE = False +SESSION_COOKIE_SECURE = False +SECURE_SSL_REDIRECT = False + +# Content Security Policy settings for development +CSP_DEFAULT_SRC = ("'self'",) +CSP_STYLE_SRC = ("'self'",) +CSP_SCRIPT_SRC = ("'self'", "blob:") +CSP_IMG_SRC = ("'self'", "blob:") +CSP_MEDIA_SRC = ("'self'", "blob:") +CSP_CONNECT_SRC = ("'self'", "blob:") +CSP_FONT_SRC = ("'self'",) + +# Static files +STATIC_URL = 'static/' + +# File upload settings +DATA_UPLOAD_MAX_MEMORY_SIZE = 52428800 # 50 MB +FILE_UPLOAD_MAX_MEMORY_SIZE = 52428800 # 50 MB \ No newline at end of file diff --git a/server/core/config/production.py b/server/core/config/production.py index eac9dc6..8abbb56 100644 --- a/server/core/config/production.py +++ b/server/core/config/production.py @@ -1,10 +1,18 @@ from .base import * -MEDIA_URL = 'https://cms.2077.xyz/media/' +MEDIA_URL = "https://cms.2077.xyz/media/" -DEBUG = bool(config('DJANGO_DEBUG', default=False)) +DEBUG = bool(config("DJANGO_DEBUG", default=False)) -ALLOWED_HOSTS = ['74.119.195.253', 'cms.2077.xyz'] +ALLOWED_HOSTS = config( + "ALLOWED_HOSTS", + default="74.119.195.253,cms.2077.xyz", + cast=lambda v: [s.strip() for s in v.split(",")], +) + +# Add localhost for testing production settings locally +if DEBUG: + ALLOWED_HOSTS.extend(["localhost", "127.0.0.1"]) CSRF_TRUSTED_ORIGINS = [] for host in ALLOWED_HOSTS: @@ -12,42 +20,46 @@ CSRF_TRUSTED_ORIGINS.append(f"http://{host}") CORS_ALLOWED_ORIGINS = [ - "https://cms.2077.xyz", # Https version of Django - "http://74.119.195.253", # Http version of Astro - "http://127.0.0.1:4321", # Local Dev - "http://localhost:4321", # Local Dev - ] + "https://cms.2077.xyz", # Https version of Django + "http://74.119.195.253", +] CORS_ALLOW_CREDENTIALS = True -#REDISCLOUD_URL = config("REDISCLOUD_URL") +# REDISCLOUD_URL = config("REDISCLOUD_URL") -STATIC_URL = 'staticfiles/' +STATIC_URL = "staticfiles/" DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': config('DB_NAME'), - 'USER': config('DB_USER'), - 'PASSWORD': config('DB_PASS'), - 'HOST': config('DB_HOST'), - 'PORT': config('DB_PORT'), + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": config("DB_NAME"), + "USER": config("DB_USER"), + "PASSWORD": config("DB_PASS"), + "HOST": config("DB_HOST"), + "PORT": config("DB_PORT"), } } -CSP_DEFAULT_SRC = ("self",) +CSP_DEFAULT_SRC = ("'self'",) -CSP_STYLE_SRC = ("self",) +CSP_STYLE_SRC = ("'self'",) -CSP_SCRIPT_SRC = ("self", "blob:") +CSP_SCRIPT_SRC = ("'self'", "blob:") -CSP_IMG_SRC = ("self", "http://cms.2077.xyz", "https://cms.2077.xyz", "http://74.119.195.253", "blob:") +CSP_IMG_SRC = ( + "'self'", + "http://cms.2077.xyz", + "https://cms.2077.xyz", + "http://74.119.195.253", + "blob:", +) CSP_MEDIA_SRC = ("'self'", "blob:") CSP_CONNECT_SRC = ("'self'", "blob:") -CSP_FONT_SRC = ("self",) +CSP_FONT_SRC = ("'self'",) CSRF_COOKIE_SECURE = True @@ -57,15 +69,15 @@ SECURE_HSTS_PRELOAD = True -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SECURE_SSL_REDIRECT = False SESSION_COOKIE_SECURE = True -#PROXY_SETTING for Astro server +# PROXY_SETTING for Astro server PROXY_ASTERISK = True -DATA_UPLOAD_MAX_MEMORY_SIZE = 52428800 # 50 MB +DATA_UPLOAD_MAX_MEMORY_SIZE = 52428800 # 50 MB -FILE_UPLOAD_MAX_MEMORY_SIZE = 52428800 # 50 MB \ No newline at end of file +FILE_UPLOAD_MAX_MEMORY_SIZE = 52428800 # 50 MB diff --git a/server/core/wsgi.py b/server/core/wsgi.py index 55b3b50..04d2ed2 100644 --- a/server/core/wsgi.py +++ b/server/core/wsgi.py @@ -14,6 +14,7 @@ from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.config.local') +settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', 'core.config.production') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module) -application = get_wsgi_application() +application = get_wsgi_application() \ No newline at end of file diff --git a/server/manage.py b/server/manage.py index 06e9401..ac979a0 100755 --- a/server/manage.py +++ b/server/manage.py @@ -5,10 +5,12 @@ from dotenv import load_dotenv load_dotenv() -print(os.environ.get('DJANGO_SETTINGS_MODULE')) +print(os.environ.get("DJANGO_SETTINGS_MODULE")) + def main(): """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.config.local') + settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', 'core.config.production') + os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module) try: from django.core.management import execute_from_command_line except ImportError as exc: @@ -20,5 +22,5 @@ def main(): execute_from_command_line(sys.argv) -if __name__ == '__main__': - main() +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/server/requirements.txt b/server/requirements.txt index 14c434d..434fa9c 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -44,6 +44,7 @@ kombu==5.4.0 openai==1.57.4 pillow==10.4.0 prompt_toolkit==3.0.47 +psycopg2-binary==2.9.10 pycparser==2.22 pycryptodome==3.21.0 pydantic==2.10.3