import os from flask import Blueprint, current_app, flash, redirect, render_template, request, url_for from flask_login import current_user from sqlalchemy import func from app import db from app.auth_utils import admin_required from app.models import Photo, User bp = Blueprint("admin", __name__, url_prefix="/admin") @bp.route("/") @admin_required def dashboard(): stats = { "users": User.query.count(), "photos": Photo.query.count(), "admins": User.query.filter_by(is_admin=True).count(), "storage": int( db.session.query(func.coalesce(func.sum(Photo.file_size), 0)).scalar() or 0 ), } recent_users = User.query.order_by(User.created_at.desc()).limit(5).all() recent_photos = Photo.query.order_by(Photo.created_at.desc()).limit(8).all() return render_template( "admin/dashboard.html", stats=stats, recent_users=recent_users, recent_photos=recent_photos, ) @bp.route("/users") @admin_required def users(): all_users = User.query.order_by(User.created_at.desc()).all() return render_template("admin/users.html", users=all_users) @bp.route("/users//toggle-admin", methods=["POST"]) @admin_required def toggle_admin(user_id): user = User.query.get_or_404(user_id) if user.id == current_user.id: flash("Нельзя снять права администратора с самого себя", "error") return redirect(url_for("admin.users")) admin_count = User.query.filter_by(is_admin=True).count() if user.is_admin and admin_count <= 1: flash("Нельзя удалить последнего администратора", "error") return redirect(url_for("admin.users")) user.is_admin = not user.is_admin db.session.commit() action = "назначен администратором" if user.is_admin else "лишён прав администратора" flash(f"Пользователь {user.username} {action}", "success") return redirect(url_for("admin.users")) @bp.route("/users//toggle-active", methods=["POST"]) @admin_required def toggle_active(user_id): user = User.query.get_or_404(user_id) if user.id == current_user.id: flash("Нельзя заблокировать самого себя", "error") return redirect(url_for("admin.users")) user.is_active = not user.is_active db.session.commit() action = "разблокирован" if user.is_active else "заблокирован" flash(f"Пользователь {user.username} {action}", "success") return redirect(url_for("admin.users")) @bp.route("/users//delete", methods=["POST"]) @admin_required def delete_user(user_id): user = User.query.get_or_404(user_id) if user.id == current_user.id: flash("Нельзя удалить самого себя", "error") return redirect(url_for("admin.users")) if user.is_admin and User.query.filter_by(is_admin=True).count() <= 1: flash("Нельзя удалить последнего администратора", "error") return redirect(url_for("admin.users")) for photo in user.photos.all(): filepath = os.path.join(current_app.config["UPLOAD_FOLDER"], photo.filename) if os.path.exists(filepath): os.remove(filepath) db.session.delete(photo) db.session.delete(user) db.session.commit() flash(f"Пользователь {user.username} удалён", "success") return redirect(url_for("admin.users")) @bp.route("/photos") @admin_required def photos(): all_photos = Photo.query.order_by(Photo.created_at.desc()).all() return render_template("admin/photos.html", photos=all_photos) @bp.route("/photos//delete", methods=["POST"]) @admin_required def delete_photo(photo_id): photo = Photo.query.get_or_404(photo_id) filepath = os.path.join(current_app.config["UPLOAD_FOLDER"], photo.filename) if os.path.exists(filepath): os.remove(filepath) db.session.delete(photo) db.session.commit() flash("Фото удалено", "success") return redirect(url_for("admin.photos"))