Skip to content

Commit 1a018cf

Browse files
committed
Capture logged-in user's permissions for accessing user folders
Add path utilities to compute sliced paths, resolve relative paths, and verify path relationships Add pre-execution access validation that raises an error before remote file system command Add user permission validation for: handle, handle_many, download, download_many, mkdir, makedirs, listdir, walk, properties, exists, versions, permalink, copy, move, delete, upload, upload_file
1 parent 32e76a0 commit 1a018cf

12 files changed

Lines changed: 250 additions & 244 deletions

File tree

cterasdk/asynchronous/core/files/browser.py

Lines changed: 16 additions & 34 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, strict_permission=False):
145+
async def copy(self, *paths, destination=None, resolver=None, cursor=None, wait=False):
146146
"""
147147
Copy one or more files or folders.
148148
@@ -156,16 +156,7 @@ 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(
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()
159+
return await Copy(io.copy, self._core, wait, *paths, destination=destination, resolver=resolver, cursor=cursor).a_execute()
169160
except ValueError:
170161
raise ValueError('Copy destination was not specified.')
171162

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

187-
async def upload(self, destination, handle, name=None, size=None, strict_permission=False):
178+
async def upload(self, destination, handle, name=None, size=None):
188179
"""
189180
Upload from file handle.
190181
@@ -204,10 +195,10 @@ async def upload(self, destination, handle, name=None, size=None, strict_permiss
204195
handle,
205196
name,
206197
size,
207-
strict_permission=strict_permission
198+
208199
).a_execute()
209200

210-
async def upload_file(self, path, destination, strict_permission=False):
201+
async def upload_file(self, path, destination):
211202
"""
212203
Upload a file.
213204
@@ -224,10 +215,10 @@ async def upload_file(self, path, destination, strict_permission=False):
224215
handle,
225216
name,
226217
commonfs.properties(path)['size'],
227-
strict_permission=strict_permission
218+
228219
)
229220

230-
async def mkdir(self, path, strict_permission=False):
221+
async def mkdir(self, path):
231222
"""
232223
Create a directory.
233224
@@ -236,9 +227,9 @@ async def mkdir(self, path, strict_permission=False):
236227
:rtype: str
237228
:raises cterasdk.exceptions.io.core.CreateDirectoryError: Raised on error creating directory.
238229
"""
239-
return await CreateDirectory(io.mkdir, self._core, path, strict_permission=strict_permission).a_execute()
230+
return await CreateDirectory(io.mkdir, self._core, path, ).a_execute()
240231

241-
async def makedirs(self, path, strict_permission=False):
232+
async def makedirs(self, path):
242233
"""
243234
Recursively create a directory.
244235
@@ -247,9 +238,9 @@ async def makedirs(self, path, strict_permission=False):
247238
:rtype: str
248239
:raises cterasdk.exceptions.io.core.CreateDirectoryError: Raised on error creating directory.
249240
"""
250-
return await CreateDirectory(io.mkdir, self._core, path, True, strict_permission=strict_permission).a_execute()
241+
return await CreateDirectory(io.mkdir, self._core, path, True, ).a_execute()
251242

252-
async def rename(self, path, name, *, resolver=None, wait=False, strict_permission=False):
243+
async def rename(self, path, name, *, resolver=None, wait=False):
253244
"""
254245
Rename a file or folder.
255246
@@ -268,10 +259,10 @@ async def rename(self, path, name, *, resolver=None, wait=False, strict_permissi
268259
path,
269260
name,
270261
resolver,
271-
strict_permission=strict_permission
262+
272263
).a_execute()
273264

274-
async def delete(self, *paths, wait=False, strict_permission=False):
265+
async def delete(self, *paths, wait=False):
275266
"""
276267
Delete one or more files or folders.
277268
@@ -281,7 +272,7 @@ async def delete(self, *paths, wait=False, strict_permission=False):
281272
:rtype: cterasdk.common.object.Object or :class:`cterasdk.lib.tasks.AwaitablePortalTask`
282273
:raises cterasdk.exceptions.io.core.DeleteError: Raised on error deleting resources.
283274
"""
284-
return await Delete(io.delete, self._core, wait, *paths, strict_permission=strict_permission).a_execute()
275+
return await Delete(io.delete, self._core, wait, *paths, ).a_execute()
285276

286277
async def undelete(self, *paths, wait=False):
287278
"""
@@ -295,7 +286,7 @@ async def undelete(self, *paths, wait=False):
295286
"""
296287
return await Recover(io.undelete, self._core, wait, *paths).a_execute()
297288

298-
async def move(self, *paths, destination=None, resolver=None, cursor=None, wait=False, strict_permission=False):
289+
async def move(self, *paths, destination=None, resolver=None, cursor=None, wait=False):
299290
"""
300291
Move one or more files or folders.
301292
@@ -309,16 +300,7 @@ async def move(self, *paths, destination=None, resolver=None, cursor=None, wait=
309300
:raises cterasdk.exceptions.io.core.MoveError: Raised on error moving resources.
310301
"""
311302
try:
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()
303+
return await Move(io.move, self._core, wait, *paths, destination=destination, resolver=resolver, cursor=cursor).a_execute()
322304
except ValueError:
323305
raise ValueError('Move destination was not specified.')
324306

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import logging
2+
3+
from ...core.enum import RoleResolver
4+
from ...core.types import RoleSettings
5+
from .base_command import BaseCommand
6+
7+
8+
logger = logging.getLogger('cterasdk.core')
9+
10+
11+
class Roles(BaseCommand):
12+
"""
13+
Role Settings APIs
14+
"""
15+
16+
@staticmethod
17+
def find(role):
18+
"""
19+
Find Role
20+
"""
21+
options = {k: v for k, v in RoleResolver.__dict__.items() if not k.startswith('_')}
22+
return options.get(role, None)
23+
24+
async def get(self, role):
25+
"""
26+
Get Role
27+
28+
:param str role: Role
29+
:returns: Role settings
30+
:rtype: cterasdk.core.types.RoleSettings
31+
"""
32+
name = Roles.find(role)
33+
if name:
34+
return RoleSettings.from_server_object(await self._core.v1.api.get(f'/rolesSettings/{name}'))
35+
logger.warning('Could not find role. %s', {'role': role})
36+
return None

cterasdk/cio/common.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
11
import urllib.parse
2+
from functools import wraps
23
from pathlib import PurePosixPath
34
from ..common import Object
45
from ..common.utils import utf8_decode
56
from ..convert.serializers import toxmlstr
67

78

9+
def resolver(func):
10+
@wraps(func)
11+
def wrapper(self, p):
12+
if isinstance(p, BasePath):
13+
p = p.reference
14+
elif isinstance(p, str):
15+
pass
16+
else:
17+
raise ValueError(
18+
f"Parameter 'p' must be str or BasePath, got {type(p).__name__}"
19+
)
20+
return func(self, p)
21+
return wrapper
22+
23+
824
class BasePath:
925
"""Base Path for CTERA Portal and CTERA Edge"""
1026

@@ -20,7 +36,7 @@ def __init__(self, scope, reference):
2036
if isinstance(reference, str):
2137
reference = reference.lstrip('/')
2238
self._scope = PurePosixPath(scope)
23-
self._reference = PurePosixPath(reference)
39+
self._reference = PurePosixPath(*reference) if isinstance(reference, tuple) else PurePosixPath(reference)
2440

2541
@property
2642
def scope(self):
@@ -58,6 +74,14 @@ def absolute_encode(self):
5874
def absolute_parent(self):
5975
return self.parent.as_posix()
6076

77+
@resolver
78+
def is_relative_to(self, p):
79+
return self.reference.is_relative_to(p)
80+
81+
@resolver
82+
def relative_to(self, p):
83+
return self.__class__(self.reference.relative_to(p).as_posix()) # pylint: disable=no-value-for-parameter
84+
6185
@property
6286
def extension(self):
6387
return self.reference.suffix
@@ -74,6 +98,14 @@ def join(self, p):
7498
def parts(self):
7599
return self.reference.parts
76100

101+
def __getitem__(self, key):
102+
if isinstance(key, slice):
103+
return self.__class__(self.parts[key])
104+
elif isinstance(key, int):
105+
return self.parts[key]
106+
else:
107+
raise TypeError("Invalid argument type")
108+
77109
def __eq__(self, p):
78110
return self.absolute == p.absolute
79111

0 commit comments

Comments
 (0)