-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add AgentResolver #40
Changes from 13 commits
d801561
acd7549
882c510
685f4cd
1df1699
332c21d
82684e8
b75d0d2
a2e694e
78abb1a
c84e85a
aac3cbd
8a3fe41
a9d810a
b62f007
609e668
e72b4f4
5af1576
bec4dff
67db65e
ad9a4c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package resolvers | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"io" | ||
"net/http" | ||
|
||
"github.com/gofrs/uuid/v5" | ||
"github.com/iden3/go-iden3-core/v2/w3c" | ||
"github.com/iden3/go-schema-processor/v2/verifiable" | ||
"github.com/iden3/iden3comm/v2" | ||
"github.com/iden3/iden3comm/v2/packers" | ||
"github.com/iden3/iden3comm/v2/protocol" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
type ctxKeySenderDID struct{} | ||
|
||
// WithSenderDID puts the user DID in the context | ||
func WithSenderDID(ctx context.Context, userDID *w3c.DID) context.Context { | ||
return context.WithValue(ctx, ctxKeySenderDID{}, userDID) | ||
} | ||
|
||
// GetSenderDID extract the sender's DID from the context. | ||
// Returns nil if nothing is found. | ||
func GetSenderDID(ctx context.Context) *w3c.DID { | ||
v := ctx.Value(ctxKeySenderDID{}) | ||
if v == nil { | ||
return nil | ||
} | ||
return v.(*w3c.DID) | ||
} | ||
|
||
// AgentResolverConfig options for credential status verification | ||
type AgentResolverConfig struct { | ||
PackageManager *iden3comm.PackageManager | ||
} | ||
|
||
// AgentResolver is a struct that allows to interact with the issuer's agent to get revocation status. | ||
type AgentResolver struct { | ||
config AgentResolverConfig | ||
} | ||
|
||
// NewAgentResolver returns new agent resolver | ||
func NewAgentResolver(config AgentResolverConfig) *AgentResolver { | ||
return &AgentResolver{config} | ||
} | ||
|
||
// Resolve is a method to resolve a credential status from an agent. | ||
func (r AgentResolver) Resolve(ctx context.Context, | ||
status verifiable.CredentialStatus) (out verifiable.RevocationStatus, err error) { | ||
|
||
vmidyllic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
revocationBody := protocol.RevocationStatusRequestMessageBody{ | ||
RevocationNonce: status.RevocationNonce, | ||
} | ||
rawBody, err := json.Marshal(revocationBody) | ||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
|
||
idUUID, err := uuid.NewV4() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use github.com/google/uuid to generate uuid There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
if err != nil { | ||
return out, err | ||
} | ||
threadUUID, err := uuid.NewV4() | ||
if err != nil { | ||
return out, err | ||
} | ||
|
||
senderDID := GetSenderDID(ctx) | ||
if senderDID == nil { | ||
return out, errors.New("sender DID not found in the context") | ||
} | ||
issuerDID := verifiable.GetIssuerDID(ctx) | ||
if issuerDID == nil { | ||
return out, errors.New("issuer DID not found in the context") | ||
} | ||
msg := iden3comm.BasicMessage{ | ||
ID: idUUID.String(), | ||
ThreadID: threadUUID.String(), | ||
From: senderDID.String(), | ||
To: issuerDID.String(), | ||
Type: protocol.RevocationStatusRequestMessageType, | ||
Body: rawBody, | ||
} | ||
bytesMsg, err := json.Marshal(msg) | ||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
|
||
iden3commMsg, err := r.config.PackageManager.Pack(packers.MediaTypePlainMessage, bytesMsg, nil) | ||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
|
||
resp, err := http.DefaultClient.Post(status.ID, "application/json", bytes.NewBuffer(iden3commMsg)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pass the http client as option There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
defer func() { | ||
err2 := resp.Body.Close() | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if err2 != nil? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just return revocationStatus.RevocationStatus, err in the end of the function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
err = errors.WithStack(err2) | ||
} | ||
}() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Accept range of 2xx codes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 200 is expected on all other clients. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
return out, errors.Errorf("bad status code: %d", resp.StatusCode) | ||
} | ||
|
||
b, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
|
||
basicMessage, _, err := r.config.PackageManager.Unpack(b) | ||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
|
||
if basicMessage.Type != protocol.RevocationStatusResponseMessageType { | ||
return out, errors.Errorf("unexpected message type: %s", basicMessage.Type) | ||
} | ||
|
||
var revocationStatus protocol.RevocationStatusResponseMessageBody | ||
if err := json.Unmarshal(basicMessage.Body, &revocationStatus); err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
|
||
return revocationStatus.RevocationStatus, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use an options pattern? Or if it required field pass the PackageManager directly to
NewAgentResolver
constructor?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it looks like you missed our discussions