def get(self, user_id): user = User.query.filter_by(id=user_id).first_or_404() form = self.form(user) member_group = db.and_( * [ db.not_(getattr(Group, p)) for p in ['admin', 'mod', 'super_mod', 'banned', 'guest'] ] ) filt = db.or_( Group.id.in_(g.id for g in current_user.groups), member_group ) if Permission(IsAtleastSuperModerator, identity=current_user): filt = db.or_(filt, Group.mod) if Permission(IsAdmin, identity=current_user): filt = db.or_(filt, Group.admin, Group.super_mod) if Permission(CanBanUser, identity=current_user): filt = db.or_(filt, Group.banned) group_query = Group.query.filter(filt) form.primary_group.query = group_query form.secondary_groups.query = group_query return render_template( 'management/user_form.html', form=form, title=_('Edit User') )
def _fix_post_counts(self, forum): clauses = [ Topic.forum_id == forum.id ] if self.hidden: clauses.extend([ Topic.id != self.id, Topic.hidden != True, ]) else: clauses.append(db.or_(Topic.id == self.id, Topic.hidden != True)) forum.topic_count = Topic.query.filter(*clauses).count() post_count = clauses + [ Post.topic_id == Topic.id, ] if self.hidden: post_count.append(Post.hidden != True) else: post_count.append( db.or_(Post.hidden != True, Post.id == self.first_post.id) ) forum.post_count = Post.query.distinct().filter(*post_count).count()
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 _update_counts(self): if self.hidden: clauses = [Post.hidden != True, Post.id != self.id] else: clauses = [db.or_(Post.hidden != True, Post.id == self.id)] user_post_clauses = clauses + [ Post.user_id == self.user.id, Topic.id == Post.topic_id, Topic.hidden != True, ] # Update the post counts self.user.post_count = Post.query.filter(*user_post_clauses).count() if self.topic.hidden: self.topic.post_count = 0 else: topic_post_clauses = clauses + [ Post.topic_id == self.topic.id, ] self.topic.post_count = Post.query.filter( *topic_post_clauses).count() forum_post_clauses = clauses + [ Post.topic_id == Topic.id, Topic.forum_id == self.topic.forum.id, Topic.hidden != True, ] self.topic.forum.post_count = Post.query.filter( *forum_post_clauses).count()
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: if user.check_password(password): # reset them after a successful login attempt user.login_attempts = 0 user.save() return user # user exists, wrong password user.login_attempts += 1 user.last_failed_login = datetime.utcnow() user.save() # protection against account enumeration timing attacks dummy_password = os.urandom(15).encode("base-64") check_password_hash(dummy_password, password) raise AuthenticationError
def _update_counts(self): if self.hidden: clauses = [Post.hidden != True, Post.id != self.id] else: clauses = [db.or_(Post.hidden != True, Post.id == self.id)] user_post_clauses = clauses + [ Post.user_id == self.user.id, Topic.id == Post.topic_id, Topic.hidden != True, ] # Update the post counts self.user.post_count = Post.query.filter(*user_post_clauses).count() if self.topic.hidden: self.topic.post_count = 0 else: topic_post_clauses = clauses + [ Post.topic_id == self.topic.id, ] self.topic.post_count = Post.query.filter( *topic_post_clauses ).count() forum_post_clauses = clauses + [ Post.topic_id == Topic.id, Topic.forum_id == self.topic.forum.id, Topic.hidden != True, ] self.topic.forum.post_count = Post.query.filter( *forum_post_clauses ).count()
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 # 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, 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 = datetime.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 = datetime.utcnow() forumsread.save() return True # Nothing updated, because there are still more than 0 unread topics return False
def edit_user(user_id): user = User.query.filter_by(id=user_id).first_or_404() if not Permission(CanEditUser, identity=current_user): flash(_("You are not allowed to edit this user."), "danger") return redirect(url_for("management.users")) 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"))
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') )
def edit_user(user_id): user = User.query.filter_by(id=user_id).first_or_404() if not can_edit_user(current_user): flash(_("You are not allowed to edit this user."), "danger") return redirect(url_for("management.users")) 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 user.groups), member_group) if any(user.permissions[p] for p in ['super_mod', 'admin']): filt = db.or_(filt, Group.mod) if user.permissions['admin']: filt = db.or_(filt, Group.admin, Group.super_mod) 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 successfully 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"))
def authenticate(cls, login, password): """ A classmethod for authenticating users It returns true if the user exists and has entered a correct password """ user = cls.query.filter(db.or_(User.username == login, User.email == login)).first() if user: authenticated = user.check_password(password) else: authenticated = False return user, authenticated
def authenticate(cls, login, password): """A classmethod for authenticating users It returns true if the user exists and has entered a correct password :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: authenticated = user.check_password(password) else: authenticated = False return user, authenticated
def authenticate(cls, login, password): """A classmethod for authenticating users. It returns true if the user exists and has entered a correct password :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: authenticated = user.check_password(password) else: authenticated = False return user, authenticated
def update_read(self, user, forum, forumsread=None): """Update the topics read status if the user hasn't read the latest post. :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 """ read_cutoff = datetime.utcnow() - timedelta( days=current_app.config['TRACKER_LENGTH']) # Anonymous User or the post is too old for inserting it in the # TopicsRead model if not user.is_authenticated() or \ read_cutoff > self.last_post.date_created: return topicread = TopicsRead.query.\ filter(TopicsRead.user_id == user.id, TopicsRead.topic_id == self.id).first() # Can be None 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 # A new post has been submitted that the user hasn't read. # Updating... if topicread and (topicread.last_read < self.last_post.date_created): topicread.last_read = datetime.utcnow() topicread.save() # The user has not visited the topic before. Inserting him in # the TopicsRead model. elif not topicread: topicread = TopicsRead() topicread.user_id = user.id topicread.topic_id = self.id topicread.forum_id = self.forum_id topicread.last_read = datetime.utcnow() topicread.save() # else: no unread posts if forum: # 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 == forum.id, 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: forumread = ForumsRead.query.\ filter(ForumsRead.user_id == user.id, ForumsRead.forum_id == forum.id).first() # ForumsRead is already up-to-date. if forumread and forumread.last_read > topicread.last_read: return # ForumRead Entry exists - Updating it because a new post # has been submitted that the user hasn't read. elif forumread: forumread.last_read = datetime.utcnow() forumread.save() # No ForumRead Entry existing - creating one. else: forumread = ForumsRead() forumread.user_id = user.id forumread.forum_id = forum.id forumread.last_read = datetime.utcnow() forumread.save()
def update_read(self, user, forum, forumsread=None): """Update the topics read status if the user hasn't read the latest post. :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 """ read_cutoff = datetime.utcnow() - timedelta( days=current_app.config['TRACKER_LENGTH']) # Anonymous User or the post is too old for inserting it in the # TopicsRead model if not user.is_authenticated() or \ read_cutoff > self.last_post.date_created: return topicread = TopicsRead.query.\ filter(TopicsRead.user_id == user.id, TopicsRead.topic_id == self.id).first() # Can be None 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 # A new post has been submitted that the user hasn't read. # Updating... if topicread and (topicread.last_read < self.last_post.date_created): topicread.last_read = datetime.utcnow() topicread.save() # The user has not visited the topic before. Inserting him in # the TopicsRead model. elif not topicread: topicread = TopicsRead() topicread.user_id = user.id topicread.topic_id = self.id topicread.forum_id = self.forum_id topicread.last_read = datetime.utcnow() topicread.save() # else: no unread posts if forum: # 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 == forum.id, 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: forumread = ForumsRead.query.\ filter(ForumsRead.user_id == user.id, ForumsRead.forum_id == forum.id).first() # ForumsRead is already up-to-date. if forumread and forumread.last_read > topicread.last_read: return # ForumRead Entry exists - Updating it because a new post # has been submitted that the user hasn't read. elif forumread: forumread.last_read = datetime.utcnow() forumread.save() # No ForumRead Entry existing - creating one. else: forumread = ForumsRead() forumread.user_id = user.id forumread.forum_id = forum.id forumread.last_read = datetime.utcnow() forumread.save()
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, # 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