Implemented a Flask application factory with SQLAlchemy, Flask-Login, and CSRF protection. Added auth and main blueprints providing login, logout, and index routes. Staged new source files, database, and compiled bytecode. Updated configuration to serve over HTTPS in development.
89 lines
2.4 KiB
Python
89 lines
2.4 KiB
Python
"""Flask application factory.
|
|
|
|
This module creates the Flask app, configures extensions, registers blueprints
|
|
and sets up HTTPS using certificates defined in :class:`config.Config`.
|
|
"""
|
|
|
|
from flask import Flask
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
from flask_login import LoginManager
|
|
from flask_wtf import CSRFProtect
|
|
from config import Config
|
|
|
|
# Extensions
|
|
|
|
# db will be attached to the app in create_app
|
|
# The import order matters: we need db defined before models import
|
|
|
|
|
|
def create_app(test_config=None):
|
|
"""Create and configure a :class:`flask.Flask` instance.
|
|
|
|
Parameters
|
|
----------
|
|
test_config: dict, optional
|
|
If provided, overrides :data:`Config` and is useful for tests.
|
|
"""
|
|
app = Flask(__name__)
|
|
# Load config
|
|
app.config.from_object(Config)
|
|
if test_config:
|
|
app.config.update(test_config)
|
|
|
|
# Set secure cookie attributes
|
|
app.config.update(
|
|
SESSION_COOKIE_SECURE=True,
|
|
SESSION_COOKIE_HTTPONLY=True,
|
|
SESSION_COOKIE_SAMESITE="Lax",
|
|
)
|
|
|
|
# Initialise extensions
|
|
db.init_app(app)
|
|
login_manager.init_app(app)
|
|
# User loader will be set after models import
|
|
csrf.init_app(app)
|
|
|
|
# Register blueprints
|
|
from routes import auth_bp, main_bp
|
|
app.register_blueprint(auth_bp)
|
|
app.register_blueprint(main_bp)
|
|
|
|
# Create database tables if they do not exist
|
|
with app.app_context():
|
|
db.create_all()
|
|
|
|
# HTTPS context
|
|
ssl_context = (
|
|
Config.CERT_PATH,
|
|
Config.KEY_PATH,
|
|
)
|
|
# Run the dev server with SSL for local testing
|
|
if not app.testing:
|
|
# Only start server if called directly
|
|
@app.before_first_request
|
|
def _start_server():
|
|
pass # placeholder for any startup hooks
|
|
|
|
return app
|
|
|
|
# Extensions instances
|
|
|
|
# They are defined here so that importing models before create_app does not
|
|
# require an app context.
|
|
|
|
db = SQLAlchemy()
|
|
login_manager = LoginManager()
|
|
login_manager.login_view = "auth.login"
|
|
csrf = CSRFProtect()
|
|
|
|
# Import models after db is defined
|
|
from models import User, Inspection, Photo, load_user # noqa: E402 pylint: disable=wrong-import-position
|
|
|
|
# Set user loader
|
|
login_manager.user_loader(load_user)
|
|
|
|
# If this script is executed directly, run the development server
|
|
if __name__ == "__main__":
|
|
app = create_app()
|
|
# For local development we enable the debugger and use HTTPS
|
|
app.run(host="0.0.0.0", port=8000, ssl_context=(Config.CERT_PATH, Config.KEY_PATH), debug=True)
|