"""Роуты админки: пользователи, роли, удаление.""" from flask import render_template, request, redirect, url_for, session from sqlmodel import Session, select from ..db import engine from ..models import ( User, Project, PortalFile, ProjectMember, Workshop, WorkshopAssistant, UserSession, EventSubscriber, ProjectTask, Notification, ProjectPost, WorkshopPost, ) from ..helpers import require_role def register(app): @app.route("/admin/users") @require_role("admin") def admin_users(): q = (request.args.get("q") or "").strip().lower() with Session(engine) as db_session: users = db_session.exec(select(User).order_by(User.username)).all() if q: users = [ u for u in users if q in (u.username or "").lower() or q in (u.full_name or "").lower() or q in (u.email or "").lower() ] return render_template("admin_users.html", users=users, q=q) @app.route("/admin/users//role", methods=["POST"]) @require_role("admin") def change_user_role(user_id): new_role = request.form.get("role") valid = ["admin", "professor", "lead", "member", "student", "guest"] if new_role not in valid: return "Ошибка", 400 with Session(engine) as db_session: user = db_session.get(User, user_id) if user: if user.id == session.get("user_id") and new_role != "admin": return "Нельзя снять с себя админа", 400 user.role = new_role db_session.add(user) db_session.commit() return redirect(url_for("admin_users")) @app.route("/admin/users//toggle_active", methods=["POST"]) @require_role("admin") def toggle_user_active(user_id): """Блокировка/разблокировка вместо удаления — безопаснее.""" if user_id == session.get("user_id"): return "Нельзя заблокировать себя", 400 with Session(engine) as db_session: user = db_session.get(User, user_id) if user: user.is_active = not user.is_active db_session.add(user) db_session.commit() return redirect(url_for("admin_users")) @app.route("/admin/users//delete", methods=["POST"]) @require_role("admin") def delete_user(user_id): if user_id == session.get("user_id"): return "Нельзя удалить себя", 400 with Session(engine) as db_session: user = db_session.get(User, user_id) if not user: return redirect(url_for("admin_users")) # ── Проверки: нельзя удалить, если есть hard-FK зависимости ── if db_session.exec(select(Project).where(Project.owner_id == user_id)).all(): return "У пользователя есть проекты (передайте владение сначала)", 400 if db_session.exec(select(PortalFile).where(PortalFile.uploaded_by == user_id)).all(): return "У пользователя есть загруженные файлы", 400 if db_session.exec(select(Workshop).where(Workshop.lead_id == user_id)).all(): return "Пользователь ведёт мастер-классы", 400 # Ниже — FK с NOT NULL, без этих проверок DELETE упадёт if db_session.exec(select(ProjectPost).where(ProjectPost.author_id == user_id)).all(): return "У пользователя есть посты в проектах (удалите/переатрибутируйте сначала)", 400 if db_session.exec(select(WorkshopPost).where(WorkshopPost.author_id == user_id)).all(): return "У пользователя есть посты в мастер-классах", 400 if db_session.exec(select(ProjectTask).where(ProjectTask.created_by == user_id)).all(): return "Пользователь создавал задачи (сначала переатрибутируйте)", 400 # ── Развязываем то, что можно обнулить / удалить каскадно ── for pm in db_session.exec(select(ProjectMember).where(ProjectMember.user_id == user_id)).all(): db_session.delete(pm) for wa in db_session.exec(select(WorkshopAssistant).where(WorkshopAssistant.user_id == user_id)).all(): db_session.delete(wa) for ss in db_session.exec(select(UserSession).where(UserSession.user_id == user_id)).all(): db_session.delete(ss) for sub in db_session.exec(select(EventSubscriber).where(EventSubscriber.user_id == user_id)).all(): sub.user_id = None db_session.add(sub) for t in db_session.exec(select(ProjectTask).where(ProjectTask.assignee_id == user_id)).all(): t.assignee_id = None db_session.add(t) for n in db_session.exec(select(Notification).where(Notification.user_id == user_id)).all(): db_session.delete(n) db_session.delete(user) db_session.commit() return redirect(url_for("admin_users"))