Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 9 additions & 10 deletions nc_py_api/ex_app/ui/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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:
Expand All @@ -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),
)
Expand All @@ -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

Expand All @@ -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
5 changes: 4 additions & 1 deletion tests/ui_files_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -102,14 +104,15 @@ 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)
assert fs_node.etag == fs_object.etag
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
Expand Down