06/16 Phase 6
This commit is contained in:
@@ -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"))
|
||||
|
||||
Reference in New Issue
Block a user