def step_impl(context, inviter: str, invitee: str): inviter_url = context.config.userdata.get(inviter) invitee_url = context.config.userdata.get(invitee) assert inviter in context.connection_id_dict, f'no connection IDs saved for "{inviter}"' assert invitee in context.connection_id_dict[inviter], f'no connection ID saved from "{inviter}" to "{invitee}"' inviter_connection_id = context.connection_id_dict[inviter][invitee] assert invitee in context.connection_id_dict, f'no connection IDs saved for "{invitee}"' assert inviter in context.connection_id_dict[invitee], f'no connection ID saved from "{invitee}" to "{inviter}"' invitee_connection_id = context.connection_id_dict[invitee][inviter] (resp_status, resp_text) = agent_backchannel_GET( inviter_url + "/agent/command/", "connection", id=inviter_connection_id, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" inviter_connection = resp_text (resp_status, resp_text) = agent_backchannel_GET( invitee_url + "/agent/command/", "connection", id=invitee_connection_id, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" invitee_connection = resp_text
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) credential_revocation = { "cred_rev_id": context.cred_rev_id, "rev_registry_id": context.rev_reg_id, "publish_immediately": True, } (resp_status, resp_text) = agent_backchannel_POST(issuer_url + "/agent/command/", "revocation", operation="revoke", data=credential_revocation) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' #resp_json = json.loads(resp_text) # Check the Holder wallet for the credential # Should be a 200 since the revoke doesn't remove the cred from the holders wallet. # What else to check? (resp_status, resp_text) = agent_backchannel_GET(context.config.userdata.get(context.holder_name) + "/agent/command/", "credential", id=context.credential_id_dict[context.schema['schema_name']][len(context.credential_id_dict[context.schema['schema_name']])-1]) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' # if this is ACA-py then there is provision for the holder to check the revocation status of the cred then they can take action, # like delete it from thier wallet. This should be done, since the algorithm that if "delete_cred_from_wallet" in context.tags: # Call the revocation status api #(resp_status, resp_text) = agent_backchannel_GET(context.prover_url + "/agent/command/", "revocation", operation="credential-record", data=credential_revocation) (resp_status, resp_text) = agent_backchannel_GET(context.prover_url + "/agent/command/", "credential", operation="revoked", id=context.credential_id_dict[context.schema['schema_name']][len(context.credential_id_dict[context.schema['schema_name']])-1]) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' # get the credential status verified out of the response # Could also add the cred status to the cred id dict. Maybe later if needed. resp_json = json.loads(resp_text) revoked = resp_json["revoked"] if revoked == True: # Call the delete on the credential in the wallet (resp_status, resp_text) = agent_backchannel_DELETE(context.prover_url + "/agent/command/", "credential", id=context.credential_id_dict[context.schema['schema_name']][len(context.credential_id_dict[context.schema['schema_name']])-1]) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}'
def step_impl(context, holder): holder_url = context.config.userdata.get(holder) # get the credential from the holders wallet (resp_status, resp_text) = agent_backchannel_GET(holder_url + "/agent/command/", "credential", id=context.credential_id_dict[context.schema['schema_name']]) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) assert resp_json["referent"] == context.credential_id_dict[context.schema['schema_name']] assert resp_json["schema_id"] == context.issuer_schema_id_dict[context.schema["schema_name"]] assert resp_json["cred_def_id"] == context.credential_definition_id_dict[context.schema["schema_name"]] # Make sure the issuer is not holding the credential # get the credential from the holders wallet (resp_status, resp_text) = agent_backchannel_GET(context.issuer_url + "/agent/command/", "credential", id=context.credential_id_dict[context.schema['schema_name']]) assert resp_status == 404, f'resp_status {resp_status} is not 404; {resp_text}'
def step_impl(context, requester, responder): requester_url = context.config.userdata.get(requester) requester_did = context.requester_did data = { "their_public_did": requester_did } (resp_status, resp_text) = agent_backchannel_POST(requester_url + "/agent/command/", "did-exchange", operation="create-request-resolvable-did", data=data) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) requester_did_doc = resp_json context.requester_public_did_doc = requester_did_doc # get the requesters connection id request_id = context.requester_public_did_doc["@id"] (resp_status, resp_text) = agent_backchannel_GET(requester_url + "/agent/response/", "did-exchange", id=request_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) # setup the initial connection id dictionary if one doesn't exist. if not hasattr(context, 'connection_id_dict'): context.connection_id_dict = {} # Check for responder key existing in dict if requester not in context.connection_id_dict: context.connection_id_dict[requester] = {} # Some agents (afgo) do not have a webhook that give a connection id at this point in the protocol. # If it is not here, skip this and check for one later in the process and add it then. if "connection_id" in resp_text: context.connection_id_dict[requester][context.responder_name] = resp_json["connection_id"]
def step_impl(context, responder): responder_url = context.config.userdata.get(responder) # If the connection id dict is not populated for the responder to requester relationship, it means the agent in use doesn't # support giving the responders connection_id before the send-request # Make a call to the responder for the connection id and add it to the collection if context.requester_name not in context.connection_id_dict[responder]: # One way (maybe preferred) to get the connection id is to get it from the probable webhook that the controller gets because of the previous step invitation_id = context.responder_invitation["@id"] (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange", id=invitation_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) # The second way to do this is to call the connection protocol for the connection id given the invitation_id or a thread id. # This method is disabled for now, will be enabled if afgo can't get the connection id for the webhook above. #(resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/command/", connections, id=invitation_id) if "connection_id" in resp_text: context.connection_id_dict[responder][ context.requester_name] = resp_json["connection_id"] responder_connection_id = context.connection_id_dict[responder][ context.requester_name] # responder already recieved the connection request in the send-request call so get connection and verify status. #assert expected_agent_state(responder_url, "didexchange", responder_connection_id, "request-recieved") #invitation_id = context.responder_invitation["@id"] assert expected_agent_state(responder_url, "connection", responder_connection_id, "request-received")
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) (resp_status, resp_text) = agent_backchannel_GET(issuer_url + "/agent/command/", "did") assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) issuer_did = resp_json if "schema" not in context: # check for a schema already loaded in the context. If it is not, load the template if "schema" not in context: context.schema = SCHEMA_TEMPLATE.copy() context.schema[ "schema_name"] = context.schema["schema_name"] + issuer #context.issuer_did = issuer_did["did"] if 'issuer_did_dict' in context: context.issuer_did_dict[ context.schema['schema_name']] = issuer_did["did"] else: context.issuer_did_dict = { context.schema['schema_name']: issuer_did["did"] }
def step_impl(context, holder): holder_url = context.config.userdata.get(holder) # get the credential from the holders wallet (resp_status, resp_text) = agent_backchannel_GET( holder_url + "/agent/command/", "credential", id=context.credential_id_dict[context.schema["schema_name"]] [len(context.credential_id_dict[context.schema["schema_name"]]) - 1], ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) if "state" in resp_json and resp_json["state"] == "N/A": # backchannel can't get the credential pass else: schema_name = context.schema["schema_name"] credentials = context.credential_id_dict[schema_name] # Check with last credential id assert resp_json["referent"] == credentials[-1] # Some agents don't return or have a schema id or cred_def_id, so only check it it exists. if "schema_id" in resp_json: assert resp_json["schema_id"] == context.issuer_schema_id_dict[ schema_name] if "cred_def_id" in resp_json: assert (resp_json["cred_def_id"] == context.credential_definition_id_dict[schema_name])
def step_impl(context, responder): responder_url = context.config.userdata.get(responder) # If the connection id dict is not populated for the responder to requester relationship, it means the agent in use doesn't # support giving the responders connection_id before the send-request # Make a call to the responder for the connection id and add it to the collection if context.requester_name not in context.connection_id_dict[responder]: # One way (maybe preferred) to get the connection id is to get it from the probable webhook that the controller gets because of the previous step invitation_id = context.responder_invitation["@id"] time.sleep(0.5) # delay for webhook to execute (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange", id=invitation_id) # {} assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) # The second way to do this is to call the connection protocol for the connection id given the invitation_id or a thread id. # This method is disabled for now, will be enabled if afgo can't get the connection id for the webhook above. # (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/command/", connections, id=invitation_id) if "connection_id" in resp_text: context.connection_id_dict[responder][ context.requester_name] = resp_json["connection_id"] else: assert False, f"Could not retreive responders connection_id"
def step_impl(context, responder: str): responder_url = context.config.userdata.get(responder) # If the connection id dict is not populated for the responder to requester relationship, it means the agent in use doesn't # support giving the responders connection_id before the send-request # Make a call to the responder for the connection id and add it to the collection if context.requester_name not in context.connection_id_dict[responder]: # One way (maybe preferred) to get the connection id is to get it from the probable webhook that the controller gets because of the previous step invitation_id = context.responder_invitation["@id"] time.sleep(0.5) # delay for webhook to execute (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange", id=invitation_id) # {} assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) if "connection_id" not in resp_text: # If we weren't able to find the connection_id it means the request # probably never arrived. We don't have to do a check return context.connection_id_dict[responder][ context.requester_name] = resp_json["connection_id"] # Check the request never arrived assert expected_agent_state( responder_url, "did-exchange", context.connection_id_dict[responder][context.requester_name], ["invitation-sent"])
def step_impl(context, requester: str, responder: str): requester_url = context.config.userdata.get(requester) requester_did = context.requester_did data = {"their_public_did": requester_did, "their_did": requester_did} (resp_status, resp_text) = agent_backchannel_POST( requester_url + "/agent/command/", "did-exchange", operation="create-request-resolvable-did", data=data, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) requester_did_doc = resp_json context.requester_public_did_doc = requester_did_doc if "connection_id" not in resp_json: # get the requesters connection id request_id = context.requester_public_did_doc["@id"] (resp_status, resp_text) = agent_backchannel_GET(requester_url + "/agent/response/", "did-exchange", id=request_id) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) # Some agents (afgo) do not have a webhook that give a connection id at this point in the protocol. # If it is not here, skip this and check for one later in the process and add it then. if "connection_id" in resp_text: context.connection_id_dict[requester][responder] = resp_json[ "connection_id"]
def step_impl(context, requester): requester_url = context.config.userdata.get(requester) (resp_status, resp_text) = agent_backchannel_GET(requester_url + "/agent/command/", "did") assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) context.requester_public_did = resp_json
def step_impl(context, invitee): invitee_url = context.config.userdata.get(invitee) data = context.inviter_invitation # If mediator is set for the current connection, set the mediator_connection_id mediator = context.mediator_dict.get(invitee) if mediator: data["mediator_connection_id"] = context.connection_id_dict[invitee][ mediator] (resp_status, resp_text) = agent_backchannel_POST( invitee_url + "/agent/command/", "connection", operation="receive-invitation", data=data, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) context.connection_id_dict[invitee][ context.inviter_name] = resp_json["connection_id"] # Also add the inviter into the main connection_id_dict. if the len is 0 that means its already been cleared and this may be Mallory. if len(context.temp_connection_id_dict) != 0: context.connection_id_dict[context.inviter_name][ invitee] = context.temp_connection_id_dict[context.inviter_name] # clear the temp connection id dict used in the initial step. We don't need it anymore. context.temp_connection_id_dict.clear() else: # This means the connection id was not retreived for the inviter in the create invitation step # Get the connection id for the inviter given the invitation_id (alt_resp_status, alt_resp_text) = agent_backchannel_GET( context.inviter_url + "/agent/response/", "connection", id=context.inviter_invitation["@id"], ) assert (alt_resp_status == 200 ), f"resp_status {alt_resp_status} is not 200; {alt_resp_text}" alt_resp_json = json.loads(alt_resp_text) context.connection_id_dict[ context.inviter_name][invitee] = alt_resp_json["connection_id"] # Check to see if the invitee_name exists in context. If not, antother suite is using it so set the invitee name and url if not context.invitee_name: context.invitee_url = invitee_url context.invitee_name = invitee # get connection and verify status assert expected_agent_state( invitee_url, "connection", context.connection_id_dict[invitee][context.inviter_name], "invited", )
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) (resp_status, resp_text) = agent_backchannel_GET(issuer_url + "/agent/command/", "did") assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) issuer_did = resp_json context.issuer_did = issuer_did["did"]
def step_impl(context, holder, cred_format): holder_url = context.config.userdata.get(holder) # a credential id shouldn't be needed with a cred_ex_id being passed # credential_id = { # "credential_id": context.cred_thread_id, # } credential_id = {"comment": "storing credential"} sleep(1) (resp_status, resp_text) = agent_backchannel_POST(holder_url + "/agent/command/", "issue-credential-v2", operation="store", id=context.cred_thread_id, data=credential_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) assert resp_json["state"] == "done" #credential_id = resp_json[cred_format]["credential_id"] credential_id = resp_json["cred_ex_record"]["cred_id_stored"] if 'credential_id_dict' in context: try: context.credential_id_dict[context.schema['schema_name']].append( credential_id) except KeyError: context.credential_id_dict[context.schema['schema_name']] = [ credential_id ] else: context.credential_id_dict = { context.schema['schema_name']: [credential_id] } # Verify issuer status # TODO This is returning none instead of Done. Should this be the case. Needs investigation. #assert expected_agent_state(context.issuer_url, "issue-credential-v2", context.cred_thread_id, "done") # if the credential supports revocation, get the Issuers webhook callback JSON from the store command # From that JSON save off the credential revocation identifier, and the revocation registry identifier. if "support_revocation" in context: if context.support_revocation: (resp_status, resp_text) = agent_backchannel_GET( context.config.userdata.get(context.issuer_name) + "/agent/response/", "revocation-registry", id=context.cred_thread_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) context.cred_rev_id = resp_json["revocation_id"] context.rev_reg_id = resp_json["revoc_reg_id"]
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) issuer_schema_id = context.issuer_schema_id_dict[context.schema['schema_name']] (resp_status, resp_text) = agent_backchannel_GET(issuer_url + "/agent/command/", "schema", id=issuer_schema_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) #context.issuer_schema = resp_json if 'issuer_schema_dict' in context: context.issuer_schema_dict[context.schema['schema_name']] = resp_json else: context.issuer_schema_dict = {context.schema['schema_name']: resp_json}
def step_impl(context, invitee): invitee_url = context.config.userdata.get(invitee) data = context.inviter_invitation (resp_status, resp_text) = agent_backchannel_POST(invitee_url + "/agent/command/", "connection", operation="receive-invitation", data=data) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) if not hasattr(context, 'connection_id_dict'): context.connection_id_dict = {} context.connection_id_dict[invitee] = {} context.connection_id_dict[invitee][ context.inviter_name] = resp_json["connection_id"] # Also add the inviter into the main connection_id_dict. if the len is 0 that means its already been cleared and this may be Mallory. if "temp_connection_id_dict" in context: if len(context.temp_connection_id_dict) != 0: context.connection_id_dict[context.inviter_name] = { invitee: context.temp_connection_id_dict[context.inviter_name] } #clear the temp connection id dict used in the initial step. We don't need it anymore. context.temp_connection_id_dict.clear() else: # This means the connection id was not retreived for the inviter in the create invitation step # Get the connection id for the inviter given the invitation_id #context.connection_id_dict[context.inviter_name] = {invitee: resp_json["connection_id"]} (alt_resp_status, alt_resp_text) = agent_backchannel_GET( context.inviter_url + "/agent/response/", "connection", id=context.inviter_invitation["@id"]) assert alt_resp_status == 200, f'resp_status {alt_resp_status} is not 200; {alt_resp_text}' alt_resp_json = json.loads(alt_resp_text) context.connection_id_dict[context.inviter_name] = { invitee: alt_resp_json["connection_id"] } # Check to see if the invitee_name exists in context. If not, another suite is using it so set the invitee name and url if not hasattr(context, 'invitee_name'): context.invitee_url = invitee_url context.invitee_name = invitee # get connection and verify status assert expected_agent_state( invitee_url, "connection", context.connection_id_dict[invitee][context.inviter_name], "invited")
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) issuer_schema_id = context.issuer_schema_id_dict[ context.schema["schema_name"]] (resp_status, resp_text) = agent_backchannel_GET(issuer_url + "/agent/command/", "schema", id=issuer_schema_id) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) context.issuer_schema_dict[context.schema["schema_name"]] = resp_json
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) issuer_credential_definition_id = context.credential_definition_id (resp_status, resp_text) = agent_backchannel_GET(issuer_url + "/agent/command/", "credential-definition", id=issuer_credential_definition_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) issuer_credential_definition = resp_json context.issuer_credential_definition = issuer_credential_definition
def step_impl(context, responder: str, requester: str): responder_url = context.config.userdata.get(responder) data = {"use_public_did": False} # If mediator is set for the current connection, set the mediator_connection_id mediator = context.mediator_dict.get(responder) if mediator: data["mediator_connection_id"] = context.connection_id_dict[responder][ mediator] (resp_status, resp_text) = agent_backchannel_POST( responder_url + "/agent/command/", "out-of-band", operation="send-invitation-message", data=data, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) assert resp_json["state"] == "invitation-sent" context.responder_invitation = resp_json["invitation"] # TODO drill into the handshake protocol in the invitation and remove anything else besides didexchange. # Get the responders's connection id from the above request's response webhook in the backchannel invitation_id = context.responder_invitation["@id"] (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange", id=invitation_id) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) # Some agents (afgo) do not have a webhook that give a connection id at this point in the protocol. # If it is not here, skip this and check for one later in the process and add it then. if "connection_id" in resp_text: context.connection_id_dict[responder][requester] = resp_json[ "connection_id"] # Check to see if the responder name is the same as this person. If not, it is a 3rd person acting as an issuer that needs a connection # TODO: it would be nicer to pass the names on every call to remove the need for global keeping of who's the requester / responder if context.responder_name != responder: context.responder_name = responder context.responder_url = responder_url if context.requester_name != requester: context.requester_name = requester context.requester_url = context.config.userdata.get(requester)
def step_impl(context, inviter: str, invitee: str): inviter_url = context.config.userdata.get(inviter) invitation = context.invitation_v2[inviter] invitation_id = invitation["id"] (resp_status, resp_text) = agent_backchannel_GET( inviter_url + "/agent/command/", "oob-v2", operation="invitation-connection", id=invitation_id, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) context.connection_id_dict[inviter][invitee] = resp_json["connection_id"]
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) (resp_status, resp_text) = agent_backchannel_GET(issuer_url + "/agent/command/", "issue-credential-v3", id="retrieve-credential-proposal") credential_proposal = json.loads(resp_text) pthid_from_proposal = credential_proposal["pthid"] expected_pthid = context.invitation_v2[issuer]["id"] assert pthid_from_proposal == expected_pthid, \ f"Failed to correlate the credential proposal with the out of band invitation. " \ f"The pthid in the proposal is {pthid_from_proposal} but {expected_pthid} was expected."
def step_impl(context, issuer): issuer_url = context.config.userdata.get(issuer) (resp_status, resp_text) = agent_backchannel_GET(issuer_url + "/agent/command/", "issue-credential-v3", id="retrieve-credential-application") assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' credential_application_attachment = json.loads(resp_text) manifest_id_in_credential_application = credential_application_attachment[ "credential_application"]["manifest_id"] assert manifest_id_in_credential_application == context.manifest_id, \ f"Credential Manifest ID in the received Credential Application ({manifest_id_in_credential_application}) " \ f"is unknown. Was expecting {context.manifest_id}"
def step_impl(context, responder): responder_url = context.config.userdata.get(responder) # If the connection id dict is not populated for the responder to requester relationship, it means the agent in use doesn't # support giving the responders connection_id before the send-request # Make a call to the responder for the connection id and add it to the collection if context.requester_name not in context.connection_id_dict[responder]: # One way (maybe preferred) to get the connection id is to get it from the probable webhook that the controller gets because of the previous step invitation_id = context.responder_invitation["@id"] time.sleep(0.5) # delay for webhook to execute (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange", id=invitation_id) # {} assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) # The second way to do this is to call the connection protocol for the connection id given the invitation_id or a thread id. # This method is disabled for now, will be enabled if afgo can't get the connection id for the webhook above. #(resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/command/", connections, id=invitation_id) if "connection_id" in resp_text: context.connection_id_dict[responder][ context.requester_name] = resp_json["connection_id"] else: assert False, f'Could not retreive responders connection_id' # It is probably the case that we are dealing with a Public DID invitation that does not have the webhook message keyed on # invitation_id. In this case, try to grab the latest unkeyed message off of the webhook queue. # see issue 944 for full details https://app.zenhub.com/workspaces/von---verifiable-organization-network-5adf53987ccbaa70597dbec0/issues/hyperledger/aries-cloudagent-python/944 # (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange") # assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' # resp_json = json.loads(resp_text) # if "connection_id" in resp_text: # context.connection_id_dict[responder][context.requester_name] = resp_json["connection_id"] # else: # assert False, f'Could not retreive responders connection_id' responder_connection_id = context.connection_id_dict[responder][ context.requester_name] # responder already recieved the connection request in the send-request call so get connection and verify status. assert expected_agent_state(responder_url, "did-exchange", responder_connection_id, "request-received")
def step_impl(context, responder): responder_url = context.config.userdata.get(responder) data = {"use_public_did": False} (resp_status, resp_text) = agent_backchannel_POST(responder_url + "/agent/command/", "out-of-band", operation="send-invitation-message", data=data) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) assert resp_json["state"] == "invitation-sent" #assert "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/didexchange/v1.0" in resp_text context.responder_invitation = resp_json["invitation"] # TODO drill into the handshake protocol in the invitation and remove anything else besides didexchange. # setup the initial connection id dictionary if one doesn't exist. if not hasattr(context, 'connection_id_dict'): context.connection_id_dict = {} # Check for responder key existing in dict if responder not in context.connection_id_dict: context.connection_id_dict[responder] = {} # Get the responders's connection id from the above request's response webhook in the backchannel invitation_id = context.responder_invitation["@id"] (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange", id=invitation_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) # Some agents (afgo) do not have a webhook that give a connection id at this point in the protocol. # If it is not here, skip this and check for one later in the process and add it then. if "connection_id" in resp_text: context.connection_id_dict[responder][ context.requester_name] = resp_json["connection_id"] # Check to see if the responder name is the same as this person. If not, it is a 3rd person acting as an issuer that needs a connection if context.responder_name != responder: context.responder_name = responder
def step_impl(context, holder): holder_url = context.config.userdata.get(holder) # a credential id shouldn't be needed with a cred_ex_id being passed credential_id = { "credential_id": context.cred_thread_id, } # (resp_status, resp_text) = agent_backchannel_POST(holder_url + "/agent/command/", "credential", operation="store", id=context.holder_cred_ex_id) sleep(3) (resp_status, resp_text) = agent_backchannel_POST( holder_url + "/agent/command/", "issue-credential", operation="store", id=context.cred_thread_id, data=credential_id, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) assert resp_json["state"] == "done" # Store credential id context.credential_id_dict[context.schema["schema_name"]].append( resp_json["credential_id"]) # Verify issuer status # This is returning none instead of Done. Should this be the case. Needs investigation. # assert expected_agent_state(context.issuer_url, "issue-credential", context.cred_thread_id, "done") # if the credential supports revocation, get the Issuers webhook callback JSON from the store command # From that JSON save off the credential revocation identifier, and the revocation registry identifier. if context.support_revocation: (resp_status, resp_text) = agent_backchannel_GET( context.config.userdata.get(context.issuer_name) + "/agent/response/", "revocation-registry", id=context.cred_thread_id, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) context.cred_rev_id = resp_json["revocation_id"] context.rev_reg_id = resp_json["revoc_reg_id"]
def step_impl(context, holder, cred_format): holder_url = context.config.userdata.get(holder) # get the credential from the holders wallet (resp_status, resp_text) = agent_backchannel_GET( holder_url + "/agent/command/", "credential", id=context.credential_id_dict[context.schema['schema_name']][-1]) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) if cred_format == CRED_FORMAT_INDY: #assert resp_json["schema_id"] == context.issuer_schema_id_dict[context.schema["schema_name"]] #assert resp_json["cred_def_id"] == context.credential_definition_id_dict[context.schema["schema_name"]] assert resp_json["referent"] == context.credential_id_dict[ context.schema['schema_name']][-1] elif cred_format == CRED_FORMAT_JSON_LD: # TODO: do not use schema name for credential_id_dict assert resp_json["credential_id"] == context.credential_id_dict[ context.schema['schema_name']][-1]
def step_impl(context, responder: str, requester: str): responder_url = context.config.userdata.get(responder) data = {"use_public_did": True} (resp_status, resp_text) = agent_backchannel_POST( responder_url + "/agent/command/", "out-of-band", operation="send-invitation-message", data=data, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) assert resp_json["state"] == "invitation-sent" # assert "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/didexchange/v1.0" in resp_text context.responder_invitation = resp_json["invitation"] # TODO drill into the handshake protocol in the invitation and remove anything else besides didexchange. # Get the responders's connection id from the above request's response webhook in the backchannel invitation_id = context.responder_invitation["@id"] (resp_status, resp_text) = agent_backchannel_GET(responder_url + "/agent/response/", "did-exchange", id=invitation_id) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) if "connection_id" in resp_text: context.connection_id_dict[responder][requester] = resp_json[ "connection_id"] # Check to see if the responder name is the same as this person. If not, it is a 3rd person acting as an issuer that needs a connection # TODO: it would be nicer to pass the names on every call to remove the need for global keeping of who's the requester / responder if context.responder_name != responder: context.responder_name = responder context.responder_url = responder_url if context.requester_name != requester: context.requester_name = requester context.requester_url = context.config.userdata.get(requester)
def step_impl(context, holder): holder_url = context.holder_url # If @indy then we can be sure we cannot start the protocol from this command. We can be sure that we have previously # gotten the cred_ex_id or have a thread_id. if "Indy" in context.tags: sleep(1) (resp_status, resp_text) = agent_backchannel_POST(holder_url + "/agent/command/", "issue-credential", operation="send-request", id=context.holder_cred_ex_id) # We are starting from here in the protocol so you won't have the cred_ex_id or the thread_id else: (resp_status, resp_text) = agent_backchannel_POST( holder_url + "/agent/command/", "issue-credential", operation="send-request", id=context.connection_id_dict[holder]) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) assert resp_json["state"] == "request_sent" # Check the state of the issuer through the webhook sleep( 1 ) # It seems like you have to wait here for a moment in order to wait for the webhook to happen. (resp_status, resp_text) = agent_backchannel_GET(context.issuer_url + "/agent/response/", "issue-credential", id=context.cred_thread_id) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) # Need to log a bug for this. It should be "request_recieved" #assert resp_json["state"] == "request_recieved" #its in offer_sent assert resp_json["state"] == "offer_sent"
def step_impl(context, holder): holder_url = context.config.userdata.get(holder) # get the credential from the holders wallet (resp_status, resp_text) = agent_backchannel_GET( holder_url + "/agent/command/", "credential", id=context.credential_id_dict[context.schema['schema_name']] [len(context.credential_id_dict[context.schema['schema_name']]) - 1]) assert resp_status == 200, f'resp_status {resp_status} is not 200; {resp_text}' resp_json = json.loads(resp_text) if "state" in resp_json and resp_json["state"] == "N/A": # backchannel can't get the credential pass else: assert resp_json["referent"] == context.credential_id_dict[ context.schema['schema_name']][len(context.credential_id_dict[ context.schema['schema_name']]) - 1] assert resp_json["schema_id"] == context.issuer_schema_id_dict[ context.schema["schema_name"]] assert resp_json[ "cred_def_id"] == context.credential_definition_id_dict[ context.schema["schema_name"]]
def step_impl(context, holder, cred_format): holder_url = context.config.userdata.get(holder) sleep(1) (resp_status, resp_text) = agent_backchannel_POST( holder_url + "/agent/command/", "issue-credential-v2", operation="store", id=context.cred_thread_id, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) state = resp_json["state"] assert state == "done", f"state is '{state}', expected 'done'" # FIXME: the return value of this is very ACA-Py specific, should just be credential_id credential_id = resp_json[cred_format]["credential_id"] context.credential_id_dict[context.schema["schema_name"]].append( credential_id) # Verify issuer status # TODO This is returning none instead of Done. Should this be the case. Needs investigation. # assert expected_agent_state(context.issuer_url, "issue-credential-v2", context.cred_thread_id, "done") # if the credential supports revocation, get the Issuers webhook callback JSON from the store command # From that JSON save off the credential revocation identifier, and the revocation registry identifier. if context.support_revocation: (resp_status, resp_text) = agent_backchannel_GET( context.config.userdata.get(context.issuer_name) + "/agent/response/", "revocation-registry", id=context.cred_thread_id, ) assert resp_status == 200, f"resp_status {resp_status} is not 200; {resp_text}" resp_json = json.loads(resp_text) context.cred_rev_id = resp_json["revocation_id"] context.rev_reg_id = resp_json["revoc_reg_id"]