06/16 Phase 6

This commit is contained in:
2026-06-16 13:29:32 -04:00
parent 2e9025fe55
commit 479afde2fa
16 changed files with 527 additions and 8 deletions
+98 -1
View File
@@ -9,10 +9,14 @@ from app.models.listing import Listing
from app.models.plan import Plan
from app.models.trust import TrustEvent
from app.models.audit import AuditLog
from app.models.enums import UserStatus, TrustEventType
from app.models.report import Report
from app.models.enums import UserStatus, TrustEventType, ListingStatus
from app.utils import admin_required
from app.services import admin_users as usvc
from app.services import admin_dashboard as dash
from app.services import moderation as msvc
from app.services.settings import get_setting, set_setting
from app.services import audit
admin_bp = Blueprint("admin", __name__)
@@ -125,3 +129,96 @@ def trust_adjust(user_id):
db.session.commit()
flash(_("Trust adjusted."), "success")
return redirect(url_for("admin.user_detail", user_id=user.id))
# --- listing moderation ---
@admin_bp.route("/admin/listings")
@admin_required
def listings():
page = request.args.get("page", 1, type=int)
pagination = msvc.flag_queue(page=page, per_page=PER_PAGE)
flag_threshold = get_setting("flag_threshold", 5)
keyword_blocklist = get_setting("keyword_blocklist", [])
return render_template("admin/listings.html", pagination=pagination,
flag_threshold=flag_threshold,
keyword_blocklist=keyword_blocklist)
@admin_bp.route("/admin/listings/settings", methods=["POST"])
@admin_required
def listings_settings():
threshold = request.form.get("flag_threshold", type=int) or 5
raw_blocklist = request.form.get("keyword_blocklist", "")
blocklist = [line.strip() for line in raw_blocklist.splitlines() if line.strip()]
set_setting("flag_threshold", threshold)
set_setting("keyword_blocklist", blocklist)
audit.log_action(current_user, "settings.updated", "setting", None,
meta={"flag_threshold": threshold, "keyword_blocklist": blocklist})
db.session.commit()
flash(_("Moderation settings updated."), "success")
return redirect(url_for("admin.listings"))
@admin_bp.route("/admin/listings/<int:listing_id>/approve", methods=["POST"])
@admin_required
def approve_listing(listing_id):
listing = Listing.query.get_or_404(listing_id)
msvc.approve(listing, actor=current_user)
db.session.commit()
flash(_("Listing approved."), "success")
return redirect(url_for("admin.listings"))
@admin_bp.route("/admin/listings/<int:listing_id>/hide", methods=["POST"])
@admin_required
def hide_listing(listing_id):
listing = Listing.query.get_or_404(listing_id)
msvc.hide(listing, actor=current_user)
db.session.commit()
flash(_("Listing hidden."), "warning")
return redirect(url_for("admin.listings"))
@admin_bp.route("/admin/listings/<int:listing_id>/remove", methods=["POST"])
@admin_required
def remove_listing(listing_id):
listing = Listing.query.get_or_404(listing_id)
msvc.remove(listing, actor=current_user)
db.session.commit()
flash(_("Listing removed."), "danger")
return redirect(url_for("admin.listings"))
# --- reports queue ---
@admin_bp.route("/admin/reports")
@admin_required
def reports():
candidates = (Report.query.join(Listing, Report.listing_id == Listing.id)
.filter(Listing.status == ListingStatus.flagged)
.order_by(Report.created_at.desc()).all())
dismissed_ids = {a.target_id for a in
AuditLog.query.filter_by(target_type="report", action="report.dismissed").all()}
open_reports = [r for r in candidates if r.id not in dismissed_ids]
return render_template("admin/reports.html", reports=open_reports)
@admin_bp.route("/admin/reports/<int:report_id>/dismiss", methods=["POST"])
@admin_required
def dismiss_report(report_id):
report = Report.query.get_or_404(report_id)
audit.log_action(current_user, "report.dismissed", "report", report.id,
meta={"listing_id": report.listing_id, "reporter_id": report.reporter_id})
db.session.commit()
flash(_("Report dismissed."), "info")
return redirect(url_for("admin.reports"))
@admin_bp.route("/admin/reports/<int:report_id>/escalate", methods=["POST"])
@admin_required
def escalate_report(report_id):
report = Report.query.get_or_404(report_id)
audit.log_action(current_user, "report.escalated", "report", report.id,
meta={"listing_id": report.listing_id, "reporter_id": report.reporter_id})
db.session.commit()
flash(_("Report escalated."), "warning")
return redirect(url_for("admin.reports"))