|
@@ -17,15 +17,17 @@ from flask import (Blueprint, current_app, request, redirect, url_for, flash,
|
|
from flask_login import current_user
|
|
from flask_login import current_user
|
|
from flask_plugins import get_all_plugins, get_plugin, get_plugin_from_all
|
|
from flask_plugins import get_all_plugins, get_plugin, get_plugin_from_all
|
|
from flask_babelex import gettext as _
|
|
from flask_babelex import gettext as _
|
|
|
|
+from flask_allows import Permission, Not
|
|
|
|
|
|
from flaskbb import __version__ as flaskbb_version
|
|
from flaskbb import __version__ as flaskbb_version
|
|
from flaskbb._compat import iteritems
|
|
from flaskbb._compat import iteritems
|
|
from flaskbb.forum.forms import UserSearchForm
|
|
from flaskbb.forum.forms import UserSearchForm
|
|
from flaskbb.utils.settings import flaskbb_config
|
|
from flaskbb.utils.settings import flaskbb_config
|
|
|
|
+from flaskbb.utils.requirements import (
|
|
|
|
+ IsAtleastModerator, IsAdmin, CanBanUser, CanEditUser, IsAtleastSuperModerator
|
|
|
|
+)
|
|
|
|
+from flaskbb.extensions import db, allows
|
|
from flaskbb.utils.helpers import render_template, time_diff, get_online_users
|
|
from flaskbb.utils.helpers import render_template, time_diff, get_online_users
|
|
-from flaskbb.utils.decorators import admin_required, moderator_required
|
|
|
|
-from flaskbb.utils.permissions import can_ban_user, can_edit_user
|
|
|
|
-from flaskbb.extensions import db
|
|
|
|
from flaskbb.user.models import Guest, User, Group
|
|
from flaskbb.user.models import Guest, User, Group
|
|
from flaskbb.forum.models import Post, Topic, Forum, Category, Report
|
|
from flaskbb.forum.models import Post, Topic, Forum, Category, Report
|
|
from flaskbb.management.models import Setting, SettingsGroup
|
|
from flaskbb.management.models import Setting, SettingsGroup
|
|
@@ -38,7 +40,7 @@ management = Blueprint("management", __name__)
|
|
|
|
|
|
|
|
|
|
@management.route("/")
|
|
@management.route("/")
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def overview():
|
|
def overview():
|
|
# user and group stats
|
|
# user and group stats
|
|
banned_users = User.query.filter(
|
|
banned_users = User.query.filter(
|
|
@@ -72,7 +74,7 @@ def overview():
|
|
|
|
|
|
@management.route("/settings", methods=["GET", "POST"])
|
|
@management.route("/settings", methods=["GET", "POST"])
|
|
@management.route("/settings/<path:slug>", methods=["GET", "POST"])
|
|
@management.route("/settings/<path:slug>", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def settings(slug=None):
|
|
def settings(slug=None):
|
|
slug = slug if slug else "general"
|
|
slug = slug if slug else "general"
|
|
|
|
|
|
@@ -113,7 +115,7 @@ def settings(slug=None):
|
|
|
|
|
|
# Users
|
|
# Users
|
|
@management.route("/users", methods=['GET', 'POST'])
|
|
@management.route("/users", methods=['GET', 'POST'])
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def users():
|
|
def users():
|
|
page = request.args.get("page", 1, type=int)
|
|
page = request.args.get("page", 1, type=int)
|
|
search_form = UserSearchForm()
|
|
search_form = UserSearchForm()
|
|
@@ -133,30 +135,28 @@ def users():
|
|
|
|
|
|
|
|
|
|
@management.route("/users/<int:user_id>/edit", methods=["GET", "POST"])
|
|
@management.route("/users/<int:user_id>/edit", methods=["GET", "POST"])
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def edit_user(user_id):
|
|
def edit_user(user_id):
|
|
user = User.query.filter_by(id=user_id).first_or_404()
|
|
user = User.query.filter_by(id=user_id).first_or_404()
|
|
|
|
|
|
- if not can_edit_user(current_user):
|
|
|
|
|
|
+ if not Permission(CanEditUser, identity=current_user):
|
|
flash(_("You are not allowed to edit this user."), "danger")
|
|
flash(_("You are not allowed to edit this user."), "danger")
|
|
return redirect(url_for("management.users"))
|
|
return redirect(url_for("management.users"))
|
|
|
|
|
|
- member_group = db.and_(*[db.not_(getattr(Group, p)) for p in ['admin',
|
|
|
|
- 'mod',
|
|
|
|
- 'super_mod',
|
|
|
|
- 'banned',
|
|
|
|
- 'guest'
|
|
|
|
- ]])
|
|
|
|
|
|
+ member_group = db.and_(*[db.not_(getattr(Group, p)) for p in
|
|
|
|
+ ['admin', 'mod', 'super_mod', 'banned', 'guest']])
|
|
|
|
|
|
- filt = db.or_(Group.id.in_(g.id for g in user.groups),
|
|
|
|
- member_group)
|
|
|
|
|
|
+ filt = db.or_(Group.id.in_(g.id for g in current_user.groups), member_group)
|
|
|
|
|
|
- if any(user.permissions[p] for p in ['super_mod', 'admin']):
|
|
|
|
|
|
+ if Permission(IsAtleastSuperModerator, identity=current_user):
|
|
filt = db.or_(filt, Group.mod)
|
|
filt = db.or_(filt, Group.mod)
|
|
|
|
|
|
- if user.permissions['admin']:
|
|
|
|
|
|
+ if Permission(IsAdmin, identity=current_user):
|
|
filt = db.or_(filt, Group.admin, Group.super_mod)
|
|
filt = db.or_(filt, Group.admin, Group.super_mod)
|
|
|
|
|
|
|
|
+ if Permission(CanBanUser, identity=current_user):
|
|
|
|
+ filt = db.or_(filt, Group.banned)
|
|
|
|
+
|
|
group_query = Group.query.filter(filt)
|
|
group_query = Group.query.filter(filt)
|
|
|
|
|
|
form = EditUserForm(user)
|
|
form = EditUserForm(user)
|
|
@@ -181,7 +181,7 @@ def edit_user(user_id):
|
|
|
|
|
|
@management.route("/users/delete", methods=["POST"])
|
|
@management.route("/users/delete", methods=["POST"])
|
|
@management.route("/users/<int:user_id>/delete", methods=["POST"])
|
|
@management.route("/users/<int:user_id>/delete", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def delete_user(user_id=None):
|
|
def delete_user(user_id=None):
|
|
# ajax request
|
|
# ajax request
|
|
if request.is_xhr:
|
|
if request.is_xhr:
|
|
@@ -220,7 +220,7 @@ def delete_user(user_id=None):
|
|
|
|
|
|
|
|
|
|
@management.route("/users/add", methods=["GET", "POST"])
|
|
@management.route("/users/add", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def add_user():
|
|
def add_user():
|
|
form = AddUserForm()
|
|
form = AddUserForm()
|
|
if form.validate_on_submit():
|
|
if form.validate_on_submit():
|
|
@@ -233,7 +233,7 @@ def add_user():
|
|
|
|
|
|
|
|
|
|
@management.route("/users/banned", methods=["GET", "POST"])
|
|
@management.route("/users/banned", methods=["GET", "POST"])
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def banned_users():
|
|
def banned_users():
|
|
page = request.args.get("page", 1, type=int)
|
|
page = request.args.get("page", 1, type=int)
|
|
search_form = UserSearchForm()
|
|
search_form = UserSearchForm()
|
|
@@ -256,9 +256,9 @@ def banned_users():
|
|
|
|
|
|
@management.route("/users/ban", methods=["POST"])
|
|
@management.route("/users/ban", methods=["POST"])
|
|
@management.route("/users/<int:user_id>/ban", methods=["POST"])
|
|
@management.route("/users/<int:user_id>/ban", methods=["POST"])
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def ban_user(user_id=None):
|
|
def ban_user(user_id=None):
|
|
- if not can_ban_user(current_user):
|
|
|
|
|
|
+ if not Permission(CanBanUser, identity=current_user):
|
|
flash(_("You do not have the permissions to ban this user."), "danger")
|
|
flash(_("You do not have the permissions to ban this user."), "danger")
|
|
return redirect(url_for("management.overview"))
|
|
return redirect(url_for("management.overview"))
|
|
|
|
|
|
@@ -271,10 +271,11 @@ def ban_user(user_id=None):
|
|
for user in users:
|
|
for user in users:
|
|
# don't let a user ban himself and do not allow a moderator to ban
|
|
# don't let a user ban himself and do not allow a moderator to ban
|
|
# a admin user
|
|
# a admin user
|
|
- if current_user.id == user.id or \
|
|
|
|
- user.get_permissions()['admin'] and \
|
|
|
|
- (current_user.permissions['mod'] or
|
|
|
|
- current_user.permissions['super_mod']):
|
|
|
|
|
|
+ if (
|
|
|
|
+ current_user.id == user.id or
|
|
|
|
+ Permission(IsAdmin, identity=user)
|
|
|
|
+ and Permission(Not(IsAdmin), current_user)
|
|
|
|
+ ):
|
|
continue
|
|
continue
|
|
|
|
|
|
elif user.ban():
|
|
elif user.ban():
|
|
@@ -297,9 +298,8 @@ def ban_user(user_id=None):
|
|
user = User.query.filter_by(id=user_id).first_or_404()
|
|
user = User.query.filter_by(id=user_id).first_or_404()
|
|
|
|
|
|
# Do not allow moderators to ban admins
|
|
# Do not allow moderators to ban admins
|
|
- if user.get_permissions()['admin'] and \
|
|
|
|
- (current_user.permissions['mod'] or
|
|
|
|
- current_user.permissions['super_mod']):
|
|
|
|
|
|
+ if Permission(IsAdmin, identity=user) and \
|
|
|
|
+ Permission(Not(IsAdmin), identity=current_user):
|
|
|
|
|
|
flash(_("A moderator cannot ban an admin user."), "danger")
|
|
flash(_("A moderator cannot ban an admin user."), "danger")
|
|
return redirect(url_for("management.overview"))
|
|
return redirect(url_for("management.overview"))
|
|
@@ -314,9 +314,9 @@ def ban_user(user_id=None):
|
|
|
|
|
|
@management.route("/users/unban", methods=["POST"])
|
|
@management.route("/users/unban", methods=["POST"])
|
|
@management.route("/users/<int:user_id>/unban", methods=["POST"])
|
|
@management.route("/users/<int:user_id>/unban", methods=["POST"])
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def unban_user(user_id=None):
|
|
def unban_user(user_id=None):
|
|
- if not can_ban_user(current_user):
|
|
|
|
|
|
+ if not Permission(CanBanUser, identity=current_user):
|
|
flash(_("You do not have the permissions to unban this user."),
|
|
flash(_("You do not have the permissions to unban this user."),
|
|
"danger")
|
|
"danger")
|
|
return redirect(url_for("management.overview"))
|
|
return redirect(url_for("management.overview"))
|
|
@@ -356,7 +356,7 @@ def unban_user(user_id=None):
|
|
|
|
|
|
# Reports
|
|
# Reports
|
|
@management.route("/reports")
|
|
@management.route("/reports")
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def reports():
|
|
def reports():
|
|
page = request.args.get("page", 1, type=int)
|
|
page = request.args.get("page", 1, type=int)
|
|
reports = Report.query.\
|
|
reports = Report.query.\
|
|
@@ -367,7 +367,7 @@ def reports():
|
|
|
|
|
|
|
|
|
|
@management.route("/reports/unread")
|
|
@management.route("/reports/unread")
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def unread_reports():
|
|
def unread_reports():
|
|
page = request.args.get("page", 1, type=int)
|
|
page = request.args.get("page", 1, type=int)
|
|
reports = Report.query.\
|
|
reports = Report.query.\
|
|
@@ -380,7 +380,7 @@ def unread_reports():
|
|
|
|
|
|
@management.route("/reports/<int:report_id>/markread", methods=["POST"])
|
|
@management.route("/reports/<int:report_id>/markread", methods=["POST"])
|
|
@management.route("/reports/markread", methods=["POST"])
|
|
@management.route("/reports/markread", methods=["POST"])
|
|
-@moderator_required
|
|
|
|
|
|
+@allows.requires(IsAtleastModerator)
|
|
def report_markread(report_id=None):
|
|
def report_markread(report_id=None):
|
|
# AJAX request
|
|
# AJAX request
|
|
if request.is_xhr:
|
|
if request.is_xhr:
|
|
@@ -437,7 +437,7 @@ def report_markread(report_id=None):
|
|
|
|
|
|
# Groups
|
|
# Groups
|
|
@management.route("/groups")
|
|
@management.route("/groups")
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def groups():
|
|
def groups():
|
|
page = request.args.get("page", 1, type=int)
|
|
page = request.args.get("page", 1, type=int)
|
|
|
|
|
|
@@ -449,7 +449,7 @@ def groups():
|
|
|
|
|
|
|
|
|
|
@management.route("/groups/<int:group_id>/edit", methods=["GET", "POST"])
|
|
@management.route("/groups/<int:group_id>/edit", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def edit_group(group_id):
|
|
def edit_group(group_id):
|
|
group = Group.query.filter_by(id=group_id).first_or_404()
|
|
group = Group.query.filter_by(id=group_id).first_or_404()
|
|
|
|
|
|
@@ -471,7 +471,7 @@ def edit_group(group_id):
|
|
|
|
|
|
@management.route("/groups/<int:group_id>/delete", methods=["POST"])
|
|
@management.route("/groups/<int:group_id>/delete", methods=["POST"])
|
|
@management.route("/groups/delete", methods=["POST"])
|
|
@management.route("/groups/delete", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def delete_group(group_id=None):
|
|
def delete_group(group_id=None):
|
|
if request.is_xhr:
|
|
if request.is_xhr:
|
|
ids = request.get_json()["ids"]
|
|
ids = request.get_json()["ids"]
|
|
@@ -516,7 +516,7 @@ def delete_group(group_id=None):
|
|
|
|
|
|
|
|
|
|
@management.route("/groups/add", methods=["GET", "POST"])
|
|
@management.route("/groups/add", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def add_group():
|
|
def add_group():
|
|
form = AddGroupForm()
|
|
form = AddGroupForm()
|
|
if form.validate_on_submit():
|
|
if form.validate_on_submit():
|
|
@@ -530,14 +530,14 @@ def add_group():
|
|
|
|
|
|
# Forums and Categories
|
|
# Forums and Categories
|
|
@management.route("/forums")
|
|
@management.route("/forums")
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def forums():
|
|
def forums():
|
|
categories = Category.query.order_by(Category.position.asc()).all()
|
|
categories = Category.query.order_by(Category.position.asc()).all()
|
|
return render_template("management/forums.html", categories=categories)
|
|
return render_template("management/forums.html", categories=categories)
|
|
|
|
|
|
|
|
|
|
@management.route("/forums/<int:forum_id>/edit", methods=["GET", "POST"])
|
|
@management.route("/forums/<int:forum_id>/edit", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def edit_forum(forum_id):
|
|
def edit_forum(forum_id):
|
|
forum = Forum.query.filter_by(id=forum_id).first_or_404()
|
|
forum = Forum.query.filter_by(id=forum_id).first_or_404()
|
|
|
|
|
|
@@ -559,7 +559,7 @@ def edit_forum(forum_id):
|
|
|
|
|
|
|
|
|
|
@management.route("/forums/<int:forum_id>/delete", methods=["POST"])
|
|
@management.route("/forums/<int:forum_id>/delete", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def delete_forum(forum_id):
|
|
def delete_forum(forum_id):
|
|
forum = Forum.query.filter_by(id=forum_id).first_or_404()
|
|
forum = Forum.query.filter_by(id=forum_id).first_or_404()
|
|
|
|
|
|
@@ -574,7 +574,7 @@ def delete_forum(forum_id):
|
|
|
|
|
|
@management.route("/forums/add", methods=["GET", "POST"])
|
|
@management.route("/forums/add", methods=["GET", "POST"])
|
|
@management.route("/forums/<int:category_id>/add", methods=["GET", "POST"])
|
|
@management.route("/forums/<int:category_id>/add", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def add_forum(category_id=None):
|
|
def add_forum(category_id=None):
|
|
form = AddForumForm()
|
|
form = AddForumForm()
|
|
|
|
|
|
@@ -593,7 +593,7 @@ def add_forum(category_id=None):
|
|
|
|
|
|
|
|
|
|
@management.route("/category/add", methods=["GET", "POST"])
|
|
@management.route("/category/add", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def add_category():
|
|
def add_category():
|
|
form = CategoryForm()
|
|
form = CategoryForm()
|
|
|
|
|
|
@@ -607,7 +607,7 @@ def add_category():
|
|
|
|
|
|
|
|
|
|
@management.route("/category/<int:category_id>/edit", methods=["GET", "POST"])
|
|
@management.route("/category/<int:category_id>/edit", methods=["GET", "POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def edit_category(category_id):
|
|
def edit_category(category_id):
|
|
category = Category.query.filter_by(id=category_id).first_or_404()
|
|
category = Category.query.filter_by(id=category_id).first_or_404()
|
|
|
|
|
|
@@ -623,7 +623,7 @@ def edit_category(category_id):
|
|
|
|
|
|
|
|
|
|
@management.route("/category/<int:category_id>/delete", methods=["POST"])
|
|
@management.route("/category/<int:category_id>/delete", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def delete_category(category_id):
|
|
def delete_category(category_id):
|
|
category = Category.query.filter_by(id=category_id).first_or_404()
|
|
category = Category.query.filter_by(id=category_id).first_or_404()
|
|
|
|
|
|
@@ -638,14 +638,14 @@ def delete_category(category_id):
|
|
|
|
|
|
# Plugins
|
|
# Plugins
|
|
@management.route("/plugins")
|
|
@management.route("/plugins")
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def plugins():
|
|
def plugins():
|
|
plugins = get_all_plugins()
|
|
plugins = get_all_plugins()
|
|
return render_template("management/plugins.html", plugins=plugins)
|
|
return render_template("management/plugins.html", plugins=plugins)
|
|
|
|
|
|
|
|
|
|
@management.route("/plugins/<path:plugin>/enable", methods=["POST"])
|
|
@management.route("/plugins/<path:plugin>/enable", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def enable_plugin(plugin):
|
|
def enable_plugin(plugin):
|
|
plugin = get_plugin_from_all(plugin)
|
|
plugin = get_plugin_from_all(plugin)
|
|
if not plugin.enabled:
|
|
if not plugin.enabled:
|
|
@@ -677,7 +677,7 @@ def enable_plugin(plugin):
|
|
|
|
|
|
|
|
|
|
@management.route("/plugins/<path:plugin>/disable", methods=["POST"])
|
|
@management.route("/plugins/<path:plugin>/disable", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def disable_plugin(plugin):
|
|
def disable_plugin(plugin):
|
|
try:
|
|
try:
|
|
plugin = get_plugin(plugin)
|
|
plugin = get_plugin(plugin)
|
|
@@ -705,7 +705,7 @@ def disable_plugin(plugin):
|
|
|
|
|
|
|
|
|
|
@management.route("/plugins/<path:plugin>/uninstall", methods=["POST"])
|
|
@management.route("/plugins/<path:plugin>/uninstall", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def uninstall_plugin(plugin):
|
|
def uninstall_plugin(plugin):
|
|
plugin = get_plugin_from_all(plugin)
|
|
plugin = get_plugin_from_all(plugin)
|
|
if plugin.uninstallable:
|
|
if plugin.uninstallable:
|
|
@@ -720,7 +720,7 @@ def uninstall_plugin(plugin):
|
|
|
|
|
|
|
|
|
|
@management.route("/plugins/<path:plugin>/install", methods=["POST"])
|
|
@management.route("/plugins/<path:plugin>/install", methods=["POST"])
|
|
-@admin_required
|
|
|
|
|
|
+@allows.requires(IsAdmin)
|
|
def install_plugin(plugin):
|
|
def install_plugin(plugin):
|
|
plugin = get_plugin_from_all(plugin)
|
|
plugin = get_plugin_from_all(plugin)
|
|
if plugin.installable and not plugin.uninstallable:
|
|
if plugin.installable and not plugin.uninstallable:
|