Skip to content

Commit

Permalink
load a VC into a wallet via the internal API (#2643)
Browse files Browse the repository at this point in the history
  • Loading branch information
woutslakhorst authored Dec 5, 2023
1 parent a33a934 commit 9913b5a
Show file tree
Hide file tree
Showing 4 changed files with 350 additions and 0 deletions.
32 changes: 32 additions & 0 deletions docs/_static/vcr/vcr_v2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,39 @@ paths:
$ref: "#/components/schemas/VerifiablePresentation"
default:
$ref: '../common/error_response.yaml'
/internal/vcr/v2/holder/{did}/vc:
post:
summary: Load a VerifiableCredential into the holders wallet.
description: |
If a VerifiableCredential is not directly issued to the wallet through e.g. OpenID4VCI, this API allows to add it to a wallet.
The DID of the holder has to be provided in the path.
It's assumed that the credentialSubject.id equals the holder DID.
error returns:
* 400 - Invalid credential
* 500 - An error occurred while processing the request
operationId: loadVC
tags:
- credential
parameters:
- name: did
in: path
description: URL encoded DID.
required: true
example: "did:web:example.com:iam:123"
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/VerifiableCredential"
responses:
"204":
description: The credential will not be altered in any way, so no need to return it.
default:
$ref: '../common/error_response.yaml'
components:
schemas:
VerifiableCredential:
Expand Down
17 changes: 17 additions & 0 deletions vcr/api/vcr/v2/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,23 @@ func (w *Wrapper) VerifyVP(ctx context.Context, request VerifyVPRequestObject) (
return VerifyVP200JSONResponse(result), nil
}

func (w *Wrapper) LoadVC(ctx context.Context, request LoadVCRequestObject) (LoadVCResponseObject, error) {
// the actual holder is ignored for now, since we only support a single wallet...
_, err := did.ParseDID(request.Did)
if err != nil {
return nil, core.InvalidInputError("invalid holder did: %w", err)
}

if request.Body == nil {
return nil, core.InvalidInputError("missing credential in body")
}
err = w.VCR.Wallet().Put(ctx, *request.Body)
if err != nil {
return nil, err
}
return LoadVC204Response{}, nil
}

// TrustIssuer handles API request to start trusting an issuer of a Verifiable Credential.
func (w *Wrapper) TrustIssuer(ctx context.Context, request TrustIssuerRequestObject) (TrustIssuerResponseObject, error) {
if err := changeTrust(*request.Body, w.VCR.Trust); err != nil {
Expand Down
40 changes: 40 additions & 0 deletions vcr/api/vcr/v2/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,46 @@ func parsedTimeStr(t time.Time) (time.Time, string) {
return parsed, formatted
}

func TestWrapper_LoadVC(t *testing.T) {
holderDID := "did:web:example.com:iam:123"
credentialID := "did:web:example.com:iam:456#1"
credentialURI := ssi.MustParseURI(credentialID)
expectedVC := vc.VerifiableCredential{ID: &credentialURI}

t.Run("test integration with vcr", func(t *testing.T) {
t.Run("successful load", func(t *testing.T) {
testContext := newMockContext(t)
testContext.mockWallet.EXPECT().Put(gomock.Any(), expectedVC).Return(nil)

response, err := testContext.client.LoadVC(testContext.requestCtx, LoadVCRequestObject{Did: holderDID, Body: &expectedVC})

assert.NoError(t, err)
assert.IsType(t, response, LoadVC204Response{})
})

t.Run("vcr returns an error", func(t *testing.T) {
testContext := newMockContext(t)
testContext.mockWallet.EXPECT().Put(gomock.Any(), expectedVC).Return(assert.AnError)

response, err := testContext.client.LoadVC(testContext.requestCtx, LoadVCRequestObject{Did: holderDID, Body: &expectedVC})

assert.Empty(t, response)
assert.EqualError(t, err, assert.AnError.Error())
})
})

t.Run("param check", func(t *testing.T) {
t.Run("invalid credential id format", func(t *testing.T) {
testContext := newMockContext(t)

response, err := testContext.client.LoadVC(testContext.requestCtx, LoadVCRequestObject{Did: "%%"})

assert.Empty(t, response)
assert.EqualError(t, err, "invalid holder did: invalid DID")
})
})
}

func TestWrapper_CreateVP(t *testing.T) {
issuerURI := ssi.MustParseURI("did:nuts:123")
credentialType := ssi.MustParseURI("ExampleType")
Expand Down
Loading

0 comments on commit 9913b5a

Please sign in to comment.