14
14
# limitations under the License.
15
15
#
16
16
import functools
17
+ from dataclasses import dataclass
18
+
17
19
from typing import Union , List
18
20
19
21
from labkey .server_context import ServerContext
20
22
21
23
SECURITY_CONTROLLER = "security"
22
24
USER_CONTROLLER = "user"
25
+ LOGIN_CONTROLLER = "login"
23
26
24
27
25
28
def activate_users (
@@ -156,7 +159,7 @@ def get_roles(server_context: ServerContext, container_path: str = None):
156
159
url = server_context .build_url (
157
160
SECURITY_CONTROLLER , "getRoles.api" , container_path = container_path
158
161
)
159
- return server_context .make_request (url , None )
162
+ return server_context .make_request (url )
160
163
161
164
162
165
def get_user_by_email (server_context : ServerContext , email : str ):
@@ -167,7 +170,7 @@ def get_user_by_email(server_context: ServerContext, email: str):
167
170
:return:
168
171
"""
169
172
url = server_context .build_url (USER_CONTROLLER , "getUsers.api" )
170
- payload = dict ( includeDeactivatedAccounts = True )
173
+ payload = { " includeDeactivatedAccounts" : True }
171
174
result = server_context .make_request (url , payload )
172
175
173
176
if result is None or result ["users" ] is None :
@@ -184,7 +187,6 @@ def list_groups(
184
187
server_context : ServerContext , include_site_groups : bool = False , container_path : str = None
185
188
):
186
189
url = server_context .build_url (SECURITY_CONTROLLER , "listProjectGroups.api" , container_path )
187
-
188
190
return server_context .make_request (url , {"includeSiteGroups" : include_site_groups })
189
191
190
192
@@ -242,10 +244,68 @@ def reset_password(server_context: ServerContext, email: str, container_path: st
242
244
:return:
243
245
"""
244
246
url = server_context .build_url (SECURITY_CONTROLLER , "adminRotatePassword.api" , container_path )
245
-
246
247
return server_context .make_request (url , {"email" : email })
247
248
248
249
250
+ def impersonate_user (
251
+ server_context : ServerContext ,
252
+ user_id : int = None ,
253
+ email : str = None ,
254
+ container_path : str = None ,
255
+ ):
256
+ """
257
+ For site-admins or project-admins only, start impersonating a user.
258
+
259
+ Admins may impersonate other users to perform actions on their behalf.
260
+ Site users may impersonate any user in any project. Project admins must
261
+ execute this command in a project in which they have admin permission
262
+ and may impersonate any user that has access to the project.
263
+
264
+ To finish an impersonation session use `stop_impersonating`.
265
+
266
+ :param user_id: to impersonate (must supply this or email)
267
+ :param email: to impersonate (must supply this or user_id)
268
+ :param container_path: in which to impersonate the user
269
+ """
270
+ if email is None and user_id is None :
271
+ raise ValueError ("Must supply either [email] or [user_id]" )
272
+
273
+ url = server_context .build_url (USER_CONTROLLER , "impersonateUser.api" , container_path )
274
+ return server_context .make_request (url , {"userId" : user_id , "email" : email })
275
+
276
+
277
+ def stop_impersonating (server_context : ServerContext ):
278
+ """
279
+ Stop impersonating a user while keeping the original user logged in.
280
+ """
281
+ url = server_context .build_url (LOGIN_CONTROLLER , "stopImpersonating.api" )
282
+ return server_context .make_request (url )
283
+
284
+
285
+ @dataclass
286
+ class WhoAmI :
287
+ id : int
288
+ email : str
289
+ display_name : str
290
+ impersonated : str
291
+ CSRF : str
292
+
293
+
294
+ def who_am_i (server_context : ServerContext ) -> WhoAmI :
295
+ """
296
+ Calls the whoami API and returns a WhoAmI object.
297
+ """
298
+ url = server_context .build_url ("login" , "whoami.api" )
299
+ response = server_context .make_request (url )
300
+ return WhoAmI (
301
+ response ["id" ],
302
+ response ["email" ],
303
+ response ["displayName" ],
304
+ response ["impersonated" ],
305
+ response ["CSRF" ],
306
+ )
307
+
308
+
249
309
def __make_security_group_api_request (
250
310
server_context : ServerContext ,
251
311
api : str ,
@@ -378,3 +438,15 @@ def remove_from_role(
378
438
@functools .wraps (reset_password )
379
439
def reset_password (self , email : str , container_path : str = None ):
380
440
return reset_password (self .server_context , email , container_path )
441
+
442
+ @functools .wraps (impersonate_user )
443
+ def impersonate_user (self , user_id : int = None , email : str = None , container_path : str = None ):
444
+ return impersonate_user (self .server_context , user_id , email , container_path )
445
+
446
+ @functools .wraps (stop_impersonating )
447
+ def stop_impersonating (self ):
448
+ return stop_impersonating (self .server_context )
449
+
450
+ @functools .wraps (who_am_i )
451
+ def who_am_i (self ):
452
+ return who_am_i (self .server_context )
0 commit comments