66from enum import Enum
77
88import ast
9- from typing import Dict , Literal , Any
9+ from typing import Dict , List , Literal , Any , Union
1010from uuid import UUID
1111
1212import geoengine_openapi_client
13+ import geoengine_openapi_client .api
14+ import geoengine_openapi_client .models
15+ import geoengine_openapi_client .models .role
1316
1417from geoengine .auth import get_session
1518from geoengine .datasets import DatasetName
1619from geoengine .error import GeoEngineException
1720from geoengine .layers import LayerCollectionId , LayerId
21+ from geoengine .ml import MlModelName
1822
1923
2024class RoleId :
2125 '''A wrapper for a role id'''
26+ __role_id : UUID
2227
2328 def __init__ (self , role_id : UUID ) -> None :
2429 self .__role_id = role_id
@@ -48,6 +53,48 @@ def __repr__(self) -> str:
4853 return repr (self .__role_id )
4954
5055
56+ class Role :
57+ '''A wrapper for a role'''
58+ name : str
59+ id : RoleId
60+
61+ def __init__ (self , role_id : Union [UUID , RoleId , str ], role_name : str ):
62+ ''' Create a role with name and id '''
63+
64+ if isinstance (role_id , UUID ):
65+ real_id = RoleId (role_id )
66+ elif isinstance (role_id , str ):
67+ real_id = RoleId (UUID (role_id ))
68+ else :
69+ real_id = role_id
70+
71+ self .id = real_id
72+ self .name = role_name
73+
74+ @classmethod
75+ def from_response (cls , response : geoengine_openapi_client .models .role .Role ) -> Role :
76+ '''Parse a http response to an `RoleId`'''
77+
78+ role_id = response .id
79+ role_name = response .name
80+
81+ return Role (role_id , role_name )
82+
83+ def __eq__ (self , other ) -> bool :
84+ '''Checks if two role ids are equal'''
85+ if not isinstance (other , self .__class__ ):
86+ return False
87+
88+ return self .id == other .id and self .name == other .name
89+
90+ def role_id (self ) -> RoleId :
91+ '''get the role id'''
92+ return self .id
93+
94+ def __repr__ (self ) -> str :
95+ return 'id: ' + repr (self .id ) + ', name: ' + repr (self .name )
96+
97+
5198class UserId :
5299 '''A wrapper for a role id'''
53100
@@ -82,11 +129,14 @@ def __repr__(self) -> str:
82129class Resource :
83130 '''A wrapper for a resource id'''
84131
85- def __init__ (self , resource_type : Literal ['dataset' , 'layer' , 'layerCollection' ],
132+ id : str
133+ type : Literal ['dataset' , 'layer' , 'layerCollection' , 'mlModel' , 'project' ]
134+
135+ def __init__ (self , resource_type : Literal ['dataset' , 'layer' , 'layerCollection' , 'mlModel' , 'project' ],
86136 resource_id : str ) -> None :
87137 '''Create a resource id'''
88- self .__type = resource_type
89- self .__id = resource_id
138+ self .type = resource_type
139+ self .id = resource_id
90140
91141 @classmethod
92142 def from_layer_id (cls , layer_id : LayerId ) -> Resource :
@@ -99,25 +149,100 @@ def from_layer_collection_id(cls, layer_collection_id: LayerCollectionId) -> Res
99149 return Resource ('layerCollection' , str (layer_collection_id ))
100150
101151 @classmethod
102- def from_dataset_name (cls , dataset_name : DatasetName ) -> Resource :
103- '''Create a resource id from a dataset id'''
104- return Resource ('dataset' , str (dataset_name ))
152+ def from_dataset_name (cls , dataset_name : Union [DatasetName , str ]) -> Resource :
153+ '''Create a resource id from a dataset name'''
154+ if isinstance (dataset_name , DatasetName ):
155+ dataset_name = str (dataset_name )
156+ return Resource ('dataset' , dataset_name )
157+
158+ @classmethod
159+ def from_ml_model_name (cls , ml_model_name : Union [MlModelName , str ]) -> Resource :
160+ '''Create a resource from an ml model name'''
161+ if isinstance (ml_model_name , MlModelName ):
162+ ml_model_name = str (ml_model_name )
163+ return Resource ('mlModel' , ml_model_name )
105164
106165 def to_api_dict (self ) -> geoengine_openapi_client .Resource :
107166 '''Convert to a dict for the API'''
108167 inner : Any = None
109168
110- if self .__type == "layer" :
111- inner = geoengine_openapi_client .LayerResource (type = "layer" , id = self .__id )
112- elif self .__type == "layerCollection" :
113- inner = geoengine_openapi_client .LayerCollectionResource (type = "layerCollection" , id = self .__id )
114- elif self .__type == "project" :
115- inner = geoengine_openapi_client .ProjectResource (type = "project" , id = self .__id )
116- elif self .__type == "dataset" :
117- inner = geoengine_openapi_client .DatasetResource (type = "dataset" , id = self .__id )
169+ if self .type == "layer" :
170+ inner = geoengine_openapi_client .LayerResource (type = "layer" , id = self .id )
171+ elif self .type == "layerCollection" :
172+ inner = geoengine_openapi_client .LayerCollectionResource (type = "layerCollection" , id = self .id )
173+ elif self .type == "project" :
174+ inner = geoengine_openapi_client .ProjectResource (type = "project" , id = self .id )
175+ elif self .type == "dataset" :
176+ inner = geoengine_openapi_client .DatasetResource (type = "dataset" , id = self .id )
177+ elif self .type == "mlModel" :
178+ inner = geoengine_openapi_client .MlModelResource (type = "mlModel" , id = self .id )
179+ else :
180+ raise KeyError (f"Unknown resource type: { self .type } " )
118181
119182 return geoengine_openapi_client .Resource (inner )
120183
184+ @classmethod
185+ def from_response (cls , response : geoengine_openapi_client .Resource ) -> Resource :
186+ '''Convert to a dict for the API'''
187+ inner : Resource
188+ if isinstance (response .actual_instance , geoengine_openapi_client .LayerResource ):
189+ inner = Resource ('layer' , response .actual_instance .id )
190+ elif isinstance (response .actual_instance , geoengine_openapi_client .LayerCollectionResource ):
191+ inner = Resource ('layerCollection' , response .actual_instance .id )
192+ elif isinstance (response .actual_instance , geoengine_openapi_client .ProjectResource ):
193+ inner = Resource ('project' , response .actual_instance .id )
194+ elif isinstance (response .actual_instance , geoengine_openapi_client .DatasetResource ):
195+ inner = Resource ('dataset' , response .actual_instance .id )
196+ elif isinstance (response .actual_instance , geoengine_openapi_client .MlModelResource ):
197+ inner = Resource ('mlModel' , response .actual_instance .id )
198+ else :
199+ raise KeyError (f"Unknown resource type from API: { response .actual_instance } " )
200+ return inner
201+
202+ def __repr__ (self ):
203+ return 'id: ' + repr (self .id ) + ', type: ' + repr (self .type )
204+
205+ def __eq__ (self , value ):
206+ '''Checks if two listings are equal'''
207+ if not isinstance (value , self .__class__ ):
208+ return False
209+ return self .id == value .id and self .type == value .type
210+
211+
212+ class PermissionListing :
213+ """
214+ PermissionListing
215+ """
216+ permission : Permission
217+ resource : Resource
218+ role : Role
219+
220+ def __init__ (self , permission : Permission , resource : Resource , role : Role ):
221+ ''' Create a PermissionListing '''
222+ self .permission = permission
223+ self .resource = resource
224+ self .role = role
225+
226+ @classmethod
227+ def from_response (cls , response : geoengine_openapi_client .models .PermissionListing ) -> PermissionListing :
228+ ''' Transforms a response PermissionListing to a PermissionListing '''
229+ return PermissionListing (
230+ permission = Permission .from_response (response .permission ),
231+ resource = Resource .from_response (response .resource ),
232+ role = Role .from_response (response .role )
233+ )
234+
235+ def __eq__ (self , other ) -> bool :
236+ '''Checks if two listings are equal'''
237+ if not isinstance (other , self .__class__ ):
238+ return False
239+ return self .permission == other .permission and self .resource == other .resource and self .role == other .role
240+
241+ def __repr__ (self ) -> str :
242+ return 'Role: ' + repr (self .role ) + ', ' \
243+ + 'Resource: ' + repr (self .resource ) + ', ' \
244+ + 'Permission: ' + repr (self .permission )
245+
121246
122247class Permission (str , Enum ):
123248 '''A permission'''
@@ -128,6 +253,10 @@ def to_api_dict(self) -> geoengine_openapi_client.Permission:
128253 '''Convert to a dict for the API'''
129254 return geoengine_openapi_client .Permission (self .value )
130255
256+ @classmethod
257+ def from_response (cls , response : geoengine_openapi_client .Permission ) -> Permission :
258+ return Permission (response )
259+
131260
132261ADMIN_ROLE_ID : RoleId = RoleId (UUID ("d5328854-6190-4af9-ad69-4e74b0961ac9" ))
133262REGISTERED_USER_ROLE_ID : RoleId = RoleId (UUID ("4e8081b6-8aa6-4275-af0c-2fa2da557d28" ))
@@ -164,6 +293,24 @@ def remove_permission(role: RoleId, resource: Resource, permission: Permission,
164293 ))
165294
166295
296+ def list_permissions (resource : Resource , timeout : int = 60 , offset = 0 , limit = 20 ) -> List [PermissionListing ]:
297+ '''Lists the roles and permissions assigned to a ressource'''
298+
299+ session = get_session ()
300+
301+ with geoengine_openapi_client .ApiClient (session .configuration ) as api_client :
302+ permission_api = geoengine_openapi_client .PermissionsApi (api_client )
303+ res = permission_api .get_resource_permissions_handler (
304+ resource_id = resource .id ,
305+ resource_type = resource .type ,
306+ offset = offset ,
307+ limit = limit ,
308+ _request_timeout = timeout
309+ )
310+
311+ return [PermissionListing .from_response (r ) for r in res ]
312+
313+
167314def add_role (name : str , timeout : int = 60 ) -> RoleId :
168315 """Add a new role. Requires admin role."""
169316
0 commit comments