]> git.lizzy.rs Git - cheatdb.git/commitdiff
Add the ability to lock threads
authorrubenwardy <rw@rubenwardy.com>
Sat, 11 Jul 2020 00:34:51 +0000 (01:34 +0100)
committerrubenwardy <rw@rubenwardy.com>
Sat, 11 Jul 2020 00:42:47 +0000 (01:42 +0100)
app/blueprints/threads/__init__.py
app/models.py
app/templates/macros/threads.html
app/templates/threads/view.html
migrations/versions/8679442b8dde_.py [new file with mode: 0644]

index a4728a0352926bddf7ad9abff2a636bd7bd3720e..e54c7c82ff53909cd44b2df25b86163c56ee1ed3 100644 (file)
@@ -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
 
 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/<int:id>/unsubscribe/", methods=["POST"])
@@ -75,9 +75,30 @@ 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/<int:id>/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)
+
+       db.session.commit()
+
+       if thread.locked:
+               flash("Locked thread", "success")
+       else:
+               flash("Unlocked thread", "success")
+
+       return redirect(thread.getViewURL())
 
 
 @bp.route("/threads/<int:id>/", methods=["GET", "POST"])
@@ -89,12 +110,13 @@ 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:
                        reply = ThreadReply()
index acd427a3cb737307df2e8d6da1a419b2c0dfbe5a..d37dea30603e1a635c0eb77acf0c8e29fb41d3f4 100644 (file)
@@ -90,6 +90,8 @@ class Permission(enum.Enum):
        EDIT_EDITREQUEST   = "EDIT_EDITREQUEST"
        SEE_THREAD         = "SEE_THREAD"
        CREATE_THREAD      = "CREATE_THREAD"
+       COMMENT_THREAD     = "COMMENT_THREAD"
+       LOCK_THREAD        = "LOCK_THREAD"
        UNAPPROVE_PACKAGE  = "UNAPPROVE_PACKAGE"
        TOPIC_DISCARD      = "TOPIC_DISCARD"
        CREATE_TOKEN       = "CREATE_TOKEN"
@@ -1075,12 +1077,14 @@ class Thread(db.Model):
        package_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True)
        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_id  = db.Column(db.Integer, db.ForeignKey("package_review.id"), nullable=True)
+       review     = db.relationship("PackageReview", foreign_keys=[review_id])
 
        author_id  = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
        title      = db.Column(db.String(100), nullable=False)
-       private    = db.Column(db.Boolean, server_default="0")
+       private    = db.Column(db.Boolean, server_default="0", nullable=False)
+
+       locked     = db.Column(db.Boolean, server_default="0", nullable=False)
 
        created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
 
@@ -1111,8 +1115,16 @@ class Thread(db.Model):
                if self.package:
                        isMaintainer = isMaintainer or user in self.package.maintainers
 
+               canSee = not self.private or isMaintainer or user.rank.atLeast(UserRank.EDITOR)
+
                if perm == Permission.SEE_THREAD:
-                       return not self.private or isMaintainer or user.rank.atLeast(UserRank.EDITOR)
+                       return canSee
+
+               elif perm == Permission.COMMENT_THREAD:
+                       return canSee and (not self.locked or user.rank.atLeast(UserRank.MODERATOR))
+
+               elif perm == Permission.LOCK_THREAD:
+                       return user.rank.atLeast(UserRank.MODERATOR)
 
                else:
                        raise Exception("Permission {} is not related to threads".format(perm.name))
index 4732af20c81210ed7b9a1b5d7d0beaa8ea06f140..f9f298a5f7e49b9e3d09771ede1b76f152f87320 100644 (file)
@@ -8,7 +8,7 @@
                                <img class="img-responsive user-photo img-thumbnail img-thumbnail-1" src="{{ r.author.getProfilePicURL() }}">
                        </a>
                </div>
-               <div class="col">
+               <div class="col pr-0">
                        <div class="card">
                                <div class="card-header">
                                        <a class="author {{ r.author.rank.name }}"
        {% endfor %}
 </ul>
 
+{% if thread.locked %}
+       <p class="my-0 py-4 text-center">
+               <i class="fas fa-lock mr-3"></i>
+               {{ _("This thread has been locked by a moderator.") }}
+       </p>
+{% endif %}
+
 {% if current_user.is_authenticated %}
 <div class="row mt-0 mb-4 comments mx-0">
        <div class="col-md-1 p-1">
                                <a name="reply"></a>
                        </div>
 
-                       {% if current_user.canCommentRL() %}
+                       {% if not current_user.canCommentRL() %}
+                               <div class="card-body">
+                                       <textarea class="form-control" readonly disabled>{{ _("Please wait before commenting again.") }}</textarea><br />
+                                       <input class="btn btn-primary" type="submit" disabled value="Comment" />
+                               </div>
+                       {% elif not thread.checkPerm(current_user, "COMMENT_THREAD") %}
+                               <div class="card-body">
+                                       {% if thread.locked %}
+                                               <textarea class="form-control" readonly disabled>{{ _("This thread has been locked.") }}</textarea><br />
+                                       {% else %}
+                                               <textarea class="form-control" readonly disabled>{{ _("You don't have permission to post.") }}</textarea><br />
+                                       {% endif %}
+                                       <input class="btn btn-primary" type="submit" disabled value="Comment" />
+                               </div>
+                       {% else %}
                                <form method="post" action="{{ url_for('threads.view', id=thread.id)}}" class="card-body">
                                        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
                                        <textarea class="form-control markdown" required maxlength=500 name="comment"></textarea><br />
                                        <input class="btn btn-primary" type="submit" value="Comment" />
                                </form>
-                       {% else %}
-                               <div class="card-body">
-                                       <textarea class="form-control" readonly disabled>Please wait before commenting again.</textarea><br />
-                                       <input class="btn btn-primary" type="submit" disabled value="Comment" />
-                               </div>
                        {% endif %}
                </div>
        </div>
index ef53d1f526b408e48e6a8ccdf5fa4f89e776f033..f92ef3996e4ffe0b2a8ddb025f045f9cc996abec 100644 (file)
                                <input type="submit" class="btn btn-primary" value="Subscribe" />
                        </form>
                {% endif %}
+               {% if thread and thread.checkPerm(current_user, "LOCK_THREAD") %}
+                       {% if thread.locked %}
+                               <form method="post" action="{{ url_for('threads.set_lock', id=thread.id, lock=0) }}" class="float-right mr-2">
+                                       <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
+                                       <input type="submit" class="btn btn-secondary" value="{{ _('Unlock Thread') }}" />
+                               </form>
+                       {% else %}
+                               <form method="post" action="{{ url_for('threads.set_lock', id=thread.id, lock=1) }}" class="float-right mr-2">
+                                       <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
+                                       <input type="submit" class="btn btn-secondary" value="{{ _('Lock Thread') }}" />
+                               </form>
+                       {% endif %}
+               {% endif %}
        {% endif %}
 
        {% if current_user == thread.author and thread.review %}
diff --git a/migrations/versions/8679442b8dde_.py b/migrations/versions/8679442b8dde_.py
new file mode 100644 (file)
index 0000000..337d0fc
--- /dev/null
@@ -0,0 +1,28 @@
+"""empty message
+
+Revision ID: 8679442b8dde
+Revises: f612e293070a
+Create Date: 2020-07-11 00:14:02.330903
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '8679442b8dde'
+down_revision = 'f612e293070a'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.add_column('thread', sa.Column('locked', sa.Boolean(), server_default='0', nullable=False))
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_column('thread', 'locked')
+    # ### end Alembic commands ###