Ejemplo n.º 1
0
def test_topic_is_unread(guest, user, forum, topic, topicsread, forumsread):
    # test guest
    assert not topic_is_unread(None, None, guest)

    # compare topicsread.last_read with topic.last_post.date_created
    assert topic_is_unread(topic, topicsread, user, forumsread)

    # TopicsRead is none and the forum has never been marked as read
    assert topic_is_unread(topic, topicsread=None, user=user, forumsread=forumsread)

    # lets mark the forum as read
    forumsread.cleared = time_utcnow()
    forumsread.last_read = time_utcnow()
    forumsread.save()
    assert not topic_is_unread(topic, topicsread=None, user=user, forumsread=forumsread)

    # disabled tracker
    flaskbb_config["TRACKER_LENGTH"] = 0
    assert not topic_is_unread(topic, None, user, None)

    # post is older than tracker length
    time_posted = time_utcnow() - dt.timedelta(days=2)
    flaskbb_config["TRACKER_LENGTH"] = 1
    topic.last_post.date_created = time_posted
    topic.last_updated = time_posted
    topic.save()
    assert not topic_is_unread(topic, None, user, None)
Ejemplo n.º 2
0
    def post(self, report_id=None):

        # AJAX request
        if request.is_xhr:
            ids = request.get_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"))
Ejemplo n.º 3
0
    def update_read(self, user, forum, forumsread):
        """Updates the topicsread and forumsread tracker for a specified user,
        if the topic contains new posts or the user hasn't read the topic.
        Returns True if the tracker has been updated.

        :param user: The user for whom the readstracker should be updated.
        :param forum: The forum in which the topic is.
        :param forumsread: The forumsread object. It is used to check if there
                           is a new post since the forum has been marked as
                           read.
        """
        # User is not logged in - abort
        if not user.is_authenticated:
            return False

        topicsread = TopicsRead.query.\
            filter(TopicsRead.user_id == user.id,
                   TopicsRead.topic_id == self.id).first()

        if not self.tracker_needs_update(forumsread, topicsread):
            return False

        # Because we return True/False if the trackers have been
        # updated, we need to store the status in a temporary variable
        updated = False

        # A new post has been submitted that the user hasn't read.
        # Updating...
        if topicsread:
            logger.debug("Updating existing TopicsRead '{}' object."
                         .format(topicsread))
            topicsread.last_read = time_utcnow()
            topicsread.save()
            updated = True

        # The user has not visited the topic before. Inserting him in
        # the TopicsRead model.
        elif not topicsread:
            logger.debug("Creating new TopicsRead object.")
            topicsread = TopicsRead()
            topicsread.user = user
            topicsread.topic = self
            topicsread.forum = self.forum
            topicsread.last_read = time_utcnow()
            topicsread.save()
            updated = True

        # No unread posts
        else:
            updated = False

        # Save True/False if the forums tracker has been updated.
        updated = forum.update_read(user, forumsread, topicsread)

        return updated
Ejemplo n.º 4
0
    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"))
Ejemplo n.º 5
0
    def save(self, conversation=None):
        """Saves a private message.

        :param conversation: The  conversation to which the message
                             belongs to.
        """
        if conversation is not None:
            self.conversation = conversation
            conversation.date_modified = time_utcnow()
            self.date_created = time_utcnow()

        db.session.add(self)
        db.session.commit()
        return self
Ejemplo n.º 6
0
    def tracker_needs_update(self, forumsread, topicsread):
        """Returns True if the topicsread tracker needs an update.
        Also, if the ``TRACKER_LENGTH`` is configured, it will just recognize
        topics that are newer than the ``TRACKER_LENGTH`` (in days) as unread.

        :param forumsread: The ForumsRead object is needed because we also
                           need to check if the forum has been cleared
                           sometime ago.
        :param topicsread: The topicsread object is used to check if there is
                           a new post in the topic.
        """
        read_cutoff = None
        if flaskbb_config['TRACKER_LENGTH'] > 0:
            read_cutoff = time_utcnow() - timedelta(
                days=flaskbb_config['TRACKER_LENGTH'])

        # The tracker is disabled - abort
        if read_cutoff is None:
            return False

        # Else the topic is still below the read_cutoff
        elif read_cutoff > self.last_post.date_created:
            return False

        # Can be None (cleared) if the user has never marked the forum as read.
        # If this condition is false - we need to update the tracker
        if forumsread and forumsread.cleared is not None and \
                forumsread.cleared >= self.last_post.date_created:
            return False

        if topicsread and topicsread.last_read >= self.last_post.date_created:
            return False

        return True
Ejemplo n.º 7
0
 def update_lastseen():
     """Updates `lastseen` before every reguest if the user is
     authenticated."""
     if current_user.is_authenticated:
         current_user.lastseen = time_utcnow()
         db.session.add(current_user)
         db.session.commit()
Ejemplo n.º 8
0
    def authenticate(cls, login, password):
        """A classmethod for authenticating users.
        It returns the user object if the user/password combination is ok.
        If the user has entered too often a wrong password, he will be locked
        out of his account for a specified time.

        :param login: This can be either a username or a email address.
        :param password: The password that is connected to username and email.
        """
        user = cls.query.filter(db.or_(User.username == login,
                                       User.email == login)).first()

        if user is not None:
            if user.check_password(password):
                # reset them after a successful login attempt
                user.login_attempts = 0
                user.save()
                return user

            # user exists, wrong password
            # never had a bad login before
            if user.login_attempts is None:
                user.login_attempts = 1
            else:
                user.login_attempts += 1
            user.last_failed_login = time_utcnow()
            user.save()

        # protection against account enumeration timing attacks
        check_password_hash("dummy password", password)

        raise AuthenticationError
Ejemplo n.º 9
0
def edit_post(post_id):
    post = Post.query.filter_by(id=post_id).first_or_404()

    if not Permission(CanEditPost):
        flash(_("You do not have the permissions to edit this post."),
              "danger")
        return redirect(post.topic.url)

    form = ReplyForm()
    if form.validate_on_submit():
        if "preview" in request.form:
            return render_template(
                "forum/new_post.html", topic=post.topic,
                form=form, preview=form.content.data
            )
        else:
            form.populate_obj(post)
            post.date_modified = time_utcnow()
            post.modified_by = current_user.username
            post.save()
            return redirect(post.topic.url)
    else:
        form.content.data = post.content

    return render_template("forum/new_post.html", topic=post.topic, form=form)
Ejemplo n.º 10
0
 def save(self):
     user = User(username=self.username.data,
                 email=self.email.data,
                 password=self.password.data,
                 date_joined=time_utcnow(),
                 primary_group_id=4,
                 language=self.language.data)
     return user.save()
Ejemplo n.º 11
0
    def save(self, message=None):
        """Saves a conversation and returns the saved conversation object.

        :param message: If given, it will also save the message for the
                        conversation. It expects a Message object.
        """
        if message is not None:
            # create the conversation
            self.date_created = time_utcnow()
            db.session.add(self)
            db.session.commit()

            # create the actual message for the conversation
            message.save(self)
            return self

        self.date_modified = time_utcnow()
        db.session.add(self)
        db.session.commit()
        return self
def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('conversations', schema=None) as batch_op:
        batch_op.add_column(sa.Column('date_modified', flaskbb.utils.database.UTCDateTime(timezone=True), nullable=True))

    with op.batch_alter_table('conversations', schema=None) as batch_op:
        date_modified = sa.sql.table('conversations', sa.sql.column('date_modified'))
        batch_op.execute(date_modified.update().values(date_modified=time_utcnow()))
        batch_op.alter_column('date_modified',
            existing_type=flaskbb.utils.database.UTCDateTime(timezone=True),
            nullable=False
        )
Ejemplo n.º 13
0
    def save(self, user=None, forum=None, post=None):
        """Saves a topic and returns the topic object. If no parameters are
        given, it will only update the topic.

        :param user: The user who has created the topic
        :param forum: The forum where the topic is stored
        :param post: The post object which is connected to the topic
        """

        # Updates the topic
        if self.id:
            db.session.add(self)
            db.session.commit()
            return self

        # Set the forum and user id
        self.forum_id = forum.id
        self.user_id = user.id
        self.username = user.username

        # Set the last_updated time. Needed for the readstracker
        self.last_updated = time_utcnow()

        self.date_created = time_utcnow()

        # Insert and commit the topic
        db.session.add(self)
        db.session.commit()

        # Create the topic post
        post.save(user, self)

        # Update the first post id
        self.first_post_id = post.id

        # Update the topic count
        forum.topic_count += 1
        db.session.commit()

        return self
Ejemplo n.º 14
0
    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
        )
Ejemplo n.º 15
0
    def __init__(self, title=None, user=None):
        """Creates a topic object with some initial values.

        :param title: The title of the topic.
        :param user: The user of the post.
        """
        if title:
            self.title = title

        if user:
            self.user_id = user.id
            self.username = user.username

        self.date_created = self.last_updated = time_utcnow()
Ejemplo n.º 16
0
def edit_conversation(conversation_id):
    conversation = Conversation.query.filter_by(
        id=conversation_id,
        user_id=current_user.id
    ).first_or_404()

    if not conversation.draft:
        flash(_("You cannot edit a sent message."), "danger")
        return redirect(url_for("message.inbox"))

    form = ConversationForm()

    if request.method == "POST":
        if "save_message" in request.form:
            to_user = User.query.filter_by(username=form.to_user.data).first()

            conversation.draft = True
            conversation.to_user_id = to_user.id
            conversation.first_message.message = form.message.data
            conversation.save()

            flash(_("Message saved."), "success")
            return redirect(url_for("message.drafts"))

        if "send_message" in request.form and form.validate():
            to_user = User.query.filter_by(username=form.to_user.data).first()
            # Save the message in the recievers inbox
            form.save(from_user=current_user.id,
                      to_user=to_user.id,
                      user_id=to_user.id,
                      unread=True,
                      shared_id=conversation.shared_id)

            # Move the message from ``Drafts`` to ``Sent``.
            conversation.draft = False
            conversation.to_user = to_user
            conversation.date_created = time_utcnow()
            conversation.save()

            flash(_("Message sent."), "success")
            return redirect(url_for("message.sent"))
    else:
        form.to_user.data = conversation.to_user.username
        form.subject.data = conversation.subject
        form.message.data = conversation.first_message.message

    return render_template("message/message_form.html", form=form,
                           title=_("Edit Message"))
Ejemplo n.º 17
0
    def save(self, user=None, topic=None):
        """Saves a new post. If no parameters are passed we assume that
        you will just update an existing post. It returns the object after the
        operation was successful.

        :param user: The user who has created the post
        :param topic: The topic in which the post was created
        """
        current_app.pluggy.hook.flaskbb_event_post_save_before(post=self)

        # update/edit the post
        if self.id:
            db.session.add(self)
            db.session.commit()
            current_app.pluggy.hook.flaskbb_event_post_save_after(post=self,
                                                                  is_new=False)
            return self

        # Adding a new post
        if user and topic:
            created = time_utcnow()
            self.user = user
            self.username = user.username
            self.topic = topic
            self.date_created = created

            if not topic.hidden:
                topic.last_updated = created
                topic.last_post = self

                # Update the last post info for the forum
                topic.forum.last_post = self
                topic.forum.last_post_user = self.user
                topic.forum.last_post_title = topic.title
                topic.forum.last_post_username = user.username
                topic.forum.last_post_created = created

                # Update the post counts
                user.post_count += 1
                topic.post_count += 1
                topic.forum.post_count += 1

            # And commit it!
            db.session.add(topic)
            db.session.commit()
            current_app.pluggy.hook.flaskbb_event_post_save_after(post=self,
                                                                  is_new=True)
            return self
Ejemplo n.º 18
0
    def save(self, user=None, forum=None, post=None):
        """Saves a topic and returns the topic object. If no parameters are
        given, it will only update the topic.

        :param user: The user who has created the topic
        :param forum: The forum where the topic is stored
        :param post: The post object which is connected to the topic
        """
        current_app.pluggy.hook.flaskbb_event_topic_save_before(topic=self)

        # Updates the topic
        if self.id:
            db.session.add(self)
            db.session.commit()
            current_app.pluggy.hook.flaskbb_event_topic_save_after(
                topic=self, is_new=False
            )
            return self

        # Set the forum and user id
        self.forum = forum
        self.user = user
        self.username = user.username

        # Set the last_updated time. Needed for the readstracker
        self.date_created = self.last_updated = time_utcnow()

        # Insert and commit the topic
        db.session.add(self)
        db.session.commit()

        if post is not None:
            self._post = post

        # Create the topic post
        self._post.save(user, self)

        # Update the first and last post id
        self.last_post = self.first_post = self._post

        # Update the topic count
        forum.topic_count += 1
        db.session.commit()

        current_app.pluggy.hook.flaskbb_event_topic_save_after(topic=self,
                                                               is_new=True)
        return self
Ejemplo n.º 19
0
def edit_conversation(conversation_id):
    conversation = Conversation.query.filter_by(
        id=conversation_id, user_id=current_user.id).first_or_404()

    if not conversation.draft:
        flash(_("You cannot edit a sent message."), "danger")
        return redirect(url_for("message.inbox"))

    form = ConversationForm()

    if request.method == "POST":
        if "save_message" in request.form:
            to_user = User.query.filter_by(username=form.to_user.data).first()

            conversation.draft = True
            conversation.to_user_id = to_user.id
            conversation.first_message.message = form.message.data
            conversation.save()

            flash(_("Message saved."), "success")
            return redirect(url_for("message.drafts"))

        if "send_message" in request.form and form.validate():
            to_user = User.query.filter_by(username=form.to_user.data).first()
            # Save the message in the recievers inbox
            form.save(from_user=current_user.id,
                      to_user=to_user.id,
                      user_id=to_user.id,
                      unread=True,
                      shared_id=conversation.shared_id)

            # Move the message from ``Drafts`` to ``Sent``.
            conversation.draft = False
            conversation.to_user = to_user
            conversation.date_created = time_utcnow()
            conversation.save()

            flash(_("Message sent."), "success")
            return redirect(url_for("message.sent"))
    else:
        form.to_user.data = conversation.to_user.username
        form.subject.data = conversation.subject
        form.message.data = conversation.first_message.message

    return render_template("message/message_form.html",
                           form=form,
                           title=_("Edit Message"))
Ejemplo n.º 20
0
    def save(self, user=None, forum=None, post=None):
        """Saves a topic and returns the topic object. If no parameters are
        given, it will only update the topic.

        :param user: The user who has created the topic
        :param forum: The forum where the topic is stored
        :param post: The post object which is connected to the topic
        """
        current_app.pluggy.hook.flaskbb_event_topic_save_before(topic=self)

        # Updates the topic
        if self.id:
            db.session.add(self)
            db.session.commit()
            current_app.pluggy.hook.flaskbb_event_topic_save_after(
                topic=self, is_new=False
            )
            return self

        # Set the forum and user id
        self.forum = forum
        self.user = user
        self.username = user.username

        # Set the last_updated time. Needed for the readstracker
        self.date_created = self.last_updated = time_utcnow()

        # Insert and commit the topic
        db.session.add(self)
        db.session.commit()

        if post is not None:
            self._post = post

        # Create the topic post
        self._post.save(user, self)

        # Update the first and last post id
        self.last_post = self.first_post = self._post

        # Update the topic count
        forum.topic_count += 1
        db.session.commit()

        current_app.pluggy.hook.flaskbb_event_topic_save_after(topic=self,
                                                               is_new=True)
        return self
Ejemplo n.º 21
0
    def save(self, user=None, topic=None):
        """Saves a new post. If no parameters are passed we assume that
        you will just update an existing post. It returns the object after the
        operation was successful.

        :param user: The user who has created the post
        :param topic: The topic in which the post was created
        """
        # update/edit the post
        if self.id:
            db.session.add(self)
            db.session.commit()
            return self

        # Adding a new post
        if user and topic:
            created = time_utcnow()
            self.user_id = user.id
            self.username = user.username
            self.topic_id = topic.id
            self.date_created = created

            topic.last_updated = created

            # This needs to be done before the last_post_id gets updated.
            db.session.add(self)
            db.session.commit()

            # Now lets update the last post id
            topic.last_post_id = self.id

            # Update the last post info for the forum
            topic.forum.last_post_id = self.id
            topic.forum.last_post_title = topic.title
            topic.forum.last_post_user_id = user.id
            topic.forum.last_post_username = user.username
            topic.forum.last_post_created = created

            # Update the post counts
            user.post_count += 1
            topic.post_count += 1
            topic.forum.post_count += 1

            # And commit it!
            db.session.add(topic)
            db.session.commit()
            return self
Ejemplo n.º 22
0
    def save(self, user=None, topic=None):
        """Saves a new post. If no parameters are passed we assume that
        you will just update an existing post. It returns the object after the
        operation was successful.

        :param user: The user who has created the post
        :param topic: The topic in which the post was created
        """
        # update/edit the post
        if self.id:
            db.session.add(self)
            db.session.commit()
            return self

        # Adding a new post
        if user and topic:
            created = time_utcnow()
            self.user_id = user.id
            self.username = user.username
            self.topic_id = topic.id
            self.date_created = created

            topic.last_updated = created

            # This needs to be done before the last_post_id gets updated.
            db.session.add(self)
            db.session.commit()

            # Now lets update the last post id
            topic.last_post_id = self.id

            # Update the last post info for the forum
            topic.forum.last_post_id = self.id
            topic.forum.last_post_title = topic.title
            topic.forum.last_post_user_id = user.id
            topic.forum.last_post_username = user.username
            topic.forum.last_post_created = created

            # Update the post counts
            user.post_count += 1
            topic.post_count += 1
            topic.forum.post_count += 1

            # And commit it!
            db.session.add(topic)
            db.session.commit()
            return self
Ejemplo n.º 23
0
    def __init__(self, title=None, user=None):
        """Creates a topic object with some initial values.

        :param title: The title of the topic.
        :param user: The user of the post.
        """
        if title:
            self.title = title

        if user:
            # setting the user here, even with setting the id, breaks the bulk insert
            # stuff as they use the session.bulk_save_objects which does not trigger
            # relationships
            self.user_id = user.id
            self.username = user.username

        self.date_created = self.last_updated = time_utcnow()
def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('conversations', schema=None) as batch_op:
        batch_op.add_column(
            sa.Column('date_modified',
                      flaskbb.utils.database.UTCDateTime(timezone=True),
                      nullable=True))

    with op.batch_alter_table('conversations', schema=None) as batch_op:
        date_modified = sa.sql.table('conversations',
                                     sa.sql.column('date_modified'))
        batch_op.execute(
            date_modified.update().values(date_modified=time_utcnow()))
        batch_op.alter_column(
            'date_modified',
            existing_type=flaskbb.utils.database.UTCDateTime(timezone=True),
            nullable=False)
Ejemplo n.º 25
0
    def save(self, user, topic):
        # new post
        if self.post is None:
            self.post = Post(content=self.content.data)
        else:
            self.post.date_modified = time_utcnow()
            self.post.modified_by = user.username

        if self.track_topic.data:
            user.track_topic(topic)
        else:
            user.untrack_topic(topic)

        current_app.pluggy.hook.flaskbb_form_post_save(
            form=self, post=self.post
        )
        return self.post.save(user=user, topic=topic)
Ejemplo n.º 26
0
    def __init__(self, title=None, user=None):
        """Creates a topic object with some initial values.

        :param title: The title of the topic.
        :param user: The user of the post.
        """
        if title:
            self.title = title

        if user:
            # setting the user here, even with setting the id, breaks the bulk insert
            # stuff as they use the session.bulk_save_objects which does not trigger
            # relationships
            self.user_id = user.id
            self.username = user.username

        self.date_created = self.last_updated = time_utcnow()
Ejemplo n.º 27
0
    def save(self, user=None, topic=None):
        """Saves a new post. If no parameters are passed we assume that
        you will just update an existing post. It returns the object after the
        operation was successful.

        :param user: The user who has created the post
        :param topic: The topic in which the post was created
        """
        # update/edit the post
        if self.id:
            db.session.add(self)
            db.session.commit()
            current_app.pluggy.hook.flaskbb_event_after_post(post=self,
                                                             is_new=False)
            return self

        # Adding a new post
        if user and topic:
            created = time_utcnow()
            self.user = user
            self.username = user.username
            self.topic = topic
            self.date_created = created

            if not topic.hidden:
                topic.last_updated = created
                topic.last_post = self

                # Update the last post info for the forum
                topic.forum.last_post = self
                topic.forum.last_post_user = self.user
                topic.forum.last_post_title = topic.title
                topic.forum.last_post_username = user.username
                topic.forum.last_post_created = created

                # Update the post counts
                user.post_count += 1
                topic.post_count += 1
                topic.forum.post_count += 1

            # And commit it!
            db.session.add(topic)
            db.session.commit()
            current_app.pluggy.hook.flaskbb_event_after_post(post=self,
                                                             is_new=True)
            return self
Ejemplo n.º 28
0
    def __init__(self, content=None, user=None, topic=None):
        """Creates a post object with some initial values.

        :param content: The content of the post.
        :param user: The user of the post.
        :param topic: Can either be the topic_id or the topic object.
        """
        if content:
            self.content = content

        if user:
            self.user_id = user.id
            self.username = user.username

        if topic:
            self.topic_id = topic if isinstance(topic, int) else topic.id

        self.date_created = time_utcnow()
Ejemplo n.º 29
0
    def save(self, user, topic):
        # new post
        if self.post is None:
            self.post = Post(content=self.content.data)
        else:
            self.post.date_modified = time_utcnow()
            self.post.modified_by = user.display_name
            self.post.modified_by_user_id = user.id

        if self.track_topic.data:
            user.track_topic(topic)
        else:
            user.untrack_topic(topic)

        current_app.pluggy.hook.flaskbb_form_post_save(
            form=self, post=self.post
        )
        return self.post.save(user=user, topic=topic)
Ejemplo n.º 30
0
    def save(self, message=None):
        """Saves a conversation and returns the saved conversation object.

        :param message: If given, it will also save the message for the
                        conversation. It expects a Message object.
        """
        if message is not None:
            # create the conversation
            self.date_created = time_utcnow()
            db.session.add(self)
            db.session.commit()

            # create the actual message for the conversation
            message.save(self)
            return self

        db.session.add(self)
        db.session.commit()
        return self
Ejemplo n.º 31
0
    def save(self, user, forum):
        if self.track_topic.data:
            user.track_topic(self.topic)
        else:
            user.untrack_topic(self.topic)

        if (
            self.topic.last_post_id == forum.last_post_id
            and self.title.data != forum.last_post_title
        ):
            forum.last_post_title = self.title.data

        self.topic.first_post.date_modified = time_utcnow()
        self.topic.first_post.modified_by = user.username

        current_app.pluggy.hook.flaskbb_form_topic_save(
            form=self, topic=self.topic
        )
        return self.topic.save(user=user, forum=forum)
Ejemplo n.º 32
0
    def save(self, user, forum):
        if self.track_topic.data:
            user.track_topic(self.topic)
        else:
            user.untrack_topic(self.topic)

        if (
            self.topic.last_post_id == forum.last_post_id
            and self.title.data != forum.last_post_title
        ):
            forum.last_post_title = self.title.data

        self.topic.first_post.date_modified = time_utcnow()
        self.topic.first_post.modified_by = user.username
        self.topic.first_post.modified_by_user_id = user.id

        current_app.pluggy.hook.flaskbb_form_topic_save(
            form=self, topic=self.topic
        )
        return self.topic.save(user=user, forum=forum)
Ejemplo n.º 33
0
    def __init__(self, content=None, user=None, topic=None):
        """Creates a post object with some initial values.

        :param content: The content of the post.
        :param user: The user of the post.
        :param topic: Can either be the topic_id or the topic object.
        """
        if content:
            self.content = content

        if user:
            # setting user here -- even with setting the user id explicitly
            # breaks the bulk insert for some reason
            self.user_id = user.id
            self.username = user.username

        if topic:
            self.topic_id = topic if isinstance(topic, int) else topic.id

        self.date_created = time_utcnow()
Ejemplo n.º 34
0
    def __init__(self, content=None, user=None, topic=None):
        """Creates a post object with some initial values.

        :param content: The content of the post.
        :param user: The user of the post.
        :param topic: Can either be the topic_id or the topic object.
        """
        if content:
            self.content = content

        if user:
            # setting user here -- even with setting the user id explicitly
            # breaks the bulk insert for some reason
            self.user_id = user.id
            self.username = user.username

        if topic:
            self.topic_id = topic if isinstance(topic, int) else topic.id

        self.date_created = time_utcnow()
Ejemplo n.º 35
0
    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():
            if 'preview' in request.form:
                return render_template(
                    'forum/new_post.html',
                    topic=post.topic,
                    form=form,
                    preview=form.content.data,
                    edit_mode=True
                )
            else:
                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)
Ejemplo n.º 36
0
    def save(self, post=None, user=None):
        """Saves a report.

        :param post: The post that should be reported
        :param user: The user who has reported the post
        :param reason: The reason why the user has reported the post
        """

        if self.id:
            db.session.add(self)
            db.session.commit()
            return self

        if post and user:
            self.reporter_id = user.id
            self.reported = time_utcnow()
            self.post_id = post.id

        db.session.add(self)
        db.session.commit()
        return self
Ejemplo n.º 37
0
    def save(self, post=None, user=None):
        """Saves a report.

        :param post: The post that should be reported
        :param user: The user who has reported the post
        :param reason: The reason why the user has reported the post
        """

        if self.id:
            db.session.add(self)
            db.session.commit()
            return self

        if post and user:
            self.reporter_id = user.id
            self.reported = time_utcnow()
            self.post_id = post.id

        db.session.add(self)
        db.session.commit()
        return self
Ejemplo n.º 38
0
    def tracker_needs_update(self, forumsread, topicsread):
        """Returns True if the topicsread tracker needs an update.
        Also, if the ``TRACKER_LENGTH`` is configured, it will just recognize
        topics that are newer than the ``TRACKER_LENGTH`` (in days) as unread.

        :param forumsread: The ForumsRead object is needed because we also
                           need to check if the forum has been cleared
                           sometime ago.
        :param topicsread: The topicsread object is used to check if there is
                           a new post in the topic.
        """
        read_cutoff = None
        if flaskbb_config['TRACKER_LENGTH'] > 0:
            read_cutoff = time_utcnow() - timedelta(
                days=flaskbb_config['TRACKER_LENGTH'])

        # The tracker is disabled - abort
        if read_cutoff is None:
            logger.debug("Readtracker is disabled.")
            return False

        # Else the topic is still below the read_cutoff
        elif read_cutoff > self.last_post.date_created:
            logger.debug("Topic is below the read_cutoff (too old).")
            return False

        # Can be None (cleared) if the user has never marked the forum as read.
        # If this condition is false - we need to update the tracker
        if forumsread and forumsread.cleared is not None and \
                forumsread.cleared >= self.last_post.date_created:
            logger.debug("User has marked the forum as read. No new posts "
                         "since then.")
            return False

        if topicsread and topicsread.last_read >= self.last_post.date_created:
            logger.debug("The last post in this topic has already been read.")
            return False

        logger.debug("Topic is unread.")
        return True
Ejemplo n.º 39
0
def edit_post(post_id):
    post = Post.query.filter_by(id=post_id).first_or_404()

    if not Permission(CanEditPost):
        flash(_("You do not have the permissions to edit this post."),
              "danger")
        return redirect(post.topic.url)

    if post.first_post:
        form = NewTopicForm()
    else:
        form = ReplyForm()

    if form.validate_on_submit():
        if "preview" in request.form:
            return render_template("forum/new_post.html",
                                   topic=post.topic,
                                   form=form,
                                   preview=form.content.data,
                                   edit_mode=True)
        else:
            form.populate_obj(post)
            post.date_modified = time_utcnow()
            post.modified_by = current_user.username
            post.save()

            if post.first_post:
                post.topic.title = form.title.data
                post.topic.save()
            return redirect(post.topic.url)
    else:
        if post.first_post:
            form.title.data = post.topic.title

        form.content.data = post.content

    return render_template("forum/new_post.html",
                           topic=post.topic,
                           form=form,
                           edit_mode=True)
Ejemplo n.º 40
0
    def save(self, user=None, forum=None, post=None):
        """Saves a topic and returns the topic object. If no parameters are
        given, it will only update the topic.

        :param user: The user who has created the topic
        :param forum: The forum where the topic is stored
        :param post: The post object which is connected to the topic
        """

        # Updates the topic
        if self.id:
            db.session.add(self)
            db.session.commit()
            return self

        # Set the forum and user id
        self.forum_id = forum.id
        self.user_id = user.id
        self.username = user.username

        # Set the last_updated time. Needed for the readstracker
        created = time_utcnow()
        self.date_created = self.last_updated = created

        # Insert and commit the topic
        db.session.add(self)
        db.session.commit()

        # Create the topic post
        post.save(user, self)

        # Update the first post id
        self.first_post_id = post.id

        # Update the topic count
        forum.topic_count += 1
        db.session.commit()
        return self
Ejemplo n.º 41
0
    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():
            try:
                current_app.pluggy.hook.flaskbb_form_edit_post_save(form=form)
                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))
            except StopEditPost as e:
                flash(e.reason, "danger")
            except BaseFlaskBBError as e:
                flask(e.reason, "warning")
            except Exception:
                flash(_("Unrecoverable error while submiting modified post"))

        return render_template("forum/new_post.html",
                               topic=post.topic,
                               form=form,
                               edit_mode=True)
Ejemplo n.º 42
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 flaskbb_config['TRACKER_LENGTH'] > 0:
            read_cutoff = time_utcnow() - timedelta(
                days=flaskbb_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,
                          TopicsRead.last_read < Topic.last_updated)).\
            count()

        # No unread topics available - trying to mark the forum as read
        if unread_count == 0:

            if forumsread and forumsread.last_read > topicsread.last_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:
                forumsread.last_read = time_utcnow()
                forumsread.save()
                return True

            # No ForumRead Entry existing - creating one.
            forumsread = ForumsRead()
            forumsread.user_id = user.id
            forumsread.forum_id = self.id
            forumsread.last_read = time_utcnow()
            forumsread.save()
            return True

        # Nothing updated, because there are still more than 0 unread
        # topicsread
        return False
Ejemplo n.º 43
0
 def days_registered(self):
     """Returns the amount of days the user is registered."""
     days_registered = (time_utcnow() - self.date_joined).days
     if not days_registered:
         return 1
     return days_registered
Ejemplo n.º 44
0
    def post(self, report_id=None):

        # 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 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_or_next(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_or_next(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_or_next(url_for("management.reports"))
Ejemplo n.º 45
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 flaskbb_config['TRACKER_LENGTH'] > 0:
            read_cutoff = time_utcnow() - timedelta(
                days=flaskbb_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,
                          TopicsRead.last_read < Topic.last_updated)).\
            count()

        # No unread topics available - trying to mark the forum as read
        if unread_count == 0:

            if forumsread and forumsread.last_read > topicsread.last_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:
                forumsread.last_read = time_utcnow()
                forumsread.save()
                return True

            # No ForumRead Entry existing - creating one.
            forumsread = ForumsRead()
            forumsread.user_id = user.id
            forumsread.forum_id = self.id
            forumsread.last_read = time_utcnow()
            forumsread.save()
            return True

        # Nothing updated, because there are still more than 0 unread
        # topicsread
        return False
Ejemplo n.º 46
0
 def days_registered(self):
     """Returns the amount of days the user is registered."""
     days_registered = (time_utcnow() - self.date_joined).days
     if not days_registered:
         return 1
     return days_registered