mirror of
https://github.com/minetest/contentdb.git
synced 2024-11-09 17:13:45 +01:00
Add temp banning and ban messages
This commit is contained in:
parent
7a650eb1e4
commit
3d35f6507a
@ -13,6 +13,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import datetime
|
||||
|
||||
from flask import *
|
||||
@ -26,7 +27,6 @@ from flask_login import logout_user, current_user, LoginManager
|
||||
import os, redis
|
||||
from app.markdown import init_markdown, MARKDOWN_EXTENSIONS, MARKDOWN_EXTENSION_CONFIG
|
||||
|
||||
|
||||
app = Flask(__name__, static_folder="public/static")
|
||||
app.config["FLATPAGES_ROOT"] = "flatpages"
|
||||
app.config["FLATPAGES_EXTENSION"] = ".md"
|
||||
@ -86,27 +86,39 @@ def load_user(user_id):
|
||||
from .blueprints import create_blueprints
|
||||
create_blueprints(app)
|
||||
|
||||
|
||||
@app.route("/uploads/<path:path>")
|
||||
def send_upload(path):
|
||||
return send_from_directory(app.config["UPLOAD_DIR"], path)
|
||||
|
||||
|
||||
@app.route("/<path:path>/")
|
||||
def flatpage(path):
|
||||
page = pages.get_or_404(path)
|
||||
template = page.meta.get("template", "flatpage.html")
|
||||
return render_template(template, page=page)
|
||||
|
||||
|
||||
@app.before_request
|
||||
def check_for_ban():
|
||||
if current_user.is_authenticated:
|
||||
if current_user.rank == models.UserRank.BANNED:
|
||||
flash(gettext("You have been banned."), "danger")
|
||||
if current_user.ban and current_user.ban.has_expired:
|
||||
models.db.session.delete(current_user.ban)
|
||||
if current_user.rank == models.UserRank.BANNED:
|
||||
current_user.rank = models.UserRank.MEMBER
|
||||
models.db.session.commit()
|
||||
elif current_user.ban or current_user.rank == models.UserRank.BANNED:
|
||||
if current_user.ban:
|
||||
flash(gettext("Banned:") + " " + current_user.ban.message, "danger")
|
||||
else:
|
||||
flash(gettext("You have been banned."), "danger")
|
||||
logout_user()
|
||||
return redirect(url_for("users.login"))
|
||||
elif current_user.rank == models.UserRank.NOT_JOINED:
|
||||
current_user.rank = models.UserRank.MEMBER
|
||||
models.db.session.commit()
|
||||
|
||||
|
||||
from .utils import clearNotifications, is_safe_url
|
||||
|
||||
|
||||
@ -115,6 +127,7 @@ def check_for_notifications():
|
||||
if current_user.is_authenticated:
|
||||
clearNotifications(request.path)
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return render_template("404.html"), 404
|
||||
@ -145,7 +158,6 @@ def get_locale():
|
||||
return locale
|
||||
|
||||
|
||||
|
||||
@app.route("/set-locale/", methods=["POST"])
|
||||
@csrf.exempt
|
||||
def set_locale():
|
||||
|
@ -358,11 +358,45 @@ def modtools_ban(username):
|
||||
if not user.checkPerm(current_user, Permission.CHANGE_RANK):
|
||||
abort(403)
|
||||
|
||||
user.rank = UserRank.BANNED
|
||||
message = request.form["message"]
|
||||
expires_at = request.form.get("expires_at")
|
||||
|
||||
addAuditLog(AuditSeverity.MODERATION, current_user, f"Banned {user.username}",
|
||||
user.ban = UserBan()
|
||||
user.ban.banned_by = current_user
|
||||
user.ban.message = message
|
||||
|
||||
if expires_at and expires_at != "":
|
||||
user.ban.expires_at = expires_at
|
||||
else:
|
||||
user.rank = UserRank.BANNED
|
||||
|
||||
addAuditLog(AuditSeverity.MODERATION, current_user, f"Banned {user.username}, expires {user.ban.expires_at or '-'}, message: {message}",
|
||||
url_for("users.profile", username=user.username), None)
|
||||
db.session.commit()
|
||||
|
||||
flash(f"Banned {user.username}", "success")
|
||||
return redirect(url_for("users.modtools", username=username))
|
||||
return redirect(url_for("users.modtools", username=username))
|
||||
|
||||
|
||||
@bp.route("/users/<username>/modtools/unban/", methods=["POST"])
|
||||
@rank_required(UserRank.MODERATOR)
|
||||
def modtools_unban(username):
|
||||
user: User = User.query.filter_by(username=username).first()
|
||||
if not user:
|
||||
abort(404)
|
||||
|
||||
if not user.checkPerm(current_user, Permission.CHANGE_RANK):
|
||||
abort(403)
|
||||
|
||||
if user.ban:
|
||||
db.session.delete(user.ban)
|
||||
|
||||
if user.rank == UserRank.BANNED:
|
||||
user.rank = UserRank.MEMBER
|
||||
|
||||
addAuditLog(AuditSeverity.MODERATION, current_user, f"Unbanned {user.username}",
|
||||
url_for("users.profile", username=user.username), None)
|
||||
db.session.commit()
|
||||
|
||||
flash(f"Unbanned {user.username}", "success")
|
||||
return redirect(url_for("users.modtools", username=username))
|
||||
|
@ -183,6 +183,8 @@ class User(db.Model, UserMixin):
|
||||
replies = db.relationship("ThreadReply", back_populates="author", lazy="dynamic", cascade="all, delete, delete-orphan", order_by=db.desc("created_at"))
|
||||
forum_topics = db.relationship("ForumTopic", back_populates="author", lazy="dynamic", cascade="all, delete, delete-orphan")
|
||||
|
||||
ban = db.relationship("UserBan", foreign_keys="UserBan.user_id", back_populates="user", uselist=False)
|
||||
|
||||
def __init__(self, username=None, active=False, email=None, password=None):
|
||||
self.username = username
|
||||
self.display_name = username
|
||||
@ -482,3 +484,21 @@ class UserNotificationPreferences(db.Model):
|
||||
|
||||
value = 1 if value else 0
|
||||
setattr(self, "pref_" + notification_type.toName(), value)
|
||||
|
||||
|
||||
class UserBan(db.Model):
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
|
||||
user = db.relationship("User", foreign_keys=[user_id], back_populates="ban")
|
||||
|
||||
message = db.Column(db.UnicodeText, nullable=False)
|
||||
|
||||
banned_by_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
||||
banned_by = db.relationship("User", foreign_keys=[banned_by_id])
|
||||
|
||||
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
|
||||
|
||||
expires_at = db.Column(db.DateTime, nullable=True, default=None)
|
||||
|
||||
@property
|
||||
def has_expired(self):
|
||||
return self.expires_at and datetime.datetime.now() > self.expires_at
|
||||
|
@ -434,15 +434,18 @@
|
||||
|
||||
{% if package.type == package.type.MOD %}
|
||||
<h3>{{ _("Compatible Games") }}</h3>
|
||||
{% for support in package.getSortedSupportedGames() %}
|
||||
<a class="badge badge-secondary"
|
||||
href="{{ support.game.getURL('packages.view') }}">
|
||||
{{ _("%(title)s by %(display_name)s",
|
||||
title=support.game.title, display_name=support.game.author.display_name) }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ _("No specific game is required") }}
|
||||
{% endfor %}
|
||||
<div style="max-height: 300px; overflow: hidden auto;">
|
||||
{% for support in package.getSortedSupportedGames() %}
|
||||
<a class="badge badge-secondary"
|
||||
href="{{ support.game.getURL('packages.view') }}">
|
||||
{{ _("%(title)s by %(display_name)s",
|
||||
title=support.game.title, display_name=support.game.author.display_name) }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ _("No specific game is required") }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<p class="text-muted small mt-2 mb-0">
|
||||
{{ _("This is an experimental feature.") }}
|
||||
{{ _("Supported games are determined by an algorithm, and may not be correct.") }}
|
||||
|
@ -41,13 +41,37 @@
|
||||
|
||||
{% if not user.rank.atLeast(current_user.rank) %}
|
||||
<h3>{{ _("Ban") }}</h3>
|
||||
{% if user.rank.name == "BANNED" %}
|
||||
{% if user.ban %}
|
||||
<p>
|
||||
Banned.
|
||||
Banned by {{ user.ban.banned_by.display_name }} at {{ user.ban.created_at | full_datetime }}
|
||||
{% if user.ban.expires_at %}
|
||||
until {{ user.ban.expires_at | date }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<blockquote>
|
||||
{{ user.ban.message }}
|
||||
</blockquote>
|
||||
<form method="POST" action="{{ url_for('users.modtools_unban', username=user.username) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<input type="submit" value="{{ _('Unban') }}" class="btn btn-primary" />
|
||||
</form>
|
||||
{% else %}
|
||||
<form method="POST" action="{{ url_for('users.modtools_ban', username=user.username) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<div class="form-group">
|
||||
<label for="message">{{ _("Message") }}</label>
|
||||
<input id="message" class="form-control" type="text" name="message" required minlength="5">
|
||||
<small class="form-text text-muted">
|
||||
{{ _("Message to display to banned user") }}
|
||||
</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="expires_at">{{ _("Expires At") }}</label>
|
||||
<input id="expires_at" class="form-control" type="date" name="expires_at">
|
||||
<small class="form-text text-muted">
|
||||
{{ _("Expiry date. Leave blank for permanent ban") }}
|
||||
</small>
|
||||
</div>
|
||||
<input type="submit" value="{{ _('Ban') }}" class="btn btn-danger" />
|
||||
</form>
|
||||
{% endif %}
|
||||
|
33
migrations/versions/01f8d5de29e1_.py
Normal file
33
migrations/versions/01f8d5de29e1_.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 01f8d5de29e1
|
||||
Revises: e571b3498f9e
|
||||
Create Date: 2022-02-13 10:12:20.150232
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '01f8d5de29e1'
|
||||
down_revision = 'e571b3498f9e'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table('user_ban',
|
||||
sa.Column('user_id', sa.Integer(), nullable=False),
|
||||
sa.Column('message', sa.UnicodeText(), nullable=False),
|
||||
sa.Column('banned_by_id', sa.Integer(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('expires_at', sa.DateTime(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['banned_by_id'], ['user.id'], ),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
|
||||
sa.PrimaryKeyConstraint('user_id')
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table('user_ban')
|
Loading…
Reference in New Issue
Block a user