Exemple #1
0
    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'))
Exemple #2
0
    def validate_name(self, field):
        if hasattr(self, "group"):
            group = Group.query.filter(
                db.and_(Group.name.like(field.data.lower()),
                        db.not_(Group.id == self.group.id))).first()
        else:
            group = Group.query.filter(Group.name.like(
                field.data.lower())).first()

        if group:
            raise ValidationError(_("This group name is already taken."))
Exemple #3
0
    def validate_email(self, field):
        if hasattr(self, "user"):
            user = User.query.filter(
                db.and_(User.email.like(field.data.lower()),
                        db.not_(User.id == self.user.id))).first()
        else:
            user = User.query.filter(User.email.like(
                field.data.lower())).first()

        if user:
            raise ValidationError(_("This email address is already taken."))
Exemple #4
0
    def validate_guest(self, field):
        if hasattr(self, "group"):
            group = Group.query.filter(
                db.and_(Group.guest,
                        db.not_(Group.id == self.group.id))).count()
        else:
            group = Group.query.filter_by(guest=True).count()

        if field.data and group > 0:
            raise ValidationError(
                _("There is already a group of type "
                  "'Guest'."))
Exemple #5
0
    def get_forums(cls, category_id, user):
        """Get the forums for the category.
        It returns a tuple with the category and the forums with their
        forumsread object are stored in a list.

        A return value can look like this for a category with two forums::

            (<Category 1>, [(<Forum 1>, None), (<Forum 2>, None)])

        :param category_id: The category id
        :param user: The user object is needed to check if we also need their
                     forumsread object.
        """
        from flaskpet.user.models import Group
        if user.is_authenticated:
            # get list of user group ids
            user_groups = [gr.id for gr in user.groups]
            # filter forums by user groups
            user_forums = Forum.query.\
                filter(Forum.groups.any(Group.id.in_(user_groups))).\
                subquery()

            forum_alias = aliased(Forum, user_forums)
            forums = cls.query.\
                filter(cls.id == category_id).\
                join(forum_alias, cls.id == forum_alias.category_id).\
                outerjoin(ForumsRead,
                          db.and_(ForumsRead.forum_id == forum_alias.id,
                                  ForumsRead.user_id == user.id)).\
                add_entity(forum_alias).\
                add_entity(ForumsRead).\
                order_by(forum_alias.position).\
                all()
        else:
            guest_group = Group.get_guest_group()
            # filter forums by guest groups
            guest_forums = Forum.query.\
                filter(Forum.groups.any(Group.id == guest_group.id)).\
                subquery()

            forum_alias = aliased(Forum, guest_forums)
            forums = cls.query.\
                filter(cls.id == category_id).\
                join(forum_alias, cls.id == forum_alias.category_id).\
                add_entity(forum_alias).\
                order_by(forum_alias.position).\
                all()

        if not forums:
            abort(404)

        return get_forums(forums, user)
Exemple #6
0
    def get_all(cls, user):
        """Get all categories with all associated forums.
        It returns a list with tuples. Those tuples are containing the category
        and their associated forums (whose are stored in a list).

        For example::

            [(<Category 1>, [(<Forum 2>, <ForumsRead>), (<Forum 1>, None)]),
             (<Category 2>, [(<Forum 3>, None), (<Forum 4>, None)])]

        :param user: The user object is needed to check if we also need their
                     forumsread object.
        """
        # import Group model locally to avoid cicular imports
        from flaskpet.user.models import Group
        if user.is_authenticated:
            # get list of user group ids
            user_groups = [gr.id for gr in user.groups]
            # filter forums by user groups
            user_forums = Forum.query.\
                filter(Forum.groups.any(Group.id.in_(user_groups))).\
                subquery()

            forum_alias = aliased(Forum, user_forums)
            # get all
            forums = cls.query.\
                join(forum_alias, cls.id == forum_alias.category_id).\
                outerjoin(ForumsRead,
                          db.and_(ForumsRead.forum_id == forum_alias.id,
                                  ForumsRead.user_id == user.id)).\
                add_entity(forum_alias).\
                add_entity(ForumsRead).\
                order_by(Category.position, Category.id,
                         forum_alias.position).\
                all()
        else:
            guest_group = Group.get_guest_group()
            # filter forums by guest groups
            guest_forums = Forum.query.\
                filter(Forum.groups.any(Group.id == guest_group.id)).\
                subquery()

            forum_alias = aliased(Forum, guest_forums)
            forums = cls.query.\
                join(forum_alias, cls.id == forum_alias.category_id).\
                add_entity(forum_alias).\
                order_by(Category.position, Category.id,
                         forum_alias.position).\
                all()

        return get_categories_and_forums(forums, user)
Exemple #7
0
    def get(self):
        page = request.args.get("page", 1, type=int)
        topics = real(current_user).tracked_topics.\
            outerjoin(
                TopicsRead,
                db.and_(
                    TopicsRead.topic_id == Topic.id,
                    TopicsRead.user_id == real(current_user).id
                )).\
            outerjoin(Post, Topic.last_post_id == Post.id).\
            outerjoin(Forum, Topic.forum_id == Forum.id).\
            outerjoin(
                ForumsRead,
                db.and_(
                    ForumsRead.forum_id == Forum.id,
                    ForumsRead.user_id == real(current_user).id
                )).\
            add_entity(Post).\
            add_entity(TopicsRead).\
            add_entity(ForumsRead).\
            order_by(Topic.last_updated.desc()).\
            paginate(page, flaskpet_config["TOPICS_PER_PAGE"], True)

        return render_template("forum/topictracker.html", topics=topics)
Exemple #8
0
    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)
Exemple #9
0
    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 #10
0
    def get_forum(cls, forum_id, user):
        """Returns the forum and forumsread object as a tuple for the user.

        :param forum_id: The forum id
        :param user: The user object is needed to check if we also need their
                     forumsread object.
        """
        if user.is_authenticated:
            forum, forumsread = Forum.query.\
                filter(Forum.id == forum_id).\
                options(db.joinedload("category")).\
                outerjoin(ForumsRead,
                          db.and_(ForumsRead.forum_id == Forum.id,
                                  ForumsRead.user_id == user.id)).\
                add_entity(ForumsRead).\
                first_or_404()
        else:
            forum = Forum.query.filter(Forum.id == forum_id).first_or_404()
            forumsread = None

        return forum, forumsread
Exemple #11
0
    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, app=current_app)

            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 #12
0
    def get_topics(cls, forum_id, user, page=1, per_page=20):
        """Get the topics for the forum. If the user is logged in,
        it will perform an outerjoin for the topics with the topicsread and
        forumsread relation to check if it is read or unread.

        :param forum_id: The forum id
        :param user: The user object
        :param page: The page whom should be loaded
        :param per_page: How many topics per page should be shown
        """
        if user.is_authenticated:
            # Now thats intersting - if i don't do the add_entity(Post)
            # the n+1 still exists when trying to access 'topic.last_post'
            # but without it it will fire another query.
            # This way I don't have to use the last_post object when I
            # iterate over the result set.
            topics = Topic.query.filter_by(forum_id=forum_id).\
                outerjoin(TopicsRead,
                          db.and_(TopicsRead.topic_id == Topic.id,
                                  TopicsRead.user_id == user.id)).\
                outerjoin(Post, Topic.last_post_id == Post.id).\
                add_entity(Post).\
                add_entity(TopicsRead).\
                order_by(Topic.important.desc(), Topic.last_updated.desc()).\
                paginate(page, per_page, True)
        else:
            topics = Topic.query.filter_by(forum_id=forum_id).\
                outerjoin(Post, Topic.last_post_id == Post.id).\
                add_entity(Post).\
                order_by(Topic.important.desc(), Topic.last_updated.desc()).\
                paginate(page, per_page, True)

            topics.items = [(topic, last_post, None)
                            for topic, last_post, in topics.items]

        return topics
Exemple #13
0
    def update_read(self, user, forumsread, topicsread):
        """Updates the ForumsRead status for the user. In order to work
        correctly, be sure that `topicsread is **not** `None`.

        :param user: The user for whom we should check if he has read the
                     forum.

        :param forumsread: The forumsread object. It is needed to check if
                           if the forum is unread. If `forumsread` is `None`
                           and the forum is unread, it will create a new entry
                           in the `ForumsRead` relation, else (and the forum
                           is still unread) we are just going to update the
                           entry in the `ForumsRead` relation.

        :param topicsread: The topicsread object is used in combination
                           with the forumsread object to check if the
                           forumsread relation should be updated and
                           therefore is unread.
        """
        if not user.is_authenticated or topicsread is None:
            return False

        read_cutoff = None
        if flaskpet_config['TRACKER_LENGTH'] > 0:
            read_cutoff = time_utcnow() - timedelta(
                days=flaskpet_config['TRACKER_LENGTH'])

        # fetch the unread posts in the forum
        unread_count = Topic.query.\
            outerjoin(TopicsRead,
                      db.and_(TopicsRead.topic_id == Topic.id,
                              TopicsRead.user_id == user.id)).\
            outerjoin(ForumsRead,
                      db.and_(ForumsRead.forum_id == Topic.forum_id,
                              ForumsRead.user_id == user.id)).\
            filter(Topic.forum_id == self.id,
                   Topic.last_updated > read_cutoff,
                   db.or_(TopicsRead.last_read == None,  # noqa: E711
                          TopicsRead.last_read < Topic.last_updated),
                   db.or_(ForumsRead.last_read == None,  # noqa: E711
                          ForumsRead.last_read < Topic.last_updated)).\
            count()

        # No unread topics available - trying to mark the forum as read
        if unread_count == 0:
            logger.debug("No unread topics. Trying to mark the forum as read.")

            if forumsread and forumsread.last_read > topicsread.last_read:
                logger.debug("forumsread.last_read is newer than "
                             "topicsread.last_read. Everything is read.")
                return False

            # ForumRead Entry exists - Updating it because a new topic/post
            # has been submitted and has read everything (obviously, else the
            # unread_count would be useless).
            elif forumsread:
                logger.debug(
                    "Updating existing ForumsRead '{}' object.".format(
                        forumsread))
                forumsread.last_read = time_utcnow()
                forumsread.save()
                return True

            # No ForumRead Entry existing - creating one.
            logger.debug("Creating new ForumsRead object.")
            forumsread = ForumsRead()
            forumsread.user = user
            forumsread.forum = self
            forumsread.last_read = time_utcnow()
            forumsread.save()
            return True

        # Nothing updated, because there are still more than 0 unread
        # topicsread
        logger.debug("No ForumsRead object updated - there are still {} "
                     "unread topics.".format(unread_count))
        return False