1
1
import json
2
2
import re
3
- from typing import Any , Dict , Optional
3
+ from typing import Any , Callable , Dict , Optional , Union
4
4
from base58 import b58decode , b58encode
5
5
from hashlib import sha256
6
6
7
- from .doc_visitor import DocVisitor
8
7
9
8
# Regex patterns
10
9
BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
@@ -90,21 +89,63 @@ def decode(did: str) -> Dict[str, Any]:
90
89
return _decode_doc (encoded_doc )
91
90
92
91
93
- def decoded_to_resolved (did : str , document : dict ) -> dict :
94
- """Add DID and controller to verification methods and relationships."""
92
+ def _operate_on_embedded (
93
+ visitor : Callable [[dict ], dict ]
94
+ ) -> Callable [[Union [dict , str ]], Union [dict , str ]]:
95
+ """Return an adapter function that turns a vm visitor into a vm | ref visitor.
96
+
97
+ The adapter function calls a visitor on embedded vms but just returns on refs.
98
+ """
99
+
100
+ def _adapter (vm : Union [dict , str ]) -> Union [dict , str ]:
101
+ if isinstance (vm , dict ):
102
+ return visitor (vm )
103
+ return vm
104
+
105
+ return _adapter
95
106
96
- class Visitor (DocVisitor ):
97
- def visit_verification_method (self , value : dict ):
98
- if "controller" not in value :
99
- value ["controller" ] = did
100
- return value
101
107
102
- def visit_verification_relationship_embedded (self , value : dict ):
103
- if "controller" not in value :
104
- value ["controller" ] = did
105
- return value
108
+ def _visit_verification_methods (document : dict , visitor : Callable [[dict ], dict ]):
109
+ """Visit all verification methods in a document.
110
+
111
+ This includes the main verificationMethod list as well as verification
112
+ methods embedded in relationships.
113
+ """
114
+ verification_methods = document .get ("verificationMethod" )
115
+ if verification_methods :
116
+ document ["verificationMethod" ] = [visitor (vm ) for vm in verification_methods ]
117
+
118
+ for relationship in (
119
+ "authentication" ,
120
+ "assertionMethod" ,
121
+ "keyAgreement" ,
122
+ "capabilityInvocation" ,
123
+ "capabilityDelegation" ,
124
+ ):
125
+ vms_and_refs = document .get (relationship )
126
+ if vms_and_refs :
127
+ document [relationship ] = [
128
+ _operate_on_embedded (visitor )(vm ) for vm in vms_and_refs
129
+ ]
106
130
107
- document = Visitor (document ).visit ()
131
+ return document
132
+
133
+
134
+ def contextualize_document (did : str , document : dict ) -> dict :
135
+ """Perform contextualization of the document with the given DID.
136
+
137
+ This includes setting the id and alsoKnownAs fields as well as setting the
138
+ controller for all verification methods (including verification methods
139
+ embedded in verification relationships), if not already set.
140
+ """
141
+ document ["id" ] = did
142
+
143
+ def _visitor (value : dict ):
144
+ if "controller" not in value :
145
+ value ["controller" ] = did
146
+ return value
147
+
148
+ document = _visit_verification_methods (document , _visitor )
108
149
return document
109
150
110
151
@@ -123,9 +164,8 @@ def resolve(did: str) -> Dict[str, Any]:
123
164
"""
124
165
125
166
decoded = decode (did )
126
- document = decoded_to_resolved (did , decoded )
167
+ document = contextualize_document (did , decoded )
127
168
document .setdefault ("alsoKnownAs" , []).append (long_to_short (did ))
128
- document ["id" ] = did
129
169
return document
130
170
131
171
@@ -136,9 +176,8 @@ def resolve_short(did: str):
136
176
"""
137
177
decoded = decode (did )
138
178
short_did = long_to_short (did )
139
- document = decoded_to_resolved (short_did , decoded )
179
+ document = contextualize_document (short_did , decoded )
140
180
document .setdefault ("alsoKnownAs" , []).append (did )
141
- document ["id" ] = short_did
142
181
return document
143
182
144
183
0 commit comments