Skip to content

Commit ffa5d67

Browse files
committed
feat: support status field on user create, document invite caveat
Adds an optional `status` parameter to `mgmt.user.create()` (sync and async), matching the status field already supported by the create-user API and by `patch()`. Also documents in the README that `invite` only controls whether an invitation message is sent, not the resulting user status.
1 parent 65a2791 commit ffa5d67

5 files changed

Lines changed: 44 additions & 0 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,11 @@ descope_client.mgmt.user.invite(
700700
invite_url="invite.me"
701701
)
702702

703+
# NOTE: `invite` only controls whether an invitation message is sent - it does NOT
704+
# change the user's status. A newly invited user starts out in the "invited" status,
705+
# not "enabled". If your use case requires the user to be active immediately, set
706+
# `status="enabled"` explicitly via `create`/`patch`, or call `activate()` afterwards.
707+
703708
# Batch invite
704709
descope_client.mgmt.user.invite_batch(
705710
users=[

descope/management/_user_base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def _compose_create_body(
9595
sso_app_ids: Optional[List[str]] = None,
9696
template_id: str = "",
9797
locale: Optional[str] = None,
98+
status: Optional[str] = None,
9899
) -> dict:
99100
body = UserBase._compose_update_body(
100101
login_id=login_id,
@@ -127,6 +128,8 @@ def _compose_create_body(
127128
body["templateId"] = template_id
128129
if locale is not None:
129130
body["locale"] = locale
131+
if status is not None:
132+
body["status"] = status
130133
return body
131134

132135
@staticmethod

descope/management/user.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def create(
3232
invite_url: Optional[str] = None,
3333
additional_login_ids: Optional[List[str]] = None,
3434
sso_app_ids: Optional[List[str]] = None,
35+
status: Optional[str] = None,
3536
) -> dict:
3637
"""
3738
Create a new user. Users can have any number of optional fields, including email, phone number and authorization.
@@ -48,6 +49,7 @@ def create(
4849
picture (str): Optional url for user picture
4950
custom_attributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console app
5051
sso_app_ids (List[str]): Optional, list of SSO applications IDs to be associated with the user.
52+
status (str): Optional status field. Can be one of: "enabled", "disabled", "invited", "expired".
5153
5254
Return value (dict):
5355
Return dict in the format
@@ -57,6 +59,17 @@ def create(
5759
Raise:
5860
AuthException: raised if create operation fails
5961
"""
62+
if status is not None and status not in [
63+
"enabled",
64+
"disabled",
65+
"invited",
66+
"expired",
67+
]:
68+
raise AuthException(
69+
400,
70+
ERROR_TYPE_INVALID_ARGUMENT,
71+
f"Invalid status value: {status}. Must be one of: enabled, disabled, invited, expired",
72+
)
6073
role_names = [] if role_names is None else role_names
6174
user_tenants = [] if user_tenants is None else user_tenants
6275

@@ -83,6 +96,7 @@ def create(
8396
None,
8497
additional_login_ids,
8598
sso_app_ids,
99+
status=status,
86100
),
87101
)
88102
return response.json()

descope/management/user_async.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ async def create(
3636
invite_url: Optional[str] = None,
3737
additional_login_ids: Optional[List[str]] = None,
3838
sso_app_ids: Optional[List[str]] = None,
39+
status: Optional[str] = None,
3940
) -> dict:
4041
"""
4142
Create a new user. Users can have any number of optional fields, including email, phone number and authorization.
@@ -52,6 +53,7 @@ async def create(
5253
picture (str): Optional url for user picture
5354
custom_attributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console app
5455
sso_app_ids (List[str]): Optional, list of SSO applications IDs to be associated with the user.
56+
status (str): Optional status field. Can be one of: "enabled", "disabled", "invited", "expired".
5557
5658
Return value (dict):
5759
Return dict in the format
@@ -61,6 +63,17 @@ async def create(
6163
Raise:
6264
AuthException: raised if create operation fails
6365
"""
66+
if status is not None and status not in [
67+
"enabled",
68+
"disabled",
69+
"invited",
70+
"expired",
71+
]:
72+
raise AuthException(
73+
400,
74+
ERROR_TYPE_INVALID_ARGUMENT,
75+
f"Invalid status value: {status}. Must be one of: enabled, disabled, invited, expired",
76+
)
6477
role_names = [] if role_names is None else role_names
6578
user_tenants = [] if user_tenants is None else user_tenants
6679

@@ -87,6 +100,7 @@ async def create(
87100
None,
88101
additional_login_ids,
89102
sso_app_ids,
103+
status=status,
90104
),
91105
)
92106
return response.json()

tests/management/test_user.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ async def test_create(self, client_factory):
2525
with pytest.raises(AuthException):
2626
await client.invoke(client.mgmt.user.create("valid-id"))
2727

28+
with pytest.raises(AuthException) as exc_info:
29+
await client.invoke(
30+
client.mgmt.user.create("valid-id", status="invalid_status")
31+
)
32+
assert "Invalid status value: invalid_status" in str(exc_info.value)
33+
2834
# Test success flow
2935
with client.mock_mgmt_post(make_response({"user": {"id": "u1"}})) as mock_post:
3036
resp = await client.invoke(
@@ -40,6 +46,7 @@ async def test_create(self, client_factory):
4046
custom_attributes={"ak": "av"},
4147
additional_login_ids=["id-1", "id-2"],
4248
sso_app_ids=["app1", "app2"],
49+
status="disabled",
4350
)
4451
)
4552
user = resp["user"]
@@ -70,6 +77,7 @@ async def test_create(self, client_factory):
7077
"invite": False,
7178
"additionalLoginIds": ["id-1", "id-2"],
7279
"ssoAppIDs": ["app1", "app2"],
80+
"status": "disabled",
7381
},
7482
follow_redirects=False,
7583
)

0 commit comments

Comments
 (0)