2022-08-13 23:36:10 +02:00
|
|
|
#!/usr/bin/python3
|
|
|
|
"""
|
|
|
|
Main file
|
|
|
|
"""
|
|
|
|
import os
|
2024-01-16 18:50:19 +01:00
|
|
|
import sys
|
2024-01-13 12:44:28 +01:00
|
|
|
import datetime
|
2023-09-08 13:56:08 +02:00
|
|
|
import subprocess
|
2024-01-16 18:50:19 +01:00
|
|
|
import importlib.util
|
2022-08-13 23:36:10 +02:00
|
|
|
|
2024-01-29 18:37:30 +01:00
|
|
|
from flask import Flask, g, redirect, render_template, request, send_file, flash, session, abort, url_for
|
2022-08-16 20:14:56 +02:00
|
|
|
from werkzeug.security import generate_password_hash
|
2024-01-22 16:06:03 +01:00
|
|
|
from flask_babel import Babel, _
|
2022-08-16 20:14:56 +02:00
|
|
|
|
2024-01-29 18:37:30 +01:00
|
|
|
from .modules.utils import User, Album, get_all_albums, user_count, partition_count
|
2024-01-17 12:56:01 +01:00
|
|
|
from .modules import albums, auth, partition, admin, groupe, thumbnails, logging
|
2023-08-28 14:14:57 +02:00
|
|
|
from .modules.auth import admin_required, login_required
|
2022-08-31 13:54:13 +02:00
|
|
|
from .modules.db import get_db
|
2022-08-13 23:36:10 +02:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
2024-01-22 16:06:03 +01:00
|
|
|
def get_locale():
|
|
|
|
return request.accept_languages.best_match(app.config['LANGUAGES'])
|
|
|
|
|
|
|
|
babel = Babel(app, locale_selector=get_locale)
|
|
|
|
|
|
|
|
|
2024-01-16 18:50:19 +01:00
|
|
|
|
|
|
|
def load_config():
|
|
|
|
app.config.from_object('default_config')
|
|
|
|
app.instance_path = os.path.abspath(app.config["INSTANCE_PATH"])
|
|
|
|
|
|
|
|
if not os.path.exists(app.instance_path):
|
|
|
|
print("[ERROR] Instance path does not exist. Make sure to use an existing directory.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if os.path.exists(f"{app.instance_path}/config.py"):
|
|
|
|
# Load module from instance_path/config.py in user_config object
|
|
|
|
spec = importlib.util.spec_from_file_location(
|
|
|
|
".",
|
|
|
|
os.path.join(app.instance_path, "config.py")
|
|
|
|
)
|
2024-01-17 12:56:01 +01:00
|
|
|
|
|
|
|
if spec is None:
|
|
|
|
print("[ERROR] Failed to load $INSTANCE_PATH/config.py")
|
|
|
|
sys.exit(1)
|
|
|
|
|
2024-01-16 18:50:19 +01:00
|
|
|
user_config = importlib.util.module_from_spec(spec)
|
|
|
|
spec.loader.exec_module(user_config)
|
|
|
|
|
|
|
|
app.config.from_object(user_config)
|
|
|
|
|
|
|
|
if os.path.abspath(app.config["INSTANCE_PATH"]) != app.instance_path:
|
2024-01-16 21:32:00 +01:00
|
|
|
print(("[ERROR] Using two different instance path.\n"
|
|
|
|
"Please modify INSTANCE_PATH only in default_config.py ",
|
|
|
|
"and remove it from $INSTANCE_PATH/config.py"))
|
2024-01-16 18:50:19 +01:00
|
|
|
sys.exit(1)
|
|
|
|
else:
|
|
|
|
print("[WARNING] Using default config")
|
|
|
|
|
|
|
|
app.config.from_mapping(
|
|
|
|
DATABASE=os.path.join(app.instance_path, f"{__name__}.sqlite"),
|
|
|
|
)
|
|
|
|
|
2024-01-19 13:48:23 +01:00
|
|
|
|
|
|
|
def setup_logging():
|
2024-01-17 12:56:01 +01:00
|
|
|
logging.log_file = os.path.join(app.instance_path, "logs.txt")
|
2024-01-19 13:48:23 +01:00
|
|
|
enabled = []
|
|
|
|
for event in app.config["ENABLED_LOGS"]:
|
|
|
|
try:
|
|
|
|
enabled.append(logging.LogEntry.from_string(event))
|
|
|
|
except KeyError:
|
|
|
|
print(f"[ERROR] There is an error in your config: Unknown event {event}")
|
|
|
|
|
|
|
|
logging.enabled = enabled
|
2024-01-17 12:56:01 +01:00
|
|
|
|
2024-01-16 18:50:19 +01:00
|
|
|
|
|
|
|
def get_version():
|
|
|
|
try:
|
|
|
|
result = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, check=True)
|
|
|
|
return result.stdout.decode('utf8')
|
|
|
|
except (FileNotFoundError, subprocess.CalledProcessError):
|
|
|
|
# In case git not found or any platform specific weird error
|
|
|
|
return "unknown"
|
|
|
|
|
|
|
|
|
|
|
|
load_config()
|
2024-01-19 13:48:23 +01:00
|
|
|
setup_logging()
|
2022-08-13 23:36:10 +02:00
|
|
|
|
|
|
|
app.register_blueprint(auth.bp)
|
2022-08-31 13:54:13 +02:00
|
|
|
app.register_blueprint(admin.bp)
|
2023-10-11 17:15:49 +02:00
|
|
|
app.register_blueprint(groupe.bp)
|
2022-08-13 23:36:10 +02:00
|
|
|
app.register_blueprint(albums.bp)
|
2022-08-16 18:13:00 +02:00
|
|
|
app.register_blueprint(partition.bp)
|
2024-01-16 21:00:14 +01:00
|
|
|
app.register_blueprint(thumbnails.bp)
|
2022-08-13 23:36:10 +02:00
|
|
|
|
2024-01-16 18:50:19 +01:00
|
|
|
__version__ = get_version()
|
2023-09-08 13:56:08 +02:00
|
|
|
|
2024-01-17 12:56:01 +01:00
|
|
|
logging.log([], logging.LogEntry.SERVER_RESTART)
|
|
|
|
|
2023-09-08 13:56:08 +02:00
|
|
|
|
2022-08-13 23:36:10 +02:00
|
|
|
@app.route("/")
|
|
|
|
def home():
|
2024-01-29 18:37:30 +01:00
|
|
|
"""Show launch page if enabled"""
|
|
|
|
if g.user is None:
|
|
|
|
if app.config["LAUNCH_PAGE"]:
|
|
|
|
return redirect(url_for("launch_page"))
|
|
|
|
return redirect(url_for("auth.login"))
|
|
|
|
return redirect(url_for("albums.index"))
|
|
|
|
|
|
|
|
|
|
|
|
@app.route("/launch")
|
|
|
|
def launch_page():
|
|
|
|
"""Show launch page if enabled"""
|
|
|
|
if not app.config["LAUNCH_PAGE"]:
|
|
|
|
return home()
|
|
|
|
return render_template("launch.html", user_count=user_count(), partition_count=partition_count())
|
2022-08-13 23:36:10 +02:00
|
|
|
|
|
|
|
|
2022-08-16 20:14:56 +02:00
|
|
|
@app.route("/add-user", methods=["GET", "POST"])
|
|
|
|
@admin_required
|
|
|
|
def add_user():
|
|
|
|
"""
|
|
|
|
Ajouter un utilisateur en tant qu'administrateur
|
|
|
|
"""
|
2023-06-10 16:49:07 +02:00
|
|
|
current_user = User(user_id=session.get("user_id"))
|
|
|
|
|
2022-08-16 20:14:56 +02:00
|
|
|
if request.method == "POST":
|
|
|
|
username = request.form["username"]
|
|
|
|
password = request.form["password"]
|
2022-12-19 15:19:58 +01:00
|
|
|
album_uuid = request.form["album_uuid"]
|
2022-08-16 20:14:56 +02:00
|
|
|
|
2023-12-15 13:38:32 +01:00
|
|
|
error = auth.create_user(username, password)
|
2022-08-16 20:14:56 +02:00
|
|
|
|
|
|
|
if error is None:
|
2023-12-15 13:38:32 +01:00
|
|
|
# Success, go to the login page.
|
|
|
|
user = User(name=username)
|
2024-01-17 12:56:01 +01:00
|
|
|
|
|
|
|
logging.log(
|
|
|
|
[user.username, user.id, True, current_user.username],
|
|
|
|
logging.LogEntry.NEW_USER
|
|
|
|
)
|
|
|
|
|
2022-08-16 20:14:56 +02:00
|
|
|
try:
|
2023-12-15 13:38:32 +01:00
|
|
|
if album_uuid != "":
|
|
|
|
user.join_album(album_uuid)
|
2024-01-26 09:48:11 +01:00
|
|
|
flash(_("Created user %(username)s", username=username))
|
2024-01-29 18:37:30 +01:00
|
|
|
return redirect(url_for("albums.index"))
|
2023-12-15 13:38:32 +01:00
|
|
|
except LookupError:
|
2024-01-26 09:48:11 +01:00
|
|
|
flash(_("This album does not exists, but user %(username)s has been created", username=username))
|
2024-01-29 18:37:30 +01:00
|
|
|
return redirect(url_for("albums.index"))
|
2022-08-16 20:14:56 +02:00
|
|
|
|
|
|
|
flash(error)
|
2023-06-10 16:49:07 +02:00
|
|
|
return render_template("auth/register.html", albums=get_all_albums(), user=current_user)
|
2022-08-16 20:14:56 +02:00
|
|
|
|
|
|
|
|
2024-01-13 12:44:28 +01:00
|
|
|
@app.before_request
|
|
|
|
def before_request():
|
|
|
|
"""Set cookie max age to 31 days"""
|
|
|
|
session.permanent = True
|
|
|
|
app.permanent_session_lifetime = datetime.timedelta(days=int(app.config["MAX_AGE"]))
|
|
|
|
|
2023-09-08 13:56:08 +02:00
|
|
|
@app.context_processor
|
|
|
|
def inject_default_variables():
|
2023-12-15 11:36:34 +01:00
|
|
|
"""Inject the version number in the template variables"""
|
2023-09-08 13:56:08 +02:00
|
|
|
if __version__ == "unknown":
|
2023-12-15 11:36:34 +01:00
|
|
|
return {"version": ''}
|
2024-01-27 12:25:52 +01:00
|
|
|
return {"version": __version__, "lang": get_locale()}
|
2023-09-08 13:56:08 +02:00
|
|
|
|
|
|
|
|
2023-06-24 16:05:50 +02:00
|
|
|
@app.after_request
|
|
|
|
def after_request(response):
|
2023-06-25 09:24:44 +02:00
|
|
|
"""Automatically close db after each request"""
|
2023-06-24 16:05:50 +02:00
|
|
|
if ('db' in g) and (g.db is not None):
|
|
|
|
g.db.close()
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
2022-08-13 23:36:10 +02:00
|
|
|
if __name__ == "__main__":
|
|
|
|
app.run(host="0.0.0.0")
|