From d64732330fe681f8a794f8e2671ec0fa48271ad3 Mon Sep 17 00:00:00 2001 From: Charles-William Cummings Date: Tue, 8 Aug 2023 12:54:35 -0400 Subject: [PATCH] set user dirs perms to allow read and write operations on jupyterlab --- cowbird/handlers/impl/filesystem.py | 15 +++++++++++---- tests/test_filesystem.py | 11 ++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/cowbird/handlers/impl/filesystem.py b/cowbird/handlers/impl/filesystem.py index e807046a..d94b3530 100644 --- a/cowbird/handlers/impl/filesystem.py +++ b/cowbird/handlers/impl/filesystem.py @@ -204,12 +204,15 @@ def update_secure_data_proxy_path_perms(self, src_path: str, user_name: str) -> return access_allowed @staticmethod - def create_hardlink_path(src_path: str, hardlink_path: str, access_allowed: bool) -> None: + def create_hardlink_path(src_path: str, hardlink_path: str, access_allowed: bool, dir_perms: int = 0o775) -> None: """ Creates a hardlink path from a source file, if the user has access rights. """ if access_allowed: - os.makedirs(os.path.dirname(hardlink_path), exist_ok=True) + # set umask to allow all permissions, else, mode is ignored when making directories + previous_umask = os.umask(0) + os.makedirs(os.path.dirname(hardlink_path), mode=dir_perms, exist_ok=True) + os.umask(previous_umask) # reset umask to default LOGGER.debug("Creating hardlink from file `%s` to the path `%s`", src_path, hardlink_path) try: os.link(src_path, hardlink_path) @@ -227,6 +230,9 @@ def _create_wpsoutputs_hardlink(self, src_path: str, overwrite: bool = False, if not process_user_files: return + # User workspace directories require `rwx` permissions to allow file modifications via JupyterLab for + # files with write permissions + dir_perms = 0o777 magpie_handler = HandlerFactory().get_handler("Magpie") user_name = magpie_handler.get_user_name_from_user_id(int(regex_match.group(2))) hardlink_path = self.get_user_hardlink(src_path=src_path, @@ -243,6 +249,7 @@ def _create_wpsoutputs_hardlink(self, src_path: str, overwrite: bool = False, else: # public files if not process_public_files: return + dir_perms = 0o775 hardlink_path = self._get_public_hardlink(src_path) if os.path.exists(hardlink_path): @@ -254,7 +261,7 @@ def _create_wpsoutputs_hardlink(self, src_path: str, overwrite: bool = False, "created file.", hardlink_path) os.remove(hardlink_path) - self.create_hardlink_path(src_path, hardlink_path, access_allowed) + self.create_hardlink_path(src_path, hardlink_path, access_allowed, dir_perms=dir_perms) def on_created(self, path: str) -> None: """ @@ -386,7 +393,7 @@ def _update_permissions_on_filesystem(self, permission: Permission) -> None: # Resync hardlink path if os.path.exists(hardlink_path): os.remove(hardlink_path) - self.create_hardlink_path(user_path, hardlink_path, access_allowed) + self.create_hardlink_path(user_path, hardlink_path, access_allowed, dir_perms=0o777) def permission_created(self, permission: Permission) -> None: self._update_permissions_on_filesystem(permission) diff --git a/tests/test_filesystem.py b/tests/test_filesystem.py index cd27a726..2247d331 100644 --- a/tests/test_filesystem.py +++ b/tests/test_filesystem.py @@ -17,7 +17,7 @@ from cowbird.api.schemas import ValidOperations from cowbird.handlers import HandlerFactory -from cowbird.handlers.impl.filesystem import NOTEBOOKS_DIR_NAME, SECURE_DATA_PROXY_NAME +from cowbird.handlers.impl.filesystem import NOTEBOOKS_DIR_NAME, SECURE_DATA_PROXY_NAME, USER_WPS_OUTPUTS_USER_DIR_NAME from cowbird.typedefs import JSON from tests import test_magpie, utils @@ -230,6 +230,9 @@ def test_public_wps_output_created(self): TestFileSystem.check_created_test_cases(output_file, hardlink_path) + # Check that the hardlink's parent directory have the right permissions + utils.check_path_permissions(os.path.join(filesystem_handler.get_wps_outputs_public_dir(), bird_name), 0o775) + # A create event on a folder should not be processed (no corresponding target folder created) target_dir = os.path.join(filesystem_handler.get_wps_outputs_public_dir(), bird_name) shutil.rmtree(target_dir) @@ -461,6 +464,12 @@ def test_user_wps_output_created(self): TestFileSystem.check_created_test_cases(self.output_file, self.hardlink_path) + # Check that the hardlink's parent directories have the right permissions + path_to_check = self.hardlink_path + while not path_to_check.endswith(USER_WPS_OUTPUTS_USER_DIR_NAME): + path_to_check = os.path.dirname(path_to_check) + utils.check_path_permissions(path_to_check, 0o777) + # A create event on a folder should not be processed (no corresponding target folder created) src_dir = os.path.join(self.wpsoutputs_dir, f"{self.bird_name}/users/{self.user_id}/{self.job_id}") target_dir = os.path.join(self.wps_outputs_user_dir, f"{self.bird_name}/{self.job_id}")