Skip to content

Commit

Permalink
Merge pull request #1314 from andrewwhitehead/pub-did-posture
Browse files Browse the repository at this point in the history
Set DID posture to posted when assigned as the public DID
  • Loading branch information
andrewwhitehead authored Jul 14, 2021
2 parents 0566a07 + 7fe475c commit e222b9d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 21 deletions.
56 changes: 40 additions & 16 deletions aries_cloudagent/wallet/askar.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ async def create_signing_key(
Raises:
WalletDuplicateError: If the resulting verkey already exists in the wallet
WalletError: If there is an aries_askar error
WalletError: If there is another backend error
"""

Expand Down Expand Up @@ -112,7 +112,7 @@ async def get_signing_key(self, verkey: str) -> KeyInfo:
Raises:
WalletNotFoundError: If no keypair is associated with the verification key
WalletError: If there is a aries_askar error
WalletError: If there is another backend error
"""

Expand Down Expand Up @@ -173,7 +173,7 @@ async def create_local_did(
Raises:
WalletDuplicateError: If the DID already exists in the wallet
WalletError: If there is a aries_askar error
WalletError: If there is another backend error
"""

Expand Down Expand Up @@ -250,8 +250,6 @@ async def create_local_did(
did=did, verkey=verkey, metadata=metadata, method=method, key_type=key_type
)

# FIXME implement get_public_did more efficiently (store lookup record)

async def get_local_dids(self) -> Sequence[DIDInfo]:
"""
Get list of defined local DIDs.
Expand All @@ -278,7 +276,7 @@ async def get_local_did(self, did: str) -> DIDInfo:
Raises:
WalletNotFoundError: If the DID is not found
WalletError: If there is an aries_askar error
WalletError: If there is another backend error
"""

Expand Down Expand Up @@ -350,9 +348,12 @@ async def get_public_did(self) -> DIDInfo:
"""
public_did = None
public_info = None
public_item = None
storage = AskarStorage(self._session)
try:
public = await storage.get_record(CATEGORY_CONFIG, RECORD_NAME_PUBLIC_DID)
public_item = await storage.get_record(
CATEGORY_CONFIG, RECORD_NAME_PUBLIC_DID
)
except StorageNotFoundError:
# populate public DID record
# this should only happen once, for an upgraded wallet
Expand All @@ -375,9 +376,11 @@ async def get_public_did(self) -> DIDInfo:
)
except StorageDuplicateError:
# another process stored the record first
pass
else:
public_did = json.loads(public.value)["did"]
public_item = await storage.get_record(
CATEGORY_CONFIG, RECORD_NAME_PUBLIC_DID
)
if public_item:
public_did = json.loads(public_item.value)["did"]
if public_did:
try:
public_info = await self.get_local_did(public_did)
Expand All @@ -396,17 +399,38 @@ async def set_public_did(self, did: Union[str, DIDInfo]) -> DIDInfo:
"""

if isinstance(did, str):
# will raise an exception if not found
info = await self.get_local_did(did)
try:
item = await self._session.handle.fetch(
CATEGORY_DID, did, for_update=True
)
except AskarError as err:
raise WalletError("Error when fetching local DID") from err
if not item:
raise WalletNotFoundError("Unknown DID: {}".format(did))
info = _load_did_entry(item)
else:
info = did
item = None

if info.method != DIDMethod.SOV:
raise WalletError("Setting public DID is only allowed for did:sov DIDs")

public = await self.get_public_did()
if not public or public.did != info.did:
storage = AskarStorage(self._session)
if not info.metadata.get("posted"):
metadata = {**info.metadata, "posted": True}
if item:
entry_val = item.value_json
entry_val["metadata"] = metadata
await self._session.handle.replace(
CATEGORY_DID, did, value_json=entry_val, tags=item.tags
)
else:
await self.replace_local_did_metadata(info.did, metadata)
info = info._replace(
metadata=metadata,
)
await storage.update_record(
StorageRecord(
type=CATEGORY_CONFIG,
Expand Down Expand Up @@ -558,7 +582,7 @@ async def sign_message(
Raises:
WalletError: If the message is not provided
WalletError: If the verkey is not provided
WalletError: If an aries_askar error occurs
WalletError: If another backend error occurs
"""
if not message:
Expand Down Expand Up @@ -606,7 +630,7 @@ async def verify_message(
WalletError: If the verkey is not provided
WalletError: If the signature is not provided
WalletError: If the message is not provided
WalletError: If an aries_askar error occurs
WalletError: If another backend error occurs
"""
if not from_verkey:
Expand Down Expand Up @@ -649,7 +673,7 @@ async def pack_message(
Raises:
WalletError: If no message is provided
WalletError: If an aries_askar error occurs
WalletError: If another backend error occurs
"""
if message is None:
Expand Down Expand Up @@ -680,7 +704,7 @@ async def unpack_message(self, enc_message: bytes) -> Tuple[str, str, str]:
Raises:
WalletError: If the message is not provided
WalletError: If an aries_askar error occurs
WalletError: If another backend error occurs
"""
if not enc_message:
Expand Down
15 changes: 11 additions & 4 deletions aries_cloudagent/wallet/indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,10 @@ async def get_public_did(self) -> DIDInfo:

public_did = None
public_info = None
public_item = None
storage = IndySdkStorage(self.opened)
try:
public = await storage.get_record(
public_item = await storage.get_record(
RECORD_TYPE_CONFIG, RECORD_NAME_PUBLIC_DID
)
except StorageNotFoundError:
Expand All @@ -647,9 +648,11 @@ async def get_public_did(self) -> DIDInfo:
)
except StorageDuplicateError:
# another process stored the record first
pass
else:
public_did = json.loads(public.value)["did"]
public_item = await storage.get_record(
RECORD_TYPE_CONFIG, RECORD_NAME_PUBLIC_DID
)
if public_item:
public_did = json.loads(public_item.value)["did"]
if public_did:
try:
public_info = await self.get_local_did(public_did)
Expand Down Expand Up @@ -678,6 +681,10 @@ async def set_public_did(self, did: Union[str, DIDInfo]) -> DIDInfo:

public = await self.get_public_did()
if not public or public.did != info.did:
if not info.metadata.get("posted"):
metadata = {**info.metadata, "posted": True}
await self.replace_local_did_metadata(info.did, metadata)
info = info._replace(metadata=metadata)
storage = IndySdkStorage(self.opened)
await storage.update_record(
StorageRecord(
Expand Down
6 changes: 5 additions & 1 deletion aries_cloudagent/wallet/tests/test_in_memory_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,24 +403,28 @@ async def test_set_public_did(self, wallet: InMemoryWallet):
self.test_sov_did,
self.test_metadata,
)
assert not info.metadata.get("posted")

with pytest.raises(WalletNotFoundError):
await wallet.set_public_did("55GkHamhTU1ZbTbV2ab9DF")

# test assign
info_same = await wallet.set_public_did(info.did)
assert info_same.did == info.did
assert info_same.metadata.get("posted")

info_new = await wallet.create_local_did(DIDMethod.SOV, KeyType.ED25519)
assert info_new.did != info_same.did

loc = await wallet.get_local_did(self.test_sov_did)
pub = await wallet.set_public_did(loc.did)
pub = await wallet.set_public_did(loc)
assert pub.did == loc.did
assert pub.metadata.get("posted")

# test replace
info_final = await wallet.set_public_did(info_new.did)
assert info_final.did == info_new.did
assert info_final.metadata.get("posted")

@pytest.mark.asyncio
async def test_set_public_did_x_not_sov(self, wallet: InMemoryWallet):
Expand Down

0 comments on commit e222b9d

Please sign in to comment.