def test_file_descriptors_after_sharing_with_old_team( mock_get_download_url, mock_remove_file, shared_file_upload_fixture, mock_block ): # Include a deleted file entry, and later assert that we have empty file descriptors # returned by ``file_descriptors()`` block = mock_block( descriptions=['The first file', 'The deleted file', 'The second file'], names=['File A', 'File that is deleted', 'File B'], sizes=[22, 666, 44], ) block.team.team_id = DEFAULT_TEAM_ID block.is_team_assignment.return_value = True student_item_dict = { 'student_id': DEFAULT_OWNER_ID, 'course_id': DEFAULT_COURSE_ID, 'item_id': DEFAULT_ITEM_ID, } key_a = api.get_student_file_key(student_item_dict, index=0) key_deleted = api.get_student_file_key(student_item_dict, index=1) key_b = api.get_student_file_key(student_item_dict, index=2) # create a shared upload that was shared with an old team _ = shared_file_upload_fixture(team_id='an-old-team', file_key=key_a) # create one for the file we're going to delete _ = shared_file_upload_fixture(team_id=block.team.team_id, file_key=key_deleted) # create a shared upload that's shared with the learner's current team _ = shared_file_upload_fixture(team_id=block.team.team_id, file_key=key_b) file_manager = api.FileUploadManager(block) # go and delete the file we want to delete file_manager.delete_upload(1) # file_descriptors() should only give back a record for the upload shared with the current team actual_descriptors = file_manager.file_descriptors(team_id=block.team.team_id, include_deleted=True) expected_descriptors = [ { 'download_url': None, 'name': None, 'description': None, 'size': 0, 'show_delete_button': False, }, { 'download_url': mock_get_download_url.return_value, 'name': 'File B', 'description': 'The second file', 'size': 44, 'show_delete_button': True, } ] assert expected_descriptors == actual_descriptors mock_get_download_url.assert_called_once_with(key_b) mock_remove_file.assert_called_once_with(key_deleted)
def get_files_info_from_user_state(self, username): """ Returns the files information from the user state for a given username. If the files information is present in the user state, return a list of following tuple: (file_download_url, file_description, file_name) Arguments: username(str): user's name whose state is being check for files information. Returns: List of files information tuple, if present, else empty list. """ files_info = [] user_state = self.get_user_state(username) item_dict = self.get_student_item_dict_from_username(username) if u'saved_files_descriptions' in user_state: # pylint: disable=protected-access files_descriptions = file_upload_api._safe_load_json_list( user_state.get('saved_files_descriptions')) files_names = file_upload_api._safe_load_json_list( user_state.get('saved_files_names', '[]')) for index, description in enumerate(files_descriptions): file_key = file_upload_api.get_student_file_key( item_dict, index) download_url = self._get_url_by_file_key(file_key) if download_url: file_name = files_names[index] if index < len( files_names) else '' files_info.append((download_url, description, file_name)) else: # If file has been removed, the URL doesn't exist continue return files_info
def _get_student_item_key(self, num=0): """ Simple utility method to generate a common file upload key based on the student item. Returns: A string representation of the key. """ return file_upload_api.get_student_file_key(self.get_student_item_dict(), index=num)
def test_descriptionless_files(self, xblock): """ Tests the old corner-case of a user being able to save files without descriptions. """ with patch('openassessment.fileupload.api.get_download_url') as mock_download_url: # Pretend there are two uploaded files for this XBlock. mock_download_url.side_effect = [ Mock(), Mock(), None, ] student_item_dict = xblock.get_student_item_dict() key_1 = api.get_student_file_key(student_item_dict, index=0) key_2 = api.get_student_file_key(student_item_dict, index=1) actual_keys = [upload.key for upload in xblock.file_manager.get_uploads()] self.assertEqual([key_1, key_2], actual_keys)
def get_files_info_from_user_state(self, username): """ Returns the files information from the user state for a given username. If the files information is present in the user state, return a list of following tuple: (file_download_url, file_description, file_name) Arguments: username(str): user's name whose state is being check for files information. Returns: List of files information tuple, if present, else empty list. """ files_info = [] user_state = self.get_user_state(username) item_dict = self.get_student_item_dict_from_username_or_email(username) if 'saved_files_descriptions' in user_state: # pylint: disable=protected-access files_descriptions = file_upload_api._safe_load_json_list( user_state.get('saved_files_descriptions'), log_error=True ) files_names = file_upload_api._safe_load_json_list( user_state.get('saved_files_names', '[]'), log_error=True ) for index, description in enumerate(files_descriptions): file_key = file_upload_api.get_student_file_key(item_dict, index) download_url = self._get_url_by_file_key(file_key) if download_url: file_name = files_names[index] if index < len(files_names) else '' files_info.append( file_upload_api.FileDescriptor( download_url=download_url, description=description, name=file_name, show_delete_button=False )._asdict() ) else: # If file has been removed, the URL doesn't exist logger.info( "URLWorkaround: no URL for description %s & key %s for user:%s", description, username, file_key ) continue return files_info
def get_all_upload_urls_for_user(self, username_or_email): """ For a particular ORA block, get the download URLs for all the files uploaded and still present. Used for an extreme edge case, where the stored files indices are out of sync with the uploaded files, this is a last resort to get the download URLs of all the files that have been uploaded by a learner in an ORA block(and haven't been deleted from the storage). Starting from 0 index to maximum file upload count possible, this checks if a file exists against every index. If present, add the info, else repeat it for the next indices. Arguments: username_or_email(str): username or email of the learner whose files' information is to be obtained. Returns: List of 3-valued tuples, with first value being file URL and other two values as empty string. The other 2 values have to be appended to work properly in the template. """ file_uploads = [] student_item_dict = self.get_student_item_dict_from_username_or_email(username_or_email) for index in range(self.MAX_FILES_COUNT): file_key = file_upload_api.get_student_file_key(student_item_dict, index) download_url = '' try: download_url = file_upload_api.get_download_url(file_key) except FileUploadError: pass if download_url: logger.info( "Download URL exists for key %s in block %s for user %s", file_key, username_or_email, str(self.location) ) file_uploads.append( file_upload_api.FileDescriptor( download_url=download_url, description='', name='', show_delete_button=False )._asdict() ) else: continue return file_uploads
def test_team_files_metadata(mock_get_download_url, shared_file_upload_fixture, mock_block): mock_get_download_url.return_value = "some-download-url" block = mock_block( descriptions=['The first file'], names=['File A'], sizes=[22], ) block.team.team_id = DEFAULT_TEAM_ID block.is_team_assignment.return_value = True student_item_dict = { 'student_id': DEFAULT_OWNER_ID, 'course_id': DEFAULT_COURSE_ID, 'item_id': DEFAULT_ITEM_ID, } key_a = api.get_student_file_key(student_item_dict, index=0) # create a shared upload that's shared with the learner's current team _ = shared_file_upload_fixture(team_id=block.team.team_id, file_key=key_a) # create a couple of files uploaded by teammates key_beta = api.get_student_file_key( {'student_id': 'another-student', 'course_id': DEFAULT_COURSE_ID, 'item_id': DEFAULT_ITEM_ID} ) _ = shared_file_upload_fixture( description='Another file', name='File Beta', team_id=block.team.team_id, owner_id='another-student', file_key=key_beta, ) key_delta = api.get_student_file_key( {'student_id': 'yet-another-student', 'course_id': DEFAULT_COURSE_ID, 'item_id': DEFAULT_ITEM_ID} ) _ = shared_file_upload_fixture( description='Yet another file', name='File Delta', team_id=block.team.team_id, owner_id='yet-another-student', file_key=key_delta, ) file_manager = api.FileUploadManager(block) # team_file_descriptors() should only give back records for files owned by teammates actual_descriptors = file_manager.team_file_descriptors(team_id=block.team.team_id) expected_descriptors = [ { 'download_url': mock_get_download_url.return_value, 'name': 'File Beta', 'description': 'Another file', 'size': 0, 'uploaded_by': 'some_username', }, { 'download_url': mock_get_download_url.return_value, 'name': 'File Delta', 'description': 'Yet another file', 'size': 0, 'uploaded_by': 'some_username', } ] assert expected_descriptors == actual_descriptors mock_get_download_url.assert_has_calls([ mock.call(key_beta), mock.call(key_delta), ])