def setHomeFolderMapping(event: events.Event): user = event.info homeDirsRoot = Setting().get(PluginSettings.HOME_DIRS_ROOT) homeFolder = Folder().createFolder( user, "Home", parentType="user", public=False, creator=user ) Folder().setUserAccess(homeFolder, user, AccessType.ADMIN, save=False) absDir = "%s/%s" % (homeDirsRoot, HomePathMapper().davToPhysical("/" + user["login"])) absDir = pathlib.Path(absDir) absDir.mkdir(parents=True, exist_ok=True) homeFolder.update({"fsPath": absDir.as_posix(), "isMapping": True}) # We don't want to trigger events here, amirite? Folder().save(homeFolder, validate=True, triggerEvents=False)
def _createSubdir(self, rootDir: Path, rootFolder: dict, name: str, user=None) -> dict: """Create both Girder folder and corresponding directory. The name is stored in the Girder folder, whereas the name of the directory is taken from the folder ID. This is a deliberate step to discourage renaming of directories directly on disk, which would mess up the mapping between Girder folders and directories """ folder = Folder().createFolder(rootFolder, name, creator=user) dirname = str(folder['_id']) dir = rootDir / dirname dir.mkdir(parents=True) folder.update({'fsPath': dir.absolute().as_posix(), 'isMapping': True}) folder = Folder().save(folder, validate=False, triggerEvents=False) # update the time Folder().updateFolder(rootFolder) return folder
class FileOperationsTestCase(base.TestCase): def setUp(self): super(FileOperationsTestCase, self).setUp() users = ( { "email": "*****@*****.**", "login": "******", "firstName": "Jane", "lastName": "Austin", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Sally", "lastName": "User", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Joel", "lastName": "CanTDoMuch", "password": "******", }, ) self.users = {user["login"]: User().createUser(**user) for user in users} self.public_root = tempfile.mkdtemp() self.shared_root = tempfile.mkdtemp() self.private_root = tempfile.mkdtemp() self.base_collection = Collection().createCollection( random_string(), creator=self.users["admin"], public=True, reuseExisting=True, ) self.public_folder = Folder().createFolder( self.base_collection, "public", creator=self.users["sally"], parentType="collection", public=True, reuseExisting=True, ) self.public_folder.update(dict(fsPath=self.public_root, isMapping=True)) self.public_folder = Folder().save(self.public_folder) self.private_folder = Folder().createFolder( self.base_collection, "private", creator=self.users["sally"], parentType="collection", public=False, reuseExisting=True, ) self.private_folder.update(dict(fsPath=self.private_root, isMapping=True)) self.private_folder = Folder().save(self.private_folder) def test_basic_file_ops(self): from girder.plugins.virtual_resources.rest import VirtualObject as vo root_path = pathlib.Path(self.public_folder["fsPath"]) dir1 = root_path / "some_dir" dir1.mkdir() file1 = dir1 / "some_file" file_contents = b"hello world\n" with file1.open(mode="wb") as fp: fp.write(file_contents) resp = self.request( path="/file/{}".format( vo.generate_id(file1.as_posix(), self.public_folder["_id"]) ), method="GET", user=self.users["sally"], ) self.assertStatusOk(resp) fobj = resp.json self.assertEqual(fobj["name"], "some_file") self.assertEqual(int(fobj["size"]), file1.stat().st_size) resp = self.request( path="/file/{_id}".format(**fobj), method="PUT", user=self.users["joel"], params={"name": "new_name"}, ) self.assertStatus(resp, 403) resp = self.request( path="/file/{_id}".format(**fobj), method="PUT", user=self.users["sally"], params={"name": "new_name"}, ) self.assertStatusOk(resp) fobj = resp.json self.assertFalse(file1.exists()) file1 = file1.with_name(fobj["name"]) self.assertTrue(file1.exists() and file1.is_file()) resp = self.request( path="/file/{_id}/download".format(**fobj), method="GET", user=self.users["joel"], isJson=False, ) self.assertStatusOk(resp) contentDisposition = 'filename="%s"' % fobj["name"] self.assertEqual(resp.headers["Content-Type"], "application/octet-stream") self.assertEqual( resp.headers["Content-Disposition"], "attachment; %s" % contentDisposition ) self.assertEqual(file_contents.decode(), self.getBody(resp)) # Test downloading the file with contentDisposition=inline. params = {"contentDisposition": "inline"} resp = self.request( path="/file/{_id}/download".format(**fobj), method="GET", user=self.users["joel"], isJson=False, params=params, ) self.assertStatusOk(resp) self.assertEqual(resp.headers["Content-Type"], "application/octet-stream") self.assertEqual( resp.headers["Content-Disposition"], "inline; %s" % contentDisposition ) self.assertEqual(file_contents.decode(), self.getBody(resp)) # Test downloading with an offset resp = self.request( path="/file/{_id}/download".format(**fobj), method="GET", user=self.users["joel"], isJson=False, params={"offset": 1}, ) self.assertStatus(resp, 206) self.assertEqual(file_contents[1:].decode(), self.getBody(resp)) # Test downloading with a range header and query range params respHeader = self.request( path="/file/{_id}/download".format(**fobj), method="GET", user=self.users["joel"], isJson=False, additionalHeaders=[("Range", "bytes=2-7")], ) respQuery = self.request( path="/file/{_id}/download".format(**fobj), method="GET", user=self.users["joel"], isJson=False, params={"offset": 2, "endByte": 8}, ) for resp in [respHeader, respQuery]: self.assertEqual(file_contents[2:8].decode(), self.getBody(resp)) self.assertEqual(resp.headers["Accept-Ranges"], "bytes") length = len(file_contents) begin, end = min(length, 2), min(length, 8) self.assertEqual(resp.headers["Content-Length"], end - begin) if length: self.assertStatus(resp, 206) self.assertEqual( resp.headers["Content-Range"], "bytes %d-%d/%d" % (begin, end - 1, length), ) else: self.assertStatusOk(resp) resp = self.request( path="/file/{_id}".format(**fobj), method="DELETE", user=self.users["sally"], isJson=False, ) self.assertStatusOk(resp) self.assertFalse(file1.exists()) def _testUploadFile(self, name): """ Uploads a non-empty file to the server. """ # Initialize the upload resp = self.request( path="/file", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": self.private_folder["_id"], "name": name, "size": len(chunk1) + len(chunk2), "mimeType": "text/plain", }, ) self.assertStatusOk(resp) uploadId = resp.json["_id"] # Uploading with no user should fail fields = [("offset", 0), ("uploadId", uploadId)] files = [("chunk", "helloWorld.txt", chunk1)] resp = self.multipartRequest(path="/file/chunk", fields=fields, files=files) self.assertStatus(resp, 401) # Uploading with the wrong user should fail fields = [("offset", 0), ("uploadId", uploadId)] files = [("chunk", "helloWorld.txt", chunk1)] resp = self.multipartRequest( path="/file/chunk", user=self.users["joel"], fields=fields, files=files ) self.assertStatus(resp, 403) # Sending the first chunk should fail because the default minimum chunk # size is larger than our chunk. Setting().unset(SettingKey.UPLOAD_MINIMUM_CHUNK_SIZE) fields = [("offset", 0), ("uploadId", uploadId)] files = [("chunk", "helloWorld.txt", chunk1)] resp = self.multipartRequest( path="/file/chunk", user=self.users["sally"], fields=fields, files=files ) self.assertStatus(resp, 400) self.assertEqual( resp.json, { "type": "validation", "message": "Chunk is smaller than the minimum size.", }, ) # Send the first chunk (use multipart) Setting().set(SettingKey.UPLOAD_MINIMUM_CHUNK_SIZE, 0) resp = self.multipartRequest( path="/file/chunk", user=self.users["sally"], fields=fields, files=files ) self.assertStatusOk(resp) # Attempting to send second chunk with incorrect offset should fail fields = [("offset", 0), ("uploadId", uploadId)] files = [("chunk", name, chunk2)] resp = self.multipartRequest( path="/file/chunk", user=self.users["sally"], fields=fields, files=files ) self.assertStatus(resp, 400) # Ask for completion before sending second chunk should fail resp = self.request( path="/file/completion", method="POST", user=self.users["sally"], params={"uploadId": uploadId}, ) self.assertStatus(resp, 400) # Request offset from server (simulate a resume event) resp = self.request( path="/file/offset", user=self.users["sally"], params={"uploadId": uploadId} ) self.assertStatusOk(resp) # Trying to send too many bytes should fail currentOffset = resp.json["offset"] fields = [("offset", resp.json["offset"]), ("uploadId", uploadId)] files = [("chunk", name, "extra_" + chunk2 + "_bytes")] resp = self.multipartRequest( path="/file/chunk", user=self.users["sally"], fields=fields, files=files ) self.assertStatus(resp, 400) self.assertEqual( resp.json, {"type": "validation", "message": "Received too many bytes."} ) # The offset should not have changed resp = self.request( path="/file/offset", user=self.users["sally"], params={"uploadId": uploadId} ) self.assertStatusOk(resp) self.assertEqual(resp.json["offset"], currentOffset) # Now upload the second chunk (using query params + body) resp = self.request( path="/file/chunk", method="POST", user=self.users["sally"], body=chunk2, params={"offset": resp.json["offset"], "uploadId": uploadId}, type="text/plain", ) self.assertStatusOk(resp) file = resp.json self.assertHasKeys(file, ["itemId"]) self.assertEqual(file["name"], name) self.assertEqual(file["size"], len(chunk1 + chunk2)) return file def test_upload_odd_cases(self): from girder.plugins.virtual_resources.rest import VirtualObject as vo # Change dest perms to ro dest_dir = pathlib.Path(self.private_folder["fsPath"]) dest_dir.chmod(0o551) resp = self.request( path="/file", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": self.private_folder["_id"], "name": "empty_file.txt", "size": "0", "mimeType": "text/plain", }, exception=True, ) self.assertStatus(resp, 500) self.assertEqual( resp.json["message"], "Insufficient perms to write on {}".format(self.private_folder["fsPath"]), ) dest_dir.chmod(0o751) (dest_dir / "empty_file.txt").mkdir() resp = self.request( path="/file", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": self.private_folder["_id"], "name": "empty_file.txt", "size": "0", "mimeType": "text/plain", }, exception=True, ) self.assertStatus(resp, 500) self.assertEqual( resp.json["message"], "IsADirectoryError: IsADirectoryError(21, 'Is a directory')", ) (dest_dir / "empty_file.txt").rmdir() resp = self.request( path="/file", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": self.private_folder["_id"], "name": "empty_file.txt", "size": 0, "mimeType": "text/plain", }, ) self.assertStatusOk(resp) resp = self.request( path="/file", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": self.private_folder["_id"], "name": "blah_file.txt", "size": len(chunk1), "mimeType": "text/plain", }, ) self.assertStatusOk(resp) upload = resp.json (dest_dir / "blah_file.txt").unlink() dest_dir.chmod(0o551) resp = self.request( path="/file/chunk", method="POST", user=self.users["sally"], params={"uploadId": upload["_id"], "offset": 0}, type="text/plain", body=chunk1, exception=True, ) self.assertStatus(resp, 500) self.assertEqual( resp.json["message"], "Exception: Exception('Failed to store upload.')", ) dest_dir.chmod(0o775) resp = self.request( path="/file", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": self.private_folder["_id"], "name": "full_body.txt", "size": len(chunk1), "mimeType": "text/plain", }, type="text/plain", body=chunk1, ) self.assertStatusOk(resp) fobj = resp.json self.assertEqual(fobj["size"], len(chunk1)) self.assertEqual(fobj["_modelType"], "file") dest_dir = pathlib.Path(self.private_folder["fsPath"]) / "some_dir" dest_dir.mkdir() resp = self.request( path="/file", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": vo.generate_id( dest_dir.as_posix(), self.private_folder["_id"] ), "name": "full_body.txt", "size": len(chunk1), "mimeType": "text/plain", }, type="text/plain", body=chunk1, ) self.assertStatusOk(resp) fobj = resp.json self.assertEqual(fobj["size"], len(chunk1)) self.assertTrue((dest_dir / fobj["name"]).is_file()) def testFilesystemAssetstore(self): """ Test usage of the Filesystem assetstore type. """ self.assetstore = Assetstore().getCurrent() root = self.assetstore["root"] # Clean out the test assetstore on disk shutil.rmtree(root) # First clean out the temp directory tmpdir = os.path.join(root, "temp") if os.path.isdir(tmpdir): for tempname in os.listdir(tmpdir): os.remove(os.path.join(tmpdir, tempname)) # Upload the two-chunk file file = self._testUploadFile("helloWorld1.txt") self.assertEqual(file["_modelType"], "file") # We want to make sure the file got uploaded correctly into # the assetstore and stored at the right location # self.assertEqual(os.stat(abspath).st_size, file["size"]) # self.assertEqual(os.stat(abspath).st_mode & 0o777, DEFAULT_PERMS) # Make sure access control is enforced on download resp = self.request(path="/file/%s/download" % file["_id"], method="GET") self.assertStatus(resp, 401) # Make sure access control is enforced on get info resp = self.request(path="/file/" + str(file["_id"]), method="GET") self.assertStatus(resp, 401) # Make sure we can get the file info and that it's filtered resp = self.request( path="/file/" + str(file["_id"]), method="GET", user=self.users["sally"] ) self.assertStatusOk(resp) self.assertEqual(resp.json["mimeType"], "application/octet-stream") # FIXME self.assertEqual(resp.json["exts"], ["txt"]) self.assertEqual(resp.json["_modelType"], "file") self.assertEqual(resp.json["creatorId"], str(self.users["sally"]["_id"])) self.assertEqual(resp.json["size"], file["size"]) self.assertTrue("itemId" in resp.json) # self.assertTrue("assetstoreId" in resp.json) # FIXME! # self.assertFalse("sha512" in resp.json) # FIXME ? def tearDown(self): # Folder().remove(self.public_folder) # Folder().remove(self.private_folder) # Collection().remove(self.base_collection) for user in self.users.values(): User().remove(user) for root in (self.public_root, self.shared_root, self.private_root): shutil.rmtree(root) super(FileOperationsTestCase, self).tearDown()
def copyVersionsAndRuns(event: events.Event) -> None: def get_dir_path(root_id_key, tale): if root_id_key == "versionsRootId": return util.getTaleVersionsDirPath(tale) elif root_id_key == "runsRootId": return util.getTaleRunsDirPath(tale) old_tale, new_tale = event.info creator = User().load(new_tale["creatorId"], force=True) versions_map = {} for root_id_key in ("versionsRootId", "runsRootId"): old_root = Folder().load(old_tale[root_id_key], user=creator, level=AccessType.READ) new_root = Folder().load(new_tale[root_id_key], user=creator, level=AccessType.WRITE) old_root_path = get_dir_path(root_id_key, old_tale) new_root_path = get_dir_path(root_id_key, new_tale) for src in Folder().childFolders(old_root, "folder", user=creator): dst = Folder().createFolder(new_root, src["name"], creator=creator) if root_id_key == "versionsRootId": versions_map[str(src["_id"])] = str(dst["_id"]) filtered_folder = Folder().filter(dst, creator) for key in src: if key not in filtered_folder and key not in dst: dst[key] = copy.deepcopy(src[key]) src_path = old_root_path / str(src["_id"]) dst_path = new_root_path / str(dst["_id"]) dst_path.mkdir(parents=True) shutil.copytree(src_path, dst_path, dirs_exist_ok=True, symlinks=True) dst.update({ "fsPath": dst_path.absolute().as_posix(), "isMapping": True, "created": src["created"], # preserve timestamps "updated": src["updated"], }) if root_id_key == "runsRootId": current_version = dst_path / "version" new_version_id = versions_map[current_version.resolve().name] new_version_path = ( "../../../../versions/" f"{str(new_tale['_id'])[:2]}/{new_tale['_id']}/{new_version_id}" ) current_version.unlink() current_version.symlink_to(new_version_path, True) dst["runVersionId"] = ObjectId(new_version_id) dst = Folder().save(dst, validate=False, triggerEvents=False) # update the time on root Folder().updateFolder(new_root) versions_root = Folder().load(new_tale["versionsRootId"], user=creator, level=AccessType.WRITE) for version in Folder().childFolders(versions_root, "folder", user=creator): manifest = Manifest(new_tale, creator, versionId=version["_id"], expand_folders=False) dst_path = pathlib.Path(version["fsPath"]) with open(dst_path / "manifest.json", "w") as fp: fp.write(manifest.dump_manifest()) Folder().updateFolder(versions_root)
class ResourceOperationsTestCase(base.TestCase): def setUp(self): super(ResourceOperationsTestCase, self).setUp() users = ( { "email": "*****@*****.**", "login": "******", "firstName": "Jane", "lastName": "Austin", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Sally", "lastName": "User", "password": "******", }, ) self.users = { user["login"]: User().createUser(**user) for user in users } self.public_root = tempfile.mkdtemp() self.private_root = tempfile.mkdtemp() self.base_collection = Collection().createCollection( "Virtual Resources", creator=self.users["admin"], public=True, reuseExisting=True, ) self.public_folder = Folder().createFolder( self.base_collection, "public", parentType="collection", public=True, reuseExisting=True, ) self.public_folder.update(dict(fsPath=self.public_root, isMapping=True)) self.public_folder = Folder().save(self.public_folder) self.regular_folder = Folder().createFolder( self.base_collection, "public_no_map", parentType="collection", public=True, reuseExisting=True, ) self.private_folder = Folder().createFolder( self.base_collection, "private", creator=self.users["sally"], parentType="collection", public=False, reuseExisting=True, ) self.private_folder.update( dict(fsPath=self.private_root, isMapping=True)) self.private_folder = Folder().save(self.private_folder) def test_basic_ops(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) nested_dir = root_path / "level0" nested_dir.mkdir(parents=True) file1 = root_path / "some_file.txt" file1_contents = b"Blah Blah Blah" with file1.open(mode="wb") as fp: fp.write(file1_contents) file2 = nested_dir / "some_other_file.txt" file2_contents = b"Lorem ipsum..." with file2.open(mode="wb") as fp: fp.write(file2_contents) # COPY copy_target_dir = root_path / "copy_dest" copy_target_dir.mkdir() resources = { "item": [ VirtualObject.generate_id(file1.as_posix(), self.public_folder["_id"]) ], "folder": [ VirtualObject.generate_id(nested_dir.as_posix(), self.public_folder["_id"]) ], } parentId = VirtualObject.generate_id(copy_target_dir.as_posix(), self.public_folder["_id"]) resp = self.request( path="/resource/copy", method="POST", user=self.users["admin"], params={ "parentType": "folder", "parentId": parentId, "resources": json.dumps(resources), }, ) self.assertStatusOk(resp) copied_dir = copy_target_dir / nested_dir.name self.assertTrue(copied_dir.is_dir()) copied_file1 = copy_target_dir / file1.name self.assertTrue(copied_file1.is_file()) with copied_file1.open(mode="rb") as fp: self.assertEqual(fp.read(), file1_contents) copied_file2 = copied_dir / file2.name self.assertTrue(copied_file2.is_file()) with copied_file2.open(mode="rb") as fp: self.assertEqual(fp.read(), file2_contents) # MOVE move_target_dir = root_path / "moved" move_target_dir.mkdir() resources = { "item": [ VirtualObject.generate_id(file1.as_posix(), self.public_folder["_id"]), VirtualObject.generate_id(copied_file2.as_posix(), self.public_folder["_id"]), ], "folder": [ VirtualObject.generate_id(copy_target_dir.as_posix(), self.public_folder["_id"]) ], } parentId = VirtualObject.generate_id(move_target_dir.as_posix(), self.public_folder["_id"]) resp = self.request( path="/resource/move", method="PUT", user=self.users["admin"], params={ "parentType": "folder", "parentId": parentId, "resources": json.dumps(resources), }, ) self.assertStatusOk(resp) for resource in (copy_target_dir, file1, copied_file2): self.assertFalse(resource.exists()) moved_dir = move_target_dir / copy_target_dir.name moved_file1 = move_target_dir / file1.name moved_file2 = move_target_dir / file2.name self.assertTrue(moved_dir.is_dir()) self.assertTrue(moved_file1.is_file()) self.assertTrue(moved_file2.is_file()) # DELETE regular_folder = Folder().createFolder( self.base_collection, "public", parentType="collection", public=True, reuseExisting=True, ) with file1.open(mode="wb") as fp: # Recreate fp.write(file1_contents) resources = {"item": [], "folder": [str(regular_folder["_id"])]} for path in root_path.iterdir(): if path.is_dir(): key = "folder" else: key = "item" resources[key].append( VirtualObject.generate_id(path.as_posix(), self.public_folder["_id"])) resp = self.request( path="/resource", method="DELETE", user=self.users["admin"], params={"resources": json.dumps(resources)}, ) self.assertStatusOk(resp) self.assertEqual(len(list(root_path.iterdir())), 0) regular_folder = Folder().load(regular_folder["_id"], force=True) self.assertTrue(regular_folder is None) def test_resource_op_acls(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) nested_dir = root_path / "level0" nested_dir.mkdir(parents=True) file1 = root_path / "some_file.txt" file1_contents = b"Blah Blah Blah" with file1.open(mode="wb") as fp: fp.write(file1_contents) sallys_root_path = pathlib.Path(self.private_folder["fsPath"]) # MOVE move_target_dir = sallys_root_path / "moved" move_target_dir.mkdir() resources = { "item": [ VirtualObject.generate_id(file1.as_posix(), self.public_folder["_id"]) ], "folder": [ VirtualObject.generate_id(nested_dir.as_posix(), self.public_folder["_id"]) ], } parentId = VirtualObject.generate_id(move_target_dir.as_posix(), self.private_folder["_id"]) resp = self.request( path="/resource/move", method="PUT", user=self.users["sally"], params={ "parentType": "folder", "parentId": parentId, "resources": json.dumps(resources), }, ) self.assertStatusOk(resp) self.assertTrue(nested_dir.exists()) self.assertTrue(file1.exists()) self.assertEqual(len(list(move_target_dir.iterdir())), 0) # COPY cors resp = self.request( path="/resource/copy", method="POST", user=self.users["sally"], params={ "parentType": "folder", "parentId": parentId, "resources": json.dumps(resources), }, ) self.assertStatusOk(resp) self.assertTrue((move_target_dir / nested_dir.name).is_dir()) self.assertTrue((move_target_dir / file1.name).is_file()) def test_lookup(self): root_path = pathlib.Path(self.private_folder["fsPath"]) nested_dir = root_path / "level0" nested_dir.mkdir(parents=True) file1 = root_path / "some_file.txt" file1_contents = b"Blah Blah Blah" with file1.open(mode="wb") as fp: fp.write(file1_contents) for model, lookup_path in ( ("folder", "/collection/Virtual Resources/private/level0"), ("item", "/collection/Virtual Resources/private/some_file.txt"), ): resp = self.request( path="/resource/lookup", method="GET", user=self.users["admin"], params={"path": lookup_path}, ) self.assertStatusOk(resp) self.assertEqual(resp.json["_modelType"], model) self.assertEqual(resp.json["name"], pathlib.Path(lookup_path).name) # test should return empty document for nonexisting file for path in ( "/user/nonexisting/blah", "/collection/Virtual Resources/private/level0/blah", ): resp = self.request( path="/resource/lookup", method="GET", user=self.users["admin"], params={ "path": path, "test": True }, exception=True, ) self.assertStatus(resp, 200) self.assertEqual(resp.json, None) for path, msg in ( ("/user/nonexisting/blah", "User not found: nonexisting"), ("/collection/nonexisting/blah", "Collection not found: nonexisting"), ("/blah/nonexisting/blah", "Invalid path format"), ( "/collection/Virtual Resources/private/level0/blah", "Path not found: collection/Virtual Resources/private/level0/blah", ), ): resp = self.request( path="/resource/lookup", method="GET", user=self.users["admin"], params={"path": path}, exception=True, ) self.assertStatus(resp, 400) self.assertEqual(resp.json["message"], msg) file1.unlink() nested_dir.rmdir() def test_copy_existing_name(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.private_folder["fsPath"]) file1 = root_path / "existing.txt" file1_contents = b"Blah Blah Blah" with file1.open(mode="wb") as fp: fp.write(file1_contents) resources = { "item": [ VirtualObject.generate_id(file1.as_posix(), self.private_folder["_id"]) ] } resp = self.request( path="/resource/copy", method="POST", user=self.users["admin"], params={ "parentType": "folder", "parentId": self.private_folder["_id"], "resources": json.dumps(resources), }, ) self.assertStatusOk(resp) self.assertTrue((root_path / "existing.txt (1)").is_file()) file1.unlink() (root_path / "existing.txt (1)").unlink() def test_path(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.private_folder["fsPath"]) nested_dir = root_path / "directory" nested_dir.mkdir(parents=True) file1 = nested_dir / "file.txt" file1_contents = b"Blah Blah Blah" with file1.open(mode="wb") as fp: fp.write(file1_contents) item_id = VirtualObject.generate_id(file1.as_posix(), self.private_folder["_id"]) folder_id = VirtualObject.generate_id(nested_dir.as_posix(), self.private_folder["_id"]) resp = self.request( path="/resource/{}/path".format(item_id), method="GET", user=self.users["admin"], params={"type": "item"}, ) self.assertStatusOk(resp) self.assertEqual( resp.json, "/collection/Virtual Resources/private/directory/file.txt") resp = self.request( path="/resource/{}/path".format(folder_id), method="GET", user=self.users["admin"], params={"type": "folder"}, ) self.assertStatusOk(resp) self.assertEqual(resp.json, "/collection/Virtual Resources/private/directory") for res_id, res_type in ( (item_id, "folder"), (folder_id, "item"), (item_id, "collection"), ): resp = self.request( path="/resource/{}/path".format(res_id), method="GET", user=self.users["admin"], params={"type": res_type}, exception=True, ) self.assertStatus(resp, 400) self.assertEqual(resp.json["message"], "Invalid resource id.") file1.unlink() nested_dir.rmdir() def tearDown(self): for folder in (self.public_folder, self.private_folder, self.regular_folder): Folder().remove(folder) Collection().remove(self.base_collection) for user in self.users.values(): User().remove(user) for root in (self.public_root, self.private_root): shutil.rmtree(root) super(ResourceOperationsTestCase, self).tearDown()
class FolderOperationsTestCase(base.TestCase): def setUp(self): super(FolderOperationsTestCase, self).setUp() users = ( { "email": "*****@*****.**", "login": "******", "firstName": "Jane", "lastName": "Austin", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Sally", "lastName": "User", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Joel", "lastName": "CanTDoMuch", "password": "******", }, ) self.users = { user["login"]: User().createUser(**user) for user in users } self.public_root = tempfile.mkdtemp() self.shared_root = tempfile.mkdtemp() self.private_root = tempfile.mkdtemp() self.private2_root = tempfile.mkdtemp() self.base_collection = Collection().createCollection( "Virtual Resources", creator=self.users["admin"], public=True, reuseExisting=True, ) self.public_folder = Folder().createFolder( self.base_collection, "public", parentType="collection", public=True, reuseExisting=True, ) self.public_folder.update(dict(fsPath=self.public_root, isMapping=True)) self.public_folder = Folder().save(self.public_folder) self.private_folder = Folder().createFolder( self.base_collection, "private", parentType="collection", public=False, creator=self.users["sally"], reuseExisting=True, ) self.private_folder.update( dict(fsPath=self.private_root, isMapping=True)) Folder().setUserAccess(self.private_folder, self.users["sally"], AccessType.WRITE) Folder().setUserAccess(self.private_folder, self.users["joel"], AccessType.READ) self.private_folder = Folder().save(self.private_folder) self.private_folder2 = Folder().createFolder( self.base_collection, "private2", parentType="collection", public=False, creator=self.users["sally"], reuseExisting=True, ) self.private_folder2.update( dict(fsPath=self.private2_root, isMapping=True)) Folder().setUserAccess(self.private_folder2, self.users["sally"], AccessType.WRITE) Folder().setUserAccess(self.private_folder2, self.users["joel"], AccessType.WRITE) self.private_folder2 = Folder().save(self.private_folder2) self.regular_folder = Folder().createFolder( self.base_collection, "regular", creator=self.users["sally"], parentType="collection", public=True, reuseExisting=True, ) def test_basic_folder_ops(self): from girder.plugins.virtual_resources.rest import VirtualObject resp = self.request( path="/folder", method="POST", user=self.users["admin"], params={ "parentType": "folder", "parentId": self.public_folder["_id"], "name": "test_folder", }, ) self.assertStatusOk(resp) folder = resp.json actual_folder_path = pathlib.Path(self.public_root) / folder["name"] self.assertTrue(actual_folder_path.is_dir()) decoded_path, decoded_root_id = VirtualObject.path_from_id( folder["_id"]) self.assertEqual(decoded_path, actual_folder_path) self.assertEqual(decoded_root_id, str(self.public_folder["_id"])) resp = self.request( path="/folder", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": str(self.public_folder["_id"]) }, ) self.assertStatusOk(resp) get_folders = resp.json self.assertEqual(len(get_folders), 1) self.assertEqual(get_folders[0], folder) resp = self.request( path="/folder/{_id}".format(**folder), method="GET", user=self.users["admin"], ) self.assertStatusOk(resp) self.assertEqual(resp.json, get_folders[0]) resp = self.request( path="/folder/{_id}".format(**folder), method="PUT", user=self.users["admin"], params={"name": "renamed"}, ) self.assertStatusOk(resp) folder = resp.json self.assertFalse(actual_folder_path.exists()) actual_folder_path = pathlib.Path(self.public_root) / folder["name"] self.assertTrue(actual_folder_path.is_dir()) resp = self.request( path="/folder/{_id}".format(**folder), method="DELETE", user=self.users["admin"], ) self.assertStatusOk(resp) self.assertFalse(actual_folder_path.exists()) def test_folder_move(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) dir1 = root_path / "some_dir" dir1.mkdir() file1 = dir1 / "some_file" with file1.open(mode="wb") as fp: fp.write(b"\n") folder_id = VirtualObject.generate_id(dir1, self.public_folder["_id"]) resp = self.request( path="/folder/{}".format(folder_id), method="PUT", user=self.users["admin"], params={"name": dir1.name}, exception=True, ) self.assertStatus(resp, 500) self.assertEqual( resp.json["message"], "Folder '{}' already exists in {}".format( dir1.name, self.public_folder["_id"]), ) new_root_path = pathlib.Path(self.private_folder["fsPath"]) dir2 = new_root_path / "level1" dir2.mkdir() new_folder_id = VirtualObject.generate_id(dir2, self.private_folder["_id"]) resp = self.request( path="/folder/{}".format(folder_id), method="PUT", user=self.users["admin"], params={ "parentId": new_folder_id, "parentType": "folder" }, ) self.assertStatusOk(resp) self.assertFalse(dir1.exists()) self.assertTrue((dir2 / dir1.name).exists()) new_file = dir2 / dir1.name / file1.name self.assertTrue(new_file.exists()) new_file.unlink() (dir2 / dir1.name).rmdir() dir2.rmdir() def test_move_to_root(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) dir1 = root_path / "some_dir" dir1.mkdir() file1 = dir1 / "some_file" with file1.open(mode="wb") as fp: fp.write(b"\n") folder_id = VirtualObject.generate_id(dir1, self.public_folder["_id"]) resp = self.request( path="/folder/{}".format(folder_id), method="PUT", user=self.users["admin"], params={ "parentId": self.private_folder["_id"], "parentType": "folder" }, ) self.assertStatusOk(resp) self.assertFalse(dir1.exists()) root_path = pathlib.Path(self.private_folder["fsPath"]) dir1 = root_path / "some_dir" file1 = dir1 / "some_file" self.assertTrue(dir1.exists()) self.assertTrue(file1.exists()) file1.unlink() dir1.rmdir() def test_move_acls(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.private_folder["fsPath"]) dir1 = root_path / "some_dir" dir1.mkdir() folder_id = VirtualObject.generate_id(dir1, self.private_folder["_id"]) resp = self.request( path="/folder/{}".format(folder_id), method="PUT", user=self.users["joel"], params={ "parentId": self.private_folder2["_id"], "parentType": "folder" }, ) self.assertStatus(resp, 403) resp = self.request( path="/folder/{}".format(folder_id), method="PUT", user=self.users["sally"], params={ "parentId": self.private_folder2["_id"], "parentType": "folder" }, ) self.assertStatusOk(resp) self.assertFalse(dir1.exists()) root_path = pathlib.Path(self.private_folder2["fsPath"]) dir1 = root_path / "some_dir" self.assertTrue(dir1.exists()) folder_id = VirtualObject.generate_id(dir1, self.private_folder2["_id"]) resp = self.request( path="/folder/{}".format(folder_id), method="PUT", user=self.users["joel"], params={ "parentId": self.private_folder["_id"], "parentType": "folder" }, ) self.assertStatus(resp, 403) dir1.rmdir() def test_folder_details(self): root_path = pathlib.Path(self.public_folder["fsPath"]) dir1 = root_path / "some_dir" dir1.mkdir() file1 = root_path / "some_file" with file1.open(mode="wb") as fp: fp.write(b"\n") resp = self.request( path="/folder/{_id}/details".format(**self.public_folder), method="GET", user=self.users["admin"], ) self.assertStatusOk(resp) self.assertEqual(resp.json, {"nFolders": 1, "nItems": 1}) file1.unlink() dir1.rmdir() def test_folder_rootpath(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) nested_dir = root_path / "level0" / "level1" / "level2" nested_dir.mkdir(parents=True) folder_id = VirtualObject.generate_id(nested_dir, self.public_folder["_id"]) resp = self.request( path="/folder/{}/rootpath".format(folder_id), method="GET", user=self.users["admin"], ) self.assertStatusOk(resp) self.assertEqual(len(resp.json), 4) rootpath = resp.json self.assertEqual(rootpath[0]["type"], "collection") self.assertEqual(rootpath[0]["object"]["_id"], str(self.base_collection["_id"])) self.assertEqual(rootpath[1]["type"], "folder") self.assertEqual(rootpath[1]["object"]["_id"], str(self.public_folder["_id"])) self.assertEqual(rootpath[2]["type"], "folder") self.assertEqual(rootpath[2]["object"]["name"], "level0") self.assertEqual(rootpath[3]["type"], "folder") self.assertEqual(rootpath[3]["object"]["name"], "level1") shutil.rmtree((root_path / "level0").as_posix()) def test_folder_delete_contents(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) nested_dir = root_path / "lone_survivor" nested_dir.mkdir(parents=True) folder_id = VirtualObject.generate_id(nested_dir, self.public_folder["_id"]) dir1 = nested_dir / "subfolder" dir1.mkdir() file1 = dir1 / "some_file.txt" with file1.open(mode="wb") as fp: fp.write(b"file1\n") file2 = nested_dir / "other_file.txt" with file2.open(mode="wb") as fp: fp.write(b"file2\n") self.assertEqual(len(list(nested_dir.iterdir())), 2) resp = self.request( path="/folder/{}/contents".format(folder_id), method="DELETE", user=self.users["admin"], ) self.assertStatusOk(resp) self.assertEqual(len(list(nested_dir.iterdir())), 0) nested_dir.rmdir() def test_folder_download(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) nested_dir = root_path / "lone_survivor" nested_dir.mkdir(parents=True) folder_id = VirtualObject.generate_id(nested_dir, self.public_folder["_id"]) dir1 = nested_dir / "subfolder" dir1.mkdir() file1 = dir1 / "some_file.txt" with file1.open(mode="wb") as fp: fp.write(b"file1\n") file2 = nested_dir / "other_file.txt" with file2.open(mode="wb") as fp: fp.write(b"file2\n") self.assertEqual(len(list(nested_dir.iterdir())), 2) resp = self.request( path="/folder/{}/download".format(folder_id), method="GET", user=self.users["admin"], isJson=False, ) self.assertStatusOk(resp) with zipfile.ZipFile(io.BytesIO(self.getBody(resp, text=False)), "r") as fp: self.assertEqual(sorted(fp.namelist()), ["other_file.txt", "subfolder/some_file.txt"]) # TODO should probably check the content too... def test_folder_copy(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) dir1 = root_path / "source_folder" dir1.mkdir(parents=True) folder_id = VirtualObject.generate_id(dir1, self.public_folder["_id"]) file1 = dir1 / "file.dat" with file1.open(mode="wb") as fp: fp.write(b"file1\n") resp = self.request( path="/folder/{}/copy".format(self.public_folder["_id"]), method="POST", user=self.users["sally"], params={"name": "new_copy"}, exception=True, ) self.assertStatus(resp, 500) self.assertEqual(resp.json["message"], "Copying mappings is not allowed.") resp = self.request( path="/folder/{}/copy".format(folder_id), method="POST", user=self.users["joel"], params={ "name": "new_copy", "parentId": str(self.regular_folder["_id"]), "parentType": "folder", }, ) self.assertStatus(resp, 403) resp = self.request( path="/folder/{}/copy".format(folder_id), method="POST", user=self.users["sally"], params={ "name": "new_copy", "parentId": str(self.regular_folder["_id"]), "parentType": "folder", }, exception=True, ) self.assertStatus(resp, 500) self.assertEqual( resp.json["message"], "Folder {} is not a mapping.".format(self.regular_folder["_id"]), ) resp = self.request( path="/folder/{}/copy".format(folder_id), method="POST", user=self.users["sally"], params={"name": "new_copy"}, ) self.assertStatus(resp, 403) self.assertFalse((dir1.with_name("new_copy") / file1.name).is_file()) resp = self.request( path="/folder/{}/copy".format(folder_id), method="POST", user=self.users["admin"], params={}, exception=True, ) self.assertStatus(resp, 200) new_folder = resp.json self.assertEqual(new_folder["name"], "source_folder (1)") self.assertTrue( (dir1.with_name("source_folder (1)") / file1.name).is_file()) resp = self.request( path="/folder/{}/copy".format(folder_id), method="POST", user=self.users["admin"], params={"name": "new_copy"}, ) self.assertStatusOk(resp) new_folder = resp.json self.assertEqual(new_folder["name"], "new_copy") self.assertTrue((dir1.with_name("new_copy") / file1.name).is_file()) resp = self.request( path="/folder/{}/copy".format(folder_id), method="POST", user=self.users["admin"], params={ "name": "copy_within_copy", "parentId": new_folder["_id"], "parentType": "folder", }, ) self.assertStatusOk(resp) self.assertTrue((dir1.with_name("new_copy") / "copy_within_copy" / file1.name).is_file()) def test_exists_already(self): root_path = pathlib.Path(self.public_folder["fsPath"]) some_dir = root_path / "some_folder" some_dir.mkdir(parents=True) resp = self.request( path="/folder", method="POST", user=self.users["admin"], params={ "parentType": "folder", "parentId": self.public_folder["_id"], "name": "some_folder", }, ) self.assertStatus(resp, 400) folder = resp.json self.assertEqual( folder, { "type": "validation", "message": "A folder with that name already exists here.", "field": "name", }, ) some_dir.rmdir() def test_folder_listing(self): root_path = pathlib.Path(self.public_folder["fsPath"]) some_dir = root_path / "some_folder_with_subfolders" some_dir.mkdir(parents=True) (some_dir / "subfolder1").mkdir() (some_dir / "subfolder2").mkdir() resp = self.request( path="/folder", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": str(self.public_folder["_id"]) }, ) self.assertStatusOk(resp) some_dir_obj = resp.json[0] self.assertEqual(some_dir_obj["name"], "some_folder_with_subfolders") resp = self.request( path="/folder", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": some_dir_obj["_id"] }, ) self.assertStatusOk(resp) self.assertEqual(len(resp.json), 2) resp = self.request( path="/folder", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": some_dir_obj["_id"], "name": "subfolder2", }, ) self.assertStatusOk(resp) self.assertEqual(len(resp.json), 1) self.assertEqual(resp.json[0]["name"], "subfolder2") resp = self.request( path="/folder", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": some_dir_obj["_id"], "name": "nope", }, ) self.assertStatusOk(resp) self.assertEqual(len(resp.json), 0) shutil.rmtree(some_dir.as_posix()) def tearDown(self): Folder().remove(self.public_folder) Folder().remove(self.private_folder) Folder().remove(self.private_folder2) Folder().remove(self.regular_folder) Collection().remove(self.base_collection) for user in self.users.values(): User().remove(user) for root in ( self.public_root, self.shared_root, self.private_root, self.private2_root, ): shutil.rmtree(root) super(FolderOperationsTestCase, self).tearDown()
class ItemOperationsTestCase(base.TestCase): def setUp(self): super(ItemOperationsTestCase, self).setUp() users = ( { "email": "*****@*****.**", "login": "******", "firstName": "Jane", "lastName": "Austin", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Sally", "lastName": "User", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Joel", "lastName": "CanTDoMuch", "password": "******", }, ) self.users = { user["login"]: User().createUser(**user) for user in users } self.public_root = tempfile.mkdtemp() self.private_root = tempfile.mkdtemp() self.base_collection = Collection().createCollection( "Virtual Resources", creator=self.users["admin"], public=True, reuseExisting=True, ) self.public_folder = Folder().createFolder( self.base_collection, "public", parentType="collection", public=True, reuseExisting=True, ) self.public_folder.update(dict(fsPath=self.public_root, isMapping=True)) self.public_folder = Folder().save(self.public_folder) self.regular_folder = Folder().createFolder( self.base_collection, "public_no_map", parentType="collection", public=True, reuseExisting=True, ) self.private_folder = Folder().createFolder( self.base_collection, "private", creator=self.users["sally"], parentType="collection", public=False, reuseExisting=True, ) self.private_folder.update( dict(fsPath=self.private_root, isMapping=True)) self.private_folder = Folder().save(self.private_folder) def test_basic_item_ops(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) nested_dir = root_path / "level0" nested_dir.mkdir(parents=True) parentId = VirtualObject.generate_id(nested_dir.as_posix(), self.public_folder["_id"]) resp = self.request( path="/item", method="POST", user=self.users["admin"], params={ "folderId": parentId, "name": "test_item" }, ) self.assertStatusOk(resp) item = resp.json actual_item_path = nested_dir / item["name"] self.assertTrue(actual_item_path.is_file()) decoded_path, decoded_root_id = VirtualObject.path_from_id(item["_id"]) self.assertEqual(decoded_path, actual_item_path) self.assertEqual(decoded_root_id, str(self.public_folder["_id"])) resp = self.request( path="/item", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": str(parentId), "name": "nope" }, ) self.assertStatusOk(resp) self.assertEqual(len(resp.json), 0) resp = self.request( path="/item", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": str(parentId), "name": item["name"] }, ) self.assertStatusOk(resp) self.assertEqual(len(resp.json), 1) resp = self.request( path="/item", method="GET", user=self.users["admin"], params={ "parentType": "folder", "parentId": str(parentId) }, ) self.assertStatusOk(resp) get_items = resp.json self.assertEqual(len(get_items), 1) self.assertEqual(get_items[0], item) resp = self.request(path="/item/{_id}".format(**item), method="GET", user=self.users["admin"]) self.assertStatusOk(resp) self.assertEqual(resp.json, get_items[0]) resp = self.request( path="/item/{_id}".format(**item), method="PUT", user=self.users["admin"], params={"name": "renamed"}, ) self.assertStatusOk(resp) item = resp.json self.assertFalse(actual_item_path.exists()) actual_item_path = actual_item_path.with_name(item["name"]) self.assertTrue(actual_item_path.is_file()) resp = self.request( path="/item/{_id}/files".format(**item), method="GET", user=self.users["admin"], ) self.assertStatusOk(resp) files = resp.json self.assertEqual(len(files), 1) self.assertEqual(files[0]["_id"], item["_id"]) resp = self.request(path="/item/{_id}".format(**item), method="DELETE", user=self.users["admin"]) self.assertStatusOk(resp) self.assertFalse(actual_item_path.exists()) shutil.rmtree(nested_dir.as_posix()) def test_item_rootpath(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) nested_dir = root_path / "level0" / "level1" nested_dir.mkdir(parents=True) file1 = nested_dir / "some_file" file_contents = b"hello world\n" with file1.open(mode="wb") as fp: fp.write(file_contents) item_id = VirtualObject.generate_id(file1, self.public_folder["_id"]) resp = self.request( path="/item/{}/rootpath".format(item_id), method="GET", user=self.users["admin"], ) self.assertStatusOk(resp) self.assertEqual(len(resp.json), 4) rootpath = resp.json self.assertEqual(rootpath[0]["type"], "collection") self.assertEqual(rootpath[0]["object"]["_id"], str(self.base_collection["_id"])) self.assertEqual(rootpath[1]["type"], "folder") self.assertEqual(rootpath[1]["object"]["_id"], str(self.public_folder["_id"])) self.assertEqual(rootpath[2]["type"], "folder") self.assertEqual(rootpath[2]["object"]["name"], "level0") self.assertEqual(rootpath[3]["type"], "folder") self.assertEqual(rootpath[3]["object"]["name"], "level1") shutil.rmtree((root_path / "level0").as_posix()) def test_copy_item(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) file1 = root_path / "some_file" file_contents = b"hello world\n" with file1.open(mode="wb") as fp: fp.write(file_contents) item_id = VirtualObject.generate_id(file1, self.public_folder["_id"]) # Copy in the same folder resp = self.request( path="/item/{}/copy".format(item_id), method="POST", user=self.users["admin"], params={"name": "copy"}, ) self.assertStatusOk(resp) self.assertTrue(file1.with_name("copy").is_file()) with open(file1.with_name("copy").as_posix(), "rb") as fp: self.assertEqual(fp.read(), file_contents) # Copy in the same mapping but different folder new_dir = root_path / "some_dir" new_dir.mkdir() folder_id = VirtualObject.generate_id(new_dir, self.public_folder["_id"]) resp = self.request( path="/item/{}/copy".format(item_id), method="POST", user=self.users["admin"], params={"folderId": str(folder_id)}, ) self.assertStatusOk(resp) new_file = new_dir / "some_file" self.assertTrue(new_file.is_file()) with open(new_file.as_posix(), "rb") as fp: self.assertEqual(fp.read(), file_contents) # Copy between two mappings resp = self.request( path="/item/{}/copy".format(item_id), method="POST", user=self.users["admin"], params={"folderId": str(self.private_folder["_id"])}, ) self.assertStatusOk(resp) cors_file = pathlib.Path(self.private_folder["fsPath"]) / "some_file" self.assertTrue(cors_file.is_file()) with open(cors_file.as_posix(), "rb") as fp: self.assertEqual(fp.read(), file_contents) # Try to copy to non mapping resp = self.request( path="/item/{}/copy".format(item_id), method="POST", user=self.users["admin"], params={"folderId": str(self.regular_folder["_id"])}, exception=True, ) self.assertStatus(resp, 500) self.assertEqual( resp.json["message"], "Folder {} is not a mapping.".format(self.regular_folder["_id"]), ) shutil.rmtree(new_dir.as_posix()) file1.unlink() file1.with_name("copy").unlink() cors_file.unlink() def test_move_item(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.public_folder["fsPath"]) subdir = root_path / "subdir" subdir.mkdir() file1 = subdir / "to_be_moved" file_contents = b"hello world asdfadsf\n" with file1.open(mode="wb") as fp: fp.write(file_contents) folder_id = VirtualObject.generate_id(subdir, self.public_folder["_id"]) item_id = VirtualObject.generate_id(file1, self.public_folder["_id"]) # Move with the same name (noop) resp = self.request( path="/item/{}".format(item_id), method="PUT", user=self.users["admin"], params={ "name": file1.name, "folderId": folder_id }, ) self.assertStatusOk(resp) self.assertTrue(file1.exists()) # Move within the same folder resp = self.request( path="/item/{}".format(item_id), method="PUT", user=self.users["admin"], params={ "name": "after_move", "folderId": folder_id }, ) self.assertStatusOk(resp) self.assertTrue((subdir / "after_move").exists()) self.assertFalse(file1.exists()) # Move to a different folder file1 = subdir / "after_move" item_id = VirtualObject.generate_id(file1, self.public_folder["_id"]) resp = self.request( path="/item/{}".format(item_id), method="PUT", user=self.users["admin"], params={ "name": "after_move", "folderId": self.private_folder["_id"] }, ) self.assertStatusOk(resp) self.assertFalse(file1.exists()) root_path = pathlib.Path(self.private_folder["fsPath"]) file_new = root_path / "after_move" item_id = VirtualObject.generate_id(file_new, self.private_folder["_id"]) self.assertTrue(file_new.is_file()) with open(file_new.as_posix(), "rb") as fp: self.assertEqual(fp.read(), file_contents) # Try to move not into mapping and fail resp = self.request( path="/item/{}".format(item_id), method="PUT", user=self.users["sally"], params={ "name": "after_move", "folderId": str(self.regular_folder["_id"]), "parentType": "folder", }, exception=True, ) self.assertStatus(resp, 500) self.assertEqual( resp.json["message"], "Folder {} is not a mapping.".format(self.regular_folder["_id"]), ) # move it back to subdir in a mapping resp = self.request( path="/item/{}".format(item_id), method="PUT", user=self.users["admin"], params={ "name": "final_move", "folderId": folder_id }, ) self.assertStatusOk(resp) self.assertFalse(file_new.exists()) file_new = subdir / "final_move" self.assertTrue(file_new.exists()) file_new.unlink() def test_copy_existing_name(self): from girder.plugins.virtual_resources.rest import VirtualObject root_path = pathlib.Path(self.private_folder["fsPath"]) file1 = root_path / "existing.txt" file1_contents = b"Blah Blah Blah" with file1.open(mode="wb") as fp: fp.write(file1_contents) item_id = VirtualObject.generate_id(file1, self.private_folder["_id"]) resp = self.request( path="/item/{}/copy".format(item_id), method="POST", user=self.users["admin"], params={}, ) self.assertStatusOk(resp) self.assertEqual(resp.json["name"], "existing.txt (1)") item = resp.json resp = self.request( path="/item", method="POST", user=self.users["admin"], params={ "folderId": item["folderId"], "name": item["name"] }, ) self.assertStatus(resp, 400) folder = resp.json self.assertEqual( folder, { "type": "validation", "message": "An item with that name already exists here.", "field": "name", }, ) self.assertTrue((root_path / "existing.txt (1)").is_file()) file1.unlink() (root_path / "existing.txt (1)").unlink() def tearDown(self): for folder in (self.public_folder, self.private_folder, self.regular_folder): Folder().remove(folder) Collection().remove(self.base_collection) for user in self.users.values(): User().remove(user) for root in (self.public_root, self.private_root): shutil.rmtree(root) super(ItemOperationsTestCase, self).tearDown()
class BasicOperationsTestCase(base.TestCase): def setUp(self): super(BasicOperationsTestCase, self).setUp() users = ( { "email": "*****@*****.**", "login": "******", "firstName": "Jane", "lastName": "Austin", "password": "******", }, { "email": "*****@*****.**", "login": "******", "firstName": "Sally", "lastName": "User", "password": "******", }, ) self.users = { user["login"]: User().createUser(**user) for user in users } self.public_root = tempfile.mkdtemp() self.base_collection = Collection().createCollection( random_string(), creator=self.users["admin"], public=True, reuseExisting=True, ) self.public_folder = Folder().createFolder( self.base_collection, "public", creator=self.users["sally"], parentType="collection", public=True, reuseExisting=True, ) self.public_folder.update(dict(fsPath=self.public_root, isMapping=True)) self.public_folder = Folder().save(self.public_folder) def test_vo_methods(self): from girder.plugins.virtual_resources.rest import VirtualObject as vo root_path = pathlib.Path(self.public_folder["fsPath"]) non_existing = root_path / "something" with pytest.raises(ValidationException): vo().is_file(non_existing, self.public_folder["_id"]) with pytest.raises(ValidationException): vo().is_dir(non_existing, self.public_folder["_id"]) def test_mapping_creation(self): new_folder = Folder().createFolder( self.base_collection, random_string(), creator=self.users["sally"], parentType="collection", public=True, reuseExisting=True, ) resp = self.request( path="/folder/{_id}".format(**new_folder), method="PUT", user=self.users["sally"], params={ "fsPath": "/etc", "isMapping": True }, # H4ck3r detected! ) self.assertStatus(resp, 403) self.assertEqual( resp.json, { "message": "Must be admin to setup virtual folders.", "type": "access" }, ) resp = self.request( path="/folder/{_id}".format(**new_folder), method="PUT", user=self.users["admin"], params={ "fsPath": "/etc", "isMapping": True }, # G0d ) self.assertStatusOk(resp) self.assertHasKeys(resp.json, ["fsPath", "isMapping"]) self.assertEqual(resp.json["fsPath"], "/etc") self.assertEqual(resp.json["isMapping"], True) Folder().remove(new_folder) def tearDown(self): Folder().remove(self.public_folder) Collection().remove(self.base_collection) for user in self.users.values(): User().remove(user) for root in (self.public_root, ): shutil.rmtree(root) super(BasicOperationsTestCase, self).tearDown()