Skip to content

Commit 2989563

Browse files
committed
tenant session settings functions
1 parent 50c6303 commit 2989563

File tree

3 files changed

+185
-1
lines changed

3 files changed

+185
-1
lines changed

descope/management/common.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
from enum import Enum
22
from typing import List, Optional
33

4+
class SessionExiprationUnit(Enum):
5+
MINUTES = "minutes"
6+
HOURS = "hours"
7+
DAYS = "days"
8+
WEEKS = "weeks"
9+
10+
class TenantAuthType(Enum):
11+
NONE = "none"
12+
SAML = "saml"
13+
OIDC = "oidc"
414

515
class AccessType(Enum):
616
OFFLINE = "offline"
@@ -35,6 +45,7 @@ class MgmtV1:
3545
tenant_update_path = "/v1/mgmt/tenant/update"
3646
tenant_delete_path = "/v1/mgmt/tenant/delete"
3747
tenant_load_path = "/v1/mgmt/tenant"
48+
tenant_settings_path = "/v1/mgmt/tenant/settings"
3849
tenant_load_all_path = "/v1/mgmt/tenant/all"
3950
tenant_search_all_path = "/v1/mgmt/tenant/search"
4051

@@ -292,6 +303,42 @@ def associated_tenants_to_dict(associated_tenants: List[AssociatedTenant]) -> li
292303
)
293304
return associated_tenant_list
294305

306+
class tenantSettings:
307+
"""
308+
Represents tenant settings object.
309+
"""
310+
311+
def __init__(
312+
self,
313+
self_provisioning_domains: List[str],
314+
domains: Optional[List[str]] = None,
315+
auth_type: Optional[TenantAuthType] = None,
316+
session_settings_enabled: Optional[bool] = False,
317+
refresh_token_expiration: Optional[int] = None,
318+
refresh_token_expiration_unit: Optional[SessionExiprationUnit] = None,
319+
session_token_expiration: Optional[int] = None,
320+
session_token_expiration_unit: Optional[SessionExiprationUnit] = None,
321+
stepup_token_expiration: Optional[int] = None,
322+
stepup_token_expiration_unit: Optional[SessionExiprationUnit] = None,
323+
enable_inactivity: Optional[bool] = False,
324+
inactivity_time: Optional[int] = None,
325+
inactivity_time_unit: Optional[SessionExiprationUnit] = None,
326+
JITDisabled: Optional[bool] = False,
327+
):
328+
self.domains = domains
329+
self.self_provisioning_domains = self_provisioning_domains
330+
self.auth_type = auth_type
331+
self.session_settings_enabled = session_settings_enabled
332+
self.refresh_token_expiration = refresh_token_expiration
333+
self.refresh_token_expiration_unit = refresh_token_expiration_unit
334+
self.session_token_expiration = session_token_expiration
335+
self.session_token_expiration_unit = session_token_expiration_unit
336+
self.stepup_token_expiration = stepup_token_expiration
337+
self.stepup_token_expiration_unit = stepup_token_expiration_unit
338+
self.enable_inactivity = enable_inactivity
339+
self.inactivity_time = inactivity_time
340+
self.inactivity_time_unit = inactivity_time_unit
341+
self.JITDisabled = JITDisabled
295342

296343
class SAMLIDPAttributeMappingInfo:
297344
"""

descope/management/tenant.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any, List, Optional
22

33
from descope._http_base import HTTPBase
4-
from descope.management.common import MgmtV1
4+
from descope.management.common import MgmtV1, tenantSettings
55

66

77
class Tenant(HTTPBase):
@@ -92,6 +92,27 @@ def update(
9292
),
9393
)
9494

95+
def update_settings(
96+
self,
97+
id: str,
98+
tenant_settings: tenantSettings
99+
):
100+
"""
101+
Update an existing tenant's session settings.
102+
103+
Args:
104+
id (str): The ID of the tenant to update.
105+
session_settings (dict): The session settings to set for the tenant.
106+
107+
Raise:
108+
AuthException: raised if creation operation fails
109+
"""
110+
self._http.post(
111+
MgmtV1.tenant_settings_path,
112+
params={"id": id},
113+
body= tenant_settings,
114+
)
115+
95116
def delete(
96117
self,
97118
id: str,
@@ -134,6 +155,35 @@ def load(
134155
params={"id": id},
135156
)
136157
return response.json()
158+
159+
def load_settings(
160+
self,
161+
id: str,
162+
) -> dict:
163+
"""
164+
Load tenant session settings by id.
165+
166+
Args:
167+
id (str): The ID of the tenant to load session settings for.
168+
169+
Return value (dict):
170+
Return dict in the format
171+
{ "domains":<list[str]>, "selfProvisioningDomains":<list[str]>, "authType":<str>,
172+
"enabled":<bool>, "refreshTokenExpiration":<int>, "refreshTokenExpirationUnit":<str>,
173+
"sessionTokenExpiration":<int>, "sessionTokenExpirationUnit":<str>,
174+
"stepupTokenExpiration":<int>, "stepupTokenExpirationUnit":<str>,
175+
"enableInactivity":<bool>, "inactivityTime":<int>, "inactivityTimeUnit":<str>,
176+
"JITDisabled":<bool> }
177+
Containing the loaded tenant session settings.
178+
179+
Raise:
180+
AuthException: raised if load operation fails
181+
"""
182+
response = self._http.get(
183+
MgmtV1.tenant_settings_path,
184+
params={"id": id},
185+
)
186+
return response.json()
137187

138188
def load_all(
139189
self,

tests/management/test_tenant.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,90 @@ def test_search_all(self):
366366
params=None,
367367
timeout=DEFAULT_TIMEOUT_SECONDS,
368368
)
369+
370+
def test_update_settings(self):
371+
client = DescopeClient(
372+
self.dummy_project_id,
373+
self.public_key_dict,
374+
False,
375+
self.dummy_management_key,
376+
)
377+
378+
# Test failed flows
379+
with patch("requests.post") as mock_post:
380+
mock_post.return_value.ok = False
381+
self.assertRaises(
382+
AuthException,
383+
client.mgmt.tenant.update_settings,
384+
"valid-id",
385+
{},
386+
)
387+
388+
# Test success flow
389+
with patch("requests.post") as mock_post:
390+
mock_post.return_value.ok = True
391+
tenant_settings = {
392+
"domains": ["domain1.com", "domain2.com"],
393+
"authType": "oidc",
394+
"sessionSettingsEnabled": True,
395+
}
396+
self.assertIsNone(
397+
client.mgmt.tenant.update_settings("t1", tenant_settings)
398+
)
399+
mock_post.assert_called_with(
400+
f"{common.DEFAULT_BASE_URL}{MgmtV1.tenant_settings_path}",
401+
headers={
402+
**common.default_headers,
403+
"Authorization": f"Bearer {self.dummy_project_id}:{self.dummy_management_key}",
404+
"x-descope-project-id": self.dummy_project_id,
405+
},
406+
json=tenant_settings,
407+
allow_redirects=False,
408+
verify=True,
409+
params={"id": "t1"},
410+
timeout=DEFAULT_TIMEOUT_SECONDS,
411+
)
412+
413+
def test_load_settings(self):
414+
client = DescopeClient(
415+
self.dummy_project_id,
416+
self.public_key_dict,
417+
False,
418+
self.dummy_management_key,
419+
)
420+
421+
# Test failed flows
422+
with patch("requests.get") as mock_get:
423+
mock_get.return_value.ok = False
424+
self.assertRaises(
425+
AuthException,
426+
client.mgmt.tenant.load_settings,
427+
"valid-id",
428+
)
429+
430+
# Test success flow
431+
with patch("requests.get") as mock_get:
432+
network_resp = mock.Mock()
433+
network_resp.ok = True
434+
network_resp.json.return_value = json.loads(
435+
"""
436+
{"domains": ["domain1.com", "domain2.com"], "authType": "oidc", "sessionSettingsEnabled": true}
437+
"""
438+
)
439+
mock_get.return_value = network_resp
440+
resp = client.mgmt.tenant.load_settings("t1")
441+
self.assertEqual(resp["domains"], ["domain1.com", "domain2.com"])
442+
self.assertEqual(resp["authType"], "oidc")
443+
self.assertEqual(resp["sessionSettingsEnabled"], True)
444+
mock_get.assert_called_with(
445+
f"{common.DEFAULT_BASE_URL}{MgmtV1.tenant_settings_path}",
446+
headers={
447+
**common.default_headers,
448+
"Authorization": f"Bearer {self.dummy_project_id}:{self.dummy_management_key}",
449+
"x-descope-project-id": self.dummy_project_id,
450+
},
451+
params={"id": "t1"},
452+
allow_redirects=True,
453+
verify=True,
454+
timeout=DEFAULT_TIMEOUT_SECONDS,
455+
)

0 commit comments

Comments
 (0)