Skip to content

Commit 52af5d2

Browse files
Merge pull request #402 from Aditya8369/216
fix: Missing Environment Variable Validation
2 parents 74f1753 + 409ba42 commit 52af5d2

4 files changed

Lines changed: 326 additions & 73 deletions

File tree

‎backend/app.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@
9898
# =====================================================================
9999
app = Flask(__name__, static_folder='.', static_url_path='')
100100

101+
# Validate required environment variables at startup
102+
# This will raise ValueError if any required variables are missing
103+
validate_required_env_vars()
104+
101105
# Apply configuration to Flask app
102106
app.config.update(app_config.flask_config)
103107

‎backend/config.py‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,21 @@ def validate(self) -> tuple[bool, list[str]]:
159159
"""
160160
errors = []
161161

162+
# Check for required environment variables
163+
required_vars = {
164+
'JWT_SECRET_KEY': 'JWT authentication secret key',
165+
'GOOGLE_BOOKS_API_KEY': 'Google Books API key for book discovery',
166+
'DATABASE_URL': 'Database connection URL'
167+
}
168+
169+
for var_name, description in required_vars.items():
170+
value = os.getenv(var_name, '').strip()
171+
if not value or value.startswith('your-') or value.startswith('your_'):
172+
errors.append(
173+
f"Missing or invalid {var_name}: {description}. "
174+
f"Please set {var_name} in your .env file."
175+
)
176+
162177
# Validate JWT secret key
163178
if self.jwt.secret_key == 'default-dev-secret-key':
164179
if self.is_production():
@@ -296,4 +311,31 @@ def setup_logging(config: Config) -> logging.Logger:
296311

297312

298313
# Global configuration instance
299-
app_config = get_config()
314+
app_config = get_config()
315+
316+
317+
def validate_required_env_vars() -> None:
318+
"""
319+
Validate that all required environment variables are set at startup.
320+
321+
This function checks for critical configuration values that are needed
322+
for the application to function properly. It's called before the Flask
323+
app starts accepting requests.
324+
325+
Raises:
326+
ValueError: If any required environment variables are missing or invalid.
327+
"""
328+
is_valid, errors = app_config.validate()
329+
330+
if not is_valid:
331+
error_message = (
332+
"\n" + "="*70 + "\n"
333+
"STARTUP ERROR: Missing or Invalid Environment Variables\n"
334+
"="*70 + "\n" +
335+
"\n".join(errors) +
336+
"\n\n" +
337+
"Please check your .env file and ensure all required variables are set.\n"
338+
"See config/.env.example for reference.\n" +
339+
"="*70 + "\n"
340+
)
341+
raise ValueError(error_message)

‎config/.env.example‎

Lines changed: 30 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,59 @@
1-
# BiblioDrift Environment Configuration
2-
3-
# JWT Configuration
4-
JWT_SECRET_KEY=your-super-secret-jwt-key-here
5-
6-
# Database Configuration
7-
DATABASE_URL=sqlite:///biblio.db
8-
91
# BiblioDrift Environment Configuration Example
102
# Copy this file to .env and customize for your environment
113

12-
# Application Environment (development, production, testing)
13-
APP_ENV=development
144
# =============================================================================
15-
# SECURITY: Credential Encryption (Recommended for Production)
5+
# APPLICATION ENVIRONMENT
166
# =============================================================================
17-
# To encrypt sensitive API keys, use the security_utils module:
18-
# from security_utils import encrypt_credential
19-
# encrypted_key = encrypt_credential("your-actual-api-key")
20-
#
21-
# Then set CREDENTIAL_MASTER_PASSWORD to enable decryption at runtime.
22-
# This prevents storing plain-text credentials in .env files.
23-
# =============================================================================
24-
25-
# Master password for encrypting/decrypting credentials (OPTIONAL but RECOMMENDED)
26-
# Generate a secure password using: python -c "from security_utils import CredentialEncryption; print(CredentialEncryption.generate_master_password())"
27-
CREDENTIAL_MASTER_PASSWORD=your_secure_master_password_here
7+
APP_ENV=development
288

299
# =============================================================================
30-
# SECURITY: Credential Encryption (Recommended for Production)
31-
# =============================================================================
32-
# To encrypt sensitive API keys, use the security_utils module:
33-
# from security_utils import encrypt_credential
34-
# encrypted_key = encrypt_credential("your-actual-api-key")
35-
#
36-
# Then set CREDENTIAL_MASTER_PASSWORD to enable decryption at runtime.
37-
# This prevents storing plain-text credentials in .env files.
10+
# REQUIRED: JWT & SECURITY CONFIGURATION
3811
# =============================================================================
39-
40-
# Master password for encrypting/decrypting credentials (OPTIONAL but RECOMMENDED)
41-
# Generate a secure password using: python -c "from security_utils import CredentialEncryption; print(CredentialEncryption.generate_master_password())"
42-
CREDENTIAL_MASTER_PASSWORD=your_secure_master_password_here
43-
44-
# Google Books API Key
45-
GOOGLE_BOOKS_API_KEY=your_google_id_here
46-
47-
# JWT Configuration
48-
JWT_SECRET_KEY=your-super-secret-jwt-key-here
12+
# CRITICAL: Must be set before app startup. Generate a secure key in production.
13+
JWT_SECRET_KEY=your-super-secret-jwt-key-here-min-32-chars
4914
JWT_ACCESS_TOKEN_EXPIRES_DAYS=7
5015
JWT_ALGORITHM=HS256
5116

52-
# Database Configuration
17+
# =============================================================================
18+
# REQUIRED: DATABASE CONFIGURATION
19+
# =============================================================================
20+
# CRITICAL: Must be set before app startup.
5321
DATABASE_URL=sqlite:///instance/biblio.db
5422
SQLALCHEMY_TRACK_MODIFICATIONS=False
5523

56-
# Server Configuration
24+
25+
# =============================================================================
26+
# SERVER CONFIGURATION
27+
# =============================================================================
5728
FLASK_HOST=127.0.0.1
5829
PORT=5000
59-
FLASK_DEBUG=True
60-
61-
# Rate Limiting Configuration
62-
RATE_LIMIT_ENABLED=True
63-
RATE_LIMIT_WINDOW=60
64-
RATE_LIMIT_MAX_REQUESTS=30
30+
FLASK_DEBUG=False
6531

66-
# Logging Configuration
67-
LOG_LEVEL=INFO
68-
LOG_FORMAT=%(asctime)s - %(name)s - %(levelname)s - %(message)s
69-
# LOG_FILE=logs/bibliodrift.log
32+
# =============================================================================
33+
# REQUIRED: API KEYS & EXTERNAL SERVICES
34+
# =============================================================================
35+
# CRITICAL: GOOGLE_BOOKS_API_KEY must be set before app startup.
36+
GOOGLE_BOOKS_API_KEY=your-google-books-api-key
7037

71-
# AI Service Configuration
38+
# Optional AI Service Keys
7239
OPENAI_API_KEY=your-openai-api-key
7340
GROQ_API_KEY=your-groq-api-key
7441
GEMINI_API_KEY=your-gemini-api-key
7542

76-
# Google Books API
77-
GOOGLE_BOOKS_API_KEY=your-google-books-api-key
7843

79-
# Caching Configuration
80-
CACHE_TYPE=simple # Options: simple, redis, null
44+
# =============================================================================
45+
# CACHING CONFIGURATION
46+
# =============================================================================
47+
CACHE_TYPE=simple
8148
REDIS_URL=redis://localhost:6379/0
8249

8350
# Cache TTL Values (in seconds)
84-
CACHE_MOOD_ANALYSIS_TTL=86400 # 24 hours
85-
CACHE_RECOMMENDATIONS_TTL=3600 # 1 hour
86-
CACHE_MOOD_TAGS_TTL=43200 # 12 hours
87-
CACHE_CHAT_RESPONSE_TTL=1800 # 30 minutes
88-
CACHE_GOODREADS_TTL=604800 # 7 days
89-
CACHE_DEFAULT_TIMEOUT=3600 # 1 hour
90-
91-
# Flask Configuration
92-
FLASK_DEBUG=False
93-
FLASK_HOST=127.0.0.1
94-
PORT=5000
95-
96-
# Logging
97-
LOG_LEVEL=INFO
98-
GOOGLE_BOOKS_API_KEY=your-google-books-api-key
51+
CACHE_MOOD_ANALYSIS_TTL=86400
52+
CACHE_RECOMMENDATIONS_TTL=3600
53+
CACHE_MOOD_TAGS_TTL=43200
54+
CACHE_CHAT_RESPONSE_TTL=1800
55+
CACHE_GOODREADS_TTL=604800
56+
CACHE_DEFAULT_TIMEOUT=3600
9957

10058
# LLM Configuration
10159
PREFERRED_LLM=groq

0 commit comments

Comments
 (0)