Security hardening: env-based config, CSRF protection, secure code generation, plus presenter management and email communications system

- Move all credentials from hardcoded to .env with python-dotenv (add .env.example template and .gitignore)
- Add CSRF token generation and validation on all state-changing requests
- Replace random.choices with secrets.choice for all secure code generation
- Add session cookie security headers (HttpOnly, Secure, SameSite)
- Add presenter management: assign/remove presenters to breakout sessions, presenter QR scanning
- Add email communications system: templates per event, custom email sending, sent email tracking
- Add staff/organizer profile pages with staff code display
- New DB tables: event_email_templates, sent_emails, user_communications
- New DB columns: staff.reminder_count/reminder_dates, breakout_session_organizers.presenter_code
- Expand English translation strings across all new features

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 20:34:48 +00:00
parent 934848b7f5
commit a3546b4c01
45 changed files with 8296 additions and 3207 deletions
+25 -14
View File
@@ -1,3 +1,6 @@
from dotenv import load_dotenv
load_dotenv()
import os
class Config:
@@ -5,26 +8,31 @@ class Config:
BABEL_DEFAULT_LOCALE = 'en'
BABEL_SUPPORTED_LOCALES = ['en', 'nl', 'de', 'fr', 'es', 'it', 'pl']
BABEL_TRANSLATION_DIRECTORIES = 'translations'
SECRET_KEY = os.environ.get('SECRET_KEY') or 'netevent-secret-key-change-in-production'
# Security
SECRET_KEY = os.environ.get('SECRET_KEY')
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = os.environ.get('SESSION_COOKIE_SECURE', 'false').lower() == 'true'
SESSION_COOKIE_SAMESITE = 'Lax'
# MySQL Database Configuration
DB_HOST = 'roast.duckdns.org'
DB_PORT = 33062
DB_USER = 'root'
DB_PASSWORD = 'Tiegl!!!111...'
DB_NAME = 'netevent'
DB_HOST = os.environ.get('DB_HOST', 'localhost')
DB_PORT = int(os.environ.get('DB_PORT', '3306'))
DB_USER = os.environ.get('DB_USER', 'root')
DB_PASSWORD = os.environ.get('DB_PASSWORD')
DB_NAME = os.environ.get('DB_NAME', 'netevent')
# Dedicated database user (created by init_db.py)
DB_APP_USER = 'netevent_app'
DB_APP_PASSWORD = 'netevent_pass_2024'
DB_APP_USER = os.environ.get('DB_APP_USER', 'netevent_app')
DB_APP_PASSWORD = os.environ.get('DB_APP_PASSWORD')
# Email Configuration (Brevo/Sendinblue)
MAIL_SERVER = 'smtp-relay.brevo.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USERNAME = 'a6000b001@smtp-brevo.com'
MAIL_PASSWORD = 'xsmtpsib-c242e6135185589b9d66ea911d84696b7582fc9ac4d8fd27ace4c5e745bd5f49-xtHwZO3Hu9KCN3W9'
MAIL_DEFAULT_SENDER = 'paul@bokel.nl'
MAIL_SERVER = os.environ.get('MAIL_SERVER', 'smtp-relay.brevo.com')
MAIL_PORT = int(os.environ.get('MAIL_PORT', '587'))
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', 'true').lower() == 'true'
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
MAIL_DEFAULT_SENDER = os.environ.get('MAIL_DEFAULT_SENDER', 'paul@bokel.nl')
UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'uploads')
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB max file size
@@ -33,3 +41,6 @@ class Config:
# Google reCAPTCHA Configuration
RECAPTCHA_SITE_KEY = os.environ.get('RECAPTCHA_SITE_KEY', '')
RECAPTCHA_SECRET_KEY = os.environ.get('RECAPTCHA_SECRET_KEY', '')
# Debug mode - must be explicitly enabled
DEBUG = os.environ.get('FLASK_DEBUG', 'false').lower() == 'true'