Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
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,
        )
Exemple #4
0
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"))
Exemple #5
0
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"))
Exemple #6
0
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)
Exemple #7
0
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)
Exemple #9
0
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())
Exemple #10
0
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')
        )
Exemple #11
0
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"))
Exemple #12
0
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"))
Exemple #14
0
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'))
Exemple #15
0
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
        )
Exemple #16
0
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"))
Exemple #17
0
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')
        )
Exemple #18
0
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
        )
Exemple #19
0
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
Exemple #20
0
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)
Exemple #22
0
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"))
Exemple #23
0
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"))
Exemple #24
0
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
        )
Exemple #25
0
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)
Exemple #27
0
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)
Exemple #28
0
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
        )
Exemple #29
0
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)
Exemple #30
0
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"))