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)
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"))
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
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"))
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
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
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()
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
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)
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()
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 )
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
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 __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()
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"))
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
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
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"))
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
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)
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)
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
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()
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)
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
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)
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)
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()
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)
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
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
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)
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
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)
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
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
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"))