Skip to content

Commit

Permalink
feat: Credential Management - Credential Issuance history (#1459)
Browse files Browse the repository at this point in the history
Signed-off-by: Mykhailo Sizov <[email protected]>
  • Loading branch information
mishasizov-SK authored Oct 6, 2023
1 parent 546b012 commit 9c17a39
Show file tree
Hide file tree
Showing 27 changed files with 1,240 additions and 365 deletions.
285 changes: 144 additions & 141 deletions api/spec/openapi.gen.go

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions cmd/vc-rest/startcmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -767,16 +767,17 @@ func buildEchoHandler(
}))

issuerv1.RegisterHandlers(e, issuerv1.NewController(&issuerv1.Config{
EventSvc: eventSvc,
ProfileSvc: issuerProfileSvc,
DocumentLoader: documentLoader,
IssueCredentialService: issueCredentialSvc,
VcStatusManager: statusListVCSvc,
OIDC4CIService: oidc4ciService,
ExternalHostURL: conf.StartupParameters.apiGatewayURL,
Tracer: conf.Tracer,
OpenidIssuerConfigProvider: openidCredentialIssuerConfigProviderSvc,
JSONSchemaValidator: jsonSchemaValidator,
EventSvc: eventSvc,
ProfileSvc: issuerProfileSvc,
DocumentLoader: documentLoader,
IssueCredentialService: issueCredentialSvc,
VcStatusManager: statusListVCSvc,
OIDC4CIService: oidc4ciService,
CredentialIssuanceHistoryStore: vcStatusStore,
ExternalHostURL: conf.StartupParameters.apiGatewayURL,
Tracer: conf.Tracer,
OpenidIssuerConfigProvider: openidCredentialIssuerConfigProviderSvc,
JSONSchemaValidator: jsonSchemaValidator,
}))

// Verifier Profile Management API
Expand Down
11 changes: 7 additions & 4 deletions component/credentialstatus/credentialstatus_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ type eventPublisher interface {

type cslManager interface {
CreateCSLEntry(
ctx context.Context, profile *profileapi.Issuer, credentialID string) (*credentialstatus.StatusListEntry, error)
ctx context.Context,
profile *profileapi.Issuer,
credentialMetadata *credentialstatus.CredentialMetadata,
) (*credentialstatus.StatusListEntry, error)
}

type Config struct {
Expand Down Expand Up @@ -170,18 +173,18 @@ func (s *Service) CreateStatusListEntry(
ctx context.Context,
profileID profileapi.ID,
profileVersion profileapi.Version,
credentialID string) (*credentialstatus.StatusListEntry, error) {
credentialMetadata *credentialstatus.CredentialMetadata) (*credentialstatus.StatusListEntry, error) {
logger.Debugc(ctx, "CreateStatusListEntry begin",
logfields.WithProfileID(profileID),
logfields.WithProfileVersion(profileVersion),
logfields.WithCredentialID(credentialID))
logfields.WithCredentialID(credentialMetadata.CredentialID))

profile, err := s.profileService.GetProfile(profileID, profileVersion)
if err != nil {
return nil, fmt.Errorf("get profile: %w", err)
}

statusListEntry, err := s.cslMgr.CreateCSLEntry(ctx, profile, credentialID)
statusListEntry, err := s.cslMgr.CreateCSLEntry(ctx, profile, credentialMetadata)
if err != nil {
return nil, fmt.Errorf("create CSL entry: %w", err)
}
Expand Down
61 changes: 44 additions & 17 deletions component/credentialstatus/credentialstatus_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ func TestCredentialStatusList_CreateStatusListEntry(t *testing.T) {

vcStatusStore := newMockVCStatusStore()

metadata := &credentialstatus.CredentialMetadata{CredentialID: credID}

cslMgr, err := cslmanager.New(
&cslmanager.Config{
CSLVCStore: cslVCStore,
Expand All @@ -139,11 +141,11 @@ func TestCredentialStatusList_CreateStatusListEntry(t *testing.T) {
})
require.NoError(t, err)

statusID, err := s.CreateStatusListEntry(ctx, profileID, profileVersion, credID)
statusID, err := s.CreateStatusListEntry(ctx, profileID, profileVersion, metadata)
require.NoError(t, err)
validateVCStatus(t, s, statusID, listID)

statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, credID)
statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, metadata)
require.NoError(t, err)
validateVCStatus(t, s, statusID, listID)

Expand All @@ -152,11 +154,11 @@ func TestCredentialStatusList_CreateStatusListEntry(t *testing.T) {
require.NoError(t, err)
require.NotEqual(t, updatedListID, listID)

statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, credID)
statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, metadata)
require.NoError(t, err)
validateVCStatus(t, s, statusID, updatedListID)

statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, credID)
statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, metadata)
require.NoError(t, err)
validateVCStatus(t, s, statusID, updatedListID)

Expand All @@ -166,7 +168,7 @@ func TestCredentialStatusList_CreateStatusListEntry(t *testing.T) {
require.NotEqual(t, updatedListID, updatedListIDSecond)
require.NotEqual(t, listID, updatedListIDSecond)

statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, credID)
statusID, err = s.CreateStatusListEntry(ctx, profileID, profileVersion, metadata)
require.NoError(t, err)
validateVCStatus(t, s, statusID, updatedListIDSecond)
})
Expand All @@ -180,7 +182,9 @@ func TestCredentialStatusList_CreateStatusListEntry(t *testing.T) {
})
require.NoError(t, err)

status, err := s.CreateStatusListEntry(context.Background(), profileID, profileVersion, credID)
meta := &credentialstatus.CredentialMetadata{CredentialID: credID}

status, err := s.CreateStatusListEntry(context.Background(), profileID, profileVersion, meta)
require.Error(t, err)
require.Nil(t, status)
require.Contains(t, err.Error(), "get profile")
Expand Down Expand Up @@ -281,10 +285,12 @@ func TestCredentialStatusList_UpdateVCStatus(t *testing.T) {
})
require.NoError(t, err)

statusListEntry, err := s.CreateStatusListEntry(ctx, profileID, profileVersion, credID)
meta := &credentialstatus.CredentialMetadata{CredentialID: credID}

statusListEntry, err := s.CreateStatusListEntry(ctx, profileID, profileVersion, meta)
require.NoError(t, err)

err = vcStatusStore.Put(ctx, profileID, profileVersion, credID, statusListEntry.TypedID)
err = vcStatusStore.Put(ctx, profileID, profileVersion, meta, statusListEntry.TypedID)
require.NoError(t, err)

params := credentialstatus.UpdateVCStatusParams{
Expand Down Expand Up @@ -400,8 +406,10 @@ func TestCredentialStatusList_UpdateVCStatus(t *testing.T) {
})
require.NoError(t, err)

meta := &credentialstatus.CredentialMetadata{CredentialID: credID}

err = vcStore.Put(
context.Background(), profileID, profileVersion, credID, &verifiable.TypedID{
context.Background(), profileID, profileVersion, meta, &verifiable.TypedID{
Type: string(vc.StatusList2021VCStatus)})
require.NoError(t, err)

Expand Down Expand Up @@ -436,8 +444,10 @@ func TestCredentialStatusList_UpdateVCStatus(t *testing.T) {
})
require.NoError(t, err)

meta := &credentialstatus.CredentialMetadata{CredentialID: credID}

err = vcStore.Put(
context.Background(), profileID, profileVersion, credID,
context.Background(), profileID, profileVersion, meta,
&verifiable.TypedID{Type: string(vc.StatusList2021VCStatus)})
require.NoError(t, err)

Expand Down Expand Up @@ -652,7 +662,9 @@ func TestCredentialStatusList_UpdateVCStatus(t *testing.T) {
})
require.NoError(t, err)

statusListEntry, err := s.CreateStatusListEntry(context.Background(), profileID, profileVersion, credID)
meta := &credentialstatus.CredentialMetadata{CredentialID: credID}

statusListEntry, err := s.CreateStatusListEntry(context.Background(), profileID, profileVersion, meta)
require.NoError(t, err)

err = s.updateVCStatus(
Expand Down Expand Up @@ -714,7 +726,9 @@ func TestCredentialStatusList_UpdateVCStatus(t *testing.T) {
})
require.NoError(t, err)

statusListEntry, err := s.CreateStatusListEntry(context.Background(), profile.ID, profile.Version, credID)
meta := &credentialstatus.CredentialMetadata{CredentialID: credID}

statusListEntry, err := s.CreateStatusListEntry(context.Background(), profile.ID, profile.Version, meta)
require.NoError(t, err)

require.NoError(t, s.updateVCStatus(
Expand Down Expand Up @@ -1014,14 +1028,19 @@ func (m *mockCSLVCStore) Get(_ context.Context, cslURL string) (*credentialstatu
return w, nil
}

type storeData struct {
typedID *verifiable.TypedID
metadata *credentialstatus.CredentialMetadata
}

type mockVCStore struct {
putErr error
s map[string]*verifiable.TypedID
s map[string]storeData
}

func newMockVCStatusStore() *mockVCStore {
return &mockVCStore{
s: map[string]*verifiable.TypedID{},
s: map[string]storeData{},
}
}

Expand All @@ -1031,16 +1050,24 @@ func (m *mockVCStore) Get(_ context.Context, profileID, profileVersion, vcID str
return nil, errors.New("data not found")
}

return v, nil
return v.typedID, nil
}

func (m *mockVCStore) Put(
_ context.Context, profileID, profileVersion, vcID string, typedID *verifiable.TypedID) error {
_ context.Context,
profileID, profileVersion string,
metadata *credentialstatus.CredentialMetadata,
typedID *verifiable.TypedID,
) error {
if m.putErr != nil {
return m.putErr
}

m.s[fmt.Sprintf("%s_%s_%s", profileID, profileVersion, vcID)] = typedID
m.s[fmt.Sprintf("%s_%s_%s", profileID, profileVersion, metadata.CredentialID)] = storeData{
typedID: typedID,
metadata: metadata,
}

return nil
}

Expand Down
61 changes: 61 additions & 0 deletions docs/v1/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,36 @@ paths:
description: Returns openid-config.
tags:
- issuer
'/issuer/profiles/{profileID}/{profileVersion}/issued-credentials':
parameters:
- schema:
type: string
name: profileID
in: path
required: true
description: Profile ID
- schema:
type: string
name: profileVersion
in: path
required: true
description: Profile Version
get:
summary: Request Credential Issuance history.
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
description: JSON array containing a list of credentials metadata issued by given profile.
items:
$ref: '#/components/schemas/CredentialIssuanceHistoryData'
operationId: credential-issuance-history
description: Returns Credential Issuance history.
tags:
- issuer
'/issuer/profiles/{profileID}/{profileVersion}/credentials/issue':
parameters:
- schema:
Expand Down Expand Up @@ -834,6 +864,37 @@ components:
- credential_endpoint
- credentials_supported
description: WellKnownOpenIDIssuerConfiguration represents the OIDC Configuration response for cases when VCS serves as IDP.
CredentialIssuanceHistoryData:
title: CredentialIssuanceHistory response
x-tags:
- issuer
type: object
properties:
credential_id:
type: string
description: Credential ID.
issuer:
type: string
description: Issuer identifier.
credential_types:
type: array
items:
type: string
description: JSON array of credential types.
transaction_id:
type: string
description: Transaction ID.
issuance_date:
type: string
description: Issuance Date.
expiration_date:
type: string
description: Expiration Date.
required:
- credential_id
- issuer
- credential_types
description: CredentialIssuanceHistoryData represents the credential issuance history array element.
VerifyCredentialData:
title: VerifyCredentialData
x-tags:
Expand Down
19 changes: 14 additions & 5 deletions pkg/cslmanager/cslmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX-License-Identifier: Apache-2.0

package cslmanager

//go:generate mockgen -destination cslmanager_mocks_test.go -self_package github.com/trustbloc/pkg/cslmanager -package cslmanager -source=cslmanager.go -mock_names kmsRegistry=MockKMSRegistry
//go:generate mockgen -destination cslmanager_mocks_test.go -self_package github.com/trustbloc/pkg/cslmanager -package cslmanager -source=cslmanager.go -mock_names kmsRegistry=MockKMSRegistry,vcStatusStore=MockVCStatusStore

import (
"context"
Expand Down Expand Up @@ -48,7 +48,13 @@ type cslVCStore interface {
}

type vcStatusStore interface {
Put(ctx context.Context, profileID, profileVersion, credentialID string, typedID *verifiable.TypedID) error
Put(
ctx context.Context,
profileID string,
profileVersion string,
metadata *credentialstatus.CredentialMetadata,
typedID *verifiable.TypedID,
) error
}

type Config struct {
Expand Down Expand Up @@ -86,8 +92,11 @@ func New(config *Config) (*Manager, error) {
}

// CreateCSLEntry creates CSL entry.
func (s *Manager) CreateCSLEntry(ctx context.Context,
profile *profileapi.Issuer, credentialID string) (*credentialstatus.StatusListEntry, error) {
func (s *Manager) CreateCSLEntry(
ctx context.Context,
profile *profileapi.Issuer,
credentialMetadata *credentialstatus.CredentialMetadata,
) (*credentialstatus.StatusListEntry, error) {
logger.Debugc(ctx, "CSL Manager - CreateCSLEntry",
logfields.WithProfileID(profile.ID), logfields.WithProfileVersion(profile.Version))

Expand All @@ -107,7 +116,7 @@ func (s *Manager) CreateCSLEntry(ctx context.Context,
}

// Store VC status to DB
err = s.vcStatusStore.Put(ctx, profile.ID, profile.Version, credentialID, statusListEntry.TypedID)
err = s.vcStatusStore.Put(ctx, profile.ID, profile.Version, credentialMetadata, statusListEntry.TypedID)
if err != nil {
return nil, fmt.Errorf("failed to store credential status: %w", err)
}
Expand Down
Loading

0 comments on commit 9c17a39

Please sign in to comment.