Files
fotohost/app/__init__.py
T

174 lines
5.4 KiB
Python

import os
from flask import Flask
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from dotenv import load_dotenv
load_dotenv()
db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = "auth.login"
login_manager.login_message = "Войдите для доступа к этой странице."
login_manager.login_message_category = "error"
@login_manager.user_loader
def load_user(user_id):
from app.models import User
return db.session.get(User, int(user_id))
def create_app(setup_database=True):
app = Flask(__name__)
app.config["SECRET_KEY"] = os.getenv("SECRET_KEY", "dev-secret-change-me")
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv(
"DATABASE_URL",
"postgresql://photohost:photohost_secret@localhost:5432/photohost",
)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {"pool_pre_ping": True}
app.config["UPLOAD_FOLDER"] = os.getenv("UPLOAD_FOLDER", "uploads")
app.config["MAX_CONTENT_LENGTH"] = int(os.getenv("MAX_UPLOAD_MB", "10")) * 1024 * 1024
app.config["ALLOWED_EXTENSIONS"] = {"png", "jpg", "jpeg", "gif", "webp", "bmp"}
app.config["GIT_REPO_PATH"] = os.getenv("GIT_REPO_PATH", "/repo")
app.config["ALLOW_GIT_DEPLOY"] = os.getenv("ALLOW_GIT_DEPLOY", "false").lower() in (
"1",
"true",
"yes",
)
app.config["DEFAULT_GROUP_QUOTA_MB"] = int(os.getenv("DEFAULT_GROUP_QUOTA_MB", "100"))
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
db.init_app(app)
login_manager.init_app(app)
from .routes import bp as main_bp, cabinet_bp
from .auth import bp as auth_bp
from .admin import bp as admin_bp
from .folders import bp as folders_bp
from .legal import bp as legal_bp
from .passkey import bp as passkey_bp
app.register_blueprint(main_bp)
app.register_blueprint(cabinet_bp)
app.register_blueprint(auth_bp)
app.register_blueprint(admin_bp)
app.register_blueprint(folders_bp)
app.register_blueprint(legal_bp)
app.register_blueprint(passkey_bp)
register_request_hooks(app)
register_cli(app)
# Ensure models are registered even when DB setup runs in init_db.py.
with app.app_context():
from app.models import ( # noqa: F401
AdBanner,
Folder,
FolderInvite,
FolderMember,
PasswordResetToken,
Photo,
SiteSettings,
User,
UserGroup,
UserPasskey,
UserSession,
)
@app.context_processor
def inject_banners():
from app.banner_service import get_banners_by_position
try:
return {"site_banners": get_banners_by_position()}
except Exception:
return {"site_banners": {}}
if setup_database:
with app.app_context():
from app.bootstrap import (
create_first_admin,
ensure_default_group,
ensure_site_settings,
run_schema_migrations,
)
db.create_all()
run_schema_migrations()
if os.getenv("SKIP_DB_INIT") != "1":
ensure_default_group(app)
ensure_site_settings(app)
create_first_admin(app)
return app
def register_request_hooks(app):
@app.before_request
def validate_tracked_session():
from flask import flash, redirect, request, session, url_for
from flask_login import current_user, logout_user
from app.session_service import ensure_user_session, touch_user_session, validate_user_session
if not current_user.is_authenticated:
return None
endpoint = request.endpoint or ""
if endpoint.startswith("static") or endpoint.startswith("passkey.") or endpoint.startswith("legal."):
return None
if endpoint in ("main.health",):
return None
if not validate_user_session(current_user.id):
if session.get("sid"):
logout_user()
flash("Сессия завершена. Войдите снова.", "error")
return redirect(url_for("auth.login"))
ensure_user_session(current_user)
else:
touch_user_session()
return None
def register_cli(app):
@app.cli.command("create-admin")
def create_admin_command():
"""Create or update admin user interactively."""
from getpass import getpass
from app.models import User
username = input("Username: ").strip()
email = input("Email: ").strip()
password = getpass("Password: ")
password2 = getpass("Confirm password: ")
if not username or not email or not password:
print("All fields are required.")
return
if password != password2:
print("Passwords do not match.")
return
user = User.query.filter_by(username=username).first()
if user:
user.email = email
user.is_admin = True
user.set_password(password)
print(f"User '{username}' updated and promoted to admin.")
else:
user = User(username=username, email=email, is_admin=True)
user.set_password(password)
db.session.add(user)
print(f"Admin '{username}' created.")
db.session.commit()