mirror of
https://gitlab.com/SIGBUS/nyaa.git
synced 2024-12-22 10:00:01 +00:00
Expose soft delete to users and allow reuploading of deleted torrents. (#331)
Add banning torrents for moderators which disallows reuploading. New delete UI.
This commit is contained in:
parent
81d8b0f86b
commit
e728ca1818
|
@ -45,6 +45,11 @@ def _replace_utf8_values(dict_or_list):
|
|||
def handle_torrent_upload(upload_form, uploading_user=None, fromAPI=False):
|
||||
torrent_data = upload_form.torrent_file.parsed_data
|
||||
|
||||
# Delete exisiting torrent which is marked as deleted
|
||||
if torrent_data.db_id is not None:
|
||||
models.Torrent.query.filter_by(id=torrent_data.db_id).delete()
|
||||
db.session.commit()
|
||||
|
||||
# The torrent has been validated and is safe to access with ['foo'] etc - all relevant
|
||||
# keys and values have been checked for (see UploadForm in forms.py for details)
|
||||
info_dict = torrent_data.torrent_dict['info']
|
||||
|
@ -62,7 +67,8 @@ def handle_torrent_upload(upload_form, uploading_user=None, fromAPI=False):
|
|||
# In case no encoding, assume UTF-8.
|
||||
torrent_encoding = torrent_data.torrent_dict.get('encoding', b'utf-8').decode('utf-8')
|
||||
|
||||
torrent = models.Torrent(info_hash=torrent_data.info_hash,
|
||||
torrent = models.Torrent(id=torrent_data.db_id,
|
||||
info_hash=torrent_data.info_hash,
|
||||
display_name=display_name,
|
||||
torrent_name=torrent_data.filename,
|
||||
information=information,
|
||||
|
|
|
@ -8,7 +8,7 @@ from flask_wtf.file import FileField, FileRequired
|
|||
from flask_wtf.recaptcha import RecaptchaField
|
||||
from flask_wtf.recaptcha.validators import Recaptcha as RecaptchaValidator
|
||||
from wtforms import (BooleanField, HiddenField, PasswordField, SelectField, StringField,
|
||||
TextAreaField)
|
||||
SubmitField, TextAreaField)
|
||||
from wtforms.validators import (DataRequired, Email, EqualTo, Length, Optional, Regexp,
|
||||
StopValidation, ValidationError)
|
||||
from wtforms.widgets import Select as SelectWidget # For DisabledSelectField
|
||||
|
@ -186,6 +186,13 @@ class EditForm(FlaskForm):
|
|||
])
|
||||
|
||||
|
||||
class DeleteForm(FlaskForm):
|
||||
delete = SubmitField("Delete")
|
||||
ban = SubmitField("Delete & Ban")
|
||||
undelete = SubmitField("Undelete")
|
||||
unban = SubmitField("Unban")
|
||||
|
||||
|
||||
class UploadForm(FlaskForm):
|
||||
torrent_file = FileField('Torrent file', [
|
||||
FileRequired()
|
||||
|
@ -281,14 +288,18 @@ class UploadForm(FlaskForm):
|
|||
|
||||
# Check if the info_hash exists already in the database
|
||||
existing_torrent = models.Torrent.by_info_hash(info_hash)
|
||||
if existing_torrent:
|
||||
raise ValidationError('That torrent already exists (#{})'.format(existing_torrent.id))
|
||||
existing_torrent_id = existing_torrent.id if existing_torrent else None
|
||||
if existing_torrent and not existing_torrent.deleted:
|
||||
raise ValidationError('This torrent already exists (#{})'.format(existing_torrent.id))
|
||||
if existing_torrent and existing_torrent.banned:
|
||||
raise ValidationError('This torrent is banned'.format(existing_torrent.id))
|
||||
|
||||
# Torrent is legit, pass original filename and dict along
|
||||
field.parsed_data = TorrentFileData(filename=os.path.basename(field.data.filename),
|
||||
torrent_dict=torrent_dict,
|
||||
info_hash=info_hash,
|
||||
bencoded_info_dict=bencoded_info_dict)
|
||||
bencoded_info_dict=bencoded_info_dict,
|
||||
db_id=existing_torrent_id)
|
||||
|
||||
|
||||
class UserForm(FlaskForm):
|
||||
|
|
|
@ -98,6 +98,7 @@ class TorrentFlags(IntEnum):
|
|||
REMAKE = 8
|
||||
COMPLETE = 16
|
||||
DELETED = 32
|
||||
BANNED = 64
|
||||
|
||||
|
||||
class TorrentBase(DeclarativeHelperBase):
|
||||
|
@ -250,6 +251,7 @@ class TorrentBase(DeclarativeHelperBase):
|
|||
anonymous = FlagProperty(TorrentFlags.ANONYMOUS)
|
||||
hidden = FlagProperty(TorrentFlags.HIDDEN)
|
||||
deleted = FlagProperty(TorrentFlags.DELETED)
|
||||
banned = FlagProperty(TorrentFlags.BANNED)
|
||||
trusted = FlagProperty(TorrentFlags.TRUSTED)
|
||||
remake = FlagProperty(TorrentFlags.REMAKE)
|
||||
complete = FlagProperty(TorrentFlags.COMPLETE)
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<form method="POST" enctype="multipart/form-data">
|
||||
{{ form.csrf_token }}
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ render_field(form.display_name, class_='form-control', placeholder='Display name') }}
|
||||
|
@ -46,14 +45,6 @@
|
|||
<span class="glyphicon glyphicon-unchecked"></span>
|
||||
Hidden
|
||||
</label>
|
||||
{% if g.user.is_moderator %}
|
||||
<label class="btn btn-primary {% if torrent.deleted %}active{% endif %}">
|
||||
{{ form.is_deleted }}
|
||||
<span class="glyphicon glyphicon-check"></span>
|
||||
<span class="glyphicon glyphicon-unchecked"></span>
|
||||
Deleted
|
||||
</label>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="hidden-xl"><br></div>
|
||||
<div class="btn-group" data-toggle="buttons">
|
||||
|
@ -93,4 +84,75 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-5"">
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Danger Zone</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST" action="{{ url_for('torrents.delete', torrent_id=torrent.id) }}">
|
||||
{{ delete_form.csrf_token }}
|
||||
|
||||
{% if not torrent.deleted %}
|
||||
<p class="lead">
|
||||
Delete torrent.
|
||||
{{ delete_form.delete(class="btn btn-danger pull-right") }}
|
||||
</p>
|
||||
<p>
|
||||
Deleted torrents are retained for backup purposes.<br>
|
||||
You (or someone else) will be able to reupload the torrent.
|
||||
</p>
|
||||
|
||||
{% if g.user.is_moderator %}
|
||||
<hr>
|
||||
<p class="lead">
|
||||
Delete and ban torrent.
|
||||
{{ delete_form.ban(class="btn btn-danger pull-right") }}
|
||||
</p>
|
||||
<p>
|
||||
Soft deletes the torrent and disallows reuploading it.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>This torrent is <strong>deleted</strong>{% if torrent.banned %} and <strong>banned</strong>{% endif %}.</p>
|
||||
<p class="lead">
|
||||
Undelete{% if torrent.banned %} and unban{% endif %} torrent.
|
||||
{{ delete_form.undelete(class="btn btn-info pull-right") }}
|
||||
</p>
|
||||
<p>
|
||||
Undeletes{% if torrent.banned %} and unbans{% endif %} this torrent.
|
||||
</p>
|
||||
|
||||
{% if torrent.banned %}
|
||||
<hr>
|
||||
<p class="lead">
|
||||
Unban torrent.
|
||||
{{ delete_form.unban(class="btn btn-info pull-right") }}
|
||||
</p>
|
||||
<p>
|
||||
Unbans torrent without undeleting it.<br>
|
||||
Allows reuploading this torrent again.
|
||||
</p>
|
||||
{% else%}
|
||||
<hr>
|
||||
<p class="lead">
|
||||
Ban torrent.
|
||||
{{ delete_form.ban(value="Ban", class="btn btn-danger pull-right") }}
|
||||
</p>
|
||||
<p>
|
||||
Bans the torrent.<br>
|
||||
Disallows reuploading this torrent.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -80,6 +80,7 @@ def view_torrent(torrent_id):
|
|||
def edit_torrent(torrent_id):
|
||||
torrent = models.Torrent.by_id(torrent_id)
|
||||
form = forms.EditForm(flask.request.form)
|
||||
delete_form = forms.DeleteForm()
|
||||
form.category.choices = _create_upload_category_choices()
|
||||
|
||||
editor = flask.g.user
|
||||
|
@ -147,9 +148,73 @@ def edit_torrent(torrent_id):
|
|||
|
||||
return flask.render_template('edit.html',
|
||||
form=form,
|
||||
delete_form=delete_form,
|
||||
torrent=torrent)
|
||||
|
||||
|
||||
@bp.route('/view/<int:torrent_id>/delete', endpoint='delete', methods=['POST'])
|
||||
def delete_torrent(torrent_id):
|
||||
torrent = models.Torrent.by_id(torrent_id)
|
||||
form = forms.DeleteForm(flask.request.form)
|
||||
|
||||
editor = flask.g.user
|
||||
|
||||
if not torrent:
|
||||
flask.abort(404)
|
||||
|
||||
# Only allow admins edit deleted torrents
|
||||
if torrent.deleted and not (editor and editor.is_moderator):
|
||||
flask.abort(404)
|
||||
|
||||
# Only allow torrent owners or admins edit torrents
|
||||
if not editor or not (editor is torrent.user or editor.is_moderator):
|
||||
flask.abort(403)
|
||||
|
||||
action = None
|
||||
url = flask.url_for('main.home')
|
||||
|
||||
if form.delete.data and not torrent.deleted:
|
||||
action = 'deleted'
|
||||
torrent.deleted = True
|
||||
db.session.add(torrent)
|
||||
|
||||
elif form.ban.data and not torrent.banned and editor.is_moderator:
|
||||
torrent.banned = True
|
||||
if not torrent.deleted:
|
||||
torrent.deleted = True
|
||||
action = 'deleted and banned'
|
||||
else:
|
||||
action = 'banned'
|
||||
db.session.add(torrent)
|
||||
|
||||
elif form.undelete.data and torrent.deleted:
|
||||
action = 'undeleted'
|
||||
torrent.deleted = False
|
||||
torrent.banned = False
|
||||
db.session.add(torrent)
|
||||
|
||||
elif form.unban.data and torrent.banned:
|
||||
action = 'unbanned'
|
||||
torrent.banned = False
|
||||
db.session.add(torrent)
|
||||
|
||||
if not action:
|
||||
flask.flash(flask.Markup('What the fuck are you doing?'), 'danger')
|
||||
return flask.redirect(flask.url_for('torrents.edit', torrent_id=torrent.id))
|
||||
|
||||
if editor.is_moderator:
|
||||
url = flask.url_for('torrents.view', torrent_id=torrent.id)
|
||||
if editor is not torrent.user:
|
||||
log = "Torrent [#{0}]({1}) has been {2}".format(torrent.id, url, action)
|
||||
adminlog = models.AdminLog(log=log, admin_id=editor.id)
|
||||
db.session.add(adminlog)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
flask.flash(flask.Markup('Torrent has been successfully {0}.'.format(action)), 'info')
|
||||
return flask.redirect(url)
|
||||
|
||||
|
||||
@bp.route('/view/<int:torrent_id>/magnet')
|
||||
def redirect_magnet(torrent_id):
|
||||
torrent = models.Torrent.by_id(torrent_id)
|
||||
|
|
Loading…
Reference in a new issue