def test_build_folder_metadata(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response( root_provider_fixtures['folder_metadata'], 'root') metadata = OneDriveFolderMetadata( root_provider_fixtures['folder_metadata'], od_path) assert metadata.provider == 'onedrive' assert metadata.name == 'teeth' assert metadata.path == '/F4D50E400DFE7D4E!290/' assert metadata.etag == 'aRjRENTBFNDAwREZFN0Q0RSEyOTAuMA' assert metadata.materialized_path == '/teeth/' assert metadata.extra == { 'id': 'F4D50E400DFE7D4E!290', 'etag': 'aRjRENTBFNDAwREZFN0Q0RSEyOTAuMA', 'webView': 'https://1drv.ms/f/s!AE59_g1ADtX0giI', 'modified_utc': '2017-08-17T17:53:21+00:00', 'created_utc': '2017-08-17T17:49:26+00:00', } assert metadata._json_api_links('mst3k') == { 'delete': None, 'upload': None, 'move': ('http://localhost:7777/v1/resources/mst3k/providers' '/onedrive/{}/'.format(root_provider_fixtures['folder_id'])), 'new_folder': None, }
def test_build_file_metadata(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response(root_provider_fixtures['file_metadata'], 'root') metadata = OneDriveFileMetadata(root_provider_fixtures['file_metadata'], od_path) assert metadata.provider == 'onedrive' assert metadata.created_utc == '2017-08-17T17:49:39+00:00' assert metadata.materialized_path == '/toes.txt' assert metadata.extra == { 'id': root_provider_fixtures['file_id'], 'etag': 'aRjRENTBFNDAwREZFN0Q0RSEyOTEuMg', 'webView': 'https://1drv.ms/t/s!AE59_g1ADtX0giM', } assert metadata.name == 'toes.txt' assert metadata.path == '/{}'.format(root_provider_fixtures['file_id']) assert metadata.size == 11 assert metadata.size_as_int == 11 assert metadata.modified == '2017-08-17T17:49:50.38Z' assert metadata.modified_utc == '2017-08-17T17:49:50+00:00' assert metadata.content_type == 'text/plain' assert metadata.etag == 'aRjRENTBFNDAwREZFN0Q0RSEyOTEuMg' action_url = ('http://localhost:7777/v1/resources/mst3k/providers' '/onedrive/{}'.format(root_provider_fixtures['file_id'])) assert metadata._json_api_links('mst3k') == { 'delete': None, 'upload': None, 'move': action_url, 'download': action_url, }
def test_build_file_metadata(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response( root_provider_fixtures['file_metadata'], 'root') metadata = OneDriveFileMetadata( root_provider_fixtures['file_metadata'], od_path) assert metadata.provider == 'onedrive' assert metadata.created_utc == '2017-08-17T17:49:39+00:00' assert metadata.materialized_path == '/toes.txt' assert metadata.extra == { 'id': root_provider_fixtures['file_id'], 'etag': 'aRjRENTBFNDAwREZFN0Q0RSEyOTEuMg', 'webView': 'https://1drv.ms/t/s!AE59_g1ADtX0giM', } assert metadata.name == 'toes.txt' assert metadata.path == '/{}'.format(root_provider_fixtures['file_id']) assert metadata.size == 11 assert metadata.size_as_int == 11 assert metadata.modified == '2017-08-17T17:49:50.38Z' assert metadata.modified_utc == '2017-08-17T17:49:50+00:00' assert metadata.content_type == 'text/plain' assert metadata.etag == 'aRjRENTBFNDAwREZFN0Q0RSEyOTEuMg' action_url = ('http://localhost:7777/v1/resources/mst3k/providers' '/onedrive/{}'.format(root_provider_fixtures['file_id'])) assert metadata._json_api_links('mst3k') == { 'delete': None, 'upload': None, 'move': action_url, 'download': action_url, }
async def validate_path(self, path: str, **kwargs) -> OneDrivePath: logger.debug('validate_path self::{} path::{} kwargs::{}'.format( repr(self), path, kwargs)) if path == '/': return OneDrivePath(path, _ids=[self.folder]) resp = await self.make_request('GET', self._build_item_url(path), expects=(200, ), throws=exceptions.MetadataError) logger.debug('validate_path resp::{}'.format(repr(resp))) data = await resp.json() logger.debug('validate_path data::{}'.format(json.dumps(data))) # If base folder isn't root or the immediate parent of the requested path, then we need # to verify that it actually is an ancestor of path. Otherwise, a malicious user could # try to get access to a file outside of the configured root. base_folder = None if self.folder != 'root' and self.folder != data['parentReference'][ 'id']: base_folder_resp = await self.make_request( 'GET', self._build_item_url(self.folder), expects=(200, ), throws=exceptions.MetadataError) logger.debug('validate_path base_folder_resp::{}'.format( repr(base_folder_resp))) base_folder = await base_folder_resp.json() logger.debug('validate_path base_folder::{}'.format( json.dumps(base_folder))) base_full_path = urlparse.quote( '{}/{}/'.format( urlparse.unquote(base_folder['parentReference']['path']), base_folder['name']), self.dont_escape_these) if not data['parentReference']['path'].startswith(base_full_path): # the requested file is NOT a child of self.folder raise exceptions.NotFoundError(path) # TESTME od_path = OneDrivePath.new_from_response( data, self.folder, base_folder_metadata=base_folder) logger.debug('validate_path od_path.parts::{}'.format( repr(od_path._parts))) return od_path
def test_folder_in_root(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response(root_provider_fixtures['folder_metadata'], 'root') assert od_path.identifier == root_provider_fixtures['folder_id'] assert str(od_path) == '/teeth/' assert len(od_path.parts) == 2 ids = [x.identifier for x in od_path.parts] assert ids == ['root', root_provider_fixtures['folder_id']]
def test_folder_in_root(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response( root_provider_fixtures['folder_metadata'], 'root') assert od_path.identifier == root_provider_fixtures['folder_id'] assert str(od_path) == '/teeth/' assert len(od_path.parts) == 2 ids = [x.identifier for x in od_path.parts] assert ids == ['root', root_provider_fixtures['folder_id']]
def test_api_identifier_file_id(self): path = OneDrivePath('/foo', _ids=( '123456', '7891011', )) assert path.api_identifier == ( 'items', '7891011', )
def test_subfolder_base_is_folder(self, subfolder_provider_fixtures): od_path = OneDrivePath.new_from_response(subfolder_provider_fixtures['folder_metadata'], subfolder_provider_fixtures['root_id']) assert od_path.identifier == subfolder_provider_fixtures['folder_id'] assert str(od_path) == '/crushers/' assert len(od_path.parts) == 2 ids = [x.identifier for x in od_path.parts] assert ids == [subfolder_provider_fixtures['root_id'], subfolder_provider_fixtures['folder_id']]
def test_file_in_root(self, subfolder_provider_fixtures): od_path = OneDrivePath.new_from_response(subfolder_provider_fixtures['file_metadata'], subfolder_provider_fixtures['root_id']) assert od_path.identifier == subfolder_provider_fixtures['file_id'] assert str(od_path) == '/bicuspid.txt' assert len(od_path.parts) == 2 ids = [x.identifier for x in od_path.parts] assert ids == [subfolder_provider_fixtures['root_id'], subfolder_provider_fixtures['file_id']]
def test_insert_zero_ids(self, path_fixtures): file_metadata = path_fixtures['deeply_nested_file_metadata'] od_path = OneDrivePath.new_from_response(file_metadata, 'root') file_id = path_fixtures['deeply_nested_file_id'] assert od_path.identifier == file_id assert str(od_path) == '/deep/deeper/deepest/positively abyssyal/the kraken.txt' assert len(od_path.parts) == 6 ids = [x.identifier for x in od_path.parts] assert ids == ['root', None, None, None, 'F4D50E400DFE7D4E!298', file_id]
def test_file_in_subdir(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response(root_provider_fixtures['subfile_metadata'], 'root') assert od_path.identifier == root_provider_fixtures['subfile_id'] assert str(od_path) == '/teeth/bicuspid.txt' assert len(od_path.parts) == 3 ids = [x.identifier for x in od_path.parts] assert ids == ['root', root_provider_fixtures['folder_id'], root_provider_fixtures['subfile_id']]
def test_file_in_subdir(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response( root_provider_fixtures['subfile_metadata'], 'root') assert od_path.identifier == root_provider_fixtures['subfile_id'] assert str(od_path) == '/teeth/bicuspid.txt' assert len(od_path.parts) == 3 ids = [x.identifier for x in od_path.parts] assert ids == [ 'root', root_provider_fixtures['folder_id'], root_provider_fixtures['subfile_id'] ]
def test_file_in_subdir(self, subfolder_provider_fixtures): od_path = OneDrivePath.new_from_response(subfolder_provider_fixtures['subfile_metadata'], subfolder_provider_fixtures['root_id'], base_folder_metadata=subfolder_provider_fixtures['root_metadata']) assert od_path.identifier == subfolder_provider_fixtures['subfile_id'] assert str(od_path) == '/crushers/molars.txt' assert len(od_path.parts) == 3 ids = [x.identifier for x in od_path.parts] assert ids == [subfolder_provider_fixtures['root_id'], subfolder_provider_fixtures['folder_id'], subfolder_provider_fixtures['subfile_id']]
def test_subfolder_base_is_folder(self, subfolder_provider_fixtures): od_path = OneDrivePath.new_from_response( subfolder_provider_fixtures['folder_metadata'], subfolder_provider_fixtures['root_id']) assert od_path.identifier == subfolder_provider_fixtures['folder_id'] assert str(od_path) == '/crushers/' assert len(od_path.parts) == 2 ids = [x.identifier for x in od_path.parts] assert ids == [ subfolder_provider_fixtures['root_id'], subfolder_provider_fixtures['folder_id'] ]
def test_file_in_root(self, subfolder_provider_fixtures): od_path = OneDrivePath.new_from_response( subfolder_provider_fixtures['file_metadata'], subfolder_provider_fixtures['root_id']) assert od_path.identifier == subfolder_provider_fixtures['file_id'] assert str(od_path) == '/bicuspid.txt' assert len(od_path.parts) == 2 ids = [x.identifier for x in od_path.parts] assert ids == [ subfolder_provider_fixtures['root_id'], subfolder_provider_fixtures['file_id'] ]
def test_insert_zero_ids(self, path_fixtures): file_metadata = path_fixtures['deeply_nested_file_metadata'] od_path = OneDrivePath.new_from_response(file_metadata, 'root') file_id = path_fixtures['deeply_nested_file_id'] assert od_path.identifier == file_id assert str( od_path ) == '/deep/deeper/deepest/positively abyssyal/the kraken.txt' assert len(od_path.parts) == 6 ids = [x.identifier for x in od_path.parts] assert ids == [ 'root', None, None, None, 'F4D50E400DFE7D4E!298', file_id ]
def test_file_in_subdir(self, subfolder_provider_fixtures): od_path = OneDrivePath.new_from_response( subfolder_provider_fixtures['subfile_metadata'], subfolder_provider_fixtures['root_id'], base_folder_metadata=subfolder_provider_fixtures['root_metadata']) assert od_path.identifier == subfolder_provider_fixtures['subfile_id'] assert str(od_path) == '/crushers/molars.txt' assert len(od_path.parts) == 3 ids = [x.identifier for x in od_path.parts] assert ids == [ subfolder_provider_fixtures['root_id'], subfolder_provider_fixtures['folder_id'], subfolder_provider_fixtures['subfile_id'] ]
async def validate_path(self, path: str, **kwargs) -> OneDrivePath: logger.debug('validate_path self::{} path::{} kwargs::{}'.format(repr(self), path, kwargs)) if path == '/': return OneDrivePath(path, _ids=[self.folder]) resp = await self.make_request( 'GET', self._build_item_url(path), expects=(200, ), throws=exceptions.MetadataError ) logger.debug('validate_path resp::{}'.format(repr(resp))) data = await resp.json() logger.debug('validate_path data::{}'.format(json.dumps(data))) # If base folder isn't root or the immediate parent of the requested path, then we need # to verify that it actually is an ancestor of path. Otherwise, a malicious user could # try to get access to a file outside of the configured root. base_folder = None if self.folder != 'root' and self.folder != data['parentReference']['id']: base_folder_resp = await self.make_request( 'GET', self._build_item_url(self.folder), expects=(200, ), throws=exceptions.MetadataError ) logger.debug('validate_path base_folder_resp::{}'.format(repr(base_folder_resp))) base_folder = await base_folder_resp.json() logger.debug('validate_path base_folder::{}'.format(json.dumps(base_folder))) base_full_path = urlparse.quote( '{}/{}/'.format( urlparse.unquote(base_folder['parentReference']['path']), base_folder['name'] ), self.dont_escape_these ) if not data['parentReference']['path'].startswith(base_full_path): # the requested file is NOT a child of self.folder raise exceptions.NotFoundError(path) # TESTME od_path = OneDrivePath.new_from_response(data, self.folder, base_folder_metadata=base_folder) logger.debug('validate_path od_path.parts::{}'.format(repr(od_path._parts))) return od_path
async def revalidate_path( self, # type: ignore base: OneDrivePath, path: str, folder: bool = None) -> OneDrivePath: """Take a string file/folder name ``path`` and return a OneDrivePath object representing this file under ``base``. Since the OneDrive provider is currently readonly, the only place that calls this is `core.provider._file_folder_op`. The base object passed there will always have an identifier. Once write support is added to this provider, that will no longer be the case. This probably isn't necessary for RO, and could probably be replaced by `path_from_metadata`. """ logger.debug( 'revalidate_path base::{} path::{} base.id::{} folder::{}'.format( base, path, base.identifier, folder)) base_url = self._build_drive_url(*base.api_identifier, expand='children') base_resp = await self.make_request('GET', base_url, expects=(200, ), throws=exceptions.MetadataError) logger.debug('revalidate_path base_resp::{}'.format(repr(base_resp))) base_data = await base_resp.json() logger.debug('revalidate_path base_data::{}'.format( json.dumps(base_data))) child_id = None for child in base_data['children']: if child['name'] == path and (child.get('folder', None) is not None) == folder: child_id = child['id'] break if child_id is None: raise exceptions.NotFoundError(path) return base.child(path, _id=child_id, folder=folder)
async def revalidate_path(self, # type: ignore base: OneDrivePath, path: str, folder: bool=None) -> OneDrivePath: """Take a string file/folder name ``path`` and return a OneDrivePath object representing this file under ``base``. Since the OneDrive provider is currently readonly, the only place that calls this is `core.provider._file_folder_op`. The base object passed there will always have an identifier. Once write support is added to this provider, that will no longer be the case. This probably isn't necessary for RO, and could probably be replaced by `path_from_metadata`. """ logger.debug('revalidate_path base::{} path::{} base.id::{} folder::{}'.format( base, path, base.identifier, folder)) base_url = self._build_drive_url(*base.api_identifier, expand='children') base_resp = await self.make_request( 'GET', base_url, expects=(200, ), throws=exceptions.MetadataError ) logger.debug('revalidate_path base_resp::{}'.format(repr(base_resp))) base_data = await base_resp.json() logger.debug('revalidate_path base_data::{}'.format(json.dumps(base_data))) child_id = None for child in base_data['children']: if child['name'] == path and (child.get('folder', None) is not None) == folder: child_id = child['id'] break if child_id is None: raise exceptions.NotFoundError(path) return base.child(path, _id=child_id, folder=folder)
def test_build_folder_metadata(self, root_provider_fixtures): od_path = OneDrivePath.new_from_response(root_provider_fixtures['folder_metadata'], 'root') metadata = OneDriveFolderMetadata(root_provider_fixtures['folder_metadata'], od_path) assert metadata.provider == 'onedrive' assert metadata.name == 'teeth' assert metadata.path == '/F4D50E400DFE7D4E!290/' assert metadata.etag == 'aRjRENTBFNDAwREZFN0Q0RSEyOTAuMA' assert metadata.materialized_path == '/teeth/' assert metadata.extra == { 'id': 'F4D50E400DFE7D4E!290', 'etag': 'aRjRENTBFNDAwREZFN0Q0RSEyOTAuMA', 'webView': 'https://1drv.ms/f/s!AE59_g1ADtX0giI', 'modified_utc': '2017-08-17T17:53:21+00:00', 'created_utc': '2017-08-17T17:49:26+00:00', } assert metadata._json_api_links('mst3k') == { 'delete': None, 'upload': None, 'move': ('http://localhost:7777/v1/resources/mst3k/providers' '/onedrive/{}/'.format(root_provider_fixtures['folder_id'])), 'new_folder': None, }
async def validate_v1_path(self, path: str, **kwargs) -> OneDrivePath: r"""validate that ``path`` exists and matches the implicit semantics. See `provider.BaseProvider.validate_v1_path` for more. :param str path: A string representing the requested path. This will be everthing after the provider name in the url. :param dict \*\*kwargs: Query parameters and other parameters splatted into the call. :raises: NotFoundError :rtype: OneDrivePath :return: a OneDrivePath object representing the new path. """ logger.debug('validate_v1_path self::{} path::{} kwargs::{}'.format( repr(self), path, kwargs)) if path == '/': return OneDrivePath(path, _ids=[self.folder]) resp = await self.make_request('GET', self._build_item_url(path), expects=(200, ), throws=exceptions.MetadataError) logger.debug('validate_v1_path resp::{}'.format(repr(resp))) data = await resp.json() logger.debug('validate_v1_path data::{}'.format(json.dumps(data))) implicit_folder = path.endswith('/') explicit_folder = data.get('folder', None) is not None if implicit_folder != explicit_folder: raise exceptions.NotFoundError(path) # If base folder isn't root or the immediate parent of the requested path, then we need # to verify that it actually is an ancestor of path. Otherwise, a malicious user could # try to get access to a file outside of the configured root. base_folder = None if self.folder != 'root' and self.folder != data['parentReference'][ 'id']: base_folder_resp = await self.make_request( 'GET', self._build_item_url(self.folder), expects=(200, ), throws=exceptions.MetadataError) logger.debug('validate_v1_path base_folder_resp::{}'.format( repr(base_folder_resp))) base_folder = await base_folder_resp.json() logger.debug('validate_v1_path base_folder::{}'.format( json.dumps(base_folder))) base_full_path = urlparse.quote( '{}/{}/'.format( urlparse.unquote(base_folder['parentReference']['path']), base_folder['name']), self.dont_escape_these) if not data['parentReference']['path'].startswith(base_full_path): # the requested file is NOT a child of self.folder raise exceptions.NotFoundError(path) od_path = OneDrivePath.new_from_response( data, self.folder, base_folder_metadata=base_folder) logger.debug('validate_v1_path od_path.parts::{}'.format( repr(od_path._parts))) return od_path
async def validate_v1_path(self, path: str, **kwargs) -> OneDrivePath: """validate that ``path`` exists and matches the implicit semantics. See `provider.BaseProvider.validate_v1_path` for more. :param str path: A string representing the requested path. This will be everthing after the provider name in the url. :param dict \*\*kwargs: Query parameters and other parameters splatted into the call. :raises: NotFoundError :rtype: OneDrivePath :return: a OneDrivePath object representing the new path. """ logger.debug('validate_v1_path self::{} path::{} kwargs::{}'.format(repr(self), path, kwargs)) if path == '/': return OneDrivePath(path, _ids=[self.folder]) resp = await self.make_request( 'GET', self._build_item_url(path), expects=(200, ), throws=exceptions.MetadataError ) logger.debug('validate_v1_path resp::{}'.format(repr(resp))) data = await resp.json() logger.debug('validate_v1_path data::{}'.format(json.dumps(data))) implicit_folder = path.endswith('/') explicit_folder = data.get('folder', None) is not None if implicit_folder != explicit_folder: raise exceptions.NotFoundError(path) # If base folder isn't root or the immediate parent of the requested path, then we need # to verify that it actually is an ancestor of path. Otherwise, a malicious user could # try to get access to a file outside of the configured root. base_folder = None if self.folder != 'root' and self.folder != data['parentReference']['id']: base_folder_resp = await self.make_request( 'GET', self._build_item_url(self.folder), expects=(200, ), throws=exceptions.MetadataError ) logger.debug('validate_v1_path base_folder_resp::{}'.format(repr(base_folder_resp))) base_folder = await base_folder_resp.json() logger.debug('validate_v1_path base_folder::{}'.format(json.dumps(base_folder))) base_full_path = urlparse.quote( '{}/{}/'.format( urlparse.unquote(base_folder['parentReference']['path']), base_folder['name'] ), self.dont_escape_these ) if not data['parentReference']['path'].startswith(base_full_path): # the requested file is NOT a child of self.folder raise exceptions.NotFoundError(path) od_path = OneDrivePath.new_from_response(data, self.folder, base_folder_metadata=base_folder) logger.debug('validate_v1_path od_path.parts::{}'.format(repr(od_path._parts))) return od_path
def test_fails_without_base_folder(self, root_provider_fixtures): with pytest.raises(Exception): od_path = OneDrivePath.new_from_response(root_provider_fixtures['file_metadata'])
def test_api_identifier_none(self): path = OneDrivePath('/foo', _ids=( 'root', None, )) assert path.api_identifier is None
def test_fails_without_base_folder(self, root_provider_fixtures): with pytest.raises(Exception): od_path = OneDrivePath.new_from_response( root_provider_fixtures['file_metadata'])
def test_api_identifier_root(self): path = OneDrivePath('/', _ids=('root', )) assert path.api_identifier == ('root', )
def test_api_identifier_folder_id(self): path = OneDrivePath('/', _ids=('123456', )) assert path.api_identifier == ( 'items', '123456', )