Skip to content

Commit 52fd216

Browse files
authored
Improve file operation permissions and path resolution logic (#332)
* PIM-6080 Add `strict_permission` flag to core file operations This commit introduces an optional `strict_permission` parameter to multiple file operation methods, which enables enhanced permission validation before executing actions like copy, move, upload, delete, and rename. * PIM-6080 Improve permission handling and path resolution logic in core commands This update refines permission error detection, adjusts path resolution to accommodate additional root cases, and improves response handling for task completion with warnings. * PIM-6080 Refactor strict permission error handling This commit streamlines strict permission error detection by introducing helper functions for normalizing responses and mapping errors, improving maintainability and readability of the code. * PIM-6080 Extend permission error mapping and refactor strict permission handling logic This commit adds a comprehensive task error mapping for strict permission validation, introduces a helper function for extracting task error details, and updates logging for improved debugging. * PIM-6080 Remove unused `_is_permission_denied_message` function from core commands * PIM-6080 Simplify strict permission error handling by replacing error maps with sets. * PIM-6080 Add unit tests for strict permission handling in `move` and `mkdir` operations
1 parent 56b5c35 commit 52fd216

File tree

5 files changed

+272
-53
lines changed

5 files changed

+272
-53
lines changed

cterasdk/asynchronous/core/files/browser.py

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ async def public_link(self, path, access='RO', expire_in=30):
142142
"""
143143
return await Link(io.public_link, self._core, path, access, expire_in).a_execute()
144144

145-
async def copy(self, *paths, destination=None, resolver=None, cursor=None, wait=False):
145+
async def copy(self, *paths, destination=None, resolver=None, cursor=None, wait=False, strict_permission=False):
146146
"""
147147
Copy one or more files or folders.
148148
@@ -156,7 +156,16 @@ async def copy(self, *paths, destination=None, resolver=None, cursor=None, wait=
156156
:raises cterasdk.exceptions.io.core.CopyError: Raised on failure copying resources.
157157
"""
158158
try:
159-
return await Copy(io.copy, self._core, wait, *paths, destination=destination, resolver=resolver, cursor=cursor).a_execute()
159+
return await Copy(
160+
io.copy,
161+
self._core,
162+
wait,
163+
*paths,
164+
destination=destination,
165+
resolver=resolver,
166+
cursor=cursor,
167+
strict_permission=strict_permission
168+
).a_execute()
160169
except ValueError:
161170
raise ValueError('Copy destination was not specified.')
162171

@@ -175,7 +184,7 @@ async def permalink(self, path):
175184
class CloudDrive(FileBrowser):
176185
"""Async CloudDrive API with upload and sharing functionality."""
177186

178-
async def upload(self, destination, handle, name=None, size=None):
187+
async def upload(self, destination, handle, name=None, size=None, strict_permission=False):
179188
"""
180189
Upload from file handle.
181190
@@ -187,9 +196,18 @@ async def upload(self, destination, handle, name=None, size=None):
187196
:rtype: str
188197
:raises cterasdk.exceptions.io.core.UploadError: Raised on upload failure.
189198
"""
190-
return await Upload(io.upload, self._core, io.listdir, destination, handle, name, size).a_execute()
199+
return await Upload(
200+
io.upload,
201+
self._core,
202+
io.listdir,
203+
destination,
204+
handle,
205+
name,
206+
size,
207+
strict_permission=strict_permission
208+
).a_execute()
191209

192-
async def upload_file(self, path, destination):
210+
async def upload_file(self, path, destination, strict_permission=False):
193211
"""
194212
Upload a file.
195213
@@ -201,9 +219,15 @@ async def upload_file(self, path, destination):
201219
"""
202220
_, name = commonfs.split_file_directory(path)
203221
with open(path, 'rb') as handle:
204-
return await self.upload(destination, handle, name, commonfs.properties(path)['size'])
222+
return await self.upload(
223+
destination,
224+
handle,
225+
name,
226+
commonfs.properties(path)['size'],
227+
strict_permission=strict_permission
228+
)
205229

206-
async def mkdir(self, path):
230+
async def mkdir(self, path, strict_permission=False):
207231
"""
208232
Create a directory.
209233
@@ -212,9 +236,9 @@ async def mkdir(self, path):
212236
:rtype: str
213237
:raises cterasdk.exceptions.io.core.CreateDirectoryError: Raised on error creating directory.
214238
"""
215-
return await CreateDirectory(io.mkdir, self._core, path).a_execute()
239+
return await CreateDirectory(io.mkdir, self._core, path, strict_permission=strict_permission).a_execute()
216240

217-
async def makedirs(self, path):
241+
async def makedirs(self, path, strict_permission=False):
218242
"""
219243
Recursively create a directory.
220244
@@ -223,9 +247,9 @@ async def makedirs(self, path):
223247
:rtype: str
224248
:raises cterasdk.exceptions.io.core.CreateDirectoryError: Raised on error creating directory.
225249
"""
226-
return await CreateDirectory(io.mkdir, self._core, path, True).a_execute()
250+
return await CreateDirectory(io.mkdir, self._core, path, True, strict_permission=strict_permission).a_execute()
227251

228-
async def rename(self, path, name, *, resolver=None, wait=False):
252+
async def rename(self, path, name, *, resolver=None, wait=False, strict_permission=False):
229253
"""
230254
Rename a file or folder.
231255
@@ -237,9 +261,17 @@ async def rename(self, path, name, *, resolver=None, wait=False):
237261
:rtype: cterasdk.common.object.Object or :class:`cterasdk.lib.tasks.AwaitablePortalTask`
238262
:raises cterasdk.exceptions.io.core.RenameError: Raised on error renaming object.
239263
"""
240-
return await Rename(io.move, self._core, wait, path, name, resolver).a_execute()
264+
return await Rename(
265+
io.move,
266+
self._core,
267+
wait,
268+
path,
269+
name,
270+
resolver,
271+
strict_permission=strict_permission
272+
).a_execute()
241273

242-
async def delete(self, *paths, wait=False):
274+
async def delete(self, *paths, wait=False, strict_permission=False):
243275
"""
244276
Delete one or more files or folders.
245277
@@ -249,7 +281,7 @@ async def delete(self, *paths, wait=False):
249281
:rtype: cterasdk.common.object.Object or :class:`cterasdk.lib.tasks.AwaitablePortalTask`
250282
:raises cterasdk.exceptions.io.core.DeleteError: Raised on error deleting resources.
251283
"""
252-
return await Delete(io.delete, self._core, wait, *paths).a_execute()
284+
return await Delete(io.delete, self._core, wait, *paths, strict_permission=strict_permission).a_execute()
253285

254286
async def undelete(self, *paths, wait=False):
255287
"""
@@ -263,7 +295,7 @@ async def undelete(self, *paths, wait=False):
263295
"""
264296
return await Recover(io.undelete, self._core, wait, *paths).a_execute()
265297

266-
async def move(self, *paths, destination=None, resolver=None, cursor=None, wait=False):
298+
async def move(self, *paths, destination=None, resolver=None, cursor=None, wait=False, strict_permission=False):
267299
"""
268300
Move one or more files or folders.
269301
@@ -277,7 +309,16 @@ async def move(self, *paths, destination=None, resolver=None, cursor=None, wait=
277309
:raises cterasdk.exceptions.io.core.MoveError: Raised on error moving resources.
278310
"""
279311
try:
280-
return await Move(io.move, self._core, wait, *paths, destination=destination, resolver=resolver, cursor=cursor).a_execute()
312+
return await Move(
313+
io.move,
314+
self._core,
315+
wait,
316+
*paths,
317+
destination=destination,
318+
resolver=resolver,
319+
cursor=cursor,
320+
strict_permission=strict_permission
321+
).a_execute()
281322
except ValueError:
282323
raise ValueError('Move destination was not specified.')
283324

0 commit comments

Comments
 (0)