def delete_post(post_id): """Deletes a post """ post = get_post(post_id) # In some situations a post may be in a cursor (deleting account) but have # already been deleted by this function in a previous run. if post is not None: # Delete votes and subscribers from Redis r.delete(k.POST_VOTES.format(post.get('_id'))) # Delete the post from MongoDB m.db.posts.remove({'_id': post_id}) if 'upload' in post: # If there is an upload, delete it! delete_upload(post['upload']) if 'reply_to' in post: m.db.posts.update({'_id': post['reply_to']}, {'$inc': {'comment_count': -1}}) else: # Trigger deletion all posts comments if this post isn't a reply r.delete(k.POST_SUBSCRIBERS.format(post.get('_id'))) delete_post_replies(post_id)
def test_uploads(self): """Simply tests the backend functions in `lib.uploads`. Also tests `posts.get_upload` since this is only a simple wrapper around the backend function. """ test_upload_dir = 'tests/upload_test_files/' test_upload_files = [ join(test_upload_dir, f) for f in listdir(test_upload_dir) if isfile(join(test_upload_dir, f)) ] # Create a GridFS object to test image deletion grid = gridfs.GridFS(m.db, collection='uploads') # Test each file in the upload directory for f in test_upload_files: # Don't read non image files in the directory _, ext = splitext(f) if ext not in ('.gif', '.jpg', '.jpeg', '.png'): continue image = io.BytesIO( open(f).read() ) filename, animated = process_upload(image) # Get the upload these are designed for being served directly by # Flask. This is a Flask/Werkzeug response object image = get_upload(filename) self.assertTrue(grid.exists({'filename': filename})) self.assertEqual(image.headers['Content-Type'], 'image/png') if animated: image = get_upload(animated) self.assertTrue(grid.exists({'filename': animated})) self.assertEqual(image.headers['Content-Type'], 'image/gif') # Test deletion # Ensure file is present (it will be) self.assertTrue(grid.exists({'filename': filename})) # Delete the file and ensure it is not there through GridFS delete_upload(filename) # Ensure the file has gone self.assertFalse(grid.exists({'filename': filename})) # Ensure that if we load a non-image file a None value is returned image = io.BytesIO() self.assertEqual(process_upload(image), (None, None))
def update_profile_settings(user_id, about="", hide_feed_images=False, feed_size=25, replies_size=25, alerts_size=50, reply_sort_order=-1, homepage='', location='', upload=None, permission=0): """Update all options on a users profile settings in MongoDB.""" # Ensure the homepage URL is as valid as it can be if homepage != '': homepage = fix_url(homepage) avatar = None if upload: filename = process_upload(upload, image_size=(96, 96), thumbnail=False) if filename is not None: # pragma: no cover avatar = filename update_dict = { 'about': about, 'hide_feed_images': hide_feed_images, 'feed_pagination_size': int(feed_size), 'replies_pagination_size': int(replies_size), 'alerts_pagination_size': int(alerts_size), 'reply_sort_order': reply_sort_order, 'homepage': homepage, 'location': location, 'default_permission': int(permission) } if avatar is not None: update_dict['avatar'] = avatar user = get_user(user_id) if user.get('avatar'): # Clean up any old avatars # There is no update in GridFS delete_upload(user.get('avatar')) # Update the users profile m.db.users.update({'_id': user_id}, {'$set': update_dict}) # Return the user object. We can update the current_user from this return get_user(user_id)
def update_profile_settings(user_id, about="", hide_feed_images=False, feed_size=25, replies_size=25, alerts_size=50, reply_sort_order=-1, homepage='', location='', upload=None, permission=0): """Update all options on a users profile settings in MongoDB.""" # Ensure the homepage URL is as valid as it can be if homepage != '': homepage = fix_url(homepage) avatar = None if upload: filename, _ = process_upload(upload, image_size=(96, 96), thumbnail=False) if filename is not None: # pragma: no cover avatar = filename update_dict = { 'about': about, 'hide_feed_images': hide_feed_images, 'feed_pagination_size': int(feed_size), 'replies_pagination_size': int(replies_size), 'alerts_pagination_size': int(alerts_size), 'reply_sort_order': reply_sort_order, 'homepage': homepage, 'location': location, 'default_permission': int(permission) } if avatar is not None: update_dict['avatar'] = avatar user = get_user(user_id) if user.get('avatar'): # Clean up any old avatars # There is no update in GridFS delete_upload(user.get('avatar')) # Update the users profile m.db.users.update({'_id': user_id}, {'$set': update_dict}) # Return the user object. We can update the current_user from this return get_user(user_id)
def test_uploads(self): """Simply tests the backend functions in `lib.uploads`. Also tests `posts.get_upload` since this is only a simple wrapper around the backend function. """ test_upload_dir = 'tests/upload_test_files/' test_upload_files = [ join(test_upload_dir, f) for f in listdir(test_upload_dir) if isfile(join(test_upload_dir, f)) ] # Create a GridFS object to test image deletion grid = gridfs.GridFS(m.db, collection='uploads') # Test each file in the upload directory for f in test_upload_files: image = io.BytesIO(open(f).read()) filename = process_upload(image) # Get the upload these are designed for being served directly by # Flask. This is a Flask/Werkzeug response object image = get_upload(filename) self.assertTrue(grid.exists({'filename': filename})) self.assertEqual(image.headers['Content-Type'], 'image/png') # Test deletion # Ensure file is present (it will be) self.assertTrue(grid.exists({'filename': filename})) # Delete the file and ensure it is not there through GridFS delete_upload(filename) # Ensure the file has gone self.assertFalse(grid.exists({'filename': filename})) # Ensure that if we load a non-image file a None value is returned image = io.BytesIO() self.assertIsNone(process_upload(image))
def delete_post_replies(post_id): """Delete ALL comments on post with pid. This can't be done in one single call to Mongo because we need to remove the votes from Redis! """ # Get a cursor for all the posts comments cur = m.db.posts.find({'reply_to': post_id}) # Iterate over the cursor and delete each one for reply in cur: reply_id = reply.get('_id') # Delete the comment itself from MongoDB m.db.posts.remove({'_id': reply_id}) # Remove any uploaded files if 'upload' in reply: delete_upload(reply['upload']) # Delete votes from Redis r.delete(k.POST_VOTES.format(reply_id))
def delete_account(user_id): """Will delete a users account. This **REMOVES ALL** details, posts, replies, etc. Not votes though. .. note: Ensure the user has authenticated this request. This is going to be the most *expensive* task in Pjuu, be warned. :param user_id: The `user_id` of the user to delete :type user_id: str """ # Get the user object we will need this to remove the avatar user = get_user(user_id) # Delete the user from MongoDB m.db.users.remove({'_id': user_id}) # If the user has an avatar remove it if user.get('avatar'): delete_upload(user.get('avatar')) # Remove all posts a user has ever made. This includes all votes # on the posts and all comments of the posts. # This calls the backend function from posts to do the deed posts_cursor = m.db.posts.find({'user_id': user_id}, {}) for post in posts_cursor: delete_post(post.get('_id')) # Remove all the following relationships from Redis # Delete all references to followers of the user. # This will remove the user from the other users following list # TODO Replace with ZSCAN follower_cursor = r.zrange(k.USER_FOLLOWERS.format(user_id), 0, -1) for follower_id in follower_cursor: # Clear the followers following list of the uid r.zrem(k.USER_FOLLOWING.format(follower_id), user_id) # Delete the followers list r.delete(k.USER_FOLLOWERS.format(user_id)) # Delete all references to the users the user is following # This will remove the user from the others users followers list # TODO Replace with ZSCAN followee_cursor = r.zrange(k.USER_FOLLOWING.format(user_id), 0, -1) for followee_id in followee_cursor: # Clear the followers list of people uid is following r.zrem(k.USER_FOLLOWERS.format(followee_id), user_id) # Delete the following list r.delete(k.USER_FOLLOWING.format(user_id)) # Delete the users feed, this may have been added too during this process. # Probably not but let's be on the safe side r.delete(k.USER_FEED.format(user_id)) # Delete the users alert list # DO NOT DELETE ANY ALERTS AS THESE ARE GENERIC r.delete(k.USER_ALERTS.format(user_id))