Initial commit - Mold Cost Calculator Application (Security Fixed)
This commit is contained in:
+124
@@ -0,0 +1,124 @@
|
||||
from flask import Flask
|
||||
import os
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from sqlalchemy.exc import SQLAlchemyError, OperationalError
|
||||
from sqlalchemy import inspect
|
||||
from time import sleep
|
||||
from .config import get_config
|
||||
from .logging_config import configure_logging
|
||||
from dotenv import load_dotenv
|
||||
from .extensions import db, login_manager, migrate, csrf, limiter, cache, mail
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_login import LoginManager
|
||||
from flask_migrate import Migrate
|
||||
from flask_limiter import Limiter
|
||||
from flask_limiter.util import get_remote_address
|
||||
from flask_caching import Cache
|
||||
|
||||
# Load environment variables first
|
||||
load_dotenv()
|
||||
|
||||
db = SQLAlchemy()
|
||||
migrate = Migrate()
|
||||
limiter = Limiter(key_func=get_remote_address)
|
||||
cache = Cache()
|
||||
|
||||
def create_app(config_class=None):
|
||||
app = Flask(__name__, static_folder='static')
|
||||
|
||||
@app.context_processor
|
||||
def inject_now():
|
||||
return {'now': datetime.utcnow()}
|
||||
|
||||
# Load configuration
|
||||
if config_class is None:
|
||||
config_class = get_config()
|
||||
app.config.from_object(config_class)
|
||||
|
||||
# Initialize configuration
|
||||
config_class.init_app(app)
|
||||
|
||||
# Ensure secret key is properly set
|
||||
if not app.config.get('SECRET_KEY'):
|
||||
raise ValueError("SECRET_KEY must be set in the configuration")
|
||||
app.config['SECRET_KEY'] = app.config['SECRET_KEY'].encode('utf-8')
|
||||
|
||||
# Ensure instance folder exists
|
||||
try:
|
||||
os.makedirs(app.instance_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# Configure logging
|
||||
configure_logging(app)
|
||||
|
||||
# Initialize extensions with retry logic
|
||||
max_retries = 3
|
||||
retry_delay = 5
|
||||
|
||||
# Initialize extensions only if they haven't been initialized
|
||||
if not hasattr(app, 'extensions') or 'sqlalchemy' not in app.extensions:
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
# Initialize SQLAlchemy only if not already initialized
|
||||
if 'sqlalchemy' not in app.extensions:
|
||||
db.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
|
||||
# Initialize other extensions
|
||||
if 'csrf' not in app.extensions:
|
||||
csrf.init_app(app)
|
||||
if 'limiter' not in app.extensions:
|
||||
limiter.init_app(app)
|
||||
if 'cache' not in app.extensions:
|
||||
cache.init_app(app)
|
||||
if 'mail' not in app.extensions:
|
||||
mail.init_app(app)
|
||||
if 'login_manager' not in app.extensions:
|
||||
login_manager.init_app(app)
|
||||
|
||||
# Test database connection
|
||||
with app.app_context():
|
||||
db.engine.connect()
|
||||
break
|
||||
except OperationalError as e:
|
||||
if attempt == max_retries - 1:
|
||||
app.logger.error(f"Failed to connect to database after {max_retries} attempts: {str(e)}")
|
||||
raise
|
||||
app.logger.warning(f"Database connection attempt {attempt + 1} failed: {str(e)}")
|
||||
sleep(retry_delay)
|
||||
|
||||
# Configure login manager
|
||||
login_manager.login_view = 'auth.login'
|
||||
login_manager.login_message = 'Please log in to access this page.'
|
||||
login_manager.login_message_category = 'warning'
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
from .models import User
|
||||
return User.query.get(int(user_id))
|
||||
|
||||
# Register blueprints
|
||||
from .routes import main, auth, admin
|
||||
app.register_blueprint(main.bp)
|
||||
app.register_blueprint(auth.bp)
|
||||
app.register_blueprint(admin.bp)
|
||||
|
||||
# Register error handlers
|
||||
from .errors import register_error_handlers
|
||||
register_error_handlers(app)
|
||||
|
||||
# Debug: log all registered endpoints at startup (warning level and flush)
|
||||
app.logger.warning("Registered endpoints (debug):")
|
||||
for rule in app.url_map.iter_rules():
|
||||
app.logger.warning(f"{rule.endpoint} {rule.methods} {rule.rule}")
|
||||
for handler in app.logger.handlers:
|
||||
handler.flush()
|
||||
|
||||
# Debug: write all registered endpoints to a file
|
||||
with open('logs/endpoints.log', 'w') as f:
|
||||
for rule in app.url_map.iter_rules():
|
||||
f.write(f"{rule.endpoint} {rule.methods} {rule.rule}\n")
|
||||
|
||||
return app
|
||||
Reference in New Issue
Block a user