110 lines
3.5 KiB
Python
110 lines
3.5 KiB
Python
import os
|
|
from flask import Flask, redirect, url_for, request, g, session, flash
|
|
|
|
# import blueprints
|
|
from app.blueprints.auth import auth_bp
|
|
from app.blueprints.main import main_bp
|
|
from app.blueprints.char import char_bp
|
|
from app.blueprints.public import public_bp
|
|
from app.blueprints.ajax import ajax_bp
|
|
|
|
# load_dotenv()
|
|
from .utils.settings import get_settings
|
|
from app.utils.logging import get_logger
|
|
from .utils.session_user import SessionUser
|
|
|
|
logger = get_logger()
|
|
settings = get_settings()
|
|
|
|
|
|
def create_app():
|
|
app = Flask(__name__, template_folder="templates")
|
|
app.config.update(
|
|
SECRET_KEY=settings.flask_secret_key,
|
|
APPWRITE_ENDPOINT=settings.appwrite_endpoint,
|
|
APPWRITE_PROJECT_ID=settings.appwrite_project_id,
|
|
APPWRITE_API_KEY=settings.appwrite_api_key,
|
|
)
|
|
|
|
if not app.config["APPWRITE_ENDPOINT"] or not app.config["APPWRITE_PROJECT_ID"]:
|
|
raise RuntimeError("Missing APPWRITE_ENDPOINT or APPWRITE_PROJECT_ID")
|
|
|
|
# Blueprints
|
|
app.register_blueprint(auth_bp)
|
|
app.register_blueprint(main_bp)
|
|
app.register_blueprint(char_bp)
|
|
app.register_blueprint(public_bp)
|
|
app.register_blueprint(ajax_bp)
|
|
|
|
@app.before_request
|
|
def require_login():
|
|
"""Gate all routes behind a session 'user' except auth + static."""
|
|
# Always allow static files
|
|
if request.endpoint == "static":
|
|
return
|
|
|
|
# Endpoints that should be accessible without being logged in
|
|
public_endpoints = [
|
|
"auth.login",
|
|
"auth.register",
|
|
"auth.verify",
|
|
"auth.callback",
|
|
"auth.send_verification",
|
|
# add any health checks or webhooks here
|
|
"public.home",
|
|
]
|
|
|
|
# Make session user easy to access in views/templates
|
|
g.user = session.get("user")
|
|
|
|
endpoint = (request.endpoint or "")
|
|
|
|
# Let any route under the auth blueprint through (login/verify/etc.)
|
|
if endpoint.startswith("public.") or endpoint.startswith("auth."):
|
|
return
|
|
|
|
if endpoint in public_endpoints:
|
|
return
|
|
|
|
|
|
# Block everything else unless logged in
|
|
if g.user is None:
|
|
# preserve destination for GETs
|
|
next_url = request.url if request.method == "GET" else url_for("auth.login")
|
|
flash("Please log in to continue.", "warning")
|
|
return redirect(url_for("auth.login", next=next_url))
|
|
|
|
@app.before_request
|
|
def load_user():
|
|
user_data = session.get("user")
|
|
|
|
if user_data:
|
|
g.current_user = SessionUser(
|
|
id=user_data.get("$id",""),
|
|
registered_on=user_data.get("registration",""),
|
|
email=user_data.get("email",""),
|
|
email_verified=user_data.get("emailVerification", False),
|
|
phone=user_data.get("phone",""),
|
|
phone_verified=user_data.get("phoneVerification",False),
|
|
mfa=user_data.get("mfa","")
|
|
)
|
|
else:
|
|
# Anonymous user object with same interface
|
|
class AnonymousUser:
|
|
is_authenticated = False
|
|
email_verification = False
|
|
|
|
g.current_user = AnonymousUser()
|
|
|
|
|
|
@app.context_processor
|
|
def inject_globals():
|
|
"""Add variables available to all Jinja templates."""
|
|
return dict(
|
|
app_name=settings.app_name,
|
|
app_version=settings.app_version,
|
|
current_user=getattr(g, "current_user", None),
|
|
)
|
|
|
|
return app
|