mirror of
https://github.com/minetest/contentdb.git
synced 2024-11-10 01:23:48 +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
|
# 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/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from flask import *
|
from flask import *
|
||||||
@ -26,7 +27,6 @@ from flask_login import logout_user, current_user, LoginManager
|
|||||||
import os, redis
|
import os, redis
|
||||||
from app.markdown import init_markdown, MARKDOWN_EXTENSIONS, MARKDOWN_EXTENSION_CONFIG
|
from app.markdown import init_markdown, MARKDOWN_EXTENSIONS, MARKDOWN_EXTENSION_CONFIG
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__, static_folder="public/static")
|
app = Flask(__name__, static_folder="public/static")
|
||||||
app.config["FLATPAGES_ROOT"] = "flatpages"
|
app.config["FLATPAGES_ROOT"] = "flatpages"
|
||||||
app.config["FLATPAGES_EXTENSION"] = ".md"
|
app.config["FLATPAGES_EXTENSION"] = ".md"
|
||||||
@ -86,20 +86,31 @@ def load_user(user_id):
|
|||||||
from .blueprints import create_blueprints
|
from .blueprints import create_blueprints
|
||||||
create_blueprints(app)
|
create_blueprints(app)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/uploads/<path:path>")
|
@app.route("/uploads/<path:path>")
|
||||||
def send_upload(path):
|
def send_upload(path):
|
||||||
return send_from_directory(app.config["UPLOAD_DIR"], path)
|
return send_from_directory(app.config["UPLOAD_DIR"], path)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/<path:path>/")
|
@app.route("/<path:path>/")
|
||||||
def flatpage(path):
|
def flatpage(path):
|
||||||
page = pages.get_or_404(path)
|
page = pages.get_or_404(path)
|
||||||
template = page.meta.get("template", "flatpage.html")
|
template = page.meta.get("template", "flatpage.html")
|
||||||
return render_template(template, page=page)
|
return render_template(template, page=page)
|
||||||
|
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def check_for_ban():
|
def check_for_ban():
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
|
if current_user.ban and current_user.ban.has_expired:
|
||||||
|
models.db.session.delete(current_user.ban)
|
||||||
if current_user.rank == models.UserRank.BANNED:
|
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")
|
flash(gettext("You have been banned."), "danger")
|
||||||
logout_user()
|
logout_user()
|
||||||
return redirect(url_for("users.login"))
|
return redirect(url_for("users.login"))
|
||||||
@ -107,6 +118,7 @@ def check_for_ban():
|
|||||||
current_user.rank = models.UserRank.MEMBER
|
current_user.rank = models.UserRank.MEMBER
|
||||||
models.db.session.commit()
|
models.db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
from .utils import clearNotifications, is_safe_url
|
from .utils import clearNotifications, is_safe_url
|
||||||
|
|
||||||
|
|
||||||
@ -115,6 +127,7 @@ def check_for_notifications():
|
|||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
clearNotifications(request.path)
|
clearNotifications(request.path)
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def page_not_found(e):
|
def page_not_found(e):
|
||||||
return render_template("404.html"), 404
|
return render_template("404.html"), 404
|
||||||
@ -145,7 +158,6 @@ def get_locale():
|
|||||||
return locale
|
return locale
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/set-locale/", methods=["POST"])
|
@app.route("/set-locale/", methods=["POST"])
|
||||||
@csrf.exempt
|
@csrf.exempt
|
||||||
def set_locale():
|
def set_locale():
|
||||||
|
@ -358,11 +358,45 @@ def modtools_ban(username):
|
|||||||
if not user.checkPerm(current_user, Permission.CHANGE_RANK):
|
if not user.checkPerm(current_user, Permission.CHANGE_RANK):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
|
message = request.form["message"]
|
||||||
|
expires_at = request.form.get("expires_at")
|
||||||
|
|
||||||
|
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
|
user.rank = UserRank.BANNED
|
||||||
|
|
||||||
addAuditLog(AuditSeverity.MODERATION, current_user, f"Banned {user.username}",
|
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)
|
url_for("users.profile", username=user.username), None)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
flash(f"Banned {user.username}", "success")
|
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"))
|
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")
|
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):
|
def __init__(self, username=None, active=False, email=None, password=None):
|
||||||
self.username = username
|
self.username = username
|
||||||
self.display_name = username
|
self.display_name = username
|
||||||
@ -482,3 +484,21 @@ class UserNotificationPreferences(db.Model):
|
|||||||
|
|
||||||
value = 1 if value else 0
|
value = 1 if value else 0
|
||||||
setattr(self, "pref_" + notification_type.toName(), value)
|
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,6 +434,7 @@
|
|||||||
|
|
||||||
{% if package.type == package.type.MOD %}
|
{% if package.type == package.type.MOD %}
|
||||||
<h3>{{ _("Compatible Games") }}</h3>
|
<h3>{{ _("Compatible Games") }}</h3>
|
||||||
|
<div style="max-height: 300px; overflow: hidden auto;">
|
||||||
{% for support in package.getSortedSupportedGames() %}
|
{% for support in package.getSortedSupportedGames() %}
|
||||||
<a class="badge badge-secondary"
|
<a class="badge badge-secondary"
|
||||||
href="{{ support.game.getURL('packages.view') }}">
|
href="{{ support.game.getURL('packages.view') }}">
|
||||||
@ -443,6 +444,8 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{{ _("No specific game is required") }}
|
{{ _("No specific game is required") }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="text-muted small mt-2 mb-0">
|
<p class="text-muted small mt-2 mb-0">
|
||||||
{{ _("This is an experimental feature.") }}
|
{{ _("This is an experimental feature.") }}
|
||||||
{{ _("Supported games are determined by an algorithm, and may not be correct.") }}
|
{{ _("Supported games are determined by an algorithm, and may not be correct.") }}
|
||||||
|
@ -41,13 +41,37 @@
|
|||||||
|
|
||||||
{% if not user.rank.atLeast(current_user.rank) %}
|
{% if not user.rank.atLeast(current_user.rank) %}
|
||||||
<h3>{{ _("Ban") }}</h3>
|
<h3>{{ _("Ban") }}</h3>
|
||||||
{% if user.rank.name == "BANNED" %}
|
{% if user.ban %}
|
||||||
<p>
|
<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>
|
</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 %}
|
{% else %}
|
||||||
<form method="POST" action="{{ url_for('users.modtools_ban', username=user.username) }}">
|
<form method="POST" action="{{ url_for('users.modtools_ban', username=user.username) }}">
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
<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" />
|
<input type="submit" value="{{ _('Ban') }}" class="btn btn-danger" />
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% 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