diff --git a/nyaa/forms.py b/nyaa/forms.py index db468d0..5f62d03 100644 --- a/nyaa/forms.py +++ b/nyaa/forms.py @@ -284,7 +284,6 @@ class DeleteForm(FlaskForm): class BanForm(FlaskForm): ban_user = SubmitField("Delete & Ban and Ban User") ban_userip = SubmitField("Delete & Ban and Ban User+IP") - nuke = SubmitField("Delete & Ban all torrents") unban = SubmitField("Unban") _validator = DataRequired() @@ -299,6 +298,10 @@ class BanForm(FlaskForm): ]) +class NukeForm(FlaskForm): + nuke_torrents = SubmitField("\U0001F4A3 Nuke Torrents") + + class UploadForm(FlaskForm): torrent_file = FileField('Torrent file', [ FileRequired() diff --git a/nyaa/templates/user.html b/nyaa/templates/user.html index a04243b..759803a 100644 --- a/nyaa/templates/user.html +++ b/nyaa/templates/user.html @@ -104,30 +104,34 @@
-
+
{% if not user.is_banned %} {{ ban_form.ban_user(value="Ban User", class="btn btn-danger") }} {% else %} {% endif %}
-
+
{% if not ipbanned %} {{ ban_form.ban_userip(value="Ban User+IP", class="btn btn-danger") }} {% else %} {% endif %}
-
- {% if g.user.is_superadmin %} - {{ ban_form.nuke(value="\U0001F4A3 Nuke Torrents", class="btn btn-danger") }} - {% else %} - - {% endif %} -
{% endif %} + {% if g.user.is_superadmin %} +
+
+ {{ nuke_form.csrf_token }} +
+
+ {{ nuke_form.nuke_torrents(class="btn btn-danger", formaction=url_for('users.nuke_user_torrents', user_name=user.username)) }} +
+
+
+ {% endif %}
diff --git a/nyaa/utils.py b/nyaa/utils.py index 8424ef3..54741f1 100644 --- a/nyaa/utils.py +++ b/nyaa/utils.py @@ -4,6 +4,8 @@ import random import string from collections import OrderedDict +import flask + def sha1_hash(input_bytes): """ Hash given bytes with hashlib.sha1 and return the digest (as bytes) """ @@ -78,3 +80,13 @@ def chain_get(source, *args): if value is not sentinel: return value return None + + +def admin_only(f): + @functools.wraps(f) + def wrapper(*args, **kwargs): + if flask.g.user and flask.g.user.is_superadmin: + return f(*args, **kwargs) + else: + flask.abort(401) + return wrapper diff --git a/nyaa/views/users.py b/nyaa/views/users.py index e4a84b1..229df90 100644 --- a/nyaa/views/users.py +++ b/nyaa/views/users.py @@ -13,7 +13,7 @@ from nyaa import forms, models from nyaa.extensions import db from nyaa.search import (DEFAULT_MAX_SEARCH_RESULT, DEFAULT_PER_PAGE, SERACH_PAGINATE_DISPLAY_MSG, _generate_query_string, search_db, search_elastic) -from nyaa.utils import chain_get, sha1_hash +from nyaa.utils import admin_only, chain_get, sha1_hash app = flask.current_app bp = flask.Blueprint('users', __name__) @@ -30,6 +30,7 @@ def view_user(user_name): ban_form = None bans = None ipbanned = None + nuke_form = None if flask.g.user and flask.g.user.is_moderator and flask.g.user.level > user.level: admin_form = forms.UserForm() default, admin_form.user_class.choices = _create_user_class_choices(user) @@ -37,6 +38,7 @@ def view_user(user_name): admin_form.user_class.data = default ban_form = forms.BanForm() + nuke_form = forms.NukeForm() if flask.request.method == 'POST': doban = (ban_form.ban_user.data or ban_form.unban.data or ban_form.ban_userip.data) bans = models.Ban.banned(user.id, user.last_login_ip).all() @@ -103,38 +105,6 @@ def view_user(user_name): flask.flash(flask.Markup('User has been successfully {0}.'.format(action)), 'success') return flask.redirect(url) - if flask.request.method == 'POST' and ban_form and ban_form.nuke.data: - if flask.g.user.is_superadmin: - nyaa_banned = 0 - sukebei_banned = 0 - for t in chain(user.nyaa_torrents, user.sukebei_torrents): - t.deleted = True - t.banned = True - db.session.add(t) - if isinstance(t, models.NyaaTorrent): - db.session.add(models.NyaaTrackerApi(t.info_hash, 'remove')) - nyaa_banned += 1 - else: - db.session.add(models.SukebeiTrackerApi(t.info_hash, 'remove')) - sukebei_banned += 1 - - for log_flavour, num in ((models.NyaaAdminLog, nyaa_banned), - (models.SukebeiAdminLog, sukebei_banned)): - if num > 0: - log = "Nuked {0} torrents of [{1}]({2})".format(num, - user.username, - url) - adminlog = log_flavour(log=log, admin_id=flask.g.user.id) - db.session.add(adminlog) - - db.session.commit() - flask.flash('Torrents of {0} have been nuked.'.format(user.username), - 'success') - return flask.redirect(url) - else: - flask.flash('Insufficient permissions to nuke.', 'danger') - return flask.redirect(url) - req_args = flask.request.args search_term = chain_get(req_args, 'q', 'term') @@ -219,6 +189,7 @@ def view_user(user_name): rss_filter=rss_query_string, admin_form=admin_form, ban_form=ban_form, + nuke_form=nuke_form, bans=bans, ipbanned=ipbanned) @@ -283,6 +254,45 @@ def activate_user(payload): return flask.redirect(flask.url_for('main.home')) +@bp.route('/user//nuke/torrents', methods=['POST']) +@admin_only +def nuke_user_torrents(user_name): + user = models.User.by_username(user_name) + if not user: + flask.abort(404) + + nuke_form = forms.NukeForm(flask.request.form) + if not nuke_form.validate(): + flask.abort(401) + url = flask.url_for('users.view_user', user_name=user.username) + nyaa_banned = 0 + sukebei_banned = 0 + for t in chain(user.nyaa_torrents, user.sukebei_torrents): + t.deleted = True + t.banned = True + db.session.add(t) + if isinstance(t, models.NyaaTorrent): + db.session.add(models.NyaaTrackerApi(t.info_hash, 'remove')) + nyaa_banned += 1 + else: + db.session.add(models.SukebeiTrackerApi(t.info_hash, 'remove')) + sukebei_banned += 1 + + for log_flavour, num in ((models.NyaaAdminLog, nyaa_banned), + (models.SukebeiAdminLog, sukebei_banned)): + if num > 0: + log = "Nuked {0} torrents of [{1}]({2})".format(num, + user.username, + url) + adminlog = log_flavour(log=log, admin_id=flask.g.user.id) + db.session.add(adminlog) + + db.session.commit() + flask.flash('Torrents of {0} have been nuked.'.format(user.username), + 'success') + return flask.redirect(url) + + def _create_user_class_choices(user): choices = [('regular', 'Regular')] default = 'regular'