def delete(self, story_id): try: # get token from header token = self._get_token_from_header() # identify with token username = Token.identify(token) # get story by story_id story = Story.get_story(story_id) # if username is not the uploader return 403 story_uploader = story["username"] self.logger.debug("At DELETE@/stories requesting user is {} and uploader is {}".format( username, story_uploader)) if username != story_uploader: return ResponseBuilder.build_error_response("Story is not own", 403) # delete story deleted_story_obj = Story.delete_story(story_id) deleted_story_id = str(deleted_story_obj) # generate response output = {"target_story_id": deleted_story_id} # return response return ResponseBuilder.build_response(output) except (InvalidTokenException, ExpiredTokenException, StoryNotFoundException, MissingFieldException) as e: return ResponseBuilder.build_error_response(e.message, e.error_code)
def test_delete_reaction_not_found(self): with patch.object(Persistence, "unset_on_one") as mocked_delete_reaction,\ self.assertRaises(StoryReactionNotFoundException) as context: mocked_delete_reaction.side_effect = MagicMock(return_value=None) Story.delete_reaction(object_id_mock, "pedro") exc = context.exception self.assertEqual(exc.error_code, 404) self.assertEqual(exc.message, "Story reaction was not found")
def create_indexes(): Logger(__name__).debug('Creating indexes for DB') # indexes for User User._get_coll().create_index("username") # indexes for Story Story._get_coll().create_index("username") # indexes for Comments StoryComment._get_coll().create_index("story_id")
def test_get_story_not_found(self): with patch.object(Persistence, "get_one") as mocked_story_get, \ self.assertRaises(StoryNotFoundException) as context: mocked_story_get.side_effect = MagicMock(return_value=None) mocked_story_id = object_id_mock Story.get_story(mocked_story_id) exc = context.exception self.assertEqual(exc.error_code, 404)
def test_delete_story_not_found(self): with patch.object(Persistence, "delete_one") as mocked_delete_one,\ self.assertRaises(StoryNotFoundException) as context,\ patch.object(StoryComment, "delete_comments_on_story") as mocked_delete_comments: mocked_internal_story = dict(story_mock_private_with_reaction) mocked_internal_story["_id"] = object_id_mock mocked_delete_one.side_effect = MagicMock(return_value=None) mocked_delete_comments.side_effect = MagicMock() # do nothing Story.delete_story(object_id_mock) exc = context.exception self.assertEqual(exc.error_code, 404) self.assertEqual(exc.message, "Story was not found")
def post(self, story_id): try: # get token from header token = self._get_token_from_header() # identify with token username = Token.identify(token) # get data from request comment_text = self._get_comment_text_from_request() timestamp = self._get_timestamp_from_request() # sanitize data timestamp = InputSanitizer.sanitize_positive_integer(timestamp) # post reaction to story by story_id saved_comment = Story.comment_on_story(story_id, username, comment_text, timestamp) # generate response output = saved_comment # return response return ResponseBuilder.build_response(output) except (InvalidTokenException, ExpiredTokenException, InvalidFormatException, MissingFieldException, StoryNotFoundException) as e: return ResponseBuilder.build_error_response(e.message, e.error_code)
def test_get_feed_data_from_one_story_object(self): with patch.object(StoryComment, "get_comments_on_story") as mocked_get_comments: mocked_get_comments.side_effect = MagicMock(return_value=[]) aux_story = dict(story_mock_private_with_reaction) aux_story["_id"] = object_id_mock reactions = [x for x in aux_story["reactions"].values()] expected_feed_data = { "story_id": object_id_mock, "title": aux_story['title'], "description": aux_story['description'], "likes": reactions.count(STORY_REACTION_LIKE), "dislikes": reactions.count(STORY_REACTION_DISLIKE), "funnies": reactions.count(STORY_REACTION_FUNNY), "borings": reactions.count(STORY_REACTION_BORING), "number of comments": len(aux_story['comments']), "location": aux_story['location'], "timestamp": aux_story['timestamp'], "is_private": aux_story['is_private'], "uploader": aux_story["username"] } self.assertEqual(Story._get_feed_story_data(aux_story), expected_feed_data)
def get(self, story_id): try: # get token from header token = self._get_token_from_header() # identify with token username = Token.identify(token) # get story by story_id story = Story.get_story(story_id) # if <username is not the uploader> and <story is private> and ... # ... <uploader and username are not friends> return 403 is_private = story["is_private"] story_uploader = story["username"] self.logger.debug("At GET@/stories requesting user is {}, uploader is {} and story {} private".format( username, story_uploader, "is" if is_private else "is not")) if username != story_uploader and \ InputSanitizer.sanitize_boolean(is_private) and \ not Friendship.are_friends(username, story_uploader): return ResponseBuilder.build_error_response("Story is private", 403) # generate response # return response return ResponseBuilder.build_response(story) except (InvalidTokenException, MissingFieldException, ExpiredTokenException, StoryNotFoundException) as e: return ResponseBuilder.build_error_response(e.message, e.error_code)
def test_get_stories_by_username_not_empty(self): with patch.object(Persistence, "get_many") as mocked_get_many,\ patch.object(StoryComment, "get_comments_on_story") as mocked_get_comments,\ patch.object(Story, "_serialize_story") as mocked_serialize: aux_timestamp = 123123 aux_story1 = dict(story_mock_private_with_reaction) aux_story1["timestamp"] = aux_timestamp aux_story1["_id"] = object_id_mock aux_story2 = dict(aux_story1) aux_story2["timestamp"] = aux_timestamp + 1 aux_story3 = dict(aux_story1) aux_story3["timestamp"] = aux_timestamp + 2 unsorted_stories = [aux_story1, aux_story3, aux_story2] sorted_stories = [aux_story3, aux_story2, aux_story1] mocked_get_many.side_effect = MagicMock( return_value=unsorted_stories) mocked_get_comments.side_effect = MagicMock(return_value=[]) mocked_serialize.side_effect = lambda x: x self.assertEqual(Story.get_stories_by_username("pepe"), sorted_stories)
def post(self, story_id): try: # get token from header token = self._get_token_from_header() # identify with token username = Token.identify(token) # get the reaction type reaction = self._get_reaction_from_request() reaction = InputSanitizer.sanitize_story_reaction(reaction) # post reaction to story by story_id saved_reaction = Story.react_to_story(story_id, username, reaction) # generate response output = {"reacting_user_id": username, "reaction": saved_reaction} # return response return ResponseBuilder.build_response(output) except (InvalidTokenException, ExpiredTokenException, InvalidFormatException, MissingFieldException, StoryNotFoundException) as e: return ResponseBuilder.build_error_response( e.message, e.error_code)
def _build_profile_from_user(user_data, caller_username): # retrieve all stories uploaded by username friend_ids = [ friend_id for friend_id, friendship_state in user_data["friends"].items() if friendship_state == "friends" ] # include privates only if caller username is a friend of target user or him/herself target_ids = friend_ids + [user_data["username"]] stories = Story.get_stories_by_username(user_data["username"], caller_username in target_ids) # return the profile return { # general data 'username': user_data['username'], 'profile_pic': user_data['profile_pic'], 'name': user_data['name'], # stories uploaded 'stories': stories, # interesting numbers 'number of friends': len(friend_ids), 'number of stories': len(stories) }
def _format_feed_story(story_id): serialized_story = Story.get_story(story_id) uploader = serialized_story['username'] profile_preview = User.get_profile_preview(uploader) serialized_story['name'] = profile_preview['name'] serialized_story['profile_pic'] = profile_preview['profile_pic'] return serialized_story
def test_successful_save_new(self): with patch.object(Persistence, "insert_one") as mocked_story_insert: mocked_story_insert.side_effect = self.mocked_story_insert_one story_data = dict(story_data_mock_with_title_and_description) story_data['username'] = "******" self.assertEqual(Story.save_new(story_data), object_id_mock)
def save_new_story(story_data): """Facade for Story.save_new, also checks that user indeed exists""" username = story_data['username'] Logger(__name__).info( 'Trying to save new story for user {}.'.format(username)) # check user exists user = User._get_one({'username': username}) if user is None: raise UserNotFoundException return Story.save_new(story_data)
def _safe_delete_user(user): # delete from every friend username = user['username'] for friend_name in user['friends']: friend_user = User._get_one({'username': friend_name}) # if for any reason user didn't exist anymore, continue silently if friend_user is None: continue # friend_user['friends'].pop(username) entry = 'friends.' + username User._delete_field_by_username(friend_user['username'], {entry: ""}) # delete every owned Story and (related Reactions and Comments? should they be deleted?) Story.delete_stories_from_user(username) Flash.delete_flashes_from_user(username) # now that the user is isolated, delete it User._delete_one(username) return username
def test_successful_delete_reaction(self): with patch.object(Persistence, "unset_on_one") as mocked_delete_reaction: mocked_delete_reaction.side_effect = MagicMock( return_value=story_mock_private_with_reaction) mocked_username, mocked_reaction = first_item_of_dict( story_mock_private_with_reaction["reactions"]) self.assertEqual( Story.delete_reaction(object_id_mock, mocked_username), mocked_reaction)
def test_successful_delete_story(self): with patch.object(Persistence, "delete_one") as mocked_delete_one,\ patch.object(StoryComment, "delete_comments_on_story") as mocked_delete_comments: mocked_internal_story = dict(story_mock_private_with_reaction) mocked_internal_story["_id"] = object_id_mock mocked_delete_one.side_effect = MagicMock( return_value=mocked_internal_story) mocked_delete_comments.side_effect = MagicMock() # do nothing self.assertEqual(Story.delete_story(object_id_mock), object_id_mock)
def test_successful_get_story_private(self): with patch.object(Persistence, "get_one") as mocked_story_get,\ patch.object(StoryComment, "get_comments_on_story") as mocked_get_comments: # prepare special mock aux = story_mock_private_without_comments_or_reactions internal_story_mock = dict(aux) internal_story_mock["is_private"] = True internal_story_mock["timestamp"] = 1615456 internal_story_mock["_id"] = aux['story_id'] mocked_story_get.side_effect = MagicMock( return_value=internal_story_mock) mocked_story_id = aux['story_id'] mocked_get_comments.side_effect = MagicMock(return_value=[]) self.assertEqual(Story.get_story(mocked_story_id), aux)
def _get_stories_feed_data(username, include_privates=False): """Formats stories uploaded by this user for easier use of the Feed Builder.""" # get all stories feed data from username story_feed_blocks = Story.get_stories_feed_data_by_username( username, include_privates) # get user specific feed data user_feed_data = User._get_user_feed_data(username, len(story_feed_blocks)) # add them to story feed blocks [ story_feed_block.update(user_feed_data) for story_feed_block in story_feed_blocks ] return story_feed_blocks
def test_successful_post_reaction(self): with patch.object(Persistence, "update_one") as mocked_story_update,\ patch.object(Persistence, "get_one") as mocked_get_one: aux = story_mock_private_with_reaction.copy() mocked_story_update.side_effect = MagicMock( return_value=story_mock_private_with_reaction) mocked_get_one.side_effect = MagicMock( return_value=object_id_mock ) # just a placeholder, not what it's actually expected mocked_story_id = object_id_mock mocked_username, mocked_reaction = first_item_of_dict( aux["reactions"]) self.assertEqual( Story.react_to_story(mocked_story_id, mocked_username, mocked_reaction), mocked_reaction)
def test_get_stories_by_username_empty(self): with patch.object(Persistence, "get_many") as mocked_get_many: mocked_get_many.side_effect = MagicMock(return_value=[]) self.assertEqual(Story.get_stories_by_username("pepe"), [])