adapt /admin and /reports to new interface

This commit is contained in:
Yusur 2025-10-23 04:26:30 +02:00
parent 6b11bf4537
commit a4144c67a9
9 changed files with 68 additions and 10 deletions

View file

@ -163,6 +163,8 @@ async def error_handler_for(status: int, message: str, template: str):
case WantsContentType.JSON: case WantsContentType.JSON:
return jsonify({'error': f'{message}', 'status': status}), status return jsonify({'error': f'{message}', 'status': status}), status
case WantsContentType.HTML: case WantsContentType.HTML:
if request.path.startswith('/admin'):
return await render_template('admin/' + template, message=f'{message}'), status
return await render_template(template, message=f'{message}'), status return await render_template(template, message=f'{message}'), status
case WantsContentType.PLAIN: case WantsContentType.PLAIN:
return f'{message} (HTTP {status})', status, {'content-type': 'text/plain; charset=UTF-8'} return f'{message} (HTTP {status})', status, {'content-type': 'text/plain; charset=UTF-8'}

View file

@ -0,0 +1,10 @@
{% extends "admin/admin_base.html" %}
{% block content %}
<div class="centered">
<h2>Bad Request</h2>
<p><a href="/">Back to homepage.</a></p>
</div>
{% endblock %}

View file

@ -0,0 +1,12 @@
{% extends "admin/admin_base.html" %}
{% from "macros/title.html" import title_tag with context %}
{% block content %}
<div class="centered">
<h2>Access Denied</h2>
<p><a href="/">Back to homepage.</a></p>
</div>
{% endblock %}

View file

@ -0,0 +1,12 @@
{% extends "admin/admin_base.html" %}
{% from "macros/title.html" import title_tag with context %}
{% block content %}
<div class="centered">
<h2>Not Found</h2>
<p><a href="/admin/">Back</a></p>
</div>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends "admin/admin_base.html" %}
{% block content %}
<div class="centered">
<h2>Internal Server Error</h2>
<p>It's on us. <a href="javascript:history.go(0)">Refresh the page</a>.</p>
</div>
{% endblock %}

View file

@ -5,7 +5,7 @@
{{ title_tag("Admin") }} {{ title_tag("Admin") }}
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/static/css/style.css"> <link rel="stylesheet" type="text/css" href="/admin/style.css">
{% for private_style in private_styles %} {% for private_style in private_styles %}
<link rel="stylesheet" href="{{ private_style }}" /> <link rel="stylesheet" href="{{ private_style }}" />
{% endfor %} {% endfor %}

View file

@ -1,6 +1,6 @@
{% macro embed_post(p) %} {% macro embed_post(p) %}
<div id="post-{{ p.id | to_b32l }}" class="post-frame" data-endpoint="{{ p.id | to_b32l }}"> <div id="post-{{ p.id | to_b32l }}" class="post-frame" data-endpoint="{{ p.id | to_b32l }}">
<h3 class="message-title"><a href="{{ p.url() }}">{{ p.title }}</a></h3> <h3 class="message-title"><a href="/={{ p.id | to_b32l }}">{{ p.title }}</a></h3>
<div class="message-meta">Posted by <a href="{{ p.author.url() }}">@{{ p.author.username }}</a> <div class="message-meta">Posted by <a href="{{ p.author.url() }}">@{{ p.author.username }}</a>
{% if p.parent_post %} {% if p.parent_post %}
as a comment on <a href="{{ p.parent_post.url() }}">post “{{ p.parent_post.title }}”</a> as a comment on <a href="{{ p.parent_post.url() }}">post “{{ p.parent_post.title }}”</a>

View file

@ -2,9 +2,10 @@
import datetime import datetime
from functools import wraps from functools import wraps
import os
from typing import Callable from typing import Callable
import warnings import warnings
from quart import Blueprint, abort, redirect, render_template, request, url_for from quart import Blueprint, abort, redirect, render_template, request, send_from_directory, url_for
from quart_auth import current_user from quart_auth import current_user
from markupsafe import Markup from markupsafe import Markup
from sqlalchemy import insert, select, update from sqlalchemy import insert, select, update
@ -23,11 +24,11 @@ current_user: UserLoader
def admin_required(func: Callable): def admin_required(func: Callable):
@wraps(func) @wraps(func)
def wrapper(*a, **ka): async def wrapper(*a, **ka):
user: User = current_user.user user: User = current_user.user
if not user or not user.is_administrator: if not user or not user.is_administrator:
abort(403) abort(403)
return func(*a, **ka) return await func(*a, **ka)
return wrapper return wrapper
@ -155,10 +156,14 @@ def escalate_report(target, source: PostReport):
async def homepage(): async def homepage():
return await render_template('admin/admin_home.html') return await render_template('admin/admin_home.html')
@bp.route('/admin/style.css')
async def style_css():
return await send_from_directory(os.path.dirname(os.path.dirname(__file__)) + '/static/css', 'style.css')
@bp.route('/admin/reports/') @bp.route('/admin/reports/')
@admin_required @admin_required
async def reports(): async def reports():
report_list = db.paginate(select(PostReport).order_by(PostReport.id.desc())) report_list = await db.paginate(select(PostReport).order_by(PostReport.id.desc()))
return await render_template('admin/admin_reports.html', return await render_template('admin/admin_reports.html',
report_list=report_list, report_reasons=REPORT_REASON_STRINGS) report_list=report_list, report_reasons=REPORT_REASON_STRINGS)
@ -169,10 +174,13 @@ async def report_detail(id: int):
report = (await session.execute(select(PostReport).where(PostReport.id == id))).scalar() report = (await session.execute(select(PostReport).where(PostReport.id == id))).scalar()
if report is None: if report is None:
abort(404) abort(404)
target = await report.target()
if target is None:
abort(404)
if request.method == 'POST': if request.method == 'POST':
form = await get_request_form() form = await get_request_form()
action = REPORT_ACTIONS[form['do']] action = REPORT_ACTIONS[form['do']]
await action(report.target(), report) await action(target, report)
return redirect(url_for('admin.reports')) return redirect(url_for('admin.reports'))
return await render_template('admin/admin_report_detail.html', report=report, return await render_template('admin/admin_report_detail.html', report=report,
report_reasons=REPORT_REASON_STRINGS) report_reasons=REPORT_REASON_STRINGS)
@ -188,7 +196,7 @@ async def strikes():
@bp.route('/admin/users/') @bp.route('/admin/users/')
@admin_required @admin_required
async def users(): async def users():
user_list = db.paginate(select(User).order_by(User.joined_at.desc())) user_list = await db.paginate(select(User).order_by(User.joined_at.desc()))
return await render_template('admin/admin_users.html', return await render_template('admin/admin_users.html',
user_list=user_list, account_status_string=colorized_account_status_string) user_list=user_list, account_status_string=colorized_account_status_string)
@ -219,5 +227,7 @@ async def user_detail(id: int):
else: else:
abort(400) abort(400)
strikes = (await session.execute(select(UserStrike).where(UserStrike.user_id == id).order_by(UserStrike.id.desc()))).scalars() strikes = (await session.execute(select(UserStrike).where(UserStrike.user_id == id).order_by(UserStrike.id.desc()))).scalars()
return render_template('admin/admin_user_detail.html', u=u, return await render_template('admin/admin_user_detail.html', u=u,
report_reasons=REPORT_REASON_STRINGS, account_status_string=colorized_account_status_string, strikes=strikes) report_reasons=REPORT_REASON_STRINGS, account_status_string=colorized_account_status_string, strikes=strikes)

View file

@ -5,6 +5,7 @@ from __future__ import annotations
from quart import Blueprint, render_template, request from quart import Blueprint, render_template, request
from quart_auth import current_user, login_required from quart_auth import current_user, login_required
from sqlalchemy import insert, select from sqlalchemy import insert, select
from suou import Snowflake
from freak import UserLoader from freak import UserLoader
from ..models import REPORT_TARGET_COMMENT, REPORT_TARGET_POST, ReportReason, User, post_report_reasons, Comment, Post, PostReport, REPORT_REASONS, db from ..models import REPORT_TARGET_COMMENT, REPORT_TARGET_POST, ReportReason, User, post_report_reasons, Comment, Post, PostReport, REPORT_REASONS, db
@ -35,7 +36,7 @@ async def report_post(id: int):
reason_code = REPORT_REASONS[reason] reason_code = REPORT_REASONS[reason]
)) ))
session.commit() session.commit()
return await render_template('reports/report_done.html', back_to_url=p.url()) return await render_template('reports/report_done.html', back_to_url='/=' + Snowflake(p.id).to_b32l())
return await render_template('reports/report_post.html', id = id, return await render_template('reports/report_post.html', id = id,
report_reasons = post_report_reasons, description_text=description_text) report_reasons = post_report_reasons, description_text=description_text)