Add company dashboard improvements and upload/auth features
This commit is contained in:
@@ -6,6 +6,7 @@ from flask import Blueprint, abort, current_app, flash, redirect, render_templat
|
||||
from flask_login import current_user, login_required, login_user
|
||||
|
||||
from ..extensions import db
|
||||
from ..uploads import abs_upload_path, ensure_company_upload_dir, is_valid_upload_relpath
|
||||
from ..models import Company, Display, DisplaySession, Playlist, PlaylistItem, User
|
||||
|
||||
bp = Blueprint("admin", __name__, url_prefix="/admin")
|
||||
@@ -20,11 +21,12 @@ def _try_delete_upload(file_path: str | None, upload_folder: str):
|
||||
"""Best-effort delete of an uploaded media file."""
|
||||
if not file_path:
|
||||
return
|
||||
if not file_path.startswith("uploads/"):
|
||||
if not is_valid_upload_relpath(file_path):
|
||||
return
|
||||
|
||||
filename = file_path.split("/", 1)[1]
|
||||
abs_path = os.path.join(upload_folder, filename)
|
||||
abs_path = abs_upload_path(upload_folder, file_path)
|
||||
if not abs_path:
|
||||
return
|
||||
try:
|
||||
if os.path.isfile(abs_path):
|
||||
os.remove(abs_path)
|
||||
@@ -55,6 +57,13 @@ def create_company():
|
||||
c = Company(name=name)
|
||||
db.session.add(c)
|
||||
db.session.commit()
|
||||
|
||||
# Create the per-company upload directory eagerly (best-effort).
|
||||
try:
|
||||
ensure_company_upload_dir(current_app.config["UPLOAD_FOLDER"], c.id)
|
||||
except Exception:
|
||||
# Upload directory is also created lazily on first upload.
|
||||
pass
|
||||
flash("Company created", "success")
|
||||
return redirect(url_for("admin.company_detail", company_id=c.id))
|
||||
|
||||
@@ -193,6 +202,43 @@ def update_user_email(user_id: int):
|
||||
return redirect(url_for("admin.company_detail", company_id=u.company_id))
|
||||
|
||||
|
||||
@bp.post("/users/<int:user_id>/delete")
|
||||
@login_required
|
||||
def delete_user(user_id: int):
|
||||
"""Admin: delete a non-admin user."""
|
||||
|
||||
admin_required()
|
||||
|
||||
u = db.session.get(User, user_id)
|
||||
if not u:
|
||||
abort(404)
|
||||
|
||||
# Safety checks
|
||||
if u.is_admin:
|
||||
flash("Cannot delete an admin user", "danger")
|
||||
return redirect(url_for("admin.dashboard"))
|
||||
|
||||
if u.id == current_user.id:
|
||||
flash("You cannot delete yourself", "danger")
|
||||
return redirect(url_for("admin.dashboard"))
|
||||
|
||||
company_id = u.company_id
|
||||
company_name = u.company.name if u.company else None
|
||||
email = u.email
|
||||
|
||||
db.session.delete(u)
|
||||
db.session.commit()
|
||||
|
||||
flash(
|
||||
f"User '{email}' deleted" + (f" from '{company_name}'." if company_name else "."),
|
||||
"success",
|
||||
)
|
||||
|
||||
if company_id:
|
||||
return redirect(url_for("admin.company_detail", company_id=company_id))
|
||||
return redirect(url_for("admin.dashboard"))
|
||||
|
||||
|
||||
@bp.post("/displays/<int:display_id>/name")
|
||||
@login_required
|
||||
def update_display_name(display_id: int):
|
||||
|
||||
Reference in New Issue
Block a user