Skip to content

Commit 852cb6c

Browse files
authored
Merge branch 'main' into renovate/actions-setup-python-6.x
2 parents 833ad20 + 8086edc commit 852cb6c

File tree

15 files changed

+405
-35
lines changed

15 files changed

+405
-35
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
- macos-latest
3232
- windows-latest
3333
steps:
34-
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
34+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
3535
with:
3636
fetch-depth: 0
3737
- name: Setup python for test ${{ matrix.py }}
@@ -64,7 +64,7 @@ jobs:
6464
env:
6565
COVERAGE_FILE: "coverage"
6666
steps:
67-
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
67+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
6868

6969
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
7070
id: download
@@ -92,7 +92,7 @@ jobs:
9292
name: gitleaks
9393
runs-on: ubuntu-latest
9494
steps:
95-
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
95+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
9696
with:
9797
fetch-depth: 0
9898
- uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2.3.9

.github/workflows/python-publish.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- name: Checkout
17-
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
17+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
1818
- name: Setup
1919
uses: descope/.github/.github/actions/python/poetry/setup@main
2020
with:

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ repos:
5252
- id: tox-ini-fmt
5353
args: ["-p", "type"]
5454
- repo: https://github.com/gitleaks/gitleaks
55-
rev: v8.29.1
55+
rev: v8.30.0
5656
hooks:
5757
- id: gitleaks
5858
- repo: local

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -975,16 +975,18 @@ descope_client.mgmt.role.create(
975975
name="My Role",
976976
description="Optional description to briefly explain what this role allows.",
977977
permission_names=["My Updated Permission"],
978-
tenant_id="Optionally scope this role for this specific tenant. If left empty, the role will be available to all tenants."
978+
tenant_id="Optionally scope this role for this specific tenant. If left empty, the role will be available to all tenants.",
979+
private=False # Optional, marks this role as private role
979980
)
980981

981982
# Update will override all fields as is. Use carefully.
982983
descope_client.mgmt.role.update(
983984
name="My Role",
984985
new_name="My Updated Role",
985986
description="A revised description",
986-
permission_names=["My Updated Permission", "Another Permission"]
987-
tenant_id="The tenant ID to which this role is associated, leave empty, if role is a global one"
987+
permission_names=["My Updated Permission", "Another Permission"],
988+
tenant_id="The tenant ID to which this role is associated, leave empty, if role is a global one",
989+
private=True # Optional, marks this role as private role
988990
)
989991

990992
# Role deletion cannot be undone. Use carefully.

descope/management/authz.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def create_relations(
181181
"tenants": ["t1", "t2"],
182182
"roles": ["r1", "r2"],
183183
"text": "full-text-search",
184-
"statuses": ["enabled|disabled|invited"],
184+
"statuses": ["enabled|disabled|invited|expired"],
185185
"ssoOnly": True|False,
186186
"withTestUser": True|False,
187187
"customAttributes": {

descope/management/common.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from enum import Enum
2-
from typing import List, Optional
2+
from typing import Dict, List, Optional, Any
33

44

55
class SessionExpirationUnit(Enum):
@@ -15,6 +15,51 @@ class TenantAuthType(Enum):
1515
OIDC = "oidc"
1616

1717

18+
class SSOSetupSuiteSettingsDisabledFeatures:
19+
def __init__(
20+
self,
21+
saml: bool = False,
22+
oidc: bool = False,
23+
scim: bool = False,
24+
sso_domains: bool = False,
25+
group_mapping: bool = False,
26+
):
27+
self.saml = saml
28+
self.oidc = oidc
29+
self.scim = scim
30+
self.sso_domains = sso_domains
31+
self.group_mapping = group_mapping
32+
33+
def to_dict(self) -> Dict[str, bool]:
34+
return {
35+
"saml": self.saml,
36+
"oidc": self.oidc,
37+
"scim": self.scim,
38+
"ssoDomains": self.sso_domains,
39+
"groupMapping": self.group_mapping,
40+
}
41+
42+
43+
class SSOSetupSuiteSettings:
44+
def __init__(
45+
self,
46+
enabled: bool,
47+
style_id: Optional[str] = None,
48+
disabled_features: Optional[SSOSetupSuiteSettingsDisabledFeatures] = None,
49+
):
50+
self.enabled = enabled
51+
self.style_id = style_id
52+
self.disabled_features = disabled_features
53+
54+
def to_dict(self) -> Dict[str, Any]:
55+
result: Dict[str, Any] = {"enabled": self.enabled}
56+
if self.style_id is not None:
57+
result["styleId"] = self.style_id
58+
if self.disabled_features is not None:
59+
result["disabledFeatures"] = self.disabled_features.to_dict()
60+
return result
61+
62+
1863
class AccessType(Enum):
1964
OFFLINE = "offline"
2065
ONLINE = "online"

descope/management/role.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ def create(
1414
permission_names: Optional[List[str]] = None,
1515
tenant_id: Optional[str] = None,
1616
default: Optional[bool] = None,
17+
private: Optional[bool] = None,
1718
):
1819
"""
1920
Create a new role.
@@ -24,6 +25,7 @@ def create(
2425
permission_names (List[str]): Optional list of names of permissions this role grants.
2526
tenant_id (str): Optional tenant ID to create the role in.
2627
default (bool): Optional marks this role as default role.
28+
private (bool): Optional marks this role as private role.
2729
2830
Raise:
2931
AuthException: raised if creation operation fails
@@ -38,6 +40,7 @@ def create(
3840
"permissionNames": permission_names,
3941
"tenantId": tenant_id,
4042
"default": default,
43+
"private": private,
4144
},
4245
)
4346

@@ -49,6 +52,7 @@ def update(
4952
permission_names: Optional[List[str]] = None,
5053
tenant_id: Optional[str] = None,
5154
default: Optional[bool] = None,
55+
private: Optional[bool] = None,
5256
):
5357
"""
5458
Update an existing role with the given various fields. IMPORTANT: All parameters are used as overrides
@@ -61,6 +65,7 @@ def update(
6165
permission_names (List[str]): Optional list of names of permissions this role grants.
6266
tenant_id (str): Optional tenant ID to update the role in.
6367
default (bool): Optional marks this role as default role.
68+
private (bool): Optional marks this role as private role.
6469
6570
Raise:
6671
AuthException: raised if update operation fails
@@ -75,6 +80,7 @@ def update(
7580
"permissionNames": permission_names,
7681
"tenantId": tenant_id,
7782
"default": default,
83+
"private": private,
7884
},
7985
)
8086

descope/management/sso_settings.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ def __init__(
123123
attribute_mapping: Optional[AttributeMapping] = None,
124124
role_mappings: Optional[List[RoleMapping]] = None,
125125
default_sso_roles: Optional[List[str]] = None,
126+
idp_additional_certs: Optional[List[str]] = None,
126127
# NOTICE - the following fields should be overridden only in case of SSO migration, otherwise, do not modify these fields
127128
sp_acs_url: Optional[str] = None,
128129
sp_entity_id: Optional[str] = None,
@@ -133,6 +134,7 @@ def __init__(
133134
self.attribute_mapping = attribute_mapping
134135
self.role_mappings = role_mappings
135136
self.default_sso_roles = default_sso_roles
137+
self.idp_additional_certs = idp_additional_certs
136138
self.sp_acs_url = sp_acs_url
137139
self.sp_entity_id = sp_entity_id
138140

@@ -174,7 +176,7 @@ def load_settings(
174176
Return value (dict):
175177
Containing the loaded SSO settings information.
176178
Return dict in the format:
177-
{"tenant": {"id": "T2AAAA", "name": "myTenantName", "selfProvisioningDomains": [], "customAttributes": {}, "authType": "saml", "domains": ["lulu", "kuku"]}, "saml": {"idpEntityId": "", "idpSSOUrl": "", "idpCertificate": "", "idpMetadataUrl": "https://dummy.com/metadata", "spEntityId": "", "spACSUrl": "", "spCertificate": "", "attributeMapping": {"name": "name", "email": "email", "username": "", "phoneNumber": "phone", "group": "", "givenName": "", "middleName": "", "familyName": "", "picture": "", "customAttributes": {}}, "groupsMapping": [], "redirectUrl": ""}, "oidc": {"name": "", "clientId": "", "clientSecret": "", "redirectUrl": "", "authUrl": "", "tokenUrl": "", "userDataUrl": "", "scope": [], "JWKsUrl": "", "userAttrMapping": {"loginId": "sub", "username": "", "name": "name", "email": "email", "phoneNumber": "phone_number", "verifiedEmail": "email_verified", "verifiedPhone": "phone_number_verified", "picture": "picture", "givenName": "given_name", "middleName": "middle_name", "familyName": "family_name"}, "manageProviderTokens": False, "callbackDomain": "", "prompt": [], "grantType": "authorization_code", "issuer": ""}}
179+
{"tenant": {"id": "T2AAAA", "name": "myTenantName", "selfProvisioningDomains": [], "customAttributes": {}, "authType": "saml", "domains": ["lulu", "kuku"]}, "saml": {"idpEntityId": "", "idpSSOUrl": "", "idpCertificate": "", "idpAdditionalCertificates": [], "idpMetadataUrl": "https://dummy.com/metadata", "spEntityId": "", "spACSUrl": "", "spCertificate": "", "attributeMapping": {"name": "name", "email": "email", "username": "", "phoneNumber": "phone", "group": "", "givenName": "", "middleName": "", "familyName": "", "picture": "", "customAttributes": {}}, "groupsMapping": [], "redirectUrl": ""}, "oidc": {"name": "", "clientId": "", "clientSecret": "", "redirectUrl": "", "authUrl": "", "tokenUrl": "", "userDataUrl": "", "scope": [], "JWKsUrl": "", "userAttrMapping": {"loginId": "sub", "username": "", "name": "name", "email": "email", "phoneNumber": "phone_number", "verifiedEmail": "email_verified", "verifiedPhone": "phone_number_verified", "picture": "picture", "givenName": "given_name", "middleName": "middle_name", "familyName": "family_name"}, "manageProviderTokens": False, "callbackDomain": "", "prompt": [], "grantType": "authorization_code", "issuer": ""}}
178180
179181
Raise:
180182
AuthException: raised if load configuration operation fails
@@ -537,6 +539,7 @@ def _compose_configure_saml_settings_body(
537539
"idpUrl": settings.idp_url,
538540
"entityId": settings.idp_entity_id,
539541
"idpCert": settings.idp_cert,
542+
"idpAdditionalCerts": settings.idp_additional_certs,
540543
"spACSUrl": settings.sp_acs_url,
541544
"spEntityId": settings.sp_entity_id,
542545
"attributeMapping": attr_mapping,

descope/management/tenant.py

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

33
from descope._http_base import HTTPBase
4-
from descope.management.common import MgmtV1, SessionExpirationUnit, TenantAuthType
4+
from descope.management.common import (
5+
MgmtV1,
6+
SessionExpirationUnit,
7+
SSOSetupSuiteSettings,
8+
TenantAuthType,
9+
)
510

611

712
class Tenant(HTTPBase):
@@ -109,6 +114,7 @@ def update_settings(
109114
inactivity_time: Optional[int] = None,
110115
inactivity_time_unit: Optional[SessionExpirationUnit] = None,
111116
JITDisabled: Optional[bool] = None,
117+
sso_setup_suite_settings: Optional[SSOSetupSuiteSettings] = None,
112118
):
113119
"""
114120
Update an existing tenant's session settings.
@@ -120,15 +126,16 @@ def update_settings(
120126
auth_type (Optional[TenantAuthType]): Authentication type for the tenant.
121127
session_settings_enabled (Optional[bool]): Whether session settings are enabled.
122128
refresh_token_expiration (Optional[int]): Expiration time for refresh tokens.
123-
refresh_token_expiration_unit (Optional[SessionExiprationUnit]): Unit for refresh token expiration.
129+
refresh_token_expiration_unit (Optional[SessionExpirationUnit]): Unit for refresh token expiration.
124130
session_token_expiration (Optional[int]): Expiration time for session tokens.
125-
session_token_expiration_unit (Optional[SessionExiprationUnit]): Unit for session token expiration.
131+
session_token_expiration_unit (Optional[SessionExpirationUnit]): Unit for session token expiration.
126132
stepup_token_expiration (Optional[int]): Expiration time for step-up tokens.
127-
stepup_token_expiration_unit (Optional[SessionExiprationUnit]): Unit for step-up token expiration.
133+
stepup_token_expiration_unit (Optional[SessionExpirationUnit]): Unit for step-up token expiration.
128134
enable_inactivity (Optional[bool]): Whether inactivity timeout is enabled.
129135
inactivity_time (Optional[int]): Inactivity timeout duration.
130-
inactivity_time_unit (Optional[SessionExiprationUnit]): Unit for inactivity timeout.
136+
inactivity_time_unit (Optional[SessionExpirationUnit]): Unit for inactivity timeout.
131137
JITDisabled (Optional[bool]): Whether JIT is disabled.
138+
sso_setup_suite_settings (Optional[SSOSetupSuiteSettings]): SSO Setup Suite configuration.
132139
133140
Raise:
134141
AuthException: raised if update operation fails
@@ -149,6 +156,9 @@ def update_settings(
149156
"inactivityTime": inactivity_time,
150157
"inactivityTimeUnit": inactivity_time_unit,
151158
"JITDisabled": JITDisabled,
159+
"ssoSetupSuiteSettings": (
160+
sso_setup_suite_settings.to_dict() if sso_setup_suite_settings else None
161+
),
152162
}
153163

154164
body = {k: v for k, v in body.items() if v is not None}
@@ -215,7 +225,7 @@ def load_settings(
215225
"sessionTokenExpiration":<int>, "sessionTokenExpirationUnit":<str>,
216226
"stepupTokenExpiration":<int>, "stepupTokenExpirationUnit":<str>,
217227
"enableInactivity":<bool>, "inactivityTime":<int>, "inactivityTimeUnit":<str>,
218-
"JITDisabled":<bool> }
228+
"JITDisabled":<bool>, "ssoSetupSuiteSettings":<dict> }
219229
Containing the loaded tenant session settings.
220230
221231
Raise:

descope/management/user.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ def patch(
438438
picture (str): Optional url for user picture
439439
custom_attributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console app
440440
sso_app_ids (List[str]): Optional, list of SSO applications IDs to be associated with the user.
441-
status (str): Optional status field. Can be one of: "enabled", "disabled", "invited".
441+
status (str): Optional status field. Can be one of: "enabled", "disabled", "invited", "expired".
442442
test (bool, optional): Set to True to update a test user. Defaults to False.
443443
444444
Return value (dict):
@@ -449,11 +449,16 @@ def patch(
449449
Raise:
450450
AuthException: raised if patch operation fails
451451
"""
452-
if status is not None and status not in ["enabled", "disabled", "invited"]:
452+
if status is not None and status not in [
453+
"enabled",
454+
"disabled",
455+
"invited",
456+
"expired",
457+
]:
453458
raise AuthException(
454459
400,
455460
ERROR_TYPE_INVALID_ARGUMENT,
456-
f"Invalid status value: {status}. Must be one of: enabled, disabled, invited",
461+
f"Invalid status value: {status}. Must be one of: enabled, disabled, invited, expired",
457462
)
458463
response = self._http.patch(
459464
MgmtV1.user_patch_path,
@@ -506,11 +511,12 @@ def patch_batch(
506511
"enabled",
507512
"disabled",
508513
"invited",
514+
"expired",
509515
]:
510516
raise AuthException(
511517
400,
512518
ERROR_TYPE_INVALID_ARGUMENT,
513-
f"Invalid status value: {user.status} for user {user.login_id}. Must be one of: enabled, disabled, invited",
519+
f"Invalid status value: {user.status} for user {user.login_id}. Must be one of: enabled, disabled, invited, expired",
514520
)
515521

516522
response = self._http.patch(
@@ -728,7 +734,7 @@ def search_all(
728734
test_users_only (bool): Optional filter only test users.
729735
with_test_user (bool): Optional include test users in search.
730736
custom_attributes (dict): Optional search for a attribute with a given value
731-
statuses (List[str]): Optional list of statuses to search for ("enabled", "disabled", "invited")
737+
statuses (List[str]): Optional list of statuses to search for ("enabled", "disabled", "invited", "expired")
732738
emails (List[str]): Optional list of emails to search for
733739
phones (List[str]): Optional list of phones to search for
734740
sso_app_ids (List[str]): Optional list of SSO application IDs to filter by
@@ -850,7 +856,7 @@ def search_all_test_users(
850856
limit (int): Optional limit of the number of users returned. Leave empty for default.
851857
page (int): Optional pagination control. Pages start at 0 and must be non-negative.
852858
custom_attributes (dict): Optional search for a attribute with a given value
853-
statuses (List[str]): Optional list of statuses to search for ("enabled", "disabled", "invited")
859+
statuses (List[str]): Optional list of statuses to search for ("enabled", "disabled", "invited", "expired")
854860
emails (List[str]): Optional list of emails to search for
855861
phones (List[str]): Optional list of phones to search for
856862
sso_app_ids (List[str]): Optional list of SSO application IDs to filter by

0 commit comments

Comments
 (0)