def alerts(): """Display a users alerts (notifications) to them on the site.""" uid = current_user.get('_id') # Pagination page = handle_page(request) _results = get_alerts(uid, page, current_user.get('alerts_pagination_size')) return render_template('alerts.html', pagination=_results)
def subscribed_filter(post_id): """A simple filter to check if the current user is subscribed to a post """ if current_user: return is_subscribed(current_user.get('_id'), post_id) return False
def remove_from_feed(post_id): """Removes ``post_id`` from current users feed.""" redirect_url = handle_next(request, url_for('users.feed')) if be_rem_from_feed(post_id, current_user.get('_id')): # pragma: no branch flash('Message has been removed from feed', 'success') return redirect(handle_next(request, redirect_url))
def reset_tips(): """Allow a user to reset all the tips from their settings page""" redirect_url = handle_next(request, url_for('users.settings_profile')) # Actually reset the tips in the database be_reset_tips(current_user.get('_id')) flash('Tip\'s have successfully been reset', 'success') return redirect(redirect_url)
def feed(): """Displays the users feed or redirects the user to the signin if they are not already signed in. """ if not current_user: return redirect(url_for('auth.signin')) # Pagination page = handle_page(request) # Get feed pagination pagination = get_feed(current_user.get('_id'), page, current_user.get('feed_pagination_size')) # Post form post_form = PostForm() return render_template('feed.html', pagination=pagination, post_form=post_form)
def delete_alert(alert_id): """Remove an alert id (aid) from a users alerts feed.""" user_id = current_user.get('_id') # Handle next redirect_url = handle_next(request, url_for('users.alerts')) if be_delete_alert(user_id, alert_id): flash('Alert has been hidden', '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 hide_tip(tip_name): """Will set a tip with `tip_name` to false for the `current_user`""" if tip_name not in k.VALID_TIP_NAMES: return abort(404) # Set the tip to False inside Mongo remove_tip(current_user.get('_id'), tip_name) redirect_url = handle_next(request, url_for('users.feed')) 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 kick_banned_user(): """ This function will check too see if the user has been banned since login. Without this we would have to wait for the user to try and login again before they are informed that they are banned. This fucntion will just ensure they are kicked out """ if current_user and current_user.get('banned', False): session.pop('user_id', None) flash('You\'re a very naughty boy!', 'error')
def voted_filter(post_id): """Checks to see if current_user has voted on the post pid. To check a post simply: item.post_id|voted These may be reffered to as items.X in lists. Will return 1 on upvote, -1 on downvote and 0 if not voted """ return has_voted(current_user.get('_id'), post_id) or 0
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 profile(username): """It will show the users posts. Referred to as "posts" on the site. .. note: Viewable to public! (Only public posts) """ uid = get_uid_username(username) if uid is None: abort(404) # Data _profile = get_profile(uid) # Pagination page = handle_page(request) # Get the page sizes taking in to account non-logged in users if current_user: page_size = current_user.get('feed_pagination_size', app.config.get('FEED_ITEMS_PER_PAGE', 25)) else: page_size = app.config.get('FEED_ITEMS_PER_PAGE', 25) # Get the posts pagination if current_user: current_user_id = current_user.get('_id') else: current_user_id = None permission = get_user_permission(_profile.get('_id'), current_user_id) _posts = get_posts(uid, page, page_size, perm=permission) # Post form post_form = PostForm() return render_template('posts.html', profile=_profile, pagination=_posts, post_form=post_form)
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) # 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 # Create the post if create_post(current_user['_id'], current_user['username'], form.body.data, post_id, upload): # 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 voted_filter(post_id): """Checks to see if current_user has voted on the post pid. To check a post simply: item.post_id|voted These may be reffered to as items.X in lists. Will return 1 on upvote, -1 on downvote and 0 if not voted """ if current_user: return has_voted(current_user.get('_id'), post_id) or 0 return False
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 settings_profile(): """Allows users to customize their profile direct from this view.""" form = ChangeProfileForm(request.form) if request.method == 'POST': if form.validate(): # Update current_user, this was highlighted by Ant is issue 1 current_user['about'] = form.about.data # Set the users new about in Redis set_about(current_user.get('_id'), form.about.data) flash('Your profile has been updated', 'success') else: flash('Oh no! There are errors in your form', 'error') return render_template('settings_profile.html', form=form)
def i_has_alerts(): """ Will return a simple JSON response to denote if the current user has any alerts since last time this was called. This will be passed in with the template but will allow something like jQuery to check. """ # We don't want this view to redirect to signin so we will throw a 403 # this will make jQuery easier to use with this endpoint if not current_user: return abort(403) uid = current_user.get('uid') return jsonify(result=be_i_has_alerts(uid))
def feed(): """ Returns the users feed """ if not current_user: return redirect(url_for('signin')) # Pagination page = handle_page(request) # Get feed pagination pagination = get_feed(current_user.get('uid'), page) # Post form post_form = PostForm() return render_template('feed.html', pagination=pagination, post_form=post_form)
def new_alerts(): """Return a simple http status response to denote if the current user has any alerts since last time this was called. This will be passed in with the template but will allow something an AJAX call to get the data also. .. note: See ``pjuu/static/js/alerts.js`` """ # We don't want this view to redirect to signin so we will throw a 403 # this will make jQuery easier to use with this endpoint if not current_user: return abort(403) uid = current_user.get('_id') # If a user has alerts then return a 200 else a 404 return jsonify({'new_alerts': be_new_alerts(uid)})
def search(): """Search for a users. This is all done via a GET query. .. note: Should be _NO_ CSRF this will appear in the URL and look shit. """ # Pagination page = handle_page(request) form = SearchForm(request.form) # Get the query string. If its not there return an empty string query = request.args.get('query', '') _results = be_search(query, page, current_user.get('feed_pagination_size')) return render_template('search.html', form=form, query=query, pagination=_results)
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 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 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 profile(username): """It will show the users posts. Referred to as "posts" on the site.""" uid = get_uid_username(username) if uid is None: abort(404) # Data _profile = get_profile(uid) # Pagination page = handle_page(request) # Get the posts pagination pagination = get_posts(uid, page, current_user.get('feed_pagination_size')) # Post form post_form = PostForm() return render_template('posts.html', profile=_profile, pagination=pagination, post_form=post_form)
def unflag_post(post_id): """Resets a posts votes to 0. .. note: OP users only. Uses a `dashboard URL` """ # Do not allow users who are not OP to log in if not current_user or not current_user.get('op', False): return abort(403) if get_post(post_id) is None: return abort(404) # Reset the posts flag. Doesn't matter if there aren't any be_unflag_post(post_id) flash('Flags have been reset for post', 'success') # Always go back to the dashboard redirect_url = url_for('dashboard.dashboard') return redirect(redirect_url)
def dashboard(): """Loops through packages looking for stats to provide a data view. """ # Do not allow users who are not OP to log in if not current_user or not current_user.get('op', False): return abort(403) # Get a list of all packages within Pjuu packages = [ name for importer, name, ispkg in pkgutil.iter_modules(pjuu.__path__, pjuu.__name__ + ".") if ispkg ] # Hold on to all stats collected stats_list = [] # Inject the server stats from this package stats_list.append(('server', get_stats())) # For each package look for the ``stats`` module and call ``get_stats`` # If there isn't one it won't be added to the stats output for package_name in packages: try: package = importlib.import_module(package_name + ".stats") except ImportError: package = None if package is not None: try: # Split the package name to get sub-package name subpackage_name = package_name.split('.') subpackage_name = subpackage_name[len(subpackage_name) - 1] # Add the tuple to the list stats_list.append((subpackage_name, package.get_stats())) except AttributeError: # pragma: no cover pass return render_template('dashboard.html', stats_list=stats_list)
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 global_feed(): """Show a weighted list of public/pjuu only posts depending if the user is logged in or not """ if current_user: page_size = current_user.get('feed_pagination_size', app.config.get('FEED_ITEMS_PER_PAGE', 25)) else: page_size = app.config.get('FEED_ITEMS_PER_PAGE', 25) if current_user: permission = 1 else: permission = 0 page = handle_page(request) _posts = get_global_feed(page, page_size, perm=permission) post_form = PostForm() return render_template('global_feed.html', pagination=_posts, post_form=post_form)
def dashboard(): """Loops through packages looking for stats to provide a data view. """ # Do not allow users who are not OP to log in if not current_user or not current_user.get('op', False): return abort(403) # Get a list of all packages within Pjuu packages = [ name for importer, name, ispkg in pkgutil.iter_modules( pjuu.__path__, pjuu.__name__ + ".") if ispkg ] # Hold on to all stats collected stats_list = [] # Inject the server stats from this package stats_list.append(('server', get_stats())) # For each package look for the ``stats`` module and call ``get_stats`` # If there isn't one it won't be added to the stats output for package_name in packages: try: package = importlib.import_module(package_name + ".stats") except ImportError: package = None if package is not None: try: # Split the package name to get sub-package name subpackage_name = package_name.split('.') subpackage_name = subpackage_name[len(subpackage_name) - 1] # Add the tuple to the list stats_list.append((subpackage_name, package.get_stats())) except AttributeError: # pragma: no cover pass return render_template('dashboard.html', stats_list=stats_list)
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, current_user.get('replies_pagination_size')) post_form = PostForm() return render_template('view_post.html', post=_post, pagination=pagination, post_form=post_form)
def flagged_filter(post_id): """Check if a user flagged the post with post id""" if current_user: return has_flagged(current_user.get('_id'), post_id) return False
def settings_profile(): """Allows users to customize their profile direct from this view.""" # Create the form and initialize the `select` field this can not be done # in the template. form = ChangeProfileForm( feed_pagination_size=(current_user.get('feed_pagination_size') or app.config.get('FEED_ITEMS_PER_PAGE')), replies_pagination_size=(current_user.get('replies_pagination_size') or app.config.get('REPLIES_ITEMS_PER_PAGE')), alerts_pagination_size=(current_user.get('alerts_pagination_size') or app.config.get('ALERT_ITEMS_PER_PAGE')), homepage=current_user.get('homepage', ''), location=current_user.get('location', '')) if request.method == 'POST': form = ChangeProfileForm() 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 # Update the current user in the session current_user['about'] = form.about.data current_user['hide_feed_images'] = form.hide_feed_images.data current_user['feed_pagination_size'] = \ int(form.feed_pagination_size.data) current_user['replies_pagination_size'] = \ int(form.replies_pagination_size.data) current_user['alerts_pagination_size'] = \ int(form.alerts_pagination_size.data) # Sort order but be 1 or -1 due to MongoDB requirements if form.reply_sort_order.data: reply_sort_order = 1 else: reply_sort_order = -1 current_user['reply_sort_order'] = reply_sort_order current_user['homepage'] = form.homepage.data current_user['location'] = form.location.data current_user['default_permission'] = int(form.permission.data) # Update the user in the database user = update_profile_settings( current_user.get('_id'), about=form.about.data, hide_feed_images=form.hide_feed_images.data, feed_size=form.feed_pagination_size.data, replies_size=form.replies_pagination_size.data, alerts_size=form.alerts_pagination_size.data, reply_sort_order=reply_sort_order, homepage=form.homepage.data, location=form.location.data, upload=upload, permission=form.permission.data) # Reload the current_user current_user.update(user) flash('Your profile has been updated', 'success') else: flash('Oh no! There are errors in your form', 'error') return render_template('settings_profile.html', form=form)
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 following_filter(_profile): """Checks if current user is following the user piped to filter.""" if current_user: return is_following(current_user.get('_id'), _profile.get('_id')) return False
def approved_filter(_profile): """Checks if current user has approved the user piped to filter.""" return is_approved(current_user.get('_id'), _profile.get('_id'))
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 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 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)