class DeletePost(MethodView): decorators = [ login_required, allows.requires( CanDeletePost, on_fail=FlashAndRedirect( message=_("You are not allowed to delete this post"), level="danger", endpoint=lambda *a, **k: current_topic.url)), ] def post(self, post_id): post = Post.query.filter_by(id=post_id).first_or_404() first_post = post.first_post topic_url = post.topic.url forum_url = post.topic.forum.url post.delete() # If the post was the first post in the topic, redirect to the forums if first_post: return redirect(forum_url) return redirect(topic_url)
class CeleryStatus(MethodView): decorators = [ allows.requires( IsAtleastModerator, on_fail=FlashAndRedirect( message=_("You are not allowed to access the management settings"), # noqa level="danger", endpoint="management.overview" ) ) ] def get(self): celery_inspect = celery.control.inspect() try: celery_running = True if celery_inspect.ping() else False except Exception: # catching Exception is bad, and just catching ConnectionError # from redis is also bad because you can run celery with other # brokers as well. celery_running = False return jsonify(celery_running=celery_running, status=200)
class ViewForum(MethodView): decorators = [allows.requires(CanAccessForum())] def get(self, forum_id, slug=None): page = request.args.get('page', 1, type=int) forum_instance, forumsread = Forum.get_forum(forum_id=forum_id, user=real(current_user)) if forum_instance.external: return redirect(forum_instance.external) topics = Forum.get_topics(forum_id=forum_instance.id, user=real(current_user), page=page, per_page=flaskbb_config['TOPICS_PER_PAGE']) return render_template( 'forum/forum.html', forum=forum_instance, topics=topics, forumsread=forumsread, )
class DeleteForum(MethodView): decorators = [ allows.requires( IsAdmin, on_fail=FlashAndRedirect( message=_("You are not allowed to modify forums"), level="danger", endpoint="management.overview" ) ) ] def post(self, forum_id): forum = Forum.query.filter_by(id=forum_id).first_or_404() involved_users = User.query.filter( Topic.forum_id == forum.id, Post.user_id == User.id ).all() forum.delete(involved_users) flash(_("Forum deleted."), "success") return redirect(url_for("management.forums"))
class DeleteCategory(MethodView): decorators = [ allows.requires( IsAdmin, on_fail=FlashAndRedirect( message=_("You are not allowed to modify categories"), level="danger", endpoint="management.overview" ) ) ] def post(self, category_id): category = Category.query.filter_by(id=category_id).first_or_404() involved_users = User.query.filter( Forum.category_id == category.id, Topic.forum_id == Forum.id, Post.user_id == User.id ).all() category.delete(involved_users) flash(_("Category with all associated forums deleted."), "success") return redirect(url_for("management.forums"))
class ReplyPost(MethodView): decorators = [allows.requires(CanPostReply), login_required] form = ReplyForm def get(self, topic_id, post_id): topic = Topic.query.filter_by(id=topic_id).first_or_404() return render_template('forum/new_post.html', topic=topic, form=self.form()) def post(self, topic_id, post_id): form = self.form() topic = Topic.query.filter_by(id=topic_id).first_or_404() if form.validate_on_submit(): if 'preview' in request.form: return render_template( 'forum/new_post.html', topic=topic, form=form, preview=form.content.data ) else: post = form.save(real(current_user), topic) return redirect(url_for('forum.view_post', post_id=post.id)) else: form.content.data = format_quote(post.username, post.content) return render_template('forum/new_post.html', topic=post.topic, form=form)
class DisablePlugin(MethodView): decorators = [allows.requires(IsAdmin)] def post(self, name): validate_plugin(name) plugin = PluginRegistry.query.filter_by(name=name).first_or_404() if not plugin.enabled: flash( _("Plugin %(plugin)s is already disabled.", plugin=plugin.name), "info" ) return redirect(url_for("management.plugins")) plugin.enabled = False plugin.save() flash( _( "Plugin %(plugin)s disabled. Please restart FlaskBB now.", plugin=plugin.name ), "success" ) return redirect(url_for("management.plugins"))
class BannedUsers(MethodView): decorators = [allows.requires(IsAtleastModerator)] form = UserSearchForm def get(self): page = request.args.get('page', 1, type=int) search_form = self.form() users = User.query.filter(Group.banned == True, Group.id == User.primary_group_id).paginate( page, flaskbb_config['USERS_PER_PAGE'], False) return render_template('management/banned_users.html', users=users, search_form=search_form) def post(self): page = request.args.get('page', 1, type=int) search_form = self.form() users = User.query.filter(Group.banned == True, Group.id == User.primary_group_id).paginate( page, flaskbb_config['USERS_PER_PAGE'], False) if search_form.validate(): users = search_form.get_results().\ paginate(page, flaskbb_config['USERS_PER_PAGE'], False) return render_template('management/banned_users.html', users=users, search_form=search_form) return render_template('management/banned_users.html', users=users, search_form=search_form)
class ConfigsView(Hub): decorators = [ allows.requires(CanAccessServerHubAdditional(), on_fail=FlashAndRedirect( message=_("You are not allowed to access the hub"), level="danger", endpoint="forum.index")) ] def get(self): server_id = request.args["server"] servers = current_app.config["BYOND_SERVERS"] for server in servers: if server.id == server_id: config_folder_entries = [ os.path.join(server.configs_path, f) for f in os.listdir(server.configs_path) ] config_files = [ f for f in config_folder_entries if os.path.isfile(f) ] config_files_names = [ os.path.split(f)[1] for f in config_files ] config_files_names = [ f for f in config_files_names if f not in server.configs_exclude ] config_files_names.sort() return render_template("hub/configs.html", **self.get_args(), configs=config_files_names) return render_template("hub/configs.html", **self.get_args())
class EditGroup(MethodView): decorators = [ allows.requires( IsAdmin, on_fail=FlashAndRedirect( message=_("You are not allowed to modify groups."), level="danger", endpoint="management.overview" ) ) ] form = EditGroupForm def get(self, group_id): group = Group.query.filter_by(id=group_id).first_or_404() form = self.form(group) return render_template( 'management/group_form.html', form=form, title=_('Edit Group') ) def post(self, group_id): group = Group.query.filter_by(id=group_id).first_or_404() form = EditGroupForm(group) if form.validate_on_submit(): form.populate_obj(group) group.save() if group.guest: Guest.invalidate_cache() flash(_('Group updated.'), 'success') return redirect(url_for('management.groups', group_id=group.id)) return render_template( 'management/group_form.html', form=form, title=_('Edit Group') )
class DeleteReport(MethodView): decorators = [ allows.requires(IsAtleastModerator, on_fail=FlashAndRedirect( message=_("You are not allowed to view reports."), level="danger", endpoint="management.overview")) ] def post(self, report_id=None): if request.get_json() is not None: ids = request.get_json().get("ids") if not ids: return jsonify(message="No ids provided.", category="error", status=404) data = [] for report in Report.query.filter(Report.id.in_(ids)).all(): if report.delete(): data.append({ "id": report.id, "type": "delete", "reverse": False, "reverse_name": None, "reverse_url": None }) return jsonify(message="{} reports deleted.".format(len(data)), category="success", data=data, status=200) report = Report.query.filter_by(id=report_id).first_or_404() report.delete() flash(_("Report deleted."), "success") return redirect_or_next(url_for("management.reports"))
class NewPost(MethodView): decorators = [allows.requires(CanPostReply), login_required] def get(self, topic_id, slug=None, post_id=None): topic = Topic.query.filter_by(id=topic_id).first_or_404() form = self.form() if post_id is not None: post = Post.query.filter_by(id=post_id).first_or_404() form.content.data = format_quote(post.username, post.content) return render_template('forum/new_post.html', topic=topic, form=form) def post(self, topic_id, slug=None, post_id=None): topic = Topic.query.filter_by(id=topic_id).first_or_404() form = self.form() # check if topic exists if post_id is not None: post = Post.query.filter_by(id=post_id).first_or_404() if form.validate_on_submit(): if 'preview' in request.form: return render_template('forum/new_post.html', topic=topic, form=form, preview=form.content.data) else: post = form.save(real(current_user), topic) return redirect(url_for('forum.view_post', post_id=post.id)) return render_template('forum/new_post.html', topic=topic, form=form) def form(self): current_app.pluggy.hook.flaskbb_form_new_post(form=ReplyForm) return ReplyForm()
class DeleteUser(MethodView): decorators = [allows.requires(IsAdmin)] def post(self, user_id=None): # ajax request if request.is_xhr: ids = request.get_json()["ids"] data = [] for user in User.query.filter(User.id.in_(ids)).all(): # do not delete current user if current_user.id == user.id: continue if user.delete(): data.append({ "id": user.id, "type": "delete", "reverse": False, "reverse_name": None, "reverse_url": None }) return jsonify(message="{} users deleted.".format(len(data)), category="success", data=data, status=200) user = User.query.filter_by(id=user_id).first_or_404() if current_user.id == user.id: flash(_("You cannot delete yourself.", "danger")) return redirect(url_for("management.users")) user.delete() flash(_("User deleted."), "success") return redirect(url_for("management.users"))
class EditGroup(MethodView): decorators = [allows.requires(IsAdmin)] form = EditGroupForm def get(self, group_id): group = Group.query.filter_by(id=group_id).first_or_404() form = self.form(group) return render_template('management/group_form.html', form=form, title=_('Edit Group')) def post(self, group_id): group = Group.query.filter_by(id=group_id).first_or_404() form = EditGroupForm(group) if form.validate_on_submit(): form.populate_obj(group) group.save() if group.guest: Guest.invalidate_cache() flash(_('Group updated.'), 'success') return redirect(url_for('management.groups', group_id=group.id)) return render_template('management/group_form.html', form=form, title=_('Edit Group'))
class ManagementSettings(MethodView): decorators = [ allows.requires( IsAdmin, on_fail=FlashAndRedirect( message=_("You are not allowed to access the management settings"), # noqa level="danger", endpoint="management.overview" ) ) ] def _determine_active_settings(self, slug, plugin): """Determines which settings are active. Returns a tuple in following order: ``form``, ``old_settings``, ``plugin_obj``, ``active_nav`` """ # Any ideas how to do this better? slug = slug if slug else 'general' active_nav = {} # used to build the navigation plugin_obj = None if plugin is not None: plugin_obj = PluginRegistry.query.filter_by(name=plugin ).first_or_404() active_nav.update( { 'key': plugin_obj.name, 'title': plugin_obj.name.title() } ) form = plugin_obj.get_settings_form() old_settings = plugin_obj.settings elif slug is not None: group_obj = SettingsGroup.query.filter_by(key=slug).first_or_404() active_nav.update({'key': group_obj.key, 'title': group_obj.name}) form = Setting.get_form(group_obj)() old_settings = Setting.get_settings(group_obj) return form, old_settings, plugin_obj, active_nav def get(self, slug=None, plugin=None): form, old_settings, plugin_obj, active_nav = \ self._determine_active_settings(slug, plugin) # get all groups and plugins - used to build the navigation all_groups = SettingsGroup.query.all() all_plugins = PluginRegistry.query.filter(db.and_( PluginRegistry.values != None, PluginRegistry.enabled == True )).all() form = populate_settings_form(form, old_settings) return render_template( "management/settings.html", form=form, all_groups=all_groups, all_plugins=all_plugins, active_nav=active_nav ) def post(self, slug=None, plugin=None): form, old_settings, plugin_obj, active_nav = \ self._determine_active_settings(slug, plugin) all_groups = SettingsGroup.query.all() all_plugins = PluginRegistry.query.filter(db.and_( PluginRegistry.values != None, PluginRegistry.enabled == True )).all() if form.validate_on_submit(): new_settings = populate_settings_dict(form, old_settings) if plugin_obj is not None: plugin_obj.update_settings(new_settings) else: Setting.update(settings=new_settings) flash(_("Settings saved."), "success") return render_template( "management/settings.html", form=form, all_groups=all_groups, all_plugins=all_plugins, active_nav=active_nav )
class BanUser(MethodView): decorators = [ allows.requires( IsAtleastModerator, on_fail=FlashAndRedirect( message=_("You are not allowed to manage users"), level="danger", endpoint="management.overview" ) ) ] def post(self, user_id=None): if not Permission(CanBanUser, identity=current_user): flash( _("You do not have the permissions to ban this user."), "danger" ) return redirect(url_for("management.overview")) json = request.get_json() if json: ids = json["ids"] data = [] users = User.query.filter(User.id.in_(ids)).all() for user in users: # don't let a user ban himself and do not allow a moderator # to ban a admin user if (current_user.id == user.id or Permission(IsAdmin, identity=user) and Permission(Not(IsAdmin), current_user)): continue elif user.ban(): data.append( { "id": user.id, "type": "ban", "reverse": "unban", "reverse_name": _("Unban"), "reverse_url": url_for("management.unban_user", user_id=user.id) } ) return jsonify( message="{} users banned.".format(len(data)), category="success", data=data, status=200 ) user = User.query.filter_by(id=user_id).first_or_404() # Do not allow moderators to ban admins if Permission(IsAdmin, identity=user) and Permission( Not(IsAdmin), identity=current_user): flash(_("A moderator cannot ban an admin user."), "danger") return redirect(url_for("management.overview")) if not current_user.id == user.id and user.ban(): flash(_("User is now banned."), "success") else: flash(_("Could not ban user."), "danger") return redirect(url_for("management.banned_users"))
class EditUser(MethodView): decorators = [ allows.requires( IsAtleastModerator, CanEditUser, on_fail=FlashAndRedirect( message=_("You are not allowed to manage users"), level="danger", endpoint="management.overview" ) ) ] form = EditUserForm def get(self, user_id): user = User.query.filter_by(id=user_id).first_or_404() form = self.form(user) 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 current_user.groups), member_group ) if Permission(IsAtleastSuperModerator, identity=current_user): filt = db.or_(filt, Group.mod) if Permission(IsAdmin, identity=current_user): 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) form.primary_group.query = group_query form.secondary_groups.query = group_query return render_template( 'management/user_form.html', form=form, title=_('Edit User') ) def post(self, user_id): user = User.query.filter_by(id=user_id).first_or_404() 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 current_user.groups), member_group ) if Permission(IsAtleastSuperModerator, identity=current_user): filt = db.or_(filt, Group.mod) if Permission(IsAdmin, identity=current_user): 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) form = EditUserForm(user) form.primary_group.query = group_query form.secondary_groups.query = group_query if form.validate_on_submit(): form.populate_obj(user) user.primary_group_id = form.primary_group.data.id # Don't override the password if form.password.data: user.password = form.password.data user.save(groups=form.secondary_groups.data) flash(_('User updated.'), 'success') return redirect(url_for('management.edit_user', user_id=user.id)) return render_template( 'management/user_form.html', form=form, title=_('Edit User') )
class LogsView(Hub): decorators = [ allows.requires( CanAccessServerHub(), on_fail=FlashAndRedirect( message=_("You are not allowed to access the hub"), level="danger", endpoint="forum.index" ) ) ] # returns list [{"name": name, "url": url)] @staticmethod def get_title_parent_folders(server_id, root_path, current_path): folders = [] path = current_path while root_path != path: name = os.path.split(path)[1] url = url_for("hub.gamelogs", server=server_id, path=os.path.relpath(path, root_path)) folders.insert(0, {"name": name, "url": url}) path = os.path.dirname(path) name = "logs" url = url_for("hub.gamelogs", server=server_id) folders.insert(0, {"name": name, "url": url}) if len(folders): folders[-1]["url"] = None return folders def get(self, **kwargs): server_id = request.args["server"] path = None if "path" in request.args: path = request.args["path"] servers = current_app.config["BYOND_SERVERS"] server = None for srv in servers: if srv.id == server_id: server = srv break if server is None: abort(404) current_path = server.logs_path if path: current_path = os.path.realpath(os.path.join(current_path, path)) if not current_path.startswith(server.logs_path + os.sep): abort(404) title_parent_folders = self.get_title_parent_folders(server_id, server.logs_path, current_path) logs_folder_entries = [os.path.join(current_path, f) for f in os.listdir(current_path)] entries = {} for entry in logs_folder_entries: entry_pure = os.path.split(entry)[1] if os.path.isfile(entry): entries[entry_pure] = url_for("hub.download_gamelog", server=server_id, path=os.path.relpath(entry, server.logs_path)) else: lll = os.path.relpath(entry, server.logs_path) entries[entry_pure] = url_for("hub.gamelogs", server=server_id, path=os.path.relpath(entry, server.logs_path)) return render_template( "hub/gamelogs.html", **self.get_args(), entries=sorted(entries.items()), title_parent_folders=title_parent_folders )
class ViewTopic(MethodView): decorators = [ allows.requires( CanAccessForum(), on_fail=FlashAndRedirect( message=_("You are not allowed to access that topic"), level="warning", endpoint=lambda *a, **k: current_category.url)) ] def get(self, topic_id, slug=None): page = request.args.get("page", 1, type=int) # Fetch some information about the topic topic = Topic.get_topic(topic_id=topic_id, user=real(current_user)) # Count the topic views topic.views += 1 topic.save() # Update the topicsread status if the user hasn't read it forumsread = None if current_user.is_authenticated: forumsread = ForumsRead.query.filter_by( user_id=current_user.id, forum_id=topic.forum_id).first() topic.update_read(real(current_user), topic.forum, forumsread) # fetch the posts in the topic posts = Post.query.outerjoin(User, Post.user_id == User.id).filter( Post.topic_id == topic.id).add_entity(User).order_by( Post.id.asc()).paginate(page, flaskbb_config["POSTS_PER_PAGE"], False) # Abort if there are no posts on this page if len(posts.items) == 0: abort(404) return render_template("forum/topic.html", topic=topic, posts=posts, last_seen=time_diff(), form=self.form()) @allows.requires( CanPostReply, on_fail=FlashAndRedirect( message=_("You are not allowed to post a reply to this topic."), level="warning", endpoint=lambda *a, **k: url_for( "forum.view_topic", topic_id=k["topic_id"], ))) def post(self, topic_id, slug=None): topic = Topic.get_topic(topic_id=topic_id, user=real(current_user)) form = self.form() if not form: flash(_("Cannot post reply"), "warning") return redirect("forum.view_topic", topic_id=topic_id, slug=slug) elif form.validate_on_submit(): post = form.save(real(current_user), topic) return redirect(url_for("forum.view_post", post_id=post.id)) else: for e in form.errors.get("content", []): flash(e, "danger") return redirect( url_for("forum.view_topic", topic_id=topic_id, slug=slug)) def form(self): if Permission(CanPostReply): return QuickreplyForm() return None
class ViewTopic(MethodView): decorators = [allows.requires(CanAccessTopic())] def get(self, topic_id, slug=None): page = request.args.get('page', 1, type=int) # Fetch some information about the topic topic = Topic.get_topic(topic_id=topic_id, user=real(current_user)) # Count the topic views topic.views += 1 topic.save() # fetch the posts in the topic posts = Post.query.\ outerjoin(User, Post.user_id == User.id).\ filter(Post.topic_id == topic.id).\ add_entity(User).\ order_by(Post.id.asc()).\ paginate(page, flaskbb_config['POSTS_PER_PAGE'], False) # Abort if there are no posts on this page if len(posts.items) == 0: abort(404) # Update the topicsread status if the user hasn't read it forumsread = None if current_user.is_authenticated: forumsread = ForumsRead.query.\ filter_by(user_id=real(current_user).id, forum_id=topic.forum.id).first() topic.update_read(real(current_user), topic.forum, forumsread) return render_template('forum/topic.html', topic=topic, posts=posts, last_seen=time_diff(), form=self.form()) @allows.requires(CanPostReply) def post(self, topic_id, slug=None): topic = Topic.get_topic(topic_id=topic_id, user=real(current_user)) form = self.form() if not form: flash(_('Cannot post reply'), 'warning') return redirect('forum.view_topic', topic_id=topic_id, slug=slug) elif form.validate_on_submit(): post = form.save(real(current_user), topic) return redirect(url_for('forum.view_post', post_id=post.id)) else: for e in form.errors.get('content', []): flash(e, 'danger') return redirect( url_for('forum.view_topic', topic_id=topic_id, slug=slug)) def form(self): if Permission(CanPostReply): return QuickreplyForm() return None
class Forums(MethodView): decorators = [allows.requires(IsAdmin)] def get(self): categories = Category.query.order_by(Category.position.asc()).all() return render_template("management/forums.html", categories=categories)
class DeleteGroup(MethodView): decorators = [ allows.requires( IsAdmin, on_fail=FlashAndRedirect( message=_("You are not allowed to modify groups."), level="danger", endpoint="management.overview" ) ) ] def post(self, group_id=None): if request.get_json() is not None: ids = request.get_json().get("ids") if not ids: return jsonify( message="No ids provided.", category="error", status=404 ) # TODO: Get rid of magic numbers if not (set(ids) & set(["1", "2", "3", "4", "5", "6"])): data = [] for group in Group.query.filter(Group.id.in_(ids)).all(): group.delete() data.append( { "id": group.id, "type": "delete", "reverse": False, "reverse_name": None, "reverse_url": None } ) return jsonify( message="{} groups deleted.".format(len(data)), category="success", data=data, status=200 ) return jsonify( message=_("You cannot delete one of the standard groups."), category="danger", data=None, status=404 ) if group_id is not None: if group_id <= 6: # there are 6 standard groups flash( _( "You cannot delete the standard groups. " "Try renaming it instead.", "danger" ) ) return redirect(url_for("management.groups")) group = Group.query.filter_by(id=group_id).first_or_404() group.delete() flash(_("Group deleted."), "success") return redirect(url_for("management.groups")) flash(_("No group chosen."), "danger") return redirect(url_for("management.groups"))
class UnbanUser(MethodView): decorators = [ allows.requires( IsAtleastModerator, on_fail=FlashAndRedirect( message=_("You are not allowed to manage users"), level="danger", endpoint="management.overview" ) ) ] def post(self, user_id=None): if not Permission(CanBanUser, identity=current_user): flash( _("You do not have the permissions to unban this user."), "danger" ) return redirect(url_for("management.overview")) # ajax request if request.get_json() is not None: ids = request.get_json().get("ids") if not ids: return jsonify( message="No ids provided.", category="error", status=404 ) data = [] for user in User.query.filter(User.id.in_(ids)).all(): if user.unban(): data.append( { "id": user.id, "type": "unban", "reverse": "ban", "reverse_name": _("Ban"), "reverse_url": url_for("management.ban_user", user_id=user.id) } ) return jsonify( message=f"{len(data)} users unbanned.", category="success", data=data, status=200 ) user = User.query.filter_by(id=user_id).first_or_404() if user.unban(): flash(_("User is now unbanned."), "success") else: flash(_("Could not unban user."), "danger") return redirect_or_next(url_for("management.users"))
class ManagementSettings(MethodView): decorators = [allows.requires(IsAdmin)] def get(self, slug=None): slug = slug if slug else 'general' # get the currently active group active_group = SettingsGroup.query.filter_by(key=slug).first_or_404() # get all groups - used to build the navigation all_groups = SettingsGroup.query.all() SettingsForm = Setting.get_form(active_group) old_settings = Setting.get_settings(active_group) form = SettingsForm() for key, values in iteritems(old_settings): try: form[key].data = values['value'] except (KeyError, ValueError): pass return render_template( 'management/settings.html', form=form, all_groups=all_groups, active_group=active_group ) def post(self, slug=None): slug = slug if slug else 'general' # get the currently active group active_group = SettingsGroup.query.filter_by(key=slug).first_or_404() # get all groups - used to build the navigation all_groups = SettingsGroup.query.all() SettingsForm = Setting.get_form(active_group) old_settings = Setting.get_settings(active_group) new_settings = {} form = SettingsForm() if form.validate_on_submit(): for key, values in iteritems(old_settings): try: # check if the value has changed if values['value'] == form[key].data: continue else: new_settings[key] = form[key].data except KeyError: pass Setting.update(settings=new_settings, app=current_app) flash(_('Settings saved.'), 'success') else: for key, values in iteritems(old_settings): try: form[key].data = values['value'] except (KeyError, ValueError): pass return render_template( 'management/settings.html', form=form, all_groups=all_groups, active_group=active_group )
class MarkReportRead(MethodView): decorators = [ allows.requires( IsAtleastModerator, on_fail=FlashAndRedirect( message=_("You are not allowed to view reports."), level="danger", endpoint="management.overview" ) ) ] def post(self, report_id=None): json = request.get_json() if json: ids = json["ids"] data = [] for report in Report.query.filter(Report.id.in_(ids)).all(): report.zapped_by = current_user.id report.zapped = time_utcnow() report.save() data.append( { "id": report.id, "type": "read", "reverse": False, "reverse_name": None, "reverse_url": None } ) return jsonify( message="{} reports marked as read.".format(len(data)), category="success", data=data, status=200 ) # mark single report as read if report_id: report = Report.query.filter_by(id=report_id).first_or_404() if report.zapped: flash( _("Report %(id)s is already marked as read.", id=report.id), "success" ) return redirect(url_for("management.reports")) report.zapped_by = current_user.id report.zapped = time_utcnow() report.save() flash(_("Report %(id)s marked as read.", id=report.id), "success") return redirect(url_for("management.reports")) # mark all as read reports = Report.query.filter(Report.zapped == None).all() report_list = [] for report in reports: report.zapped_by = current_user.id report.zapped = time_utcnow() report_list.append(report) db.session.add_all(report_list) db.session.commit() flash(_("All reports were marked as read."), "success") return redirect(url_for("management.reports"))
class PluginsView(MethodView): decorators = [allows.requires(IsAdmin)] def get(self): plugins = PluginRegistry.query.all() return render_template("management/plugins.html", plugins=plugins)
class ManageForum(MethodView): decorators = [allows.requires(IsAtleastModeratorInForum()), login_required] def get(self, forum_id, slug=None): forum_instance, forumsread = Forum.get_forum(forum_id=forum_id, user=real(current_user)) if forum_instance.external: return redirect(forum_instance.external) # remove the current forum from the select field (move). available_forums = Forum.query.order_by(Forum.position).all() available_forums.remove(forum_instance) page = request.args.get('page', 1, type=int) topics = Forum.get_topics(forum_id=forum_instance.id, user=real(current_user), page=page, per_page=flaskbb_config['TOPICS_PER_PAGE']) return render_template( 'forum/edit_forum.html', forum=forum_instance, topics=topics, available_forums=available_forums, forumsread=forumsread, ) def post(self, forum_id, slug=None): forum_instance, __ = Forum.get_forum(forum_id=forum_id, user=real(current_user)) mod_forum_url = url_for('forum.manage_forum', forum_id=forum_instance.id, slug=forum_instance.slug) ids = request.form.getlist('rowid') tmp_topics = Topic.query.filter(Topic.id.in_(ids)).all() if not len(tmp_topics) > 0: flash( _('In order to perform this action you have to select at ' 'least one topic.'), 'danger') return redirect(mod_forum_url) # locking/unlocking if 'lock' in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action='locked', reverse=False) flash(_('%(count)s topics locked.', count=changed), 'success') return redirect(mod_forum_url) elif 'unlock' in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action='locked', reverse=True) flash(_('%(count)s topics unlocked.', count=changed), 'success') return redirect(mod_forum_url) # highlighting/trivializing elif 'highlight' in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action='important', reverse=False) flash(_('%(count)s topics highlighted.', count=changed), 'success') return redirect(mod_forum_url) elif 'trivialize' in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action='important', reverse=True) flash(_('%(count)s topics trivialized.', count=changed), 'success') return redirect(mod_forum_url) # deleting elif 'delete' in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action='delete', reverse=False) flash(_('%(count)s topics deleted.', count=changed), 'success') return redirect(mod_forum_url) # moving elif 'move' in request.form: new_forum_id = request.form.get('forum') if not new_forum_id: flash(_('Please choose a new forum for the topics.'), 'info') return redirect(mod_forum_url) new_forum = Forum.query.filter_by(id=new_forum_id).first_or_404() # check the permission in the current forum and in the new forum if not Permission( And(IsAtleastModeratorInForum(forum_id=new_forum_id), IsAtleastModeratorInForum(forum=forum_instance))): flash(_('You do not have the permissions to move this topic.'), 'danger') return redirect(mod_forum_url) if new_forum.move_topics_to(tmp_topics): flash(_('Topics moved.'), 'success') else: flash(_('Failed to move topics.'), 'danger') return redirect(mod_forum_url) # hiding/unhiding elif "hide" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="hide", reverse=False) flash(_("%(count)s topics hidden.", count=changed), "success") return redirect(mod_forum_url) elif "unhide" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="unhide", reverse=False) flash(_("%(count)s topics unhidden.", count=changed), "success") return redirect(mod_forum_url) else: flash(_('Unknown action requested'), 'danger') return redirect(mod_forum_url)
class TeamView(Hub): decorators = [ allows.requires( CanAccessServerHubManagement(), on_fail=FlashAndRedirectToHub( message=_("You are not allowed to access the server team view"), level="danger" ) ) ] def __add_group_to_user(self, user_discord_id): roles = DiscordRole.query\ .join(DiscordUserRole)\ .join(DiscordUser)\ .filter(DiscordUser.id == user_discord_id)\ .all() user = User.query.filter(User.discord == user_discord_id).first() for role in roles: if role.id in hub_current_server.discord_role_to_group: group_id = hub_current_server.discord_role_to_group[role.id] group = Group.query.filter(Group.id == group_id).first() if not user: discord_user = DiscordUser.query.filter(DiscordUser.id == user_discord_id).first() assert discord_user user = User(discord=user_discord_id, display_name=discord_user.pure_name, activated=True) user.primary_group = group else: last_group = user.primary_group user.primary_group = group user.add_to_group(last_group) user.save() LogAction(current_user, "added user {name} (discord: {discord_id}) to group {group}".format( name=user.display_name, discord_id=user_discord_id, group=group.name )) flash("User {} was added to group {}".format(user.display_name, group.name)) return True flash("Failed to find appropriate group for user {}".format(user.display_name), "danger") return False def __remove_group_from_user(self, user_discord_id): user = User.query.filter(User.discord == user_discord_id).first() assert user.primary_group.id in hub_current_server.discord_role_to_group.values() removed_group = user.primary_group secondary_groups = user.secondary_groups.all() if len(secondary_groups): user.primary_group = secondary_groups[0] else: user.primary_group = Group.get_member_group() user.save() LogAction(current_user, "removed user {name} (discord: {discord_id}) from group {group}".format( name=user.display_name, discord_id=user_discord_id, group=removed_group.name )) flash("User {} was removed from group {}".format(user.display_name, removed_group.name)) def get(self): if "user_to_add" in request.args: self.__add_group_to_user(request.args["user_to_add"]) return redirect(url_for("hub.team", server=hub_current_server.id)) if "user_to_remove_group" in request.args: self.__remove_group_from_user(request.args["user_to_remove_group"]) return redirect(url_for("hub.team", server=hub_current_server.id)) @attr.s class TeamMember: id = attr.ib() username = attr.ib() group = attr.ib(default="") discord_role = attr.ib(default="") url = attr.ib(default="") remove_group_url = attr.ib(default="") members = [] for user in User.query.all(): if Permission(CanAccessServerHub(), identity=user): new_member = TeamMember( id=user.discord, username=user.display_name, group=user.primary_group.name, url=user.url) if user.primary_group.id in hub_current_server.discord_role_to_group.values(): new_member.remove_group_url = \ url_for("hub.team", server=hub_current_server.id, user_to_remove_group=user.discord) members.append(new_member) discord_users_with_pedalique_role = db.session.query(DiscordUser)\ .join(DiscordUserRole)\ .join(DiscordRole)\ .filter(DiscordUserRole.role.in_(hub_current_server.discord_full_access_titles))\ .distinct(DiscordUser.id)\ .add_entity(DiscordRole)\ .all() members_from_discord = [] for discord_user, discord_role in discord_users_with_pedalique_role: found = False for member in members: if member.id == discord_user.id: member.discord_role = discord_role.title found = True break if not found: members_from_discord.append(TeamMember(id=discord_user.id, username=discord_user.pure_name, discord_role=discord_role.title)) return render_template( "hub/team.html", **self.get_args(), members=members + members_from_discord )
class ManageForum(MethodView): decorators = [ login_required, allows.requires( IsAtleastModeratorInForum(), on_fail=FlashAndRedirect( message=_("You are not allowed to manage this forum"), level="danger", endpoint=lambda *a, **k: url_for( "forum.view_forum", forum_id=k["forum_id"], ))), ] def get(self, forum_id, slug=None): forum_instance, forumsread = Forum.get_forum(forum_id=forum_id, user=real(current_user)) if forum_instance.external: return redirect(forum_instance.external) # remove the current forum from the select field (move). available_forums = Forum.query.order_by(Forum.position).all() available_forums.remove(forum_instance) page = request.args.get("page", 1, type=int) topics = Forum.get_topics(forum_id=forum_instance.id, user=real(current_user), page=page, per_page=flaskbb_config["TOPICS_PER_PAGE"]) return render_template( "forum/edit_forum.html", forum=forum_instance, topics=topics, available_forums=available_forums, forumsread=forumsread, ) # TODO(anr): Clean this up. @_@ def post(self, forum_id, slug=None): # noqa: C901 forum_instance, __ = Forum.get_forum(forum_id=forum_id, user=real(current_user)) mod_forum_url = url_for("forum.manage_forum", forum_id=forum_instance.id, slug=forum_instance.slug) ids = request.form.getlist("rowid") tmp_topics = Topic.query.filter(Topic.id.in_(ids)).all() if not len(tmp_topics) > 0: flash( _("In order to perform this action you have to select at " "least one topic."), "danger") return redirect(mod_forum_url) # locking/unlocking if "lock" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="locked", reverse=False) flash(_("%(count)s topics locked.", count=changed), "success") return redirect(mod_forum_url) elif "unlock" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="locked", reverse=True) flash(_("%(count)s topics unlocked.", count=changed), "success") return redirect(mod_forum_url) # highlighting/trivializing elif "highlight" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="important", reverse=False) flash(_("%(count)s topics highlighted.", count=changed), "success") return redirect(mod_forum_url) elif "trivialize" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="important", reverse=True) flash(_("%(count)s topics trivialized.", count=changed), "success") return redirect(mod_forum_url) # deleting elif "delete" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="delete", reverse=False) flash(_("%(count)s topics deleted.", count=changed), "success") return redirect(mod_forum_url) # moving elif "move" in request.form: new_forum_id = request.form.get("forum") if not new_forum_id: flash(_("Please choose a new forum for the topics."), "info") return redirect(mod_forum_url) new_forum = Forum.query.filter_by(id=new_forum_id).first_or_404() # check the permission in the current forum and in the new forum if not Permission( And(IsAtleastModeratorInForum(forum_id=new_forum_id), IsAtleastModeratorInForum(forum=forum_instance))): flash(_("You do not have the permissions to move this topic."), "danger") return redirect(mod_forum_url) if new_forum.move_topics_to(tmp_topics): flash(_("Topics moved."), "success") else: flash(_("Failed to move topics."), "danger") return redirect(mod_forum_url) # hiding/unhiding elif "hide" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="hide", reverse=False) flash(_("%(count)s topics hidden.", count=changed), "success") return redirect(mod_forum_url) elif "unhide" in request.form: changed = do_topic_action(topics=tmp_topics, user=real(current_user), action="unhide", reverse=False) flash(_("%(count)s topics unhidden.", count=changed), "success") return redirect(mod_forum_url) else: flash(_("Unknown action requested"), "danger") return redirect(mod_forum_url)
class MarkRead(MethodView): decorators = [ login_required, allows.requires( CanAccessForum(), on_fail=FlashAndRedirect( message=_("You are not allowed to access that forum"), level="warning", endpoint=lambda *a, **k: current_category.url ) ), ] def post(self, forum_id=None, slug=None): # Mark a single forum as read if forum_id is not None: forum_instance = Forum.query.filter_by(id=forum_id).first_or_404() forumsread = ForumsRead.query.filter_by( user_id=real(current_user).id, forum_id=forum_instance.id ).first() TopicsRead.query.filter_by( user_id=real(current_user).id, forum_id=forum_instance.id ).delete() if not forumsread: forumsread = ForumsRead() forumsread.user = real(current_user) forumsread.forum = forum_instance forumsread.last_read = time_utcnow() forumsread.cleared = time_utcnow() db.session.add(forumsread) db.session.commit() flash( _( "Forum %(forum)s marked as read.", forum=forum_instance.title ), "success" ) return redirect(forum_instance.url) # Mark all forums as read ForumsRead.query.filter_by(user_id=real(current_user).id).delete() TopicsRead.query.filter_by(user_id=real(current_user).id).delete() forums = Forum.query.all() forumsread_list = [] for forum_instance in forums: forumsread = ForumsRead() forumsread.user = real(current_user) forumsread.forum = forum_instance forumsread.last_read = time_utcnow() forumsread.cleared = time_utcnow() forumsread_list.append(forumsread) db.session.add_all(forumsread_list) db.session.commit() flash(_("All forums marked as read."), "success") return redirect(url_for("forum.index"))