-
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 17 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,145 @@ | ||
package resolvers | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"io" | ||
"net/http" | ||
|
||
"github.com/google/uuid" | ||
"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 { | ||
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. Can we use an options pattern? Or if it required field pass the PackageManager directly to 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. no, it looks like you missed our discussions |
||
PackageManager *iden3comm.PackageManager | ||
customHTTPClient *http.Client | ||
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. It is not possible to set customHTTPClient from the external package, since the field is private. 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. made public |
||
} | ||
|
||
// 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
|
||
if status.Type != verifiable.Iden3commRevocationStatusV1 { | ||
return out, errors.New("invalid status type") | ||
} | ||
revocationBody := protocol.RevocationStatusRequestMessageBody{ | ||
RevocationNonce: status.RevocationNonce, | ||
} | ||
rawBody, err := json.Marshal(revocationBody) | ||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
|
||
idUUID, err := uuid.NewV7() | ||
if err != nil { | ||
return out, errors.WithStack(err) | ||
} | ||
threadUUID, err := uuid.NewV7() | ||
if err != nil { | ||
return out, errors.WithStack(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) | ||
} | ||
|
||
var httpClient *http.Client | ||
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. refactor to httpClient := http.DefaultClient
if r.config.customHTTPClient != nil {
httpClient = r.config.customHTTPClient
} |
||
if r.config.customHTTPClient != nil { | ||
httpClient = r.config.customHTTPClient | ||
} else { | ||
httpClient = http.DefaultClient | ||
} | ||
|
||
resp, err := httpClient.Post(status.ID, "application/json", bytes.NewBuffer(iden3commMsg)) | ||
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) | ||
} | ||
}() | ||
|
||
statusOK := resp.StatusCode >= 200 && resp.StatusCode < 300 | ||
if !statusOK { | ||
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, err | ||
} |
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.
why do we have to uuid packages? I know Illiya aksed to use goohle uuid, but in this case let's remove gofrs completely.
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.
removed