Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f8be872

Browse files
authored
Merge pull request auth0#443 from auth0/auth0-async
Add AsyncAuth0 to share a session among many services
2 parents 1098b67 + ff209fe commit f8be872

File tree

6 files changed

+150
-21
lines changed

6 files changed

+150
-21
lines changed

README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,12 @@ Then additional methods with the ``_async`` suffix will be added to modules crea
343343
data = await users.get_async(id)
344344
users.update_async(id, data)
345345
346+
347+
# To share a session amongst multiple calls to multiple services
348+
async with Auth0('domain', 'mgmt_api_token') as auth0:
349+
user = await auth0.users.get_async(user_id)
350+
connection = await auth0.connections.get_async(connection_id)
351+
346352
# Use asyncify directly on services
347353
Users = asyncify(Users)
348354
Connections = asyncify(Connections)

auth0/v3/asyncify.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,19 @@ def __init__(
7070
_gen_async(self._async_client, method),
7171
)
7272

73+
def set_session(self, session):
74+
"""Set Client Session to improve performance by reusing session.
75+
76+
Args:
77+
session (aiohttp.ClientSession): The client session which should be closed
78+
manually or within context manager.
79+
"""
80+
self._session = session
81+
self._async_client.client.set_session(self._session)
82+
7383
async def __aenter__(self):
7484
"""Automatically create and set session within context manager."""
75-
async_rest_client = self._async_client.client
76-
self._session = aiohttp.ClientSession()
77-
async_rest_client.set_session(self._session)
85+
self.set_session(aiohttp.ClientSession())
7886
return self
7987

8088
async def __aexit__(self, exc_type, exc_val, exc_tb):

auth0/v3/management/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
from ..utils import is_async_available
12
from .actions import Actions
23
from .attack_protection import AttackProtection
3-
from .auth0 import Auth0
44
from .blacklists import Blacklists
55
from .branding import Branding
66
from .client_grants import ClientGrants
@@ -28,6 +28,11 @@
2828
from .users import Users
2929
from .users_by_email import UsersByEmail
3030

31+
if is_async_available():
32+
from .async_auth0 import AsyncAuth0 as Auth0
33+
else:
34+
from .auth0 import Auth0
35+
3136
__all__ = (
3237
"Auth0",
3338
"Actions",

auth0/v3/management/async_auth0.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import aiohttp
2+
3+
from ..asyncify import asyncify
4+
from .auth0 import modules
5+
6+
7+
class AsyncAuth0(object):
8+
"""Provides easy access to all endpoint classes
9+
10+
Args:
11+
domain (str): Your Auth0 domain, for example 'username.auth0.com'
12+
13+
token (str): Management API v2 Token
14+
15+
rest_options (RestClientOptions): Pass an instance of
16+
RestClientOptions to configure additional RestClient
17+
options, such as rate-limit retries.
18+
(defaults to None)
19+
"""
20+
21+
def __init__(self, domain, token, rest_options=None):
22+
self._services = []
23+
for name, cls in modules.items():
24+
cls = asyncify(cls)
25+
service = cls(domain=domain, token=token, rest_options=rest_options)
26+
self._services.append(service)
27+
setattr(
28+
self,
29+
name,
30+
service,
31+
)
32+
33+
def set_session(self, session):
34+
"""Set Client Session to improve performance by reusing session.
35+
36+
Args:
37+
session (aiohttp.ClientSession): The client session which should be closed
38+
manually or within context manager.
39+
"""
40+
self._session = session
41+
for service in self._services:
42+
service.set_session(self._session)
43+
44+
async def __aenter__(self):
45+
"""Automatically create and set session within context manager."""
46+
self.set_session(aiohttp.ClientSession())
47+
return self
48+
49+
async def __aexit__(self, exc_type, exc_val, exc_tb):
50+
"""Automatically close session within context manager."""
51+
await self._session.close()

auth0/v3/management/auth0.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,9 @@ class Auth0(object):
7777
"""
7878

7979
def __init__(self, domain, token, rest_options=None):
80-
if is_async_available():
81-
from ..asyncify import asyncify
82-
83-
for name, cls in modules.items():
84-
cls = asyncify(cls)
85-
setattr(
86-
self,
87-
name,
88-
cls(domain=domain, token=token, rest_options=rest_options),
89-
)
90-
else:
91-
for name, cls in modules.items():
92-
setattr(
93-
self,
94-
name,
95-
cls(domain=domain, token=token, rest_options=rest_options),
96-
)
80+
for name, cls in modules.items():
81+
setattr(
82+
self,
83+
name,
84+
cls(domain=domain, token=token, rest_options=rest_options),
85+
)
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import base64
2+
import json
3+
import platform
4+
import re
5+
import sys
6+
from tempfile import TemporaryFile
7+
from unittest import IsolatedAsyncioTestCase
8+
9+
import aiohttp
10+
from aioresponses import CallbackResult, aioresponses
11+
from callee import Attrs
12+
from mock import ANY, MagicMock
13+
14+
from auth0.v3.management.async_auth0 import AsyncAuth0 as Auth0
15+
16+
clients = re.compile(r"^https://example\.com/api/v2/clients.*")
17+
factors = re.compile(r"^https://example\.com/api/v2/guardian/factors.*")
18+
payload = {"foo": "bar"}
19+
20+
21+
def get_callback(status=200):
22+
mock = MagicMock(return_value=CallbackResult(status=status, payload=payload))
23+
24+
def callback(url, **kwargs):
25+
return mock(url, **kwargs)
26+
27+
return callback, mock
28+
29+
30+
class TestAsyncify(IsolatedAsyncioTestCase):
31+
@aioresponses()
32+
async def test_get(self, mocked):
33+
callback, mock = get_callback()
34+
mocked.get(clients, callback=callback)
35+
auth0 = Auth0(domain="example.com", token="jwt")
36+
self.assertEqual(await auth0.clients.all_async(), payload)
37+
mock.assert_called_with(
38+
Attrs(path="/api/v2/clients"),
39+
allow_redirects=True,
40+
params={"include_fields": "true"},
41+
headers=ANY,
42+
timeout=ANY,
43+
)
44+
45+
@aioresponses()
46+
async def test_shared_session(self, mocked):
47+
callback, mock = get_callback()
48+
callback2, mock2 = get_callback()
49+
mocked.get(clients, callback=callback)
50+
mocked.put(factors, callback=callback2)
51+
async with Auth0(domain="example.com", token="jwt") as auth0:
52+
self.assertEqual(await auth0.clients.all_async(), payload)
53+
self.assertEqual(
54+
await auth0.guardian.update_factor_async("factor-1", {"factor": 1}),
55+
payload,
56+
)
57+
mock.assert_called_with(
58+
Attrs(path="/api/v2/clients"),
59+
allow_redirects=True,
60+
params={"include_fields": "true"},
61+
headers=ANY,
62+
timeout=ANY,
63+
)
64+
mock2.assert_called_with(
65+
Attrs(path="/api/v2/guardian/factors/factor-1"),
66+
allow_redirects=True,
67+
json={"factor": 1},
68+
headers=ANY,
69+
timeout=ANY,
70+
)

0 commit comments

Comments
 (0)