from flask import Flask, g, redirect, url_for, render_template import datetime import os def create_app(config_name='development'): app = Flask(__name__, template_folder='templates', static_folder='static') # Import config try: from config.settings import config app.config.from_object(config.get(config_name, 'default')) except ImportError: # Fallback configuration app.config['SECRET_KEY'] = 'dev-key-placeholder' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # Create the app instance folder if it doesn't exist # This is where SQLite database will be stored os.makedirs(os.path.join(app.instance_path), exist_ok=True) # Initialize extensions from app.core.extensions import db, migrate, login_manager, bcrypt, limiter, csrf db.init_app(app) migrate.init_app(app, db) login_manager.init_app(app) bcrypt.init_app(app) csrf.init_app(app) limiter.init_app(app) # Initialize login manager from app.core.auth import User @login_manager.user_loader def load_user(user_id): # Make sure we're in app context with app.app_context(): return User.query.get(int(user_id)) # Initialize CSRF protection from flask_wtf.csrf import CSRFProtect csrf = CSRFProtect() csrf.init_app(app) # Request hooks @app.before_request def before_request(): g.user = None from flask_login import current_user if current_user.is_authenticated: g.user = current_user # Add datetime to all templates g.now = datetime.datetime.utcnow() @app.context_processor def inject_now(): return {'now': datetime.datetime.utcnow()} @app.after_request def add_security_headers(response): # Security headers response.headers['X-Content-Type-Options'] = 'nosniff' response.headers['X-Frame-Options'] = 'SAMEORIGIN' response.headers['X-XSS-Protection'] = '1; mode=block' # Update last_seen for the user if hasattr(g, 'user') and g.user and g.user.is_authenticated: g.user.last_seen = datetime.datetime.utcnow() db.session.commit() return response # Add a basic index route that redirects to login or dashboard @app.route('/') def index(): from flask_login import current_user if current_user.is_authenticated: return redirect(url_for('dashboard.dashboard_home')) return redirect(url_for('auth.login')) # Register blueprints - order matters! # First auth blueprint from app.routes.auth import bp as auth_bp app.register_blueprint(auth_bp) print("Registered Auth blueprint") # Then other blueprints try: from app.routes.dashboard import bp as dashboard_bp app.register_blueprint(dashboard_bp) print("Registered Dashboard blueprint") except ImportError as e: print(f"Could not import dashboard blueprint: {e}") try: from app.routes.ipam import bp as ipam_bp app.register_blueprint(ipam_bp) print("Registered IPAM blueprint") except ImportError as e: print(f"Could not import ipam blueprint: {e}") try: from app.routes.api import bp as api_bp app.register_blueprint(api_bp) print("Registered API blueprint") except ImportError as e: print(f"Could not import API blueprint: {e}") # Create database tables with app.app_context(): try: db.create_all() print("Database tables created successfully") # Check if we need to seed the database from app.core.auth import User if User.query.count() == 0: # Run the seed database function if we have no users try: from app.scripts.db_seed import seed_database seed_database() print("Database seeded with initial data") # Create an admin user admin = User(email="admin@example.com", is_admin=True) admin.set_password("admin") db.session.add(admin) db.session.commit() print("Admin user created: admin@example.com / admin") except Exception as e: print(f"Error seeding database: {e}") except Exception as e: print(f"Error with database setup: {e}") # After all blueprint registrations, add error handlers @app.errorhandler(404) def page_not_found(e): return render_template('errors/404.html', title='Page Not Found'), 404 @app.errorhandler(500) def internal_server_error(e): return render_template('errors/500.html', title='Server Error'), 500 @app.errorhandler(403) def forbidden(e): return render_template('errors/403.html', title='Forbidden'), 403 @app.errorhandler(401) def unauthorized(e): return render_template('errors/401.html', title='Unauthorized'), 401 return app