From 15821fe7965078d3833a36cfd7d2bd71b9e236e9 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Thu, 3 Dec 2020 23:57:58 +0000 Subject: [PATCH] Add ability to delete threads --- app/blueprints/threads/__init__.py | 28 ++++++++++++++++++++---- app/models.py | 27 ++++++++++++----------- app/templates/threads/delete_thread.html | 22 +++++++++++++++++++ app/templates/threads/view.html | 7 ++++-- 4 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 app/templates/threads/delete_thread.html diff --git a/app/blueprints/threads/__init__.py b/app/blueprints/threads/__init__.py index 5380389..f8c4d8f 100644 --- a/app/blueprints/threads/__init__.py +++ b/app/blueprints/threads/__init__.py @@ -21,10 +21,7 @@ bp = Blueprint("threads", __name__) from flask_user import * from app.models import * -from app.utils import addNotification, clearNotifications, isYes, addAuditLog - -import datetime - +from app.utils import addNotification, isYes, addAuditLog from flask_wtf import FlaskForm from wtforms import * from wtforms.validators import * @@ -107,6 +104,29 @@ def set_lock(id): return redirect(thread.getViewURL()) +@bp.route("/threads//delete/", methods=["GET", "POST"]) +@login_required +def delete_thread(id): + thread = Thread.query.get(id) + if thread is None or not thread.checkPerm(current_user, Permission.DELETE_THREAD): + abort(404) + + if request.method == "GET": + return render_template("threads/delete_thread.html", thread=thread) + + summary = "\n\n".join([("<{}> {}".format(reply.author.display_name, reply.comment)) for reply in thread.replies]) + + msg = "Deleted thread {} by {}".format(thread.title, thread.author.display_name) + + db.session.delete(thread) + + addAuditLog(AuditSeverity.MODERATION, current_user, msg, None, thread.package, summary) + + db.session.commit() + + return redirect(url_for("homepage.home")) + + @bp.route("/threads//delete/", methods=["GET", "POST"]) @login_required def delete_reply(id): diff --git a/app/models.py b/app/models.py index cbb91da..a884a73 100644 --- a/app/models.py +++ b/app/models.py @@ -95,6 +95,7 @@ class Permission(enum.Enum): CREATE_THREAD = "CREATE_THREAD" COMMENT_THREAD = "COMMENT_THREAD" LOCK_THREAD = "LOCK_THREAD" + DELETE_THREAD = "DELETE_THREAD" DELETE_REPLY = "DELETE_REPLY" EDIT_REPLY = "EDIT_REPLY" UNAPPROVE_PACKAGE = "UNAPPROVE_PACKAGE" @@ -130,7 +131,7 @@ class Permission(enum.Enum): return perm.check(user) def display_name_default(context): - return context.get_current_parameters()["username"] + return context.get_current_parameters()["username"] class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) @@ -410,22 +411,22 @@ class PackagePropertyKey(enum.Enum): provides = db.Table("provides", db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True), - db.Column("metapackage_id", db.Integer, db.ForeignKey("meta_package.id"), primary_key=True) + db.Column("metapackage_id", db.Integer, db.ForeignKey("meta_package.id"), primary_key=True) ) Tags = db.Table("tags", - db.Column("tag_id", db.Integer, db.ForeignKey("tag.id"), primary_key=True), - db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True) + db.Column("tag_id", db.Integer, db.ForeignKey("tag.id"), primary_key=True), + db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True) ) ContentWarnings = db.Table("content_warnings", - db.Column("content_warning_id", db.Integer, db.ForeignKey("content_warning.id"), primary_key=True), - db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True) + db.Column("content_warning_id", db.Integer, db.ForeignKey("content_warning.id"), primary_key=True), + db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True) ) maintainers = db.Table("maintainers", - db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True), - db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True) + db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True), + db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True) ) class Dependency(db.Model): @@ -1233,8 +1234,8 @@ class EditRequestChange(db.Model): watchers = db.Table("watchers", - db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True), - db.Column("thread_id", db.Integer, db.ForeignKey("thread.id"), primary_key=True) + db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True), + db.Column("thread_id", db.Integer, db.ForeignKey("thread.id"), primary_key=True) ) class Thread(db.Model): @@ -1244,7 +1245,7 @@ class Thread(db.Model): package = db.relationship("Package", foreign_keys=[package_id]) review_id = db.Column(db.Integer, db.ForeignKey("package_review.id"), nullable=True) - review = db.relationship("PackageReview", foreign_keys=[review_id]) + review = db.relationship("PackageReview", foreign_keys=[review_id], cascade="all, delete") author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) title = db.Column(db.String(100), nullable=False) @@ -1255,7 +1256,7 @@ class Thread(db.Model): created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) replies = db.relationship("ThreadReply", backref="thread", lazy="dynamic", \ - order_by=db.asc("thread_reply_id")) + order_by=db.asc("thread_reply_id"), cascade="all, delete") watchers = db.relationship("User", secondary=watchers, lazy="subquery", \ backref=db.backref("watching", lazy=True)) @@ -1290,7 +1291,7 @@ class Thread(db.Model): elif perm == Permission.COMMENT_THREAD: return canSee and (not self.locked or user.rank.atLeast(UserRank.MODERATOR)) - elif perm == Permission.LOCK_THREAD: + elif perm == Permission.LOCK_THREAD or perm == Permission.DELETE_THREAD: return user.rank.atLeast(UserRank.MODERATOR) else: diff --git a/app/templates/threads/delete_thread.html b/app/templates/threads/delete_thread.html new file mode 100644 index 0000000..7da540a --- /dev/null +++ b/app/templates/threads/delete_thread.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} + +{% block title %} + Delete thread in {{ thread.title }} +{% endblock %} + +{% block content %} +
+ + +

Delete {{ thread.title }} by {{ thread.author.display_name }}

+
+ {{ thread.replies[0].comment | markdown }} +
+
+

Deleting is permanent

+ + Cancel + +
+
+{% endblock %} diff --git a/app/templates/threads/view.html b/app/templates/threads/view.html index f92ef39..7c6987b 100644 --- a/app/templates/threads/view.html +++ b/app/templates/threads/view.html @@ -17,16 +17,19 @@ {% endif %} + {% if thread and thread.checkPerm(current_user, "DELETE_THREAD") %} + {{ _('Delete') }} + {% endif %} {% if thread and thread.checkPerm(current_user, "LOCK_THREAD") %} {% if thread.locked %}
- +
{% else %}
- +
{% endif %} {% endif %}