def full_doc(doc_keys, doc_did, doc_proof, doc_controller): return RegisterDocument( did=doc_did, purpose=DIDType.TWIN, proof=doc_proof, revoked=True, metadata=Metadata.build('a label', 'a comment', 'http://a/url'), creator='did:iotics:iotHHHHKpPGWyEC4FFo4d6oyzVVk6MEEEEgY', spec_version=SUPPORTED_VERSIONS[0], update_time=get_unix_time_ms(), controller=doc_controller, public_keys={ doc_keys['#pub_key1'].name: doc_keys['#pub_key1'], doc_keys['#pub_key2'].name: doc_keys['#pub_key2'] }, auth_keys={ doc_keys['#auth_key1'].name: doc_keys['#auth_key1'], doc_keys['#auth_key2'].name: doc_keys['#auth_key2'] }, control_delegation_proof={ doc_keys['#deleg_control_key1'].name: doc_keys['#deleg_control_key1'], doc_keys['#deleg_control_key2'].name: doc_keys['#deleg_control_key2'] }, auth_delegation_proof={ doc_keys['#deleg_auth_key1'].name: doc_keys['#deleg_auth_key1'], doc_keys['#deleg_auth_key2'].name: doc_keys['#deleg_auth_key2'] })
def build_from_dict(self, data: dict) -> RegisterDocument: """ Build a valid immutable register document from dict. :param data: register document as dict :return: valid register document :raises: IdentityInvalidDocumentError: if invalid dict data IdentityInvalidDocumentError: if invalid document IdentityRegisterDocumentKeyConflictError: if key name is not unique """ try: for k in data['publicKey']: self.add_public_key_obj(RegisterPublicKey.from_dict(k)) for k in data.get('authentication', []): self.add_authentication_key_obj(RegisterAuthenticationPublicKey.from_dict(k)) for k in data.get('delegateAuthentication', []): self.add_authentication_delegation_obj(RegisterDelegationProof.from_dict(k)) for k in data.get('delegateControl', []): self.add_control_delegation_obj(RegisterDelegationProof.from_dict(k)) raw_controller = data.get('controller') controller = Issuer.from_string(raw_controller) if raw_controller else None return self.build(data['id'], DIDType(data['ioticsDIDType']), data['proof'], data.get('revoked', False), Metadata.from_dict(data.get('metadata', {})), data.get('creator'), data['ioticsSpecVersion'], data['updateTime'], controller) except (TypeError, KeyError, ValueError) as err: raise IdentityInvalidDocumentError(f'Can not parse invalid register document: \'{err}\'') from err
def test_can_build_a_register_doc_with_min_data(doc_did, doc_proof, min_doc_owner_pub_key): now_before_create = get_unix_time_ms() new_doc = RegisterDocumentBuilder() \ .add_public_key_obj(min_doc_owner_pub_key) \ .build(did=doc_did, purpose=DIDType.USER, proof=doc_proof, revoked=False) assert new_doc.did == doc_did assert new_doc.proof == doc_proof assert new_doc.purpose == DIDType.USER assert not new_doc.revoked # Default values assert new_doc.spec_version == DOCUMENT_VERSION assert new_doc.metadata == Metadata() assert not new_doc.creator assert now_before_create <= new_doc.update_time <= get_unix_time_ms() assert not new_doc.controller assert new_doc.public_keys == { min_doc_owner_pub_key.name: min_doc_owner_pub_key } assert not new_doc.auth_keys assert not new_doc.auth_delegation_proof assert not new_doc.control_delegation_proof
def test_can_build_a_register_doc_with_full_data(doc_keys, doc_did, doc_proof, doc_controller): now_before_create = get_unix_time_ms() metadata = Metadata.build('a label', 'a comment', 'http://a/url') spec_version = SUPPORTED_VERSIONS[0] creator = 'did:iotics:iotHHHHKpPGWyEC4FFo4d6oyzVVk6MEEEEgY' new_doc = RegisterDocumentBuilder() \ .add_public_key(doc_keys['#pub_key1'].name, doc_keys['#pub_key1'].base58, doc_keys['#pub_key1'].revoked) \ .add_public_key_obj(doc_keys['#pub_key2']) \ .add_authentication_key(doc_keys['#auth_key1'].name, doc_keys['#auth_key1'].base58, doc_keys['#auth_key1'].revoked) \ .add_authentication_key_obj(doc_keys['#auth_key2']) \ .add_control_delegation(doc_keys['#deleg_control_key1'].name, doc_keys['#deleg_control_key1'].controller, doc_keys['#deleg_control_key1'].proof, doc_keys['#deleg_control_key1'].revoked) \ .add_control_delegation_obj(doc_keys['#deleg_control_key2']) \ .add_authentication_delegation(doc_keys['#deleg_auth_key1'].name, doc_keys['#deleg_auth_key1'].controller, doc_keys['#deleg_auth_key1'].proof, doc_keys['#deleg_auth_key1'].revoked) \ .add_authentication_delegation_obj(doc_keys['#deleg_auth_key2']) \ .build(did=doc_did, purpose=DIDType.TWIN, proof=doc_proof, revoked=True, metadata=metadata, creator=creator, spec_version=spec_version, controller=doc_controller) assert new_doc.did == doc_did assert new_doc.proof == doc_proof assert new_doc.purpose == DIDType.TWIN assert new_doc.revoked assert new_doc.spec_version == spec_version assert new_doc.metadata == metadata assert new_doc.creator == creator assert now_before_create <= new_doc.update_time <= get_unix_time_ms() assert new_doc.controller == doc_controller assert len(new_doc.public_keys) == 2 compare_key(doc_keys['#pub_key1'], new_doc.public_keys['#pub_key1']) compare_key(doc_keys['#pub_key2'], new_doc.public_keys['#pub_key2']) assert len(new_doc.auth_keys) == 2 compare_key(doc_keys['#auth_key1'], new_doc.auth_keys['#auth_key1']) compare_key(doc_keys['#auth_key2'], new_doc.auth_keys['#auth_key2']) assert len(new_doc.control_delegation_proof) == 2 compare_delegation(doc_keys['#deleg_control_key1'], new_doc.control_delegation_proof['#deleg_control_key1']) compare_delegation(doc_keys['#deleg_control_key2'], new_doc.control_delegation_proof['#deleg_control_key2']) assert len(new_doc.public_keys) == 2 compare_delegation(doc_keys['#deleg_auth_key1'], new_doc.auth_delegation_proof['#deleg_auth_key1']) compare_delegation(doc_keys['#deleg_auth_key2'], new_doc.auth_delegation_proof['#deleg_auth_key2'])
def test_can_build_doc_metadata(): label = 'a label' comment = 'a comment' url = 'http://an/url' metadata = Metadata.build(label, comment, url) assert metadata.label == label assert metadata.comment == comment assert metadata.url == url assert metadata.to_dict() == { 'label': label, 'comment': comment, 'url': url }
def test_can_serialise_a_minimal_doc_to_dict(minimal_doc, min_doc_owner_pub_key): dict_doc = minimal_doc.to_dict() assert dict_doc.pop('updateTime') == minimal_doc.update_time assert dict_doc == { '@context': 'https://w3id.org/did/v1', 'id': minimal_doc.did, 'ioticsDIDType': minimal_doc.purpose.value, 'ioticsSpecVersion': minimal_doc.spec_version, 'metadata': Metadata().to_dict(), 'revoked': minimal_doc.revoked, 'proof': minimal_doc.proof, 'publicKey': [min_doc_owner_pub_key.to_dict()], 'authentication': [], 'delegateControl': [], 'delegateAuthentication': [], }
def build(self, did: str, purpose: DIDType, proof: str, revoked: bool, metadata: Metadata = Metadata(), creator: Optional[str] = None, spec_version: Optional[str] = DOCUMENT_VERSION, update_time: Optional[int] = None, controller: Issuer = None) -> RegisterDocument: """ Build a valid immutable register document. :param did: register document decentralised identifier :param purpose: register document purpose (HOST, TWIN, USER or AGENT) :param proof: register document proof :param revoked: is register document revoked :param metadata: register document optional metadata. :param creator: register document optional creator identifier. :param spec_version: register document version (default=DOCUMENT_VERSION) :param update_time: register document update time (unix time ms). Automatically set to know if not provided. :param controller: register document optional controller :return: valid register document :raises: IdentityInvalidDocumentError: if version ot supported IdentityValidationError: if invalid controller IdentityInvalidDocumentError: if invalid document (no controller and no public key) """ IdentityValidation.validate_identifier(did) if spec_version not in SUPPORTED_VERSIONS: raise IdentityInvalidDocumentError(f'Unsupported version {spec_version} not in {SUPPORTED_VERSIONS}') if creator: IdentityValidation.validate_identifier(creator) if not controller and not self.public_keys: raise IdentityInvalidDocumentError('Invalid document, no Controller or Public Keys provided') return RegisterDocument(did=did, purpose=purpose, proof=proof, revoked=revoked, metadata=metadata, creator=creator, public_keys=self.public_keys, auth_keys=self.auth_keys, control_delegation_proof=self.control_delegations, auth_delegation_proof=self.auth_delegations, spec_version=spec_version, update_time=update_time or get_unix_time_ms(), controller=controller)
def test_build_doc_metadata_raises_validaion_error_in_invalid_data( invalid_input): params = dict(label='a label', comment='a comment', url='http://an/url') params.update(invalid_input) with pytest.raises(IdentityValidationError): Metadata.build(**params)
def test_can_build_doc_metadata_from_dict(): data = {'label': 'a label', 'comment': 'a comment', 'url': 'http://an/url'} metadata = Metadata.from_dict(data) assert metadata.label == data['label'] assert metadata.comment == data['comment'] assert metadata.url == data['url']
def test_can_build_a_register_doc_from_an_other_doc_overriding_values( full_doc): existing_doc = full_doc new_creator = 'did:iotics:iotEEEEKpPGWyEC4FFo4d6oyzVVk6MEEEEgY' new_controller = Issuer.build( 'did:iotics:iotEEEEKpPGWyEC4FFo4d6oyzHHHHMEEEEgY', '#NewController') new_metadata = Metadata(label='a label') new_version = SUPPORTED_VERSIONS[0] new_pub_key = RegisterPublicKey(name='#new_pub_key1', base58=get_public_base_58_key(), revoked=False) new_auth_key = RegisterAuthenticationPublicKey( name='#new_auth_key1', base58=get_public_base_58_key(), revoked=False) a_controller = Issuer.from_string( 'did:iotics:iotHjrmKpPGWyEC4FFo4d6oyzVVk6MXEEEEE#AController') new_control_deleg_proof = RegisterDelegationProof( name='#new_deleg_control_key1', controller=a_controller, proof='a_deleg_proof_validated_by_the_resolver', revoked=False) new_auth_deleg_key = RegisterDelegationProof( name='#new_deleg_auth_key1', controller=a_controller, proof='a_deleg_proof_validated_by_the_resolver', revoked=False) new_doc = RegisterDocumentBuilder() \ .add_public_key_obj(new_pub_key) \ .add_authentication_key_obj(new_auth_key) \ .add_control_delegation_obj(new_control_deleg_proof) \ .add_authentication_delegation_obj(new_auth_deleg_key) \ .build_from_existing(existing_doc, revoked=True, metadata=new_metadata, creator=new_creator, spec_version=new_version, controller=new_controller) # Can not change assert new_doc.did == existing_doc.did assert new_doc.purpose == existing_doc.purpose assert new_doc.proof == existing_doc.proof # Overridden values assert new_doc.revoked assert new_doc.metadata == new_metadata assert new_doc.creator == new_creator assert new_doc.spec_version == new_version assert new_doc.controller == new_controller assert new_doc.public_keys == { **existing_doc.public_keys, **{ new_pub_key.name: new_pub_key } } assert new_doc.auth_keys == { **existing_doc.auth_keys, **{ new_auth_key.name: new_auth_key } } assert new_doc.control_delegation_proof == { **existing_doc.control_delegation_proof, **{ new_control_deleg_proof.name: new_control_deleg_proof } } assert new_doc.auth_delegation_proof == { **existing_doc.auth_delegation_proof, **{ new_auth_deleg_key.name: new_auth_deleg_key } } assert new_doc.update_time >= existing_doc.update_time