Skip to content

Commit c2f2ba3

Browse files
authoredJun 5, 2025··
chore: merge community PRs – bugfixes, features, and dependency upgrades (#696)
### Changes This PR consolidates multiple community contributions and dependency upgrade: - Features - [Self Service Profiles Support ](#673) ([nzetzl](https://github.com/nzetzl)) - Fixes - [Adding Global Seed](#690) [(allrob23)](https://github.com/allrob23) - Bumping Dependencies ### Testing - [x] This change adds test coverage - [x] This change has been tested on the latest version of the platform/language or why not ### Contributor Checklist - [x] I agree to adhere to the [Auth0 General Contribution Guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md). - [x] I agree to uphold the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md). - [x] All existing and new tests complete without errors
1 parent ba032e8 commit c2f2ba3

File tree

10 files changed

+338
-5
lines changed

10 files changed

+338
-5
lines changed
 

‎.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,6 @@ jobs:
8080

8181
- if: ${{ matrix.python-version == '3.10' }}
8282
name: Upload coverage
83-
uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # pin@5.4.2
83+
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # pin@5.4.3
8484
with:
8585
token: ${{ secrets.CODECOV_TOKEN }}

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ For more code samples on how to integrate the auth0-python SDK in your Python ap
122122
- Roles() ( `Auth0().roles` )
123123
- RulesConfigs() ( `Auth0().rules_configs` )
124124
- Rules() ( `Auth0().rules` )
125+
- SelfServiceProfiles() ( `Auth0().self_service_profiles` )
125126
- Stats() ( `Auth0().stats` )
126127
- Tenants() ( `Auth0().tenants` )
127128
- Tickets() ( `Auth0().tickets` )

‎auth0/management/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from .roles import Roles
2323
from .rules import Rules
2424
from .rules_configs import RulesConfigs
25+
from .self_service_profiles import SelfServiceProfiles
2526
from .stats import Stats
2627
from .tenants import Tenants
2728
from .tickets import Tickets
@@ -59,6 +60,7 @@
5960
"Roles",
6061
"RulesConfigs",
6162
"Rules",
63+
"SelfServiceProfiles",
6264
"Stats",
6365
"Tenants",
6466
"Tickets",

‎auth0/management/auth0.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from .roles import Roles
2727
from .rules import Rules
2828
from .rules_configs import RulesConfigs
29+
from .self_service_profiles import SelfServiceProfiles
2930
from .stats import Stats
3031
from .tenants import Tenants
3132
from .tickets import Tickets
@@ -86,6 +87,9 @@ def __init__(
8687
self.roles = Roles(domain, token, rest_options=rest_options)
8788
self.rules_configs = RulesConfigs(domain, token, rest_options=rest_options)
8889
self.rules = Rules(domain, token, rest_options=rest_options)
90+
self.self_service_profiles = SelfServiceProfiles(
91+
domain, token, rest_options=rest_options
92+
)
8993
self.stats = Stats(domain, token, rest_options=rest_options)
9094
self.tenants = Tenants(domain, token, rest_options=rest_options)
9195
self.tickets = Tickets(domain, token, rest_options=rest_options)
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
from __future__ import annotations
2+
3+
from typing import Any, List # List is being used as list is already a method.
4+
5+
from ..rest import RestClient, RestClientOptions
6+
from ..types import TimeoutType
7+
8+
9+
class SelfServiceProfiles:
10+
"""Auth0 Self Service Profiles endpoints
11+
12+
Args:
13+
domain (str): Your Auth0 domain, e.g: 'username.auth0.com'
14+
15+
token (str): Management API v2 Token
16+
17+
telemetry (bool, optional): Enable or disable Telemetry
18+
(defaults to True)
19+
20+
timeout (float or tuple, optional): Change the requests
21+
connect and read timeout. Pass a tuple to specify
22+
both values separately or a float to set both to it.
23+
(defaults to 5.0 for both)
24+
25+
protocol (str, optional): Protocol to use when making requests.
26+
(defaults to "https")
27+
28+
rest_options (RestClientOptions): Pass an instance of
29+
RestClientOptions to configure additional RestClient
30+
options, such as rate-limit retries.
31+
(defaults to None)
32+
"""
33+
34+
def __init__(
35+
self,
36+
domain: str,
37+
token: str,
38+
telemetry: bool = True,
39+
timeout: TimeoutType = 5.0,
40+
protocol: str = "https",
41+
rest_options: RestClientOptions | None = None,
42+
) -> None:
43+
self.domain = domain
44+
self.protocol = protocol
45+
self.client = RestClient(
46+
jwt=token, telemetry=telemetry, timeout=timeout, options=rest_options
47+
)
48+
49+
def _url(self, profile_id: str | None = None) -> str:
50+
url = f"{self.protocol}://{self.domain}/api/v2/self-service-profiles"
51+
if profile_id is not None:
52+
return f"{url}/{profile_id}"
53+
return url
54+
55+
def all(
56+
self,
57+
page: int = 0,
58+
per_page: int = 25,
59+
include_totals: bool = True,
60+
) -> List[dict[str, Any]]:
61+
"""List self-service profiles.
62+
63+
Args:
64+
page (int, optional): The result's page number (zero based). By default,
65+
retrieves the first page of results.
66+
67+
per_page (int, optional): The amount of entries per page. By default,
68+
retrieves 25 results per page.
69+
70+
include_totals (bool, optional): True if the query summary is
71+
to be included in the result, False otherwise. Defaults to True.
72+
73+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/get-self-service-profiles
74+
"""
75+
76+
params = {
77+
"page": page,
78+
"per_page": per_page,
79+
"include_totals": str(include_totals).lower(),
80+
}
81+
82+
return self.client.get(self._url(), params=params)
83+
84+
def create(self, body: dict[str, Any]) -> dict[str, Any]:
85+
"""Create a new self-service profile.
86+
87+
Args:
88+
body (dict): Attributes for the new self-service profile.
89+
90+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/post-self-service-profiles
91+
"""
92+
93+
return self.client.post(self._url(), data=body)
94+
95+
def get(self, profile_id: str) -> dict[str, Any]:
96+
"""Get a self-service profile.
97+
98+
Args:
99+
id (str): The id of the self-service profile to retrieve.
100+
101+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/get-self-service-profiles-by-id
102+
"""
103+
104+
return self.client.get(self._url(profile_id))
105+
106+
def delete(self, profile_id: str) -> None:
107+
"""Delete a self-service profile.
108+
109+
Args:
110+
id (str): The id of the self-service profile to delete.
111+
112+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/delete-self-service-profiles-by-id
113+
"""
114+
115+
self.client.delete(self._url(profile_id))
116+
117+
def update(self, profile_id: str, body: dict[str, Any]) -> dict[str, Any]:
118+
"""Update a self-service profile.
119+
120+
Args:
121+
id (str): The id of the self-service profile to update.
122+
123+
body (dict): Attributes of the self-service profile to modify.
124+
125+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/patch-self-service-profiles-by-id
126+
"""
127+
128+
return self.client.patch(self._url(profile_id), data=body)
129+
130+
def get_custom_text(
131+
self, profile_id: str, language: str, page: str
132+
) -> dict[str, Any]:
133+
"""Get the custom text for a self-service profile.
134+
135+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/get-self-service-profile-custom-text
136+
"""
137+
138+
url = self._url(f"{profile_id}/custom-text/{language}/{page}")
139+
return self.client.get(url)
140+
141+
def update_custom_text(
142+
self, profile_id: str, language: str, page: str, body: dict[str, Any]
143+
) -> dict[str, Any]:
144+
"""Update the custom text for a self-service profile.
145+
146+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/put-self-service-profile-custom-text
147+
"""
148+
149+
url = self._url(f"{profile_id}/custom-text/{language}/{page}")
150+
return self.client.put(url, data=body)
151+
152+
def create_sso_ticket(
153+
self, profile_id: str, body: dict[str, Any]
154+
) -> dict[str, Any]:
155+
"""Create a single sign-on ticket for a self-service profile.
156+
157+
Args:
158+
id (str): The id of the self-service profile to create the ticket for.
159+
160+
body (dict): Attributes for the single sign-on ticket.
161+
162+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/post-sso-ticket
163+
"""
164+
165+
url = self._url(f"{profile_id}/sso-ticket")
166+
return self.client.post(url, data=body)
167+
168+
def revoke_sso_ticket(self, profile_id: str, ticket_id: str) -> None:
169+
"""Revoke a single sign-on ticket for a self-service profile.
170+
171+
Args:
172+
id (str): The id of the self-service profile to revoke the ticket from.
173+
174+
ticket (str): The ticket to revoke.
175+
176+
See: https://auth0.com/docs/api/management/v2/self-service-profiles/post-revoke
177+
"""
178+
179+
url = self._url(f"{profile_id}/sso-ticket/{ticket_id}/revoke")
180+
self.client.post(url)

‎auth0/test/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import pytest
2+
import random
3+
4+
@pytest.fixture(autouse=True)
5+
def set_random_seed():
6+
random.seed(42)
7+
print("Random seeded to 42")
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import unittest
2+
from unittest import mock
3+
4+
from ...management.self_service_profiles import SelfServiceProfiles
5+
6+
7+
class TestSelfServiceProfiles(unittest.TestCase):
8+
def test_init_with_optionals(self):
9+
t = SelfServiceProfiles(
10+
domain="domain", token="jwttoken", telemetry=False, timeout=(10, 2)
11+
)
12+
self.assertEqual(t.client.options.timeout, (10, 2))
13+
telemetry_header = t.client.base_headers.get("Auth0-Client", None)
14+
self.assertEqual(telemetry_header, None)
15+
16+
@mock.patch("auth0.management.self_service_profiles.RestClient")
17+
def test_all(self, mock_rc):
18+
mock_instance = mock_rc.return_value
19+
20+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
21+
s.all()
22+
23+
mock_instance.get.assert_called_with(
24+
"https://domain/api/v2/self-service-profiles",
25+
params={"page": 0, "per_page": 25, "include_totals": "true"},
26+
)
27+
28+
s.all(page=1, per_page=50, include_totals=False)
29+
30+
mock_instance.get.assert_called_with(
31+
"https://domain/api/v2/self-service-profiles",
32+
params={"page": 1, "per_page": 50, "include_totals": "false"},
33+
)
34+
35+
@mock.patch("auth0.management.self_service_profiles.RestClient")
36+
def test_create(self, mock_rc):
37+
mock_instance = mock_rc.return_value
38+
39+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
40+
s.create({"name": "test"})
41+
42+
mock_instance.post.assert_called_with(
43+
"https://domain/api/v2/self-service-profiles", data={"name": "test"}
44+
)
45+
46+
@mock.patch("auth0.management.self_service_profiles.RestClient")
47+
def test_get(self, mock_rc):
48+
mock_instance = mock_rc.return_value
49+
50+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
51+
s.get("an-id")
52+
53+
mock_instance.get.assert_called_with(
54+
"https://domain/api/v2/self-service-profiles/an-id"
55+
)
56+
57+
@mock.patch("auth0.management.self_service_profiles.RestClient")
58+
def test_delete(self, mock_rc):
59+
mock_instance = mock_rc.return_value
60+
61+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
62+
s.delete("an-id")
63+
64+
mock_instance.delete.assert_called_with(
65+
"https://domain/api/v2/self-service-profiles/an-id"
66+
)
67+
68+
@mock.patch("auth0.management.self_service_profiles.RestClient")
69+
def test_update(self, mock_rc):
70+
mock_instance = mock_rc.return_value
71+
72+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
73+
s.update("an-id", {"a": "b", "c": "d"})
74+
75+
mock_instance.patch.assert_called_with(
76+
"https://domain/api/v2/self-service-profiles/an-id",
77+
data={"a": "b", "c": "d"},
78+
)
79+
80+
@mock.patch("auth0.management.self_service_profiles.RestClient")
81+
def test_get_custom_text(self, mock_rc):
82+
mock_instance = mock_rc.return_value
83+
84+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
85+
s.get_custom_text("an-id", "en", "page")
86+
87+
mock_instance.get.assert_called_with(
88+
"https://domain/api/v2/self-service-profiles/an-id/custom-text/en/page"
89+
)
90+
91+
@mock.patch("auth0.management.self_service_profiles.RestClient")
92+
def test_update_custom_text(self, mock_rc):
93+
mock_instance = mock_rc.return_value
94+
95+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
96+
s.update_custom_text("an-id", "en", "page", {"a": "b", "c": "d"})
97+
98+
mock_instance.put.assert_called_with(
99+
"https://domain/api/v2/self-service-profiles/an-id/custom-text/en/page",
100+
data={"a": "b", "c": "d"},
101+
)
102+
103+
@mock.patch("auth0.management.self_service_profiles.RestClient")
104+
def test_create_sso_ticket(self, mock_rc):
105+
mock_instance = mock_rc.return_value
106+
107+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
108+
s.create_sso_ticket("an-id", {"a": "b", "c": "d"})
109+
110+
mock_instance.post.assert_called_with(
111+
"https://domain/api/v2/self-service-profiles/an-id/sso-ticket",
112+
data={"a": "b", "c": "d"},
113+
)
114+
115+
@mock.patch("auth0.management.self_service_profiles.RestClient")
116+
def test_revoke_sso_ticket(self, mock_rc):
117+
mock_instance = mock_rc.return_value
118+
119+
s = SelfServiceProfiles(domain="domain", token="jwttoken")
120+
s.revoke_sso_ticket("an-id", "ticket-id")
121+
122+
mock_instance.post.assert_called_with(
123+
"https://domain/api/v2/self-service-profiles/an-id/sso-ticket/ticket-id/revoke"
124+
)

‎auth0/test_async/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import pytest
2+
import random
3+
4+
@pytest.fixture(autouse=True)
5+
def set_random_seed():
6+
random.seed(42)
7+
print("Random seeded to 42")

‎docs/source/management.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ management.rules module
177177
:undoc-members:
178178
:show-inheritance:
179179

180+
management.self_service_profiles module
181+
-----------------------------------------
182+
183+
.. automodule:: auth0.management.self_service_profiles
184+
:members:
185+
:undoc-members:
186+
:show-inheritance:
187+
180188
management.stats module
181189
--------------------------
182190

0 commit comments

Comments
 (0)
Please sign in to comment.