Skip to content

Commit df06819

Browse files
committed
Refactor and separate mutltitenant controller from AriesAgentController
entirely * All functionality for multitenancy now in its own class * AriesAgentController can not be used for multitenancy * AriesAgentController simplified args only admin api required * Webhook handling now optional ** Webhook URL etc only need to be and can be passed when webhook listener method is invoked
1 parent 2f1e34a commit df06819

File tree

7 files changed

+248
-242
lines changed

7 files changed

+248
-242
lines changed

libs/aries-basic-controller/aries_basic_controller/aries_controller.py

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -37,38 +37,23 @@ class AriesAgentController:
3737
----------
3838
admin_url : str
3939
The URL for the Admin API
40-
webhook_host : str
41-
The url of the webhook host
42-
webhook_port : int
43-
The exposed port for webhooks on the host
44-
webhook_base : str
45-
The base url for webhooks (default is "")
4640
is_multitenant : bool
4741
Initialise the multitenant interface (default is False)
4842
mediation : bool
4943
Initialise the mediation interface (default is False)
5044
api_key : str
5145
The API key (default is None)
52-
wallet_id : str
53-
The tenant wallet identifier (default is None)
5446
"""
5547

56-
# TODO rethink how to initialise. Too many args?
57-
# We can factor out webhook host etc further in future versions
58-
# We could also remove the wallet id from this class if we wanted
59-
# and enforce use of multitenant controller for multitenant use entirely
6048
admin_url: str
61-
webhook_host: str = None
62-
webhook_port: int = None
63-
webhook_base: str = ""
6449
is_multitenant: bool = False
6550
mediation: bool = False
6651
api_key: str = None
67-
wallet_id: str = None
6852

6953
def __post_init__(self):
70-
"""Constructs additional attributes,
71-
and logic defined by attributes set during initial instantiation
54+
"""Constructs additional attributes and logic
55+
Creates headers, instantiates a client sessions and initialises
56+
the controller interfaces for the aries swagger API.
7257
"""
7358

7459
self.webhook_site = None
@@ -83,12 +68,6 @@ def __post_init__(self):
8368
self.client_session: ClientSession = ClientSession(
8469
headers=self.headers)
8570

86-
self.webhook_listener: AriesWebhookListener = AriesWebhookListener(
87-
webhook_host=self.webhook_host,
88-
webhook_port=self.webhook_port,
89-
webhook_base=self.webhook_base,
90-
is_multitenant=self.is_multitenant)
91-
9271
# Instantiate controllers
9372
self.connections = ConnectionsController(
9473
self.admin_url,
@@ -156,19 +135,27 @@ def __post_init__(self):
156135
self.client_session
157136
)
158137

159-
# TODO: Consider whether we want this to only be available in the
160-
# multitennant controller. This still required here to update the
161-
# base wallet for the current tutorials
162-
def update_wallet_id(self, wallet_id: str):
163-
"""This wallet_id is used to register for webhooks
164-
specific to this sub_wallet
138+
def webhook_listener(
139+
self,
140+
webhook_host: str = None,
141+
webhook_port: str = None,
142+
webhook_base: str = ""):
143+
"""Create a webhooklisteners
165144
166145
Args:
167146
----
168-
wallet_id : str
169-
The tenant wallet identifier
147+
webhook_host : str
148+
The url of the webhook host (default is None)
149+
webhook_port : int
150+
The exposed port for webhooks on the host (default is None)
151+
webhook_base : str
152+
The base url for webhooks (default is "")
170153
"""
171-
self.wallet_id = wallet_id
154+
self.webhook_listener: AriesWebhookListener = AriesWebhookListener(
155+
webhook_host=webhook_host,
156+
webhook_port=webhook_port,
157+
webhook_base=webhook_base,
158+
is_multitenant=self.is_multitenant)
172159

173160
def update_api_key(self, api_key: str):
174161
"""Update the API Key attribute and the header
@@ -234,11 +221,8 @@ def add_listener(self, listener):
234221
"""
235222
try:
236223
pub_topic_path = listener['topic']
237-
if self.wallet_id:
238-
pub_topic_path = f"{self.wallet_id}.{pub_topic_path}"
239224
print("Subscribing too: " + pub_topic_path)
240225
pub.subscribe(listener["handler"], pub_topic_path)
241-
242226
logger.debug("Lister added for topic : ", pub_topic_path)
243227
except Exception as exc:
244228
logger.warning(
@@ -281,12 +265,21 @@ def remove_all_listeners(self, topic: str = None):
281265
f"Removing all webhooks listeners failed! {exc!r} occurred.")
282266

283267
async def listen_webhooks(self):
284-
if self.webhook_listener:
268+
try:
285269
await self.webhook_listener.listen_webhooks()
270+
except AttributeError:
271+
logger.warning("Missing webhook listener.")
272+
except Exception as exc:
273+
logger.warning(
274+
f"Listening webhooks failed! {exc!r} occurred.")
286275

287276
async def terminate(self):
288277
await self.client_session.close()
289278
try:
290279
await self.webhook_listener.terminate()
291280
except AttributeError:
292-
pass
281+
# There is no webhook listener
282+
return
283+
except Exception as exc:
284+
logger.warning(
285+
f"Terminate webhooks listener exception!\n {exc!r} occurred.")

libs/aries-basic-controller/aries_basic_controller/aries_multitenant_controller.py

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from dataclasses import dataclass
2+
from pubsub import pub
23

34
from .aries_controller import AriesAgentController
45

@@ -15,18 +16,6 @@ class AriesMultitenantController(AriesAgentController):
1516
1617
Attributes:
1718
----------
18-
admin_url : str
19-
The URL for the Admin API
20-
webhook_host : str
21-
The url of the webhook host
22-
webhook_port : int
23-
The exposed port for webhooks on the host
24-
webhook_base : str
25-
The base url for webhooks (default is "")
26-
mediation : bool
27-
Initialise the mediation interface (default is False)
28-
api_key : str
29-
The API key (default is None)
3019
wallet_id : str
3120
The tenant wallet identifier (default is None)
3221
is_multitenant : bool
@@ -35,6 +24,7 @@ class AriesMultitenantController(AriesAgentController):
3524
The tenant JW token (default is None)
3625
"""
3726

27+
wallet_id: str = None
3828
is_multitenant: bool = True
3929
tenant_jwt: str = None
4030

@@ -56,6 +46,40 @@ def __post_init__(self):
5646
# Update the current client session instantiated in the parent class
5747
self.client_session.headers.update(self.headers)
5848

49+
def add_listener(self, listener):
50+
"""Subscribe to a listeners for a topic
51+
Overrides parent method and uses the tenant's wallet ID to
52+
listen for that wallet's webhooks under the url defined
53+
by the wallet ID.
54+
Args:
55+
----
56+
listener : dict
57+
A dictionary comprised of "handler": handler (fct) and
58+
"topic":"topicname" key-value pairs
59+
"""
60+
try:
61+
pub_topic_path = listener['topic']
62+
if self.wallet_id:
63+
pub_topic_path = f"{self.wallet_id}.{pub_topic_path}"
64+
print("Subscribing too: " + pub_topic_path)
65+
pub.subscribe(listener["handler"], pub_topic_path)
66+
67+
logger.debug("Lister added for topic : ", pub_topic_path)
68+
except Exception as exc:
69+
logger.warning(
70+
f"Adding webhooks listener failed! {exc!r} occurred.")
71+
72+
def update_wallet_id(self, wallet_id: str):
73+
"""This wallet_id is used to register for webhooks
74+
specific to this sub_wallet
75+
76+
Args:
77+
----
78+
wallet_id : str
79+
The tenant wallet identifier
80+
"""
81+
self.wallet_id = wallet_id
82+
5983
def update_tenant_jwt(self, tenant_jwt: str, wallet_id: str):
6084
"""Update the tenant JW token attribute and the header
6185

tutorials/4. Multitenancy/notebooks/external/Configure External Agent.ipynb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,19 @@
5050
"outputs": [],
5151
"source": [
5252
"# Based on the aca-py agent you wish to control\n",
53-
"agent_controller = AriesAgentController(webhook_host=WEBHOOK_HOST, webhook_port=WEBHOOK_PORT,\n",
54-
" webhook_base=WEBHOOK_BASE, admin_url=ADMIN_URL)\n",
53+
"agent_controller = AriesAgentController(admin_url=ADMIN_URL)\n",
5554
" "
5655
]
5756
},
57+
{
58+
"cell_type": "code",
59+
"execution_count": null,
60+
"metadata": {},
61+
"outputs": [],
62+
"source": [
63+
"agent_controller.webhook_listener(webhook_host=WEBHOOK_HOST, webhook_port=WEBHOOK_PORT, webhook_base=WEBHOOK_BASE)"
64+
]
65+
},
5866
{
5967
"cell_type": "markdown",
6068
"metadata": {},

tutorials/4. Multitenancy/notebooks/mediator/Configure Mediator.ipynb

Lines changed: 20 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,9 @@
3232
},
3333
{
3434
"cell_type": "code",
35-
"execution_count": 1,
35+
"execution_count": null,
3636
"metadata": {},
37-
"outputs": [
38-
{
39-
"name": "stdout",
40-
"output_type": "stream",
41-
"text": [
42-
"IPython autoawait is `on`, and set to use `asyncio`\n"
43-
]
44-
}
45-
],
37+
"outputs": [],
4638
"source": [
4739
"%autoawait\n",
4840
"import time\n",
@@ -64,7 +56,7 @@
6456
},
6557
{
6658
"cell_type": "code",
67-
"execution_count": 2,
59+
"execution_count": null,
6860
"metadata": {},
6961
"outputs": [],
7062
"source": [
@@ -78,13 +70,21 @@
7870
},
7971
{
8072
"cell_type": "code",
81-
"execution_count": 3,
73+
"execution_count": null,
8274
"metadata": {},
8375
"outputs": [],
8476
"source": [
8577
"# Based on the aca-py agent you wish to control\n",
86-
"agent_controller = AriesAgentController(webhook_host=WEBHOOK_HOST, webhook_port=WEBHOOK_PORT,\n",
87-
" webhook_base=WEBHOOK_BASE, admin_url=ADMIN_URL, mediation=True)"
78+
"agent_controller = AriesAgentController(admin_url=ADMIN_URL, mediation=True)"
79+
]
80+
},
81+
{
82+
"cell_type": "code",
83+
"execution_count": null,
84+
"metadata": {},
85+
"outputs": [],
86+
"source": [
87+
"agent_controller.webhook_listener(webhook_host=WEBHOOK_HOST, webhook_port=WEBHOOK_PORT, webhook_base=WEBHOOK_BASE)"
8888
]
8989
},
9090
{
@@ -102,19 +102,10 @@
102102
},
103103
{
104104
"cell_type": "code",
105-
"execution_count": 4,
105+
"execution_count": null,
106106
"metadata": {},
107-
"outputs": [
108-
{
109-
"name": "stdout",
110-
"output_type": "stream",
111-
"text": [
112-
"Subscribing too: connections\n"
113-
]
114-
}
115-
],
107+
"outputs": [],
116108
"source": [
117-
"\n",
118109
"loop = asyncio.get_event_loop()\n",
119110
"loop.create_task(agent_controller.webhook_listener.listen_webhooks())\n",
120111
"\n",
@@ -147,34 +138,9 @@
147138
},
148139
{
149140
"cell_type": "code",
150-
"execution_count": 5,
141+
"execution_count": null,
151142
"metadata": {},
152-
"outputs": [
153-
{
154-
"name": "stdout",
155-
"output_type": "stream",
156-
"text": [
157-
"Connection ID 96d27a0d-5eaa-45fe-89ed-de9117021758\n",
158-
"Invitation\n",
159-
"{'@type': 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation', '@id': '290a620f-39a9-4d59-8f80-7f1a66fab9ec', 'recipientKeys': ['6jZbv5zZp8pmsqrG66BwXzqrr3NpEReHgpxuwLcaoxiP'], 'serviceEndpoint': 'https://eb407795fda3.ngrok.io', 'label': 'MEDIATOR'}\n",
160-
"wallet None\n",
161-
"Connection Handler Called\n",
162-
"Connection 96d27a0d-5eaa-45fe-89ed-de9117021758 in State invitation\n",
163-
"wallet None\n",
164-
"Connection Handler Called\n",
165-
"Connection a6e57fd2-7f5a-46be-a3b4-a008e4b958ae in State invitation\n",
166-
"wallet None\n",
167-
"Connection Handler Called\n",
168-
"Connection a6e57fd2-7f5a-46be-a3b4-a008e4b958ae in State request\n",
169-
"wallet None\n",
170-
"Connection Handler Called\n",
171-
"Connection a6e57fd2-7f5a-46be-a3b4-a008e4b958ae in State response\n",
172-
"wallet None\n",
173-
"Connection Handler Called\n",
174-
"Connection a6e57fd2-7f5a-46be-a3b4-a008e4b958ae in State active\n"
175-
]
176-
}
177-
],
143+
"outputs": [],
178144
"source": [
179145
"# Create Invitation\n",
180146
"invite = await agent_controller.connections.create_invitation(multi_use=\"true\")\n",
@@ -217,23 +183,13 @@
217183
},
218184
{
219185
"cell_type": "code",
220-
"execution_count": 6,
186+
"execution_count": null,
221187
"metadata": {
222188
"pycharm": {
223189
"name": "#%%\n"
224190
}
225191
},
226-
"outputs": [
227-
{
228-
"name": "stdout",
229-
"output_type": "stream",
230-
"text": [
231-
"Mediation Record\n",
232-
"connection_id 49431565-9d12-42e9-8341-8699834fc785\n",
233-
"State request\n"
234-
]
235-
}
236-
],
192+
"outputs": [],
237193
"source": [
238194
"response = await agent_controller.mediation.get_mediation_records()\n",
239195
"\n",

0 commit comments

Comments
 (0)