diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f4cb38e..9d7026fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## [0.0.42 - 2023-08-30] + +### Fixed + +- Created `FsNode` from `UiActionFileInfo` now have the `file_id` with the NC instance ID as from the DAV requests. + ## [0.0.41 - 2023-08-26] ### Added diff --git a/nc_py_api/ex_app/ui/files.py b/nc_py_api/ex_app/ui/files.py index d482800b..9b8c6ded 100644 --- a/nc_py_api/ex_app/ui/files.py +++ b/nc_py_api/ex_app/ui/files.py @@ -10,8 +10,6 @@ from ..._session import NcSessionApp from ...files import FilePermissions, FsNode -ENDPOINT_SUFFIX = "files/actions/menu" - class UiActionFileInfo(BaseModel): """File Information Nextcloud sends to the External Application.""" @@ -40,18 +38,17 @@ class UiActionFileInfo(BaseModel): """If the object is shared, this is a display name of the share owner.""" shareOwnerId: typing.Optional[str] """If the object is shared, this is the owner ID of the share.""" + instanceId: typing.Optional[str] + """Nextcloud instance ID.""" def to_fs_node(self) -> FsNode: - """Returns created ``FsNode`` from the file info given. - - .. note:: :py:attr:`~nc_py_api.files.FsNode.file_id` in this case is ``without`` **instance_id** - and equal to :py:attr:`~nc_py_api.files.FsNodeInfo.fileid`. - """ + """Returns usual :py:class:`~nc_py_api.files.FsNode` created from this class.""" user_path = os.path.join(self.directory, self.name).rstrip("/") is_dir = bool(self.fileType.lower() == "dir") if is_dir: user_path += "/" full_path = os.path.join(f"files/{self.userId}", user_path.lstrip("/")) + file_id = str(self.fileId).rjust(8, "0") permissions = "S" if self.shareOwnerId else "" if self.permissions & FilePermissions.PERMISSION_SHARE: @@ -71,7 +68,7 @@ def to_fs_node(self) -> FsNode: content_length=0 if is_dir else self.size, permissions=permissions, favorite=bool(self.favorite.lower() == "true"), - file_id=self.fileId, + file_id=file_id + self.instanceId if self.instanceId else file_id, fileid=self.fileId, last_modified=datetime.utcfromtimestamp(self.mtime).replace(tzinfo=timezone.utc), ) @@ -91,6 +88,8 @@ class UiFileActionHandlerInfo(BaseModel): class _UiFilesActionsAPI: """API for the drop-down menu in Nextcloud **Files app**.""" + _ep_suffix: str = "files/actions/menu" + def __init__(self, session: NcSessionApp): self._session = session @@ -109,14 +108,14 @@ def register(self, name: str, display_name: str, callback_url: str, **kwargs) -> "action_handler": callback_url, }, } - self._session.ocs(method="POST", path=f"{self._session.ae_url}/{ENDPOINT_SUFFIX}", json=params) + self._session.ocs(method="POST", path=f"{self._session.ae_url}/{self._ep_suffix}", json=params) def unregister(self, name: str, not_fail=True) -> None: """Removes files dropdown menu element.""" require_capabilities("app_ecosystem_v2", self._session.capabilities) params = {"fileActionMenuName": name} try: - self._session.ocs(method="DELETE", path=f"{self._session.ae_url}/{ENDPOINT_SUFFIX}", json=params) + self._session.ocs(method="DELETE", path=f"{self._session.ae_url}/{self._ep_suffix}", json=params) except NextcloudExceptionNotFound as e: if not not_fail: raise e from None diff --git a/tests/ui_files_test.py b/tests/ui_files_test.py index 5b7e06ab..00c3059f 100644 --- a/tests/ui_files_test.py +++ b/tests/ui_files_test.py @@ -88,6 +88,8 @@ def ui_action_check(directory: str, fs_object: FsNode): permissions += FilePermissions.PERMISSION_DELETE if fs_object.is_shareable: permissions += FilePermissions.PERMISSION_SHARE + fileid_str = str(fs_object.info.fileid) + i = fs_object.file_id.find(fileid_str) file_info = ex_app.UiActionFileInfo( fileId=fs_object.info.fileid, name=fs_object.name, @@ -102,6 +104,7 @@ def ui_action_check(directory: str, fs_object: FsNode): userId=fs_object.user, shareOwner="some_user" if fs_object.is_shared else None, shareOwnerId="some_user_id" if fs_object.is_shared else None, + instanceId=fs_object.file_id[i + len(fileid_str) :], ) fs_node = file_info.to_fs_node() assert isinstance(fs_node, FsNode) @@ -109,7 +112,7 @@ def ui_action_check(directory: str, fs_object: FsNode): assert fs_node.name == fs_object.name assert fs_node.user_path == fs_object.user_path assert fs_node.full_path == fs_object.full_path - assert fs_node.file_id == fs_object.info.fileid + assert fs_node.file_id == fs_object.file_id assert fs_node.is_dir == fs_object.is_dir # assert fs_node.mime == fs_object.mime assert fs_node.info.permissions == fs_object.info.permissions