X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=app%2Fblueprints%2Fthreads%2F__init__.py;h=5380389da67a43e6e326d40c3cd7ccac58b21b5c;hb=92fb54556ad0409a519c308e7e34b63e11621903;hp=1455c5df0fa40f03f3b467c046f7db103dc319a7;hpb=d91f537bdd4915448a189b238051905975324d71;p=cheatdb.git diff --git a/app/blueprints/threads/__init__.py b/app/blueprints/threads/__init__.py index 1455c5d..5380389 100644 --- a/app/blueprints/threads/__init__.py +++ b/app/blueprints/threads/__init__.py @@ -1,4 +1,4 @@ -# Content DB +# ContentDB # Copyright (C) 2018 rubenwardy # # This program is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ bp = Blueprint("threads", __name__) from flask_user import * from app.models import * -from app.utils import addNotification, clearNotifications +from app.utils import addNotification, clearNotifications, isYes, addAuditLog import datetime @@ -60,7 +60,7 @@ def subscribe(id): thread.watchers.append(current_user) db.session.commit() - return redirect(url_for("threads.view", id=id)) + return redirect(thread.getViewURL()) @bp.route("/threads//unsubscribe/", methods=["POST"]) @@ -75,15 +75,115 @@ def unsubscribe(id): thread.watchers.remove(current_user) db.session.commit() else: - flash("Not subscribed to thread", "success") + flash("Already not subscribed!", "success") - return redirect(url_for("threads.view", id=id)) + return redirect(thread.getViewURL()) + + +@bp.route("/threads//set-lock/", methods=["POST"]) +@login_required +def set_lock(id): + thread = Thread.query.get(id) + if thread is None or not thread.checkPerm(current_user, Permission.LOCK_THREAD): + abort(404) + + thread.locked = isYes(request.args.get("lock")) + if thread.locked is None: + abort(400) + + msg = None + if thread.locked: + msg = "Locked thread '{}'".format(thread.title) + flash("Locked thread", "success") + else: + msg = "Unlocked thread '{}'".format(thread.title) + flash("Unlocked thread", "success") + + addNotification(thread.watchers, current_user, msg, thread.getViewURL(), thread.package) + addAuditLog(AuditSeverity.MODERATION, current_user, msg, thread.getViewURL(), thread.package) + + db.session.commit() + + return redirect(thread.getViewURL()) + + +@bp.route("/threads//delete/", methods=["GET", "POST"]) +@login_required +def delete_reply(id): + thread = Thread.query.get(id) + if thread is None: + abort(404) + + reply_id = request.args.get("reply") + if reply_id is None: + abort(404) + + reply = ThreadReply.query.get(reply_id) + if reply is None or reply.thread != thread: + abort(404) + + if thread.replies[0] == reply: + flash("Cannot delete thread opening post!", "danger") + return redirect(thread.getViewURL()) + + if not reply.checkPerm(current_user, Permission.DELETE_REPLY): + abort(403) + + if request.method == "GET": + return render_template("threads/delete_reply.html", thread=thread, reply=reply) + + msg = "Deleted reply by {}".format(reply.author.display_name) + addAuditLog(AuditSeverity.MODERATION, current_user, msg, thread.getViewURL(), thread.package, reply.comment) + + db.session.delete(reply) + db.session.commit() + + return redirect(thread.getViewURL()) + + +class CommentForm(FlaskForm): + comment = TextAreaField("Comment", [InputRequired(), Length(10, 2000)]) + submit = SubmitField("Comment") + + +@bp.route("/threads//edit/", methods=["GET", "POST"]) +@login_required +def edit_reply(id): + thread = Thread.query.get(id) + if thread is None: + abort(404) + + reply_id = request.args.get("reply") + if reply_id is None: + abort(404) + + reply = ThreadReply.query.get(reply_id) + if reply is None or reply.thread != thread: + abort(404) + + if not reply.checkPerm(current_user, Permission.EDIT_REPLY): + abort(403) + + form = CommentForm(formdata=request.form, obj=reply) + if request.method == "POST" and form.validate(): + comment = form.comment.data + + msg = "Edited reply by {}".format(reply.author.display_name) + severity = AuditSeverity.NORMAL if current_user == reply.author else AuditSeverity.MODERATION + addNotification(reply.author, current_user, msg, thread.getViewURL(), thread.package) + addAuditLog(severity, current_user, msg, thread.getViewURL(), thread.package, reply.comment) + + reply.comment = comment + + db.session.commit() + + return redirect(thread.getViewURL()) + + return render_template("threads/edit_reply.html", thread=thread, reply=reply, form=form) @bp.route("/threads//", methods=["GET", "POST"]) def view(id): - clearNotifications(url_for("threads.view", id=id)) - thread = Thread.query.get(id) if thread is None or not thread.checkPerm(current_user, Permission.SEE_THREAD): abort(404) @@ -91,14 +191,15 @@ def view(id): if current_user.is_authenticated and request.method == "POST": comment = request.form["comment"] + if not thread.checkPerm(current_user, Permission.COMMENT_THREAD): + flash("You cannot comment on this thread", "danger") + return redirect(thread.getViewURL()) + if not current_user.canCommentRL(): flash("Please wait before commenting again", "danger") - if package: - return redirect(package.getDetailsURL()) - else: - return redirect(url_for("homepage.home")) + return redirect(thread.getViewURL()) - if len(comment) <= 500 and len(comment) > 3: + if len(comment) <= 2000 and len(comment) > 3: reply = ThreadReply() reply.author = current_user reply.comment = comment @@ -108,30 +209,25 @@ def view(id): if not current_user in thread.watchers: thread.watchers.append(current_user) - msg = None - if thread.package is None: - msg = "New comment on '{}'".format(thread.title) - else: - msg = "New comment on '{}' on package {}".format(thread.title, thread.package.title) - - - addNotification(thread.watchers, current_user, msg, url_for("threads.view", id=thread.id)) + msg = "New comment on '{}'".format(thread.title) + addNotification(thread.watchers, current_user, msg, thread.getViewURL(), thread.package) db.session.commit() - return redirect(url_for("threads.view", id=id)) + return redirect(thread.getViewURL()) else: - flash("Comment needs to be between 3 and 500 characters.") + flash("Comment needs to be between 3 and 2000 characters.") return render_template("threads/view.html", thread=thread) class ThreadForm(FlaskForm): title = StringField("Title", [InputRequired(), Length(3,100)]) - comment = TextAreaField("Comment", [InputRequired(), Length(10, 500)]) + comment = TextAreaField("Comment", [InputRequired(), Length(10, 2000)]) private = BooleanField("Private") submit = SubmitField("Open Thread") + @bp.route("/threads/new/", methods=["GET", "POST"]) @login_required def new(): @@ -161,7 +257,7 @@ def new(): # Only allow creating one thread when not approved elif is_review_thread and package.review_thread is not None: flash("A review thread already exists!", "danger") - return redirect(url_for("threads.view", id=package.review_thread.id)) + return redirect(package.review_thread.getViewURL()) elif not current_user.canOpenThreadRL(): flash("Please wait before opening another thread", "danger") @@ -202,19 +298,20 @@ def new(): if is_review_thread: package.review_thread = thread - notif_msg = None + if package.state == PackageState.READY_FOR_REVIEW and current_user not in package.maintainers: + package.state = PackageState.CHANGES_NEEDED + + + notif_msg = "New thread '{}'".format(thread.title) if package is not None: - notif_msg = "New thread '{}' on package {}".format(thread.title, package.title) - addNotification(package.maintainers, current_user, notif_msg, url_for("threads.view", id=thread.id)) - else: - notif_msg = "New thread '{}'".format(thread.title) + addNotification(package.maintainers, current_user, notif_msg, thread.getViewURL(), package) editors = User.query.filter(User.rank >= UserRank.EDITOR).all() - addNotification(editors, current_user, notif_msg, url_for("threads.view", id=thread.id)) + addNotification(editors, current_user, notif_msg, thread.getViewURL(), package) db.session.commit() - return redirect(url_for("threads.view", id=thread.id)) + return redirect(thread.getViewURL()) return render_template("threads/new.html", form=form, allow_private_change=allow_change, package=package)