Esempio n. 1
0
class DisablePlugin(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify plugins"),
                            level="danger",
                            endpoint="management.overview"))
    ]

    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 FlaskPet now.",
              plugin=plugin.name), "success")
        return redirect(url_for("management.plugins"))
Esempio n. 2
0
class ViewForum(MethodView):
    decorators = [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 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=flaskpet_config["TOPICS_PER_PAGE"]
        )

        return render_template(
            "forum/forum.html",
            forum=forum_instance,
            topics=topics,
            forumsread=forumsread,
        )
Esempio n. 3
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'))
Esempio n. 4
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"))

        # ajax request
        if request.is_xhr:
            ids = request.get_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"))
Esempio n. 5
0
class AddCategory(MethodView):
    decorators = [
        allows.requires(
            IsAdmin,
            on_fail=FlashAndRedirect(
                message=_("You are not allowed to modify categories"),
                level="danger",
                endpoint="management.overview"))
    ]
    form = CategoryForm

    def get(self):
        return render_template('management/category_form.html',
                               form=self.form(),
                               title=_('Add Category'))

    def post(self):
        form = self.form()

        if form.validate_on_submit():
            form.save()
            flash(_('Category added.'), 'success')
            return redirect(url_for('management.forums'))

        return render_template('management/category_form.html',
                               form=form,
                               title=_('Add Category'))
Esempio n. 6
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)
Esempio n. 7
0
class EditCategory(MethodView):
    decorators = [
        allows.requires(
            IsAdmin,
            on_fail=FlashAndRedirect(
                message=_("You are not allowed to modify categories"),
                level="danger",
                endpoint="management.overview"))
    ]
    form = CategoryForm

    def get(self, category_id):
        category = Category.query.filter_by(id=category_id).first_or_404()

        form = self.form(obj=category)

        return render_template('management/category_form.html',
                               form=form,
                               title=_('Edit Category'))

    def post(self, category_id):
        category = Category.query.filter_by(id=category_id).first_or_404()

        form = self.form(obj=category)

        if form.validate_on_submit():
            form.populate_obj(category)
            flash(_('Category updated.'), 'success')
            category.save()

        return render_template('management/category_form.html',
                               form=form,
                               title=_('Edit Category'))
Esempio n. 8
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.is_xhr:
            ids = request.get_json()["ids"]
            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(url_for("management.reports"))
Esempio n. 9
0
class NewTopic(MethodView):
    decorators = [
        login_required,
        allows.requires(
            CanAccessForum(), CanPostTopic,
            on_fail=FlashAndRedirect(
                message=_("You are not allowed to post a topic here"),
                level="warning",
                endpoint=lambda *a, **k: current_forum.url
            )
        ),
    ]

    def get(self, forum_id, slug=None):
        forum_instance = Forum.query.filter_by(id=forum_id).first_or_404()
        return render_template(
            "forum/new_topic.html", forum=forum_instance, form=self.form()
        )

    def post(self, forum_id, slug=None):
        forum_instance = Forum.query.filter_by(id=forum_id).first_or_404()
        form = self.form()
        if form.validate_on_submit():
            topic = form.save(real(current_user), forum_instance)
            return redirect(url_for("forum.view_topic", topic_id=topic.id))

        return render_template(
            "forum/new_topic.html", forum=forum_instance, form=form
        )

    def form(self):
        current_app.pluggy.hook.flaskpet_form_new_topic(form=NewTopicForm)
        return NewTopicForm()
Esempio n. 10
0
class ViewPost(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, post_id):
        """Redirects to a post in a topic."""
        post = Post.query.filter_by(id=post_id).first_or_404()
        post_in_topic = Post.query.filter(
            Post.topic_id == post.topic_id, Post.id <= post_id
        ).order_by(Post.id.asc()).count()
        page = int(
            math.ceil(post_in_topic / float(flaskpet_config["POSTS_PER_PAGE"]))
        )

        return redirect(
            url_for(
                "forum.view_topic",
                topic_id=post.topic.id,
                slug=post.topic.slug,
                page=page,
                _anchor="pid{}".format(post.id)
            )
        )
Esempio n. 11
0
class PluginsView(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify plugins"),
                            level="danger",
                            endpoint="management.overview"))
    ]

    def get(self):
        plugins = PluginRegistry.query.all()
        return render_template("management/plugins.html", plugins=plugins)
Esempio n. 12
0
class Forums(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify forums."),
                            level="danger",
                            endpoint="management.overview"))
    ]

    def get(self):
        categories = Category.query.order_by(Category.position.asc()).all()
        return render_template("management/forums.html", categories=categories)
Esempio n. 13
0
class ManagementOverview(MethodView):
    decorators = [
        allows.requires(
            IsAtleastModerator,
            on_fail=FlashAndRedirect(message=_(
                "You are not allowed to access the management panel"),
                                     level="danger",
                                     endpoint="forum.index"))
    ]

    def get(self):
        # user and group stats
        banned_users = User.query.filter(
            Group.banned == True, Group.id == User.primary_group_id).count()
        if not current_app.config["REDIS_ENABLED"]:
            online_users = User.query.filter(
                User.lastseen >= time_diff()).count()
        else:
            online_users = len(get_online_users())

        unread_reports = Report.query.\
            filter(Report.zapped == None).\
            order_by(Report.id.desc()).\
            count()

        python_version = "{}.{}.{}".format(sys.version_info[0],
                                           sys.version_info[1],
                                           sys.version_info[2])

        stats = {
            "current_app": current_app,
            "unread_reports": unread_reports,
            # stats stats
            "all_users": User.query.count(),
            "banned_users": banned_users,
            "online_users": online_users,
            "all_groups": Group.query.count(),
            "report_count": Report.query.count(),
            "topic_count": Topic.query.count(),
            "post_count": Post.query.count(),
            # components
            "python_version": python_version,
            "celery_version": celery_version,
            "flask_version": flask_version,
            "flaskpet_version": flaskpet_version,
            # plugins
            "plugins": PluginRegistry.query.all()
        }

        return render_template("management/overview.html", **stats)
Esempio n. 14
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.is_xhr:
            ids = request.get_json()["ids"]
            # 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"))
Esempio n. 15
0
class RawPost(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 get(self, post_id):
        post = Post.query.filter_by(id=post_id).first_or_404()
        return format_quote(username=post.username, content=post.content)
Esempio n. 16
0
class UninstallPlugin(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify plugins"),
                            level="danger",
                            endpoint="management.overview"))
    ]

    def post(self, name):
        validate_plugin(name)
        plugin = PluginRegistry.query.filter_by(name=name).first_or_404()
        PluginStore.query.filter_by(plugin_id=plugin.id).delete()
        db.session.commit()
        flash(_("Plugin has been uninstalled."), "success")
        return redirect(url_for("management.plugins"))
Esempio n. 17
0
class Reports(MethodView):
    decorators = [
        allows.requires(IsAtleastModerator,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to view reports."),
                            level="danger",
                            endpoint="management.overview"))
    ]

    def get(self):
        page = request.args.get("page", 1, type=int)
        reports = Report.query.\
            order_by(Report.id.asc()).\
            paginate(page, flaskpet_config['USERS_PER_PAGE'], False)

        return render_template("management/reports.html", reports=reports)
Esempio n. 18
0
class NewPost(MethodView):
    decorators = [
        login_required,
        allows.requires(
            CanAccessForum(), CanPostReply,
            on_fail=FlashAndRedirect(
                message=_("You are not allowed to post a reply"),
                level="warning",
                endpoint=lambda *a, **k: url_for(
                    "forum.view_topic",
                    topic_id=k["topic_id"],
                )
            )
        ),
    ]

    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():
            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.flaskpet_form_new_post(form=ReplyForm)
        return ReplyForm()
Esempio n. 19
0
class Groups(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify groups."),
                            level="danger",
                            endpoint="management.overview"))
    ]

    def get(self):

        page = request.args.get("page", 1, type=int)

        groups = Group.query.\
            order_by(Group.id.asc()).\
            paginate(page, flaskpet_config['USERS_PER_PAGE'], False)

        return render_template("management/groups.html", groups=groups)
Esempio n. 20
0
class UntrackTopic(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, topic_id, slug=None):
        topic = Topic.query.filter_by(id=topic_id).first_or_404()
        real(current_user).untrack_topic(topic)
        real(current_user).save()
        return redirect(topic.url)
Esempio n. 21
0
class EditForum(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify forums."),
                            level="danger",
                            endpoint="management.overview"))
    ]
    form = EditForumForm

    def get(self, forum_id):
        forum = Forum.query.filter_by(id=forum_id).first_or_404()

        form = self.form(forum)

        if forum.moderators:
            form.moderators.data = ','.join(
                [user.username for user in forum.moderators])
        else:
            form.moderators.data = None

        return render_template('management/forum_form.html',
                               form=form,
                               title=_('Edit Forum'))

    def post(self, forum_id):
        forum = Forum.query.filter_by(id=forum_id).first_or_404()

        form = self.form(forum)
        if form.validate_on_submit():
            form.save()
            flash(_('Forum updated.'), 'success')
            return redirect(url_for('management.edit_forum',
                                    forum_id=forum.id))
        else:
            if forum.moderators:
                form.moderators.data = ','.join(
                    [user.username for user in forum.moderators])
            else:
                form.moderators.data = None

        return render_template('management/forum_form.html',
                               form=form,
                               title=_('Edit Forum'))
Esempio n. 22
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"))
Esempio n. 23
0
class DeleteUser(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to manage users"),
                            level="danger",
                            endpoint="management.overview"))
    ]

    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"))
Esempio n. 24
0
class TrivializeTopic(MethodView):
    decorators = [
        login_required,
        allows.requires(
            IsAtleastModeratorInForum(),
            on_fail=FlashAndRedirect(
                message=_("You are not allowed to trivialize this topic"),
                level="danger",
                # TODO(anr): consider the referrer -- for now, back to topic
                endpoint=lambda *a, **k: current_topic.url
            )
        ),
    ]

    def post(self, topic_id=None, slug=None):
        topic = Topic.query.filter_by(id=topic_id).first_or_404()
        topic.important = False
        topic.save()
        return redirect(topic.url)
Esempio n. 25
0
class BannedUsers(MethodView):
    decorators = [
        allows.requires(IsAtleastModerator,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to manage users"),
                            level="danger",
                            endpoint="management.overview"))
    ]
    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, flaskpet_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, flaskpet_config['USERS_PER_PAGE'],
                                      False)

        if search_form.validate():
            users = search_form.get_results().\
                paginate(page, flaskpet_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)
Esempio n. 26
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"))
Esempio n. 27
0
class DeleteTopic(MethodView):
    decorators = [
        login_required,
        allows.requires(
            CanDeleteTopic,
            on_fail=FlashAndRedirect(
                message=_("You are not allowed to delete this topic"),
                level="danger",
                # TODO(anr): consider the referrer -- for now, back to topic
                endpoint=lambda *a, **k: current_topic.url
            )
        ),
    ]

    def post(self, topic_id, slug=None):
        topic = Topic.query.filter_by(id=topic_id).first_or_404()
        involved_users = User.query.filter(
            Post.topic_id == topic.id, User.id == Post.user_id
        ).all()
        topic.delete(users=involved_users)
        return redirect(url_for("forum.view_forum", forum_id=topic.forum_id))
Esempio n. 28
0
class InstallPlugin(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify plugins"),
                            level="danger",
                            endpoint="management.overview"))
    ]

    def post(self, name):
        plugin_module = validate_plugin(name)
        plugin = PluginRegistry.query.filter_by(name=name).first_or_404()

        if not plugin.enabled:
            flash(
                _("Can't install plugin. Enable '%(plugin)s' plugin first.",
                  plugin=plugin.name), "danger")
            return redirect(url_for("management.plugins"))

        plugin.add_settings(plugin_module.SETTINGS)
        flash(_("Plugin has been installed."), "success")
        return redirect(url_for("management.plugins"))
Esempio n. 29
0
class AddForum(MethodView):
    decorators = [
        allows.requires(IsAdmin,
                        on_fail=FlashAndRedirect(
                            message=_("You are not allowed to modify forums."),
                            level="danger",
                            endpoint="management.overview"))
    ]
    form = AddForumForm

    def get(self, category_id=None):
        form = self.form()

        form.groups.data = Group.query.order_by(Group.id.asc()).all()

        if category_id:
            category = Category.query.filter_by(id=category_id).first()
            form.category.data = category

        return render_template('management/forum_form.html',
                               form=form,
                               title=_('Add Forum'))

    def post(self, category_id=None):
        form = self.form()

        if form.validate_on_submit():
            form.save()
            flash(_('Forum added.'), 'success')
            return redirect(url_for('management.forums'))
        else:
            form.groups.data = Group.query.order_by(Group.id.asc()).all()
            if category_id:
                category = Category.query.filter_by(id=category_id).first()
                form.category.data = category

        return render_template('management/forum_form.html',
                               form=form,
                               title=_('Add Forum'))
Esempio n. 30
0
class EditPost(MethodView):
    decorators = [
        allows.requires(
            CanEditPost,
            on_fail=FlashAndRedirect(
                message=_("You are not allowed to edit that post"),
                level="danger",
                endpoint=lambda *a, **k: current_topic.url
            )
        ),
        login_required
    ]

    def get(self, post_id):
        post = Post.query.filter_by(id=post_id).first_or_404()
        form = self.form(obj=post)

        return render_template(
            "forum/new_post.html", topic=post.topic, form=form, edit_mode=True
        )

    def post(self, post_id):
        post = Post.query.filter_by(id=post_id).first_or_404()
        form = self.form(obj=post)

        if form.validate_on_submit():
            form.populate_obj(post)
            post.date_modified = time_utcnow()
            post.modified_by = real(current_user).username
            post.save()
            return redirect(url_for("forum.view_post", post_id=post.id))

        return render_template(
            "forum/new_post.html", topic=post.topic, form=form, edit_mode=True
        )

    def form(self, **kwargs):
        current_app.pluggy.hook.flaskpet_form_new_post(form=ReplyForm)
        return ReplyForm(**kwargs)