Skip to content

Commit 9243611

Browse files
authored
Merge pull request #222 from dataiku/feature/dss100-sc-80908-per-user-last-activity
[sc-80908] new PAPI to retrieve a user's last activity
2 parents 26f4919 + cc6ce75 commit 9243611

File tree

3 files changed

+109
-12
lines changed

3 files changed

+109
-12
lines changed

dataikuapi/dss/admin.py

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import datetime
2+
13
from .future import DSSFuture
24
import json, warnings
35

@@ -164,11 +166,22 @@ def delete(self):
164166
def get_settings(self):
165167
"""
166168
Gets the settings of the user
169+
167170
:rtype: :class:`DSSUserSettings`
168171
"""
169172
raw = self.client._perform_json("GET", "/admin/users/%s" % self.login)
170173
return DSSUserSettings(self.client, self.login, raw)
171174

175+
def get_activity(self):
176+
"""
177+
Gets the activity of the user
178+
179+
:return: the user's activity
180+
:rtype: :class:`DSSUserActivity`
181+
"""
182+
activity = self.client._perform_json("GET", "/admin/users/%s/activity" % self.login)
183+
return DSSUserActivity(self.client, self.login, activity)
184+
172185
########################################################
173186
# Legacy
174187
########################################################
@@ -224,6 +237,7 @@ def get_client_as(self):
224237
else:
225238
raise ValueError("Don't know how to proxy this client")
226239

240+
227241
class DSSOwnUser(object):
228242
"""
229243
A handle to interact with your own user
@@ -250,8 +264,7 @@ def __init__(self, settings):
250264

251265
def get_raw(self):
252266
"""
253-
:return: the raw settings of the user, as a dict. Modifications made to the returned object
254-
are reflected when saving
267+
:return: the raw settings of the user, as a dict. Modifications made to the returned object are reflected when saving
255268
:rtype: dict
256269
"""
257270
return self.settings
@@ -331,15 +344,15 @@ def admin_properties(self):
331344
"""
332345
The user properties (not editable by the user) for this user. Do not set this property, modify the dict in place
333346
334-
:rtype dict
347+
:rtype: dict
335348
"""
336349
return self.settings["adminProperties"]
337350

338351
@property
339352
def enabled(self):
340353
"""
341354
Whether this user is enabled
342-
:rtype boolean
355+
:rtype: boolean
343356
"""
344357
return self.settings["enabled"]
345358

@@ -365,6 +378,67 @@ def save(self):
365378
self.client._perform_empty("PUT", "/current-user", body = self.settings)
366379

367380

381+
class DSSUserActivity(object):
382+
"""
383+
Activity for a DSS user.
384+
Do not call this directly, use :meth:`DSSUser.get_activity` or :meth:`DSSClient.list_users_activity`
385+
"""
386+
387+
def __init__(self, client, login, activity):
388+
self.client = client
389+
self.login = login
390+
self.activity = activity
391+
392+
def get_raw(self):
393+
"""
394+
Get the raw activity of the user as a dict.
395+
396+
:return: the raw activity
397+
:rtype: dict
398+
"""
399+
return self.activity
400+
401+
@property
402+
def last_successful_login(self):
403+
"""
404+
Get the last successful login of the user as a :class:`datetime.datetime`
405+
406+
Returns None if there was no successful login for this user.
407+
408+
:return: the last successful login
409+
:rtype: :class:`datetime.datetime` or None
410+
"""
411+
timestamp = self.activity["lastSuccessfulLogin"]
412+
return datetime.datetime.fromtimestamp(timestamp / 1000) if timestamp > 0 else None
413+
414+
@property
415+
def last_failed_login(self):
416+
"""
417+
Get the last failed login of the user as a :class:`datetime.datetime`
418+
419+
Returns None if there were no failed login for this user.
420+
421+
:return: the last failed login
422+
:rtype: :class:`datetime.datetime` or None
423+
"""
424+
timestamp = self.activity["lastFailedLogin"]
425+
return datetime.datetime.fromtimestamp(timestamp / 1000) if timestamp > 0 else None
426+
427+
@property
428+
def last_session_activity(self):
429+
"""
430+
Get the last session activity of the user as a :class:`datetime.datetime`, i.e. the last time
431+
the user opened a new DSS tab or refreshed his session.
432+
433+
Returns None if there is no session activity yet.
434+
435+
:return: the last session activity
436+
:rtype: :class:`datetime.datetime` or None
437+
"""
438+
timestamp = self.activity["lastSessionActivity"]
439+
return datetime.datetime.fromtimestamp(timestamp / 1000) if timestamp > 0 else None
440+
441+
368442
class DSSGroup(object):
369443
"""
370444
A group on the DSS instance.

dataikuapi/dss/scenario.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,17 @@ def get_run(self, run_id):
134134
def get_status(self):
135135
"""
136136
Returns the status of this scenario
137-
:rtype :class:`DSSScenarioStatus`
137+
138+
:rtype: :class:`DSSScenarioStatus`
138139
"""
139140
data = self.client._perform_json("GET", "/projects/%s/scenarios/%s/light" % (self.project_key, self.id))
140141
return DSSScenarioStatus(self, data)
141142

142143
def get_settings(self):
143144
"""
144145
Returns the settings of this scenario
145-
:rtype :class:`StepBasedDSSScenarioSettings` or :class:`PythonScriptBasedScenarioSettings`
146+
147+
:rtype: :class:`StepBasedScenarioSettings` or :class:`PythonScriptBasedScenarioSettings`
146148
"""
147149
data = self.client._perform_json("GET", "/projects/%s/scenarios/%s" % (self.project_key, self.id))
148150

dataikuapi/dssclient.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from .dss.project import DSSProject
1111
from .dss.app import DSSApp
1212
from .dss.plugin import DSSPlugin
13-
from .dss.admin import DSSUser, DSSOwnUser, DSSGroup, DSSConnection, DSSGeneralSettings, DSSCodeEnv, DSSGlobalApiKey, DSSCluster, DSSGlobalUsageSummary, DSSInstanceVariables
13+
from .dss.admin import DSSUser, DSSUserActivity, DSSOwnUser, DSSGroup, DSSConnection, DSSGeneralSettings, DSSCodeEnv, DSSGlobalApiKey, DSSCluster, DSSGlobalUsageSummary, DSSInstanceVariables
1414
from .dss.meaning import DSSMeaning
1515
from .dss.sqlquery import DSSSQLQuery
1616
from .dss.discussion import DSSObjectDiscussions
@@ -329,17 +329,21 @@ def sql_query(self, query, connection=None, database=None, dataset_full_name=Non
329329
# Users
330330
########################################################
331331

332-
def list_users(self):
332+
def list_users(self, as_objects=False):
333333
"""
334334
List all users setup on the DSS instance
335335
336336
Note: this call requires an API key with admin rights
337337
338-
:return: A list of users, as a list of dicts
339-
:rtype: list of dicts
338+
:return: A list of users, as a list of :class:`dataikuapi.dss.admin.DSSUser` if as_objects is True, else as a list of dicts
339+
:rtype: list of :class:`dataikuapi.dss.admin.DSSUser` or list of dicts
340340
"""
341-
return self._perform_json(
342-
"GET", "/admin/users/")
341+
users = self._perform_json("GET", "/admin/users/")
342+
343+
if as_objects:
344+
return [DSSUser(self, user["login"]) for user in users]
345+
else:
346+
return users
343347

344348
def get_user(self, login):
345349
"""
@@ -382,6 +386,23 @@ def create_user(self, login, password, display_name='', source_type='LOCAL', gro
382386
def get_own_user(self):
383387
return DSSOwnUser(self)
384388

389+
def list_users_activity(self, enabled_users_only=False):
390+
"""
391+
List all users activity
392+
393+
Note: this call requires an API key with admin rights
394+
395+
:return: A list of user activity logs, as a list of :class:`dataikuapi.dss.admin.DSSUserActivity` if as_objects is True, else as a list of dict
396+
:rtype: list of :class:`dataikuapi.dss.admin.DSSUserActivity` or a list of dict
397+
"""
398+
params = {
399+
"enabledUsersOnly": enabled_users_only
400+
}
401+
all_activity = self._perform_json("GET", "/admin/users-activity", params=params)
402+
403+
return [DSSUserActivity(self, user_activity["login"], user_activity) for user_activity in all_activity]
404+
405+
385406
########################################################
386407
# Groups
387408
########################################################

0 commit comments

Comments
 (0)