mirror of
https://github.com/minetest/contentdb.git
synced 2024-12-22 14:02:24 +01:00
Add the ability to lock threads
This commit is contained in:
parent
5f7be4b433
commit
bf927c50f0
@ -21,7 +21,7 @@ bp = Blueprint("threads", __name__)
|
|||||||
|
|
||||||
from flask_user import *
|
from flask_user import *
|
||||||
from app.models import *
|
from app.models import *
|
||||||
from app.utils import addNotification, clearNotifications
|
from app.utils import addNotification, clearNotifications, isYes
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ def subscribe(id):
|
|||||||
thread.watchers.append(current_user)
|
thread.watchers.append(current_user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return redirect(url_for("threads.view", id=id))
|
return redirect(thread.getViewURL())
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/threads/<int:id>/unsubscribe/", methods=["POST"])
|
@bp.route("/threads/<int:id>/unsubscribe/", methods=["POST"])
|
||||||
@ -75,9 +75,30 @@ def unsubscribe(id):
|
|||||||
thread.watchers.remove(current_user)
|
thread.watchers.remove(current_user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
else:
|
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"])
|
@bp.route("/threads/<int:id>/", methods=["GET", "POST"])
|
||||||
@ -89,12 +110,13 @@ def view(id):
|
|||||||
if current_user.is_authenticated and request.method == "POST":
|
if current_user.is_authenticated and request.method == "POST":
|
||||||
comment = request.form["comment"]
|
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():
|
if not current_user.canCommentRL():
|
||||||
flash("Please wait before commenting again", "danger")
|
flash("Please wait before commenting again", "danger")
|
||||||
if package:
|
return redirect(thread.getViewURL())
|
||||||
return redirect(package.getDetailsURL())
|
|
||||||
else:
|
|
||||||
return redirect(url_for("homepage.home"))
|
|
||||||
|
|
||||||
if len(comment) <= 500 and len(comment) > 3:
|
if len(comment) <= 500 and len(comment) > 3:
|
||||||
reply = ThreadReply()
|
reply = ThreadReply()
|
||||||
|
@ -90,6 +90,8 @@ class Permission(enum.Enum):
|
|||||||
EDIT_EDITREQUEST = "EDIT_EDITREQUEST"
|
EDIT_EDITREQUEST = "EDIT_EDITREQUEST"
|
||||||
SEE_THREAD = "SEE_THREAD"
|
SEE_THREAD = "SEE_THREAD"
|
||||||
CREATE_THREAD = "CREATE_THREAD"
|
CREATE_THREAD = "CREATE_THREAD"
|
||||||
|
COMMENT_THREAD = "COMMENT_THREAD"
|
||||||
|
LOCK_THREAD = "LOCK_THREAD"
|
||||||
UNAPPROVE_PACKAGE = "UNAPPROVE_PACKAGE"
|
UNAPPROVE_PACKAGE = "UNAPPROVE_PACKAGE"
|
||||||
TOPIC_DISCARD = "TOPIC_DISCARD"
|
TOPIC_DISCARD = "TOPIC_DISCARD"
|
||||||
CREATE_TOKEN = "CREATE_TOKEN"
|
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_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True)
|
||||||
package = db.relationship("Package", foreign_keys=[package_id])
|
package = db.relationship("Package", foreign_keys=[package_id])
|
||||||
|
|
||||||
review_id = db.Column(db.Integer, db.ForeignKey("package_review.id"), nullable=True)
|
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])
|
||||||
|
|
||||||
author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
|
author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
|
||||||
title = db.Column(db.String(100), 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)
|
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
|
||||||
|
|
||||||
@ -1111,8 +1115,16 @@ class Thread(db.Model):
|
|||||||
if self.package:
|
if self.package:
|
||||||
isMaintainer = isMaintainer or user in self.package.maintainers
|
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:
|
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:
|
else:
|
||||||
raise Exception("Permission {} is not related to threads".format(perm.name))
|
raise Exception("Permission {} is not related to threads".format(perm.name))
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<img class="img-responsive user-photo img-thumbnail img-thumbnail-1" src="{{ r.author.getProfilePicURL() }}">
|
<img class="img-responsive user-photo img-thumbnail img-thumbnail-1" src="{{ r.author.getProfilePicURL() }}">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col pr-0">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<a class="author {{ r.author.rank.name }}"
|
<a class="author {{ r.author.rank.name }}"
|
||||||
@ -30,6 +30,13 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</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 %}
|
{% if current_user.is_authenticated %}
|
||||||
<div class="row mt-0 mb-4 comments mx-0">
|
<div class="row mt-0 mb-4 comments mx-0">
|
||||||
<div class="col-md-1 p-1">
|
<div class="col-md-1 p-1">
|
||||||
@ -42,17 +49,26 @@
|
|||||||
<a name="reply"></a>
|
<a name="reply"></a>
|
||||||
</div>
|
</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">
|
<form method="post" action="{{ url_for('threads.view', id=thread.id)}}" class="card-body">
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||||
<textarea class="form-control markdown" required maxlength=500 name="comment"></textarea><br />
|
<textarea class="form-control markdown" required maxlength=500 name="comment"></textarea><br />
|
||||||
<input class="btn btn-primary" type="submit" value="Comment" />
|
<input class="btn btn-primary" type="submit" value="Comment" />
|
||||||
</form>
|
</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 %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,6 +17,19 @@
|
|||||||
<input type="submit" class="btn btn-primary" value="Subscribe" />
|
<input type="submit" class="btn btn-primary" value="Subscribe" />
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% 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 %}
|
{% endif %}
|
||||||
|
|
||||||
{% if current_user == thread.author and thread.review %}
|
{% if current_user == thread.author and thread.review %}
|
||||||
|
28
migrations/versions/8679442b8dde_.py
Normal file
28
migrations/versions/8679442b8dde_.py
Normal file
@ -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 ###
|
Loading…
Reference in New Issue
Block a user