mirror of
https://github.com/thecyberlearn/quantum-ai-v2.git
synced 2026-08-18 10:13:00 +00:00
Fix security vulnerabilities and improve environment configuration
- Remove hardcoded SECRET_KEY from settings.py (now requires env var) - Remove hardcoded database credentials from PostgreSQL config - Add environment variable validation on Django startup - Fix Stripe API key logging to prevent credential exposure - Update .env.example to match Railway deployment structure - Replace exposed API key in documentation with placeholder - Maintain compatibility with existing Railway deployment setup 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
74e851b996
commit
a6e9ca54d6
65
.env.example
65
.env.example
@ -1,25 +1,48 @@
|
|||||||
SECRET_KEY=your-secret-key-here
|
# Django
|
||||||
DEBUG=False
|
SECRET_KEY=your-secret-key-here-generate-50-random-characters
|
||||||
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
|
DEBUG=True
|
||||||
CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
|
ALLOWED_HOSTS=localhost,127.0.0.1,your-domain.com
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
|
||||||
|
|
||||||
# Database
|
# Database Configuration
|
||||||
DB_NAME=netcop_hub
|
# Default: SQLite (simple, reliable, no setup required)
|
||||||
DB_USER=netcop_user
|
# Railway: Automatically uses PostgreSQL via DATABASE_URL
|
||||||
DB_PASSWORD=your-db-password
|
|
||||||
DB_HOST=localhost
|
|
||||||
DB_PORT=5432
|
|
||||||
|
|
||||||
# Stripe
|
# To use PostgreSQL locally (optional - for production parity):
|
||||||
STRIPE_SECRET_KEY=sk_live_your_stripe_secret_key
|
# 1. Set up PostgreSQL (see docs/POSTGRESQL_SETUP.md)
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
|
# 2. Uncomment one of these options:
|
||||||
|
|
||||||
# AI Assistant Webhooks
|
# Option 1: Use DATABASE_URL (explicit)
|
||||||
N8N_WEBHOOK_DATA_ANALYZER=your_n8n_webhook_url
|
DATABASE_URL=postgresql://user:password@host:port/database
|
||||||
N8N_WEBHOOK_FIVE_WHYS=your_n8n_webhook_url
|
|
||||||
N8N_WEBHOOK_JOB_POSTING=your_n8n_webhook_url
|
|
||||||
N8N_WEBHOOK_FAQ_GENERATOR=your_n8n_webhook_url
|
|
||||||
N8N_WEBHOOK_SOCIAL_ADS=your_n8n_webhook_url
|
|
||||||
|
|
||||||
# OpenWeather API
|
# Option 2: Use PostgreSQL flag (uses default credentials)
|
||||||
OPENWEATHER_API_KEY=your_openweather_api_key
|
# USE_POSTGRESQL=True
|
||||||
|
|
||||||
|
# Option 3: Force SQLite (override auto-detection)
|
||||||
|
# DATABASE_URL=sqlite:///db.sqlite3
|
||||||
|
|
||||||
|
# External API Keys
|
||||||
|
NEXT_PUBLIC_OPENWEATHER_API_KEY=your_openweather_api_key_here
|
||||||
|
OPENWEATHER_API_KEY=your_openweather_api_key_here
|
||||||
|
|
||||||
|
# Stripe Configuration
|
||||||
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_publishable_key_here
|
||||||
|
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here
|
||||||
|
STRIPE_WEBHOOK_SECRET=whsec_your_stripe_webhook_secret_here
|
||||||
|
|
||||||
|
# N8N Webhook URLs (Frontend)
|
||||||
|
NEXT_PUBLIC_N8N_WEBHOOK_DATA_ANALYZER=https://your-n8n-instance.com/webhook/data-analyzer
|
||||||
|
NEXT_PUBLIC_N8N_WEBHOOK_FIVE_WHYS=https://your-n8n-instance.com/webhook/five-whys
|
||||||
|
NEXT_PUBLIC_N8N_WEBHOOK_JOB_POSTING=https://your-n8n-instance.com/webhook/job-posting
|
||||||
|
NEXT_PUBLIC_N8N_WEBHOOK_SOCIAL_ADS=https://your-n8n-instance.com/webhook/social-ads
|
||||||
|
NEXT_PUBLIC_N8N_WEBHOOK_FAQ_GENERATOR=https://your-n8n-instance.com/webhook/faq-generator
|
||||||
|
|
||||||
|
# Django N8N Webhook URLs (Backend)
|
||||||
|
N8N_WEBHOOK_DATA_ANALYZER=https://your-n8n-instance.com/webhook/data-analyzer
|
||||||
|
N8N_WEBHOOK_FIVE_WHYS=https://your-n8n-instance.com/webhook/five-whys
|
||||||
|
N8N_WEBHOOK_JOB_POSTING=https://your-n8n-instance.com/webhook/job-posting
|
||||||
|
N8N_WEBHOOK_SOCIAL_ADS=https://your-n8n-instance.com/webhook/social-ads
|
||||||
|
N8N_WEBHOOK_FAQ_GENERATOR=https://your-n8n-instance.com/webhook/faq-generator
|
||||||
|
|
||||||
|
# Security
|
||||||
|
CSRF_TRUSTED_ORIGINS=https://your-domain.com,https://www.your-domain.com
|
||||||
@ -150,7 +150,7 @@ print("Agent created:", BaseAgent.objects.filter(slug='pdf-analyzer').exists())
|
|||||||
**Add API credentials for your agent:**
|
**Add API credentials for your agent:**
|
||||||
```bash
|
```bash
|
||||||
# Existing variables...
|
# Existing variables...
|
||||||
OPENWEATHER_API_KEY=15befe6bac7b1cd0268900fb97d31482
|
OPENWEATHER_API_KEY=your_openweather_api_key_here
|
||||||
|
|
||||||
# Add your new agent's API key
|
# Add your new agent's API key
|
||||||
DOCPARSER_API_KEY=your_actual_api_key_here
|
DOCPARSER_API_KEY=your_actual_api_key_here
|
||||||
|
|||||||
@ -25,7 +25,17 @@ sys.path.insert(0, str(BASE_DIR / 'apps'))
|
|||||||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = config('SECRET_KEY', default='django-insecure-thdd^re4==p$4geq^$52w7%egd0xxrj#fpgk1c+$xt-jrr5d7%')
|
SECRET_KEY = config('SECRET_KEY')
|
||||||
|
|
||||||
|
# Validate required environment variables
|
||||||
|
required_env_vars = ['SECRET_KEY']
|
||||||
|
missing_vars = [var for var in required_env_vars if not config(var, default='')]
|
||||||
|
if missing_vars:
|
||||||
|
import sys
|
||||||
|
print(f"❌ Missing required environment variables: {', '.join(missing_vars)}")
|
||||||
|
print("💡 Please create a .env file based on .env.example")
|
||||||
|
print("💡 For local development, copy .env.example to .env and fill in the values")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = config('DEBUG', default=True, cast=bool)
|
DEBUG = config('DEBUG', default=True, cast=bool)
|
||||||
@ -129,11 +139,11 @@ else:
|
|||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.postgresql',
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
'NAME': 'netcop_hub',
|
'NAME': config('PGDATABASE', default='netcop_hub'),
|
||||||
'USER': 'netcop_user',
|
'USER': config('PGUSER', default='netcop_user'),
|
||||||
'PASSWORD': 'netcop_pass',
|
'PASSWORD': config('PGPASSWORD'),
|
||||||
'HOST': 'localhost',
|
'HOST': config('PGHOST', default='localhost'),
|
||||||
'PORT': '5432',
|
'PORT': config('PGPORT', default='5432'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class StripePaymentHandler:
|
|||||||
print(f"🚀 [STRIPE DEBUG] Starting checkout session creation...")
|
print(f"🚀 [STRIPE DEBUG] Starting checkout session creation...")
|
||||||
print(f"👤 User: {user.id} ({user.email})")
|
print(f"👤 User: {user.id} ({user.email})")
|
||||||
print(f"💰 Amount: {amount} AED")
|
print(f"💰 Amount: {amount} AED")
|
||||||
print(f"🔑 Stripe API Key (last 4): ...{settings.STRIPE_SECRET_KEY[-4:]}")
|
print(f"🔑 Stripe API Key configured: {bool(settings.STRIPE_SECRET_KEY)}")
|
||||||
print(f"🔑 API Version: {stripe.api_version}")
|
print(f"🔑 API Version: {stripe.api_version}")
|
||||||
print(f"📍 Success URL: {success_url}")
|
print(f"📍 Success URL: {success_url}")
|
||||||
print(f"📍 Cancel URL: {cancel_url}")
|
print(f"📍 Cancel URL: {cancel_url}")
|
||||||
@ -147,7 +147,7 @@ class StripePaymentHandler:
|
|||||||
"""Verify payment directly from Stripe (bypasses webhook issues)"""
|
"""Verify payment directly from Stripe (bypasses webhook issues)"""
|
||||||
try:
|
try:
|
||||||
print(f"🔍 [STRIPE DEBUG] Starting payment verification...")
|
print(f"🔍 [STRIPE DEBUG] Starting payment verification...")
|
||||||
print(f"🔑 Using Stripe API Key (last 4): ...{settings.STRIPE_SECRET_KEY[-4:]}")
|
print(f"🔑 Stripe API Key configured: {bool(settings.STRIPE_SECRET_KEY)}")
|
||||||
print(f"🔑 API Version: {stripe.api_version}")
|
print(f"🔑 API Version: {stripe.api_version}")
|
||||||
print(f"💳 Session ID to verify: {session_id}")
|
print(f"💳 Session ID to verify: {session_id}")
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user