From 881af3d3318881467bd621e569d40c0f099106a6 Mon Sep 17 00:00:00 2001 From: Alexander Piskun Date: Sun, 15 Oct 2023 21:03:33 +0300 Subject: [PATCH 1/4] fixed LDAP user_id bug Signed-off-by: Alexander Piskun --- CHANGELOG.md | 3 ++- nc_py_api/_session.py | 36 +++++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db302d5..0eebdfe9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ This release contains some breaking changes in `users`, `notifications` API. ### Added -- `__repr__` method added for most objects(previously it was only present for `FsNode`). +- `__repr__` method added for most objects(previously it was only present for `FsNode`). #147 ### Changed @@ -21,6 +21,7 @@ This release contains some breaking changes in `users`, `notifications` API. ### Fixed - `users.get_details` with empty parameter in some cases was raised exception. +- ClientMode: in case when LDAP was used as user backend, user login differs from user_id and most API failed with 404. #148 ## [0.3.1 - 2023-10-07] diff --git a/nc_py_api/_session.py b/nc_py_api/_session.py index 420ffb50..88c6c376 100644 --- a/nc_py_api/_session.py +++ b/nc_py_api/_session.py @@ -134,15 +134,15 @@ class NcSessionBasic(ABC): adapter: Client adapter_dav: Client cfg: BasicConfig - user: str custom_headers: dict - _capabilities: dict response_headers: HttpxHeaders + _user: str + _capabilities: dict @abstractmethod def __init__(self, **kwargs): self._capabilities = {} - self.user = kwargs.get("user", "") + self._user = kwargs.get("user", "") self.custom_headers = kwargs.get("headers", {}) self.limits = Limits(max_keepalive_connections=20, max_connections=20, keepalive_expiry=60.0) self.init_adapter() @@ -168,7 +168,7 @@ def _get_stream(self, path_params: str, headers: dict, **kwargs) -> Iterator[Res "GET", f"{self.cfg.endpoint}{path_params}", headers=headers, timeout=timeout, **kwargs ) - def request_json( + def request( self, method: str, path: str, @@ -176,14 +176,25 @@ def request_json( data: Optional[Union[bytes, str]] = None, json: Optional[Union[dict, list]] = None, **kwargs, - ) -> dict: + ): method = method.upper() if params is None: params = {} params.update({"format": "json"}) headers = kwargs.pop("headers", {}) data_bytes = self.__data_to_bytes(headers, data, json) - r = self._ocs(method, f"{quote(path)}?{urlencode(params, True)}", headers, data_bytes, not_parse=True) + return self._ocs(method, f"{quote(path)}?{urlencode(params, True)}", headers, data_bytes, not_parse=True) + + def request_json( + self, + method: str, + path: str, + params: Optional[dict] = None, + data: Optional[Union[bytes, str]] = None, + json: Optional[Union[dict, list]] = None, + **kwargs, + ) -> dict: + r = self.request(method, path, params, data, json, **kwargs) return loads(r.text) if r.status_code != 304 else {} def ocs( @@ -319,6 +330,17 @@ def _create_adapter(self) -> Client: def update_server_info(self) -> None: self._capabilities = self.ocs(method="GET", path="/ocs/v1.php/cloud/capabilities") + @property + def user(self) -> str: + """Current user ID. Can be different from login name.""" + if not self._user: + self._user = self.ocs(method="GET", path="/ocs/v1.php/cloud/user")["id"] + return self._user + + @user.setter + def user(self, value: str): + self._user = value + @property def capabilities(self) -> dict: if not self._capabilities: @@ -360,7 +382,7 @@ class NcSession(NcSessionBasic): def __init__(self, **kwargs): self.cfg = Config(**kwargs) - super().__init__(user=self.cfg.auth[0]) + super().__init__() def _create_adapter(self) -> Client: return Client(auth=self.cfg.auth, follow_redirects=True, limits=self.limits, verify=self.cfg.options.nc_cert) From bde440eaad4fee83bc139d64f1f180db5dd60320 Mon Sep 17 00:00:00 2001 From: Alexander Piskun Date: Sun, 15 Oct 2023 22:20:06 +0300 Subject: [PATCH 2/4] fixed infinite recursion Signed-off-by: Alexander Piskun --- nc_py_api/_session.py | 2 +- nc_py_api/nextcloud.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nc_py_api/_session.py b/nc_py_api/_session.py index 88c6c376..0e5fc461 100644 --- a/nc_py_api/_session.py +++ b/nc_py_api/_session.py @@ -423,7 +423,7 @@ def _create_adapter(self) -> Client: return adapter def sign_request(self, headers: dict) -> None: - headers["AUTHORIZATION-APP-API"] = b64encode(f"{self.user}:{self.cfg.app_secret}".encode("UTF=8")) + headers["AUTHORIZATION-APP-API"] = b64encode(f"{self._user}:{self.cfg.app_secret}".encode("UTF=8")) def sign_check(self, request: Request) -> None: headers = { diff --git a/nc_py_api/nextcloud.py b/nc_py_api/nextcloud.py index dd70f50a..d1a8f17b 100644 --- a/nc_py_api/nextcloud.py +++ b/nc_py_api/nextcloud.py @@ -122,7 +122,7 @@ def __init__(self, **kwargs): @property def user(self) -> str: - """Returns current user name.""" + """Returns current user ID.""" return self._session.user @@ -184,7 +184,7 @@ def scope_allowed(self, scope: ApiScope) -> bool: @property def user(self) -> str: - """Property containing the current username. + """Property containing the current user ID. *System Applications* can set it and impersonate the user. For normal applications, it is set automatically. """ From c907a26baab2a8eca450285082a50515766b10a4 Mon Sep 17 00:00:00 2001 From: Alexander Piskun Date: Sun, 15 Oct 2023 22:42:27 +0300 Subject: [PATCH 3/4] do not trigger `user_id` value update for NextcloudApp Signed-off-by: Alexander Piskun --- nc_py_api/_session.py | 2 +- tests/actual_tests/user_status_test.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nc_py_api/_session.py b/nc_py_api/_session.py index 0e5fc461..5adf70ec 100644 --- a/nc_py_api/_session.py +++ b/nc_py_api/_session.py @@ -333,7 +333,7 @@ def update_server_info(self) -> None: @property def user(self) -> str: """Current user ID. Can be different from login name.""" - if not self._user: + if not self._user and isinstance(self, NcSession): # do not trigger for NextcloudApp self._user = self.ocs(method="GET", path="/ocs/v1.php/cloud/user")["id"] return self._user diff --git a/tests/actual_tests/user_status_test.py b/tests/actual_tests/user_status_test.py index 8f05f699..abd2451e 100644 --- a/tests/actual_tests/user_status_test.py +++ b/tests/actual_tests/user_status_test.py @@ -106,14 +106,14 @@ def test_set_predefined(nc, clear_at): @pytest.mark.require_nc(major=27) -def test_get_back_status_from_from_empty_user(nc): - orig_user = nc._session.user - nc._session.user = "" +def test_get_back_status_from_from_empty_user(nc_app): + orig_user = nc_app._session.user + nc_app._session.user = "" try: with pytest.raises(ValueError): - nc.user_status.get_backup_status("") + nc_app.user_status.get_backup_status("") finally: - nc._session.user = orig_user + nc_app._session.user = orig_user @pytest.mark.require_nc(major=27) From 1e2c5884748e53830b75a2321f4f2ec1f101f363 Mon Sep 17 00:00:00 2001 From: Alexander Piskun Date: Sun, 15 Oct 2023 23:04:04 +0300 Subject: [PATCH 4/4] slightly more readable code Signed-off-by: Alexander Piskun --- nc_py_api/_session.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nc_py_api/_session.py b/nc_py_api/_session.py index 5adf70ec..8072c58f 100644 --- a/nc_py_api/_session.py +++ b/nc_py_api/_session.py @@ -332,8 +332,8 @@ def update_server_info(self) -> None: @property def user(self) -> str: - """Current user ID. Can be different from login name.""" - if not self._user and isinstance(self, NcSession): # do not trigger for NextcloudApp + """Current user ID. Can be different from the login name.""" + if isinstance(self, NcSession) and not self._user: # do not trigger for NextcloudApp self._user = self.ocs(method="GET", path="/ocs/v1.php/cloud/user")["id"] return self._user