diff --git a/scripts/create_person_aid.py b/scripts/create_person_aid.py index b84afba..dc86d32 100644 --- a/scripts/create_person_aid.py +++ b/scripts/create_person_aid.py @@ -25,7 +25,7 @@ def create_aid(): oobis = client.oobis() aids = identifiers.list() - assert aids == [] + assert aids['aids'] == [] wits = [ "BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha", diff --git a/scripts/issue-ecr.sh b/scripts/issue-ecr.sh index 0d0b44e..40142e6 100755 --- a/scripts/issue-ecr.sh +++ b/scripts/issue-ecr.sh @@ -42,21 +42,24 @@ kli vc registry incept --name legal-entity --alias legal-entity --registry-name # Issue QVI credential vLEI from GLEIF External to QVI kli vc issue --name external --alias external --registry-name vLEI-external --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao --recipient EHMnCf8_nIemuPx-cUHaDQq8zSnQIFAurdEpwHpNbnvX --data @"${KERI_DEMO_SCRIPT_DIR}"/data/qvi-data.json -kli vc list --name qvi --alias qvi --poll +kli vc accept --name qvi --alias qvi --poll --auto +kli vc list --name qvi --alias qvi # Issue LE credential from QVI to Legal Entity - have to create the edges first QVI_SAID=$(kli vc list --name qvi --alias qvi --said --schema EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao) echo \"$QVI_SAID\" | jq -f "${KERI_DEMO_SCRIPT_DIR}"/data/legal-entity-edges-filter.jq > /tmp/legal-entity-edges.json kli saidify --file /tmp/legal-entity-edges.json kli vc issue --name qvi --alias qvi --registry-name vLEI-qvi --schema ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY --recipient EIitNxxiNFXC1HDcPygyfyv3KUlBfS_Zf-ZYOvwjpTuz --data @"${KERI_DEMO_SCRIPT_DIR}"/data/legal-entity-data.json --edges @/tmp/legal-entity-edges.json --rules @"${KERI_DEMO_SCRIPT_DIR}"/data/rules.json -kli vc list --name legal-entity --alias legal-entity --poll +kli vc accept --name legal-entity --alias legal-entity --poll --auto +kli vc list --name legal-entity --alias legal-entity # Issue ECR Authorization credential from Legal Entity to QVI - have to create the edges first LE_SAID=$(kli vc list --name legal-entity --alias legal-entity --said) echo \"$LE_SAID\" | jq -f "${KERI_DEMO_SCRIPT_DIR}"/data/ecr-auth-edges-filter.jq > /tmp/ecr-auth-edges.json kli saidify --file /tmp/ecr-auth-edges.json kli vc issue --name legal-entity --alias legal-entity --registry-name vLEI-legal-entity --schema EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g --recipient EHMnCf8_nIemuPx-cUHaDQq8zSnQIFAurdEpwHpNbnvX --data @"${KERI_DEMO_SCRIPT_DIR}"/data/ecr-auth-data.json --edges @/tmp/ecr-auth-edges.json --rules @"${KERI_DEMO_SCRIPT_DIR}"/data/ecr-auth-rules.json -kli vc list --name qvi --alias qvi --poll +kli vc accept --name qvi --alias qvi --poll --auto +kli vc list --name qvi --alias qvi # Issue ECR credential from QVI to Person AUTH_SAID=$(kli vc list --name qvi --alias qvi --said --schema EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g) diff --git a/src/signify/app/aiding.py b/src/signify/app/aiding.py index 5fd7694..d4b600c 100644 --- a/src/signify/app/aiding.py +++ b/src/signify/app/aiding.py @@ -27,7 +27,7 @@ def list(self, start=0, end=24): res = self.client.get(f"/identifiers", headers=headers) cr = res.headers["content-range"] - start, end, total = httping.parseRangeHeader(cr) + start, end, total = httping.parseRangeHeader(cr, "aids") return dict(start=start, end=end, total=total, aids=res.json()) diff --git a/src/signify/app/clienting.py b/src/signify/app/clienting.py index 28aca68..3ea3a96 100644 --- a/src/signify/app/clienting.py +++ b/src/signify/app/clienting.py @@ -237,6 +237,10 @@ def endroles(self): from signify.app.ending import EndRoleAuthorizations return EndRoleAuthorizations(client=self) + def notifications(self): + from signify.app.notifying import Notifications + return Notifications(client=self) + @staticmethod def raiseForStatus(res): try: diff --git a/src/signify/app/notifying.py b/src/signify/app/notifying.py new file mode 100644 index 0000000..66799b8 --- /dev/null +++ b/src/signify/app/notifying.py @@ -0,0 +1,59 @@ +# -*- encoding: utf-8 -*- +""" +SIGNIFY +signify.app.notifying module + +""" +from signify.app.clienting import SignifyClient +from signify.core import httping + + +class Notifications: + """ Domain class for accessing Endpoint Role Authorizations """ + + def __init__(self, client: SignifyClient): + self.client = client + + def list(self, start=0, end=24): + """ Returns list of notifications + + Parameters: + start (int): start index of list of notifications, defaults to 0 + end (int): end index of list of notifications, defaults to 24 + + Returns: + dict: data with start, end, total and notes of list result + + """ + headers = dict(Range=f"notes={start}-{end}") + res = self.client.get(f"/notifications", headers=headers) + cr = res.headers["content-range"] + start, end, total = httping.parseRangeHeader(cr, "notes") + + return dict(start=start, end=end, total=total, notes=res.json()) + + def markAsRead(self, nid): + """ Mark notification as read + + Parameters: + nid (str): qb64 SAID of notification to mark as read + + Returns: + bool: True means notification marked as read + + """ + res = self.client.put(f"/notifications/{nid}", json={}) + return res.status == 202 + + def delete(self, nid): + """ Delete notification + + Parameters: + nid(str): qb64 SAID of notification to delete + + Returns: + bool: True means notification deleted + + """ + res = self.client.delete(path=f"/notifications/{nid}") + return res.status == 202 diff --git a/src/signify/core/httping.py b/src/signify/core/httping.py index 6361991..0b2e93b 100644 --- a/src/signify/core/httping.py +++ b/src/signify/core/httping.py @@ -1,22 +1,23 @@ # -*- encoding: utf-8 -*- -from typing import Tuple """ SignifyPy signify.core.httping module """ +from typing import Tuple -def parseRangeHeader(header: str) -> Tuple[int, int, int]: +def parseRangeHeader(header: str, typ: str) -> Tuple[int, int, int]: """ Parse start, end and total from HTTP Content-Range header value Parameters: header (str): HTTP Content-Range header value + typ (str): Type in range header Returns: Tuple[int, int int] """ - data = header.lstrip("aids ") + data = header.lstrip(f"{typ} ") values = data.split("/") rng = values[0].split("-") diff --git a/tests/app/test_aiding.py b/tests/app/test_aiding.py index 7a0618f..7173e08 100644 --- a/tests/app/test_aiding.py +++ b/tests/app/test_aiding.py @@ -1,7 +1,15 @@ +# -*- encoding: utf-8 -*- +""" +SIGNIFY +signify.app.test_aiding module + +Testing aiding with unit tests +""" import pytest from mockito import mock, verify, when, unstub + def test_aiding_list(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) @@ -28,6 +36,7 @@ def test_aiding_list(): unstub() + def test_aiding_get(): from signify.app.clienting import SignifyClient client = SignifyClient(passcode='abcdefghijklmnop01234') @@ -49,24 +58,24 @@ def test_aiding_get(): def test_aiding_create(): - from signify.core import keeping mock_keeper = mock({'params': lambda: {'keeper': 'params'}}, spec=keeping.SaltyKeeper) mock_manager = mock(spec=keeping.Manager) from mockito import kwargs when(mock_manager).new('salty', 0, **kwargs).thenReturn(mock_keeper) - + keys = ['a signer verfer qb64'] ndigs = ['next signer digest'] - + when(mock_keeper).incept(transferable=True).thenReturn((keys, ndigs)) from keri.core import coring mock_serder = mock({'raw': b'raw bytes', 'ked': {'a': 'key event dictionary'}}, spec=coring.Serder) - + from keri.core import eventing - when(eventing).incept(keys=keys, isith='1', nsith='1', ndigs=ndigs, code='E', wits=[], toad='0', data=[]).thenReturn(mock_serder) + (when(eventing).incept(keys=keys, isith='1', nsith='1', ndigs=ndigs, code='E', wits=[], toad='0', data=[]) + .thenReturn(mock_serder)) when(mock_keeper).sign(mock_serder.raw).thenReturn(['a signature']) from signify.app.clienting import SignifyClient @@ -77,7 +86,9 @@ def test_aiding_create(): ids = Identifiers(client=mock_client) resp = mock({'json': lambda: {'post': 'success'}}) - when(mock_client).post('/identifiers', json={'name': 'new_aid', 'icp': {'a': 'key event dictionary'}, 'sigs': ['a signature'], 'proxy': None, 'salty': {'keeper': 'params'}, 'smids': ['a smid'], 'rmids': ['a rmid']}).thenReturn(resp) + when(mock_client).post('/identifiers', json={'name': 'new_aid', 'icp': {'a': 'key event dictionary'}, + 'sigs': ['a signature'], 'proxy': None, 'salty': {'keeper': 'params'}, + 'smids': ['a smid'], 'rmids': ['a rmid']}).thenReturn(resp) ids.create(name='new_aid', states=[{'i': 'a smid'}], rstates=[{'i': 'a rmid'}]) @@ -85,24 +96,26 @@ def test_aiding_create(): unstub() + def test_aiding_create_delegation(): from signify.core import keeping mock_keeper = mock({'params': lambda: {'keeper': 'params'}}, spec=keeping.SaltyKeeper) mock_manager = mock(spec=keeping.Manager) - + from mockito import kwargs when(mock_manager).new('salty', 0, **kwargs).thenReturn(mock_keeper) - + keys = ['a signer verfer qb64'] ndigs = ['next signer digest'] - + when(mock_keeper).incept(transferable=True).thenReturn((keys, ndigs)) from keri.core import coring mock_serder = mock({'raw': b'raw bytes', 'ked': {'a': 'key event dictionary'}}, spec=coring.Serder) - + from keri.core import eventing - when(eventing).delcept(keys=['a signer verfer qb64'], delpre='my delegation', isith='1', nsith='1', ndigs=['next signer digest'], code='E', wits=[], toad='0', data=[]).thenReturn(mock_serder) + when(eventing).delcept(keys=['a signer verfer qb64'], delpre='my delegation', isith='1', nsith='1', + ndigs=['next signer digest'], code='E', wits=[], toad='0', data=[]).thenReturn(mock_serder) when(mock_keeper).sign(mock_serder.raw).thenReturn(['a signature']) from signify.app.clienting import SignifyClient @@ -113,7 +126,10 @@ def test_aiding_create_delegation(): ids = Identifiers(client=mock_client) resp = mock({'json': lambda: {'post': 'success'}}) - when(mock_client).post('/identifiers', json={'name': 'new_aid', 'icp': {'a': 'key event dictionary'}, 'sigs': ['a signature'], 'proxy': None, 'salty': {'keeper': 'params'}, 'smids': ['a smid'], 'rmids': ['a rmid']}).thenReturn(resp) + when(mock_client).post('/identifiers', + json={'name': 'new_aid', 'icp': {'a': 'key event dictionary'}, 'sigs': ['a signature'], + 'proxy': None, 'salty': {'keeper': 'params'}, 'smids': ['a smid'], + 'rmids': ['a rmid']}).thenReturn(resp) ids.create(name='new_aid', delpre='my delegation', states=[{'i': 'a smid'}], rstates=[{'i': 'a rmid'}]) @@ -121,6 +137,7 @@ def test_aiding_create_delegation(): unstub() + def test_aiding_update_interact(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) @@ -139,6 +156,7 @@ def test_aiding_update_interact(): unstub() + def test_aiding_update_rotate(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) @@ -157,6 +175,7 @@ def test_aiding_update_rotate(): unstub() + def test_aiding_update_bad(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) @@ -172,6 +191,7 @@ def test_aiding_update_bad(): with pytest.raises(kering.KeriError): ids.update(name='aid1', typ='basil') + def test_aiding_delete(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) @@ -187,6 +207,7 @@ def test_aiding_delete(): unstub() + def test_aiding_interact_no_data(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) @@ -219,15 +240,16 @@ def test_aiding_interact_no_data(): when(mock_client).put('/identifiers/aid1?type=ixn', json=expected_data).thenReturn(mock_response) ids.interact(name='aid1') - + verify(ids).get('aid1') unstub() + def test_aiding_interact_with_data(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) - + from signify.core import keeping mock_manager = mock(spec=keeping.Manager) mock_client.manager = mock_manager @@ -240,7 +262,8 @@ def test_aiding_interact_with_data(): from keri.core import eventing, coring mock_serder = mock({'ked': {'a': 'key event dictionary'}, 'raw': b'serder raw bytes'}, spec=coring.Serder) - when(eventing).interact('hab prefix', sn=1, data=[{'some': 'data'}, {'some': 'more'}], dig='hab digest').thenReturn(mock_serder) + when(eventing).interact('hab prefix', sn=1, data=[{'some': 'data'}, {'some': 'more'}], dig='hab digest').thenReturn( + mock_serder) mock_keeper = mock({'algo': 'salty', 'params': lambda: {'keeper': 'params'}}, spec=keeping.SaltyKeeper) when(mock_manager).get(aid=mock_hab).thenReturn(mock_keeper) @@ -257,7 +280,7 @@ def test_aiding_interact_with_data(): when(mock_client).put('/identifiers/aid1?type=ixn', json=expected_data).thenReturn(mock_response) ids.interact(name='aid1', data=[{'some': 'data'}, {'some': 'more'}]) - + verify(ids).get('aid1') unstub() @@ -266,7 +289,7 @@ def test_aiding_interact_with_data(): def test_aiding_rotate(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) - + from signify.core import keeping mock_manager = mock(spec=keeping.Manager) mock_client.manager = mock_manager @@ -274,7 +297,8 @@ def test_aiding_rotate(): from signify.app.aiding import Identifiers ids = Identifiers(client=mock_client) - mock_hab = {'prefix': 'hab prefix', 'name': 'aid1', 'state': {'s': '0', 'd': 'hab digest', 'b': ['wit1', 'wit2', 'wit3'], 'k': ['key1']}} + mock_hab = {'prefix': 'hab prefix', 'name': 'aid1', + 'state': {'s': '0', 'd': 'hab digest', 'b': ['wit1', 'wit2', 'wit3'], 'k': ['key1']}} when(ids).get('aid1').thenReturn(mock_hab) mock_keeper = mock({'algo': 'salty', 'params': lambda: {'keeper': 'params'}}, spec=keeping.SaltyKeeper) @@ -282,32 +306,37 @@ def test_aiding_rotate(): keys = ['key1'] ndigs = ['ndig1'] - when(mock_keeper).rotate(ncodes=['A'], transferable=True, states=[{'i': 'state 1'}, {'i': 'state 2'}], rstates=[{'i': 'rstate 1'}, {'i': 'rstate 2'}]).thenReturn((keys, ndigs)) + when(mock_keeper).rotate(ncodes=['A'], transferable=True, states=[{'i': 'state 1'}, {'i': 'state 2'}], + rstates=[{'i': 'rstate 1'}, {'i': 'rstate 2'}]).thenReturn((keys, ndigs)) from keri.core import coring mock_serder = mock({'ked': {'a': 'key event dictionary'}, 'raw': b'serder raw bytes'}, spec=coring.Serder) from keri.core import eventing - when(eventing).rotate(pre='hab prefix', keys=['key1'], dig='hab digest', sn=1, isith='1', nsith='1', ndigs=['ndig1'], toad=None, wits=['wit1', 'wit2', 'wit3'], + when(eventing).rotate(pre='hab prefix', keys=['key1'], dig='hab digest', sn=1, isith='1', nsith='1', + ndigs=['ndig1'], toad=None, wits=['wit1', 'wit2', 'wit3'], cuts=[], adds=[], data=[]).thenReturn(mock_serder) when(mock_keeper).sign(ser=mock_serder.raw).thenReturn(['a signature']) from requests import Response mock_response = mock(spec=Response) - expected_data = {'rot': {'a': 'key event dictionary'}, 'sigs': ['a signature'], 'salty': {'keeper': 'params'}, 'smids': ['state 1', 'state 2'], 'rmids': ['rstate 1', 'rstate 2']} + expected_data = {'rot': {'a': 'key event dictionary'}, 'sigs': ['a signature'], 'salty': {'keeper': 'params'}, + 'smids': ['state 1', 'state 2'], 'rmids': ['rstate 1', 'rstate 2']} when(mock_client).put('/identifiers/aid1', json=expected_data).thenReturn(mock_response) when(mock_response).json().thenReturn({'success': 'yay'}) - out = ids.rotate(name='aid1', states=[{'i': 'state 1'}, {'i': 'state 2'}], rstates=[{'i': 'rstate 1'}, {'i': 'rstate 2'}]) + out = ids.rotate(name='aid1', states=[{'i': 'state 1'}, {'i': 'state 2'}], + rstates=[{'i': 'rstate 1'}, {'i': 'rstate 2'}]) assert out['success'] == 'yay' unstub() + def test_aiding_add_end_role(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) - + from signify.core import keeping mock_manager = mock(spec=keeping.Manager) mock_client.manager = mock_manager @@ -327,7 +356,6 @@ def test_aiding_add_end_role(): when(mock_manager).get(aid=mock_hab).thenReturn(mock_keeper) when(mock_keeper).sign(ser=mock_serder.raw).thenReturn(['a signature']) - from requests import Response mock_response = mock(spec=Response) expected_data = {'rpy': {'a': 'key event dictionary'}, 'sigs': ['a signature']} @@ -339,10 +367,11 @@ def test_aiding_add_end_role(): unstub() + def test_aiding_sign(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) - + from signify.core import keeping mock_manager = mock(spec=keeping.Manager) mock_client.manager = mock_manager @@ -368,10 +397,11 @@ def test_aiding_sign(): unstub() + def test_aiding_member(): from signify.app.clienting import SignifyClient mock_client = mock(spec=SignifyClient) - + from signify.app.aiding import Identifiers ids = Identifiers(client=mock_client) @@ -386,6 +416,7 @@ def test_aiding_member(): unstub() + def test_aiding_make_end_role(): expected_data = {'cid': 'a prefix', 'role': 'witness', 'eid': 'an eid'} diff --git a/tests/app/test_clienting.py b/tests/app/test_clienting.py index 17fcd58..0980dd9 100644 --- a/tests/app/test_clienting.py +++ b/tests/app/test_clienting.py @@ -1,3 +1,10 @@ +# -*- encoding: utf-8 -*- +""" +SIGNIFY +signify.app.test_clienting module + +Testing clienting with unit tests +""" from keri import kering from keri.core.coring import Tiers @@ -5,20 +12,22 @@ from signify.app.clienting import SignifyClient from signify.core.authing import Controller + def test_signify_client_defaults(): client = SignifyClient(passcode="abcdefghijklmnop01234") assert client.bran == "abcdefghijklmnop01234" assert client.pidx == 0 assert client.tier == Tiers.low - assert client.extern_modules == None + assert client.extern_modules is None assert isinstance(client.ctrl, Controller) - assert client.mgr == None - assert client.session == None - assert client.agent == None - assert client.authn == None - assert client.base == None + assert client.mgr is None + assert client.session is None + assert client.agent is None + assert client.authn is None + assert client.base is None + def test_signify_client_bad_passcode_length(): with pytest.raises(kering.ConfigurationError): diff --git a/tests/app/test_notifying.py b/tests/app/test_notifying.py new file mode 100644 index 0000000..8426d15 --- /dev/null +++ b/tests/app/test_notifying.py @@ -0,0 +1,74 @@ +# -*- encoding: utf-8 -*- +""" +SIGNIFY +signify.app.test_clienting module + +Testing notifying with unit tests +""" + +from mockito import mock, when, unstub + + +def test_notification_list(): + from signify.app.clienting import SignifyClient + mock_client = mock(spec=SignifyClient) + + from signify.app.notifying import Notifications + notes = Notifications(client=mock_client) + + from requests import Response + mock_response = mock({'headers': {'content-range': 'notes 0-10/20'}}, spec=Response) + when(mock_client).get('/notifications', headers=dict(Range=f"notes={0}-{24}")).thenReturn(mock_response) + when(mock_response).json().thenReturn( + ['note1', 'note2'] + ) + + out = notes.list() + assert out['start'] == 0 + assert out['end'] == 10 + assert out['total'] == 20 + assert out['notes'] == ['note1', 'note2'] + + unstub() + + +def test_noticiation_mark_as_read(): + from signify.app.clienting import SignifyClient + mock_client = mock(spec=SignifyClient) + + from signify.app.notifying import Notifications + notes = Notifications(client=mock_client) + + from requests import Response + mock_response = mock({'status': 202}, spec=Response) + when(mock_client).put('/notifications/ABC123', json={}).thenReturn(mock_response) + + out = notes.markAsRead(nid="ABC123") + assert out is True + + mock_response = mock({'status': 404}, spec=Response) + when(mock_client).put('/notifications/DEF456', json={}).thenReturn(mock_response) + + out = notes.markAsRead(nid="DEF456") + assert out is False + + +def test_noticiation_delete(): + from signify.app.clienting import SignifyClient + mock_client = mock(spec=SignifyClient) + + from signify.app.notifying import Notifications + notes = Notifications(client=mock_client) + + from requests import Response + mock_response = mock({'status': 202}, spec=Response) + when(mock_client).delete(path='/notifications/ABC123').thenReturn(mock_response) + + out = notes.delete(nid="ABC123") + assert out is True + + mock_response = mock({'status': 404}, spec=Response) + when(mock_client).delete(path='/notifications/DEF456').thenReturn(mock_response) + + out = notes.delete(nid="DEF456") + assert out is False diff --git a/tests/core/test_httping.py b/tests/core/test_httping.py index 09cb408..1318711 100644 --- a/tests/core/test_httping.py +++ b/tests/core/test_httping.py @@ -1,9 +1,10 @@ # -*- encoding: utf-8 -*- from signify.core import httping + def test_parseRangeHeader(): - out = httping.parseRangeHeader("aids 0-1/2") + out = httping.parseRangeHeader("aids 0-1/2", "aids") assert out[0] == 0 assert out[1] == 1 - assert out[2] == 2 \ No newline at end of file + assert out[2] == 2