def forgot(): """Allow users to get a password reset link""" form = ForgotForm(request.form) # We always go to /signin after a POST if request.method == 'POST': if form.validate(): user = get_user(get_uid(form.username.data, non_active=True)) if user is not None: # Only send e-mails to user which exist. token = generate_token({ 'action': 'reset', 'uid': user.get('_id') }) send_mail( 'Pjuu Account Notification - Password Reset', [user.get('email')], text_body=render_template('emails/forgot.txt', token=token), html_body=render_template('emails/forgot.html', token=token) ) flash('If we\'ve found your account we\'ve e-mailed you', 'information') return redirect(url_for('auth.signin')) else: flash('Please enter a username or e-mail address', 'error') return render_template('forgot.html', form=form)
def downvote(username, post_id, reply_id=None): """Downvotes a post. """ redirect_url = handle_next(request, url_for('posts.view_post', username=username, post_id=post_id)) user_id = get_uid(username) if not check_post(user_id, post_id, reply_id): return abort(404) try: if reply_id is None: vote_post(current_user['_id'], post_id, amount=-1) else: vote_post(current_user['_id'], reply_id, amount=-1) except AlreadyVoted: flash('You have already voted on this post', 'error') except CantVoteOnOwn: flash('You can not vote on your own posts', 'error') else: flash('You downvoted the ' + ("comment" if reply_id else "post"), 'success') return redirect(redirect_url)
def flag(username, post_id): """Flags a post so that moderators are aware of it. .. note: This is a requirement to enter the Apple app store. """ # Ensure the default redirect is to the correct location. reply_id = get_post(post_id).get('reply_to') if reply_id is None: redirect_url = handle_next(request, url_for('posts.view_post', username=username, post_id=post_id)) else: reply = get_post(reply_id) redirect_url = handle_next(request, url_for('posts.view_post', username=reply.get('username'), post_id=reply_id)) user_id = get_uid(username) if not check_post(user_id, post_id): return abort(404) try: flag_post(current_user['_id'], post_id) except CantFlagOwn: flash('You can not flag on your own posts', 'error') except AlreadyFlagged: flash('You have already flagged this post', 'error') else: flash('You flagged the ' + ('comment' if reply_id else 'post'), 'success') return redirect(redirect_url)
def delete_post(username, post_id, reply_id=None): """Deletes posts. """ # The default redirect is different for a post/reply deletion # Reply deletion keeps you on the page and post deletion takes you to feed if reply_id is not None: redirect_url = handle_next(request, url_for('posts.view_post', username=username, post_id=post_id)) else: redirect_url = handle_next(request, url_for('users.feed')) user_id = get_uid(username) if not check_post(user_id, post_id, reply_id): return abort(404) if reply_id is not None: _post = get_post(reply_id) if _post['user_id'] != current_user['_id'] and \ user_id != current_user['_id']: return abort(403) else: if user_id != current_user['_id']: return abort(403) if reply_id is not None: be_delete_post(reply_id) flash('Post has been deleted', 'success') else: be_delete_post(post_id) flash('Post has been deleted along with all replies', 'success') return redirect(redirect_url)
def delete_post(username, post_id, reply_id=None): """Deletes posts. """ # The default redirect is different for a post/reply deletion # Reply deletion keeps you on the page and post deletion takes you to feed if reply_id is not None: redirect_url = handle_next( request, url_for('posts.view_post', username=username, post_id=post_id)) else: redirect_url = handle_next(request, url_for('users.feed')) user_id = get_uid(username) if not check_post(user_id, post_id, reply_id): return abort(404) if reply_id is not None: _post = get_post(reply_id) if _post['user_id'] != current_user['_id'] and \ user_id != current_user['_id']: return abort(403) else: if user_id != current_user['_id']: return abort(403) if reply_id is not None: be_delete_post(reply_id) flash('Post has been deleted', 'success') else: be_delete_post(post_id) flash('Post has been deleted along with all replies', 'success') return redirect(redirect_url)
def unsubscribe(username, post_id): """Unsubscribes a user from a post """ if not check_post(get_uid(username), post_id): return abort(404) # The default URL is to go back to the posts view redirect_url = handle_next(request, url_for('posts.view_post', username=username, post_id=post_id)) # Unsubscribe the user from the post, only show them a message if they # were actually unsubscribed if be_unsubscribe(current_user['_id'], post_id): flash('You have been unsubscribed from this post', 'success') return redirect(redirect_url)
def unsubscribe(username, post_id): """Unsubscribes a user from a post """ if not check_post(get_uid(username), post_id): return abort(404) # The default URL is to go back to the posts view redirect_url = handle_next( request, url_for('posts.view_post', username=username, post_id=post_id)) # Unsubscribe the user from the post, only show them a message if they # were actually unsubscribed if be_unsubscribe(current_user['_id'], post_id): flash('You have been unsubscribed from this post', 'success') return redirect(redirect_url)
def flag(username, post_id): """Flags a post so that moderators are aware of it. .. note: This is a requirement to enter the Apple app store. """ if not check_post(get_uid(username), post_id): return abort(404) _post = get_post(post_id) # Ensure the default redirect is to the correct location. reply_id = get_post(post_id).get('reply_to') if reply_id is None: redirect_url = handle_next( request, url_for('posts.view_post', username=username, post_id=post_id)) else: reply = get_post(reply_id) redirect_url = handle_next( request, url_for('posts.view_post', username=reply.get('username'), post_id=reply_id)) # Ensue user has permission to perform the action current_user_id = current_user.get('_id') permission = get_user_permission(_post.get('user_id'), current_user_id) if permission < _post.get('permission', k.PERM_PUBLIC): flash('You do not have permission to flag this post', 'error') return redirect(redirect_url) try: flag_post(current_user['_id'], post_id) except CantFlagOwn: flash('You can not flag on your own posts', 'error') except AlreadyFlagged: flash('You have already flagged this post', 'error') else: flash('You flagged the ' + ('comment' if reply_id else 'post'), 'success') return redirect(redirect_url)
def unfollow(username): """Unfollow a user""" redirect_url = handle_next(request, url_for('users.following', username=current_user.get('username'))) user_id = get_uid(username) # If we don't get a uid from the username the page doesn't exist if user_id is None: abort(404) # Unfollow user, ensure the user doesn't unfollow themself if user_id != current_user.get('_id'): if unfollow_user(current_user.get('_id'), user_id): flash('You are no longer following %s' % username, 'success') else: flash('You can\'t follow/unfollow yourself', 'information') return redirect(redirect_url)
def forgot(): """Allow users to get a password reset link""" form = ForgotForm(request.form) # We always go to /signin after a POST if request.method == 'POST': user = get_user(get_uid(form.username.data, non_active=True)) if user is not None: # Only send e-mails to user which exist. token = generate_token({'action': 'reset', 'uid': user.get('_id')}) send_mail('Pjuu Account Notification - Password Reset', [user.get('email')], text_body=render_template('emails/forgot.txt', token=token), html_body=render_template('emails/forgot.html', token=token)) flash('If we\'ve found your account we\'ve e-mailed you', 'information') return redirect(url_for('auth.signin')) return render_template('forgot.html', form=form)
def followers(username): """Returns all a users followers as a pagination object.""" user_id = get_uid(username) if user_id is None: abort(404) # Data _profile = get_profile(user_id) # Pagination page = handle_page(request) # Get a list of users you are following _followers = get_followers(user_id, page, current_user.get('feed_pagination_size')) return render_template('followers.html', profile=_profile, pagination=_followers)
def followers(username): """Returns all a users followers as a pagination object.""" user_id = get_uid(username) if user_id is None: abort(404) # Data _profile = get_profile(user_id) # Pagination page = handle_page(request) # Get a list of users you are following _followers = get_followers(user_id, page) # Post form post_form = PostForm() return render_template('followers.html', profile=_profile, pagination=_followers, post_form=post_form)
def unfollow(username): """Unfollow a user""" redirect_url = handle_next( request, url_for('users.following', username=current_user.get('username'))) user_id = get_uid(username) # If we don't get a uid from the username the page doesn't exist if user_id is None: abort(404) # Unfollow user, ensure the user doesn't unfollow themself if user_id != current_user.get('_id'): if unfollow_user(current_user.get('_id'), user_id): flash('You are no longer following %s' % username, 'success') else: flash('You can\'t follow/unfollow yourself', 'information') return redirect(redirect_url)
def unapprove(username): """Unfollow a user""" redirect_url = handle_next( request, url_for('users.followers', username=current_user.get('username'))) user_id = get_uid(username) # If we don't get a uid from the username the page doesn't exist if user_id is None: abort(404) if user_id != current_user.get('_id'): if unapprove_user(current_user.get('_id'), user_id): flash('You have untrusted %s' % username, 'success') else: flash('You can\'t untrust a user who is not trusted', 'error') else: flash('You can\'t untrust your self', 'information') return redirect(redirect_url)
def unapprove(username): """Unfollow a user""" redirect_url = handle_next(request, url_for('users.followers', username=current_user.get('username'))) user_id = get_uid(username) # If we don't get a uid from the username the page doesn't exist if user_id is None: abort(404) if user_id != current_user.get('_id'): if unapprove_user(current_user.get('_id'), user_id): flash('You have untrusted %s' % username, 'success') else: flash('You can\'t untrust a user who is not trusted', 'error') else: flash('You can\'t untrust your self', 'information') return redirect(redirect_url)
def following(username): """Returns all users following the current user as a pagination.""" user_id = get_uid(username) if user_id is None: abort(404) # Data _profile = get_profile(user_id) # Pagination page = handle_page(request) # Get a list of users you are following _following = get_following(user_id, page, current_user.get('feed_pagination_size')) # Post form post_form = PostForm() return render_template('following.html', profile=_profile, pagination=_following, post_form=post_form)
def view_post(username, post_id): """ Displays a post along with its comments paginated. I am not sure if this should be here or in the 'posts' app. """ if not check_post(get_uid(username), post_id): return abort(404) # Pagination page = handle_page(request) # Get post and comments for the current page _post = get_post(post_id) # Stop a reply from ever being shown here if 'reply_to' in _post: return abort(404) pagination = get_replies(post_id, page) post_form = PostForm() return render_template('view_post.html', post=_post, pagination=pagination, post_form=post_form)
def view_post(username, post_id): """ Displays a post along with its comments paginated. I am not sure if this should be here or in the 'posts' app. """ if not check_post(get_uid(username), post_id): return abort(404) # Pagination page = handle_page(request) # Handle explicit sort order # Fall back to user default else default sort = request.args.get('sort', None) if sort is None: sort = current_user.get('reply_sort_order', -1) else: try: sort = int(sort) except ValueError: sort = current_user.get('reply_sort_order', -1) # Get post and comments for the current page _post = get_post(post_id) # Stop a reply from ever being shown here if 'reply_to' in _post: return abort(404) pagination = get_replies(post_id, page, current_user.get('replies_pagination_size'), sort) post_form = PostForm() return render_template('view_post.html', post=_post, pagination=pagination, post_form=post_form, sort=sort)
def view_post(username, post_id): """Displays a post along with its comments paginated. I am not sure if this should be here or in the 'posts' app. .. note: Viewable to the public if the post is public! """ if not check_post(get_uid(username), post_id): return abort(404) # Get post and comments for the current page _post = get_post(post_id) # Stop a reply from ever being shown here if 'reply_to' in _post: return abort(404) _user = get_user(get_uid(username)) # Only get the permission if the post is not owned by the current user if current_user: current_user_id = current_user.get('_id') else: current_user_id = None permission = get_user_permission(_user.get('_id'), current_user_id) if permission < _post.get('permission', k.PERM_PUBLIC): return abort(403) # Pagination page = handle_page(request) # Handle explicit sort order # Fall back to user default else default sort = request.args.get('sort', None) if sort is None: if current_user: sort = current_user.get('reply_sort_order', -1) else: sort = -1 else: try: sort = 1 if int(sort) > 0 else -1 except ValueError: if current_user: sort = current_user.get('reply_sort_order', -1) else: sort = -1 # Get the page sizes taking in to account non-logged in users if current_user: page_size = current_user.get( 'replies_pagination_size', app.config.get('REPLIES_ITEMS_PER_PAGE', 25)) else: page_size = app.config.get('REPLIES_ITEMS_PER_PAGE', 25) pagination = get_replies(post_id, page, page_size, sort) post_form = PostForm() return render_template('view_post.html', post=_post, pagination=pagination, post_form=post_form, sort=sort)
def vote(username, post_id, reply_id=None): """Upvotes a post. .. note: If the request is an XHR one the whole function will not run. It will exit out and the first chance and return JSON. """ redirect_url = handle_next(request, url_for('posts.view_post', username=username, post_id=post_id)) if not check_post(get_uid(username), post_id, reply_id): if request.is_xhr: return jsonify({'message': 'Post not found'}), 404 return abort(404) _post = get_post(post_id) # Ensuer user has permission to perform the action current_user_id = current_user.get('_id') permission = get_user_permission(_post.get('user_id'), current_user_id) # Since the upvote/downvote functions have been merged we need to # identify which action is going to be performed. if request.endpoint == 'posts.upvote': action = 'upvoted' amount = 1 else: action = 'downvoted' amount = -1 if permission < _post.get('permission', k.PERM_PUBLIC): message = 'You do not have permission to vote on this post' if request.is_xhr: return jsonify({'message': message}), 403 xflash(message, 'error') return redirect(redirect_url) try: if reply_id is None: result = vote_post(current_user['_id'], post_id, amount=amount) else: result = vote_post(current_user['_id'], reply_id, amount=amount) except AlreadyVoted: message = 'You have already voted on this post' if request.is_xhr: return jsonify({'message': message}), 400 xflash(message, 'error') except CantVoteOnOwn: message = 'You can not vote on your own posts' if request.is_xhr: return jsonify({'message': message}), 400 xflash(message, 'error') else: if (amount > 0 < result) or (amount < 0 > result): message = 'You {} the '.format(action) + ("comment" if reply_id else "post") xflash(message, 'success') else: message = 'You reversed your vote on the ' + ("comment" if reply_id else "post") xflash(message, 'success') if request.is_xhr: return jsonify({'message': message}), 200 return redirect(redirect_url)
def post(username=None, post_id=None): """Enabled current_user to create a new post on Pjuu :) This view accepts GET and POST yet only acts on a POST. This is so that the Werkzeug router does not treat this like a profile lookup. """ # Rather than just 404 if someone tries to GET this URL (which is default), # we will throw a 405. if request.method == 'GET': return abort(405) # Stop un-approved users posting comments if permissions do not let them. if post_id is not None: if not check_post(get_uid(username), post_id): return abort(404) _post = get_post(post_id) permission = get_user_permission(current_user, _post.get('_id')) if permission < _post.get('permission', k.PERM_PUBLIC): return abort(403) # Set the default redirect URLs depending on type of post it is if post_id is None: redirect_url = handle_next(request, url_for('users.profile', username=current_user['username'])) else: redirect_url = handle_next(request, url_for('posts.view_post', username=username, post_id=post_id)) # Stop muted users from creating posts if current_user.get('muted', False): flash('You have been silenced!', 'warning') return redirect(redirect_url) form = PostForm() if form.validate(): # If there is an uploaded File pass it on else pass nothing if form.upload.data: # Pass the BytesIO stream to the backend. upload = form.upload.data.stream else: upload = None try: permission = int(form.permission.data) except ValueError: # pragma: no cover permission = -1 # WTForms should stop this ever, ever firing if not (k.PERM_PUBLIC <= permission <= # pragma: no cover k.PERM_APPROVED): # pragma: no cover flash('Invalid post permission set', 'error') return redirect(redirect_url) # Create the post if create_post(current_user['_id'], current_user['username'], unicode(escape(form.body.data)), post_id, upload, permission=permission): # Inform the user we have created the post flash('Your post has been added', 'success') else: flash('There was an error creating your post', 'error') # pragma: no cover else: # Will print out all errors that happen in a post form. # This is better than "There is an error in your post" for key, value in form.errors.iteritems(): for error in value: flash(error, 'error') return redirect(redirect_url)
def view_post(username, post_id): """Displays a post along with its comments paginated. I am not sure if this should be here or in the 'posts' app. .. note: Viewable to the public if the post is public! """ if not check_post(get_uid(username), post_id): return abort(404) # Get post and comments for the current page _post = get_post(post_id) # Stop a reply from ever being shown here if 'reply_to' in _post: return abort(404) _user = get_user(get_uid(username)) # Only get the permission if the post is not owned by the current user if current_user: current_user_id = current_user.get('_id') else: current_user_id = None permission = get_user_permission(_user.get('_id'), current_user_id) if permission < _post.get('permission', k.PERM_PUBLIC): return abort(403) # Pagination page = handle_page(request) # Handle explicit sort order # Fall back to user default else default sort = request.args.get('sort', None) if sort is None: if current_user: sort = current_user.get('reply_sort_order', -1) else: sort = -1 else: try: sort = 1 if int(sort) > 0 else -1 except ValueError: if current_user: sort = current_user.get('reply_sort_order', -1) else: sort = -1 # Get the page sizes taking in to account non-logged in users if current_user: page_size = current_user.get( 'replies_pagination_size', app.config.get('REPLIES_ITEMS_PER_PAGE', 25) ) else: page_size = app.config.get('REPLIES_ITEMS_PER_PAGE', 25) pagination = get_replies(post_id, page, page_size, sort) post_form = PostForm() return render_template('view_post.html', post=_post, pagination=pagination, post_form=post_form, sort=sort)
def vote(username, post_id, reply_id=None): """Upvotes a post. .. note: If the request is an XHR one the whole function will not run. It will exit out and the first chance and return JSON. """ redirect_url = handle_next( request, url_for('posts.view_post', username=username, post_id=post_id)) if not check_post(get_uid(username), post_id, reply_id): if request.is_xhr: return jsonify({'message': 'Post not found'}), 404 return abort(404) _post = get_post(post_id) # Ensuer user has permission to perform the action current_user_id = current_user.get('_id') permission = get_user_permission(_post.get('user_id'), current_user_id) # Since the upvote/downvote functions have been merged we need to # identify which action is going to be performed. if request.endpoint == 'posts.upvote': action = 'upvoted' amount = 1 else: action = 'downvoted' amount = -1 if permission < _post.get('permission', k.PERM_PUBLIC): message = 'You do not have permission to vote on this post' if request.is_xhr: return jsonify({'message': message}), 403 xflash(message, 'error') return redirect(redirect_url) try: if reply_id is None: result = vote_post(current_user['_id'], post_id, amount=amount) else: result = vote_post(current_user['_id'], reply_id, amount=amount) except AlreadyVoted: message = 'You have already voted on this post' if request.is_xhr: return jsonify({'message': message}), 400 xflash(message, 'error') except CantVoteOnOwn: message = 'You can not vote on your own posts' if request.is_xhr: return jsonify({'message': message}), 400 xflash(message, 'error') else: if (amount > 0 < result) or (amount < 0 > result): message = 'You {} the '.format(action) + ("comment" if reply_id else "post") xflash(message, 'success') else: message = 'You reversed your vote on the ' + ("comment" if reply_id else "post") xflash(message, 'success') if request.is_xhr: return jsonify({'message': message}), 200 return redirect(redirect_url)
def post(username=None, post_id=None): """Enabled current_user to create a new post on Pjuu :) This view accepts GET and POST yet only acts on a POST. This is so that the Werkzeug router does not treat this like a profile lookup. """ # Rather than just 404 if someone tries to GET this URL (which is default), # we will throw a 405. if request.method == 'GET': return abort(405) # Stop un-approved users posting comments if permissions do not let them. if post_id is not None: if not check_post(get_uid(username), post_id): return abort(404) _post = get_post(post_id) permission = get_user_permission(current_user, _post.get('_id')) if permission < _post.get('permission', k.PERM_PUBLIC): return abort(403) # Set the default redirect URLs depending on type of post it is if post_id is None: redirect_url = handle_next( request, url_for('users.profile', username=current_user['username'])) else: redirect_url = handle_next( request, url_for('posts.view_post', username=username, post_id=post_id)) # Stop muted users from creating posts if current_user.get('muted', False): flash('You have been silenced!', 'warning') return redirect(redirect_url) form = PostForm() if form.validate(): # If there is an uploaded File pass it on else pass nothing if form.upload.data: # Pass the BytesIO stream to the backend. upload = form.upload.data.stream else: upload = None try: permission = int(form.permission.data) except ValueError: # pragma: no cover permission = -1 # WTForms should stop this ever, ever firing if not (k.PERM_PUBLIC <= permission <= # pragma: no cover k.PERM_APPROVED): # pragma: no cover flash('Invalid post permission set', 'error') return redirect(redirect_url) # Create the post if create_post(current_user['_id'], current_user['username'], unicode(escape(form.body.data)), post_id, upload, permission=permission): # Inform the user we have created the post flash('Your post has been added', 'success') else: flash('There was an error creating your post', 'error') # pragma: no cover else: # Will print out all errors that happen in a post form. # This is better than "There is an error in your post" for key, value in form.errors.iteritems(): for error in value: flash(error, 'error') return redirect(redirect_url)
def test_create_user(self): """Check basic user creation stuffs. This also in turn tests check_username(), check_username_pattern(), check_email(), check_email_pattern(), get_username() and get_email(). """ user1 = create_account('user1', '*****@*****.**', 'Password') self.assertIsNotNone(user1) # Duplicate username self.assertIsNone(create_account('user1', '*****@*****.**', 'Password')) # Duplicate email self.assertIsNone(create_account('userX', '*****@*****.**', 'Password')) # Invalid username self.assertIsNone(create_account('u', '*****@*****.**', 'Password')) # Invalid email self.assertIsNone(create_account('userX', 'userX', 'Password')) # Reserved username self.assertIsNone(create_account('help', '*****@*****.**', 'Password')) # You can't get a UID for a non-activated user self.assertEqual(get_uid('user1'), None) activate(user1) self.assertEqual(get_uid('user1'), user1) self.assertEqual(get_uid('*****@*****.**'), user1) # Shouldn't work wiht invali users self.assertIsNone(get_user(K.NIL_VALUE)) # Ensure if works with a valid user self.assertIsNotNone(get_user(user1)) self.assertIsNotNone(type(get_user(user1))) self.assertEqual(type(get_user(user1)), dict) self.assertEqual(get_user(user1).get('username'), 'user1') self.assertEqual(get_user(user1).get('email'), '*****@*****.**') # Check get_uid_* with invalid entries self.assertIsNone(get_uid_username('testymctest')) self.assertIsNone(get_uid_email('*****@*****.**')) # With valid self.assertEqual(get_uid_username('user1'), user1) self.assertEqual(get_uid_email('*****@*****.**'), user1) # Create a new user to check the defaults user2 = create_account('user2', '*****@*****.**', 'Password') # Are values set as expected? user = get_user(user2) self.assertIsNotNone(user) self.assertEqual(user.get('_id'), user2) self.assertEqual(user.get('username'), 'user2') self.assertEqual(user.get('email'), '*****@*****.**') self.assertEqual(user.get('last_login'), -1) self.assertFalse(user.get('active')) self.assertFalse(user.get('banned')) self.assertFalse(user.get('op')) self.assertFalse(user.get('muted')) self.assertEqual(user.get('about'), '') self.assertEqual(user.get('score'), 0) self.assertEqual(user.get('alerts_last_checked'), -1) self.assertIsNotNone(user.get('ttl')) # Generated values, we don't know what they SHOULD be self.assertIsNotNone(user.get('password')) self.assertIsNotNone(user.get('created')) # Check user_exists works self.assertTrue(user_exists(user1)) # Check it fails when invalid value self.assertFalse(user_exists(K.NIL_VALUE))
def test_create_user(self): """Check basic user creation stuffs. This also in turn tests check_username(), check_username_pattern(), check_email(), check_email_pattern(), get_username() and get_email(). """ user1 = create_account('user1', '*****@*****.**', 'Password') self.assertIsNotNone(user1) # Duplicate username self.assertIsNone( create_account('user1', '*****@*****.**', 'Password')) # Duplicate email self.assertIsNone( create_account('userX', '*****@*****.**', 'Password')) # Invalid username self.assertIsNone( create_account('u', '*****@*****.**', 'Password')) # Invalid email self.assertIsNone( create_account('userX', 'userX', 'Password')) # Reserved username self.assertIsNone( create_account('help', '*****@*****.**', 'Password')) # You can't get a UID for a non-activated user self.assertEqual(get_uid('user1'), None) activate(user1) self.assertEqual(get_uid('user1'), user1) self.assertEqual(get_uid('*****@*****.**'), user1) # Shouldn't work wiht invali users self.assertIsNone(get_user(K.NIL_VALUE)) # Ensure if works with a valid user self.assertIsNotNone(get_user(user1)) self.assertIsNotNone(type(get_user(user1))) self.assertEqual(type(get_user(user1)), dict) self.assertEqual(get_user(user1).get('username'), 'user1') self.assertEqual(get_user(user1).get('email'), '*****@*****.**') # Check get_uid_* with invalid entries self.assertIsNone(get_uid_username('testymctest')) self.assertIsNone(get_uid_email('*****@*****.**')) # With valid self.assertEqual(get_uid_username('user1'), user1) self.assertEqual(get_uid_email('*****@*****.**'), user1) # Create a new user to check the defaults user2 = create_account('user2', '*****@*****.**', 'Password') # Are values set as expected? user = get_user(user2) self.assertIsNotNone(user) self.assertEqual(user.get('_id'), user2) self.assertEqual(user.get('username'), 'user2') self.assertEqual(user.get('email'), '*****@*****.**') self.assertEqual(user.get('last_login'), -1) self.assertFalse(user.get('active')) self.assertFalse(user.get('banned')) self.assertFalse(user.get('op')) self.assertFalse(user.get('muted')) self.assertEqual(user.get('about'), '') self.assertEqual(user.get('score'), 0) self.assertEqual(user.get('alerts_last_checked'), -1) self.assertIsNotNone(user.get('ttl')) # Generated values, we don't know what they SHOULD be self.assertIsNotNone(user.get('password')) self.assertIsNotNone(user.get('created')) # Check user_exists works self.assertTrue(user_exists(user1)) # Check it fails when invalid value self.assertFalse(user_exists(K.NIL_VALUE))