Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: factor walletlite.Command form vcwallet.Command.
Browse files Browse the repository at this point in the history
Signed-off-by: Volodymyr Kubiv <volodymyr.kubiv@euristiq.com>
vkubiv committed Jul 25, 2022

Verified

This commit was signed with the committer’s verified signature.
vkubiv Volodymyr Kubiv
1 parent 9bdda1a commit a24b620
Showing 9 changed files with 4,523 additions and 4,063 deletions.
876 changes: 876 additions & 0 deletions pkg/controller/command/basewallet/command.go

Large diffs are not rendered by default.

1,923 changes: 1,923 additions & 0 deletions pkg/controller/command/basewallet/command_test.go

Large diffs are not rendered by default.

312 changes: 312 additions & 0 deletions pkg/controller/command/basewallet/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,312 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package basewallet

import (
"encoding/json"
"time"

"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/hyperledger/aries-framework-go/pkg/kms"
"github.com/hyperledger/aries-framework-go/pkg/wallet"
)

// CreateOrUpdateProfileRequest is request model for
// creating a new wallet profile or updating an existing wallet profile.
type CreateOrUpdateProfileRequest struct {
// Unique identifier to identify wallet user
UserID string `json:"userID"`

// passphrase for local kms for key operations.
// Optional, if this option is provided then wallet for this profile will use local KMS for key operations.
LocalKMSPassphrase string `json:"localKMSPassphrase,omitempty"`

// passphrase for web/remote kms for key operations.
// Optional, if this option is provided then wallet for this profile will use web/remote KMS for key operations.
KeyStoreURL string `json:"keyStoreURL,omitempty"`

// edv configuration for storing wallet contents for this profile
// Optional, if not provided then agent storage provider will be used as store provider.
EDVConfiguration *EDVConfiguration `json:"edvConfiguration,omitempty"`
}

// EDVConfiguration contains configuration for EDV settings for profile creation.
type EDVConfiguration struct {
// EDV server URL for storing wallet contents.
ServerURL string `json:"serverURL,omitempty"`

// EDV vault ID for storing the wallet contents.
VaultID string `json:"vaultID,omitempty"`

// Encryption key ID of already existing key in wallet profile kms.
// If profile is using localkms then wallet will create this key set for wallet user.
EncryptionKeyID string `json:"encryptionKID,omitempty"`

// MAC operation key ID of already existing key in wallet profile kms.
// If profile is using localkms then wallet will create this key set for wallet user.
MACKeyID string `json:"macKID,omitempty"`
}

// UnlockWalletRequest contains different options for unlocking wallet.
type UnlockWalletRequest struct {
// user ID of the wallet to be unlocked.
UserID string `json:"userID"`

// passphrase for local kms for key operations.
// Optional, to be used if profile for this wallet user is setup with local KMS.
LocalKMSPassphrase string `json:"localKMSPassphrase,omitempty"`

// WebKMSAuth for authorizing acccess to web/remote kms.
// Optional, to be used if profile for this wallet user is setup with web/remote KMS.
WebKMSAuth *UnlockAuth `json:"webKMSAuth"`

// Options for authorizing access to wallet's EDV content store.
// Optional, to be used only if profile for this wallet user is setup to use EDV as content store.
EDVUnlock *UnlockAuth `json:"edvUnlocks"`

// Time duration in milliseconds after which wallet will expire its unlock status.
Expiry time.Duration `json:"expiry,omitempty"`
}

// UnlockAuth contains different options for authorizing access to wallet's EDV content store & webkms.
type UnlockAuth struct {
// Http header 'authorization' bearer token to be used.
// Optional, only if required by wallet user (for webkms or edv).
AuthToken string `json:"authToken,omitempty"`

// Http header 'authorization' GNAP token to be used.
// Optional, only if required by wallet user (for webkms or edv).
GNAPToken string `json:"gnapToken,omitempty"`

// Capability if ZCAP sign header feature to be used for authorizing access.
// Optional, can be used only if ZCAP sign header feature is configured with command controller.
Capability string `json:"capability,omitempty"`

// AuthZKeyStoreURL if ZCAP sign header feature to be used for authorizing access.
// Optional, can be used only if ZCAP sign header feature is configured with command controller.
AuthZKeyStoreURL string `json:"authzKeyStoreURL,omitempty"`

// SecretShare if ZCAP sign header feature to be used for authorizing access.
// Optional, can be used only if ZCAP sign header feature is configured with command controller.
SecretShare string `json:"secretShare,omitempty"`
}

// UnlockWalletResponse contains response for wallet unlock operation.
type UnlockWalletResponse struct {
// Token for granting access to wallet for subsequent wallet operations.
Token string `json:"token,omitempty"`
}

// LockWalletRequest contains options for locking wallet.
type LockWalletRequest struct {
// user ID of the wallet to be locked.
UserID string `json:"userID"`
}

// LockWalletResponse contains response for wallet lock operation.
type LockWalletResponse struct {
// Closed status of the wallet lock operation.
// if true, wallet is closed successfully
// if false, wallet is already closed or never unlocked.
Closed bool `json:"closed"`
}

// WalletAuth contains wallet auth parameters for performing wallet operations.
type WalletAuth struct {
// Authorization token for performing wallet operations.
Auth string `json:"auth"`

// ID of wallet user.
UserID string `json:"userID"`
}

// WalletUser contains wallet user info for performing profile operations.
type WalletUser struct {
// ID of wallet user.
ID string `json:"userID"`
}

// AddContentRequest is request for adding a content to wallet.
type AddContentRequest struct {
WalletAuth

// type of the content to be added to the wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection, key
ContentType wallet.ContentType `json:"contentType"`

// content to be added to wallet content store.
Content json.RawMessage `json:"content"`

// ID of the wallet collection to which this content should belong.
CollectionID string `json:"collectionID"`
}

// RemoveContentRequest is request for removing a content from wallet.
type RemoveContentRequest struct {
WalletAuth

// type of the content to be removed from the wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection
ContentType wallet.ContentType `json:"contentType"`

// ID of the content to be removed from wallet
ContentID string `json:"contentID"`
}

// GetContentRequest is request for getting a content from wallet.
type GetContentRequest struct {
WalletAuth

// type of the content to be returned from wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection
ContentType wallet.ContentType `json:"contentType"`

// ID of the content to be returned from wallet
ContentID string `json:"contentID"`
}

// GetContentResponse response for get content from wallet operation.
type GetContentResponse struct {
// content retrieved from wallet content store.
Content json.RawMessage `json:"content"`
}

// GetAllContentRequest is request for getting all contents from wallet for given content type.
type GetAllContentRequest struct {
WalletAuth

// type of the contents to be returned from wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection
ContentType wallet.ContentType `json:"contentType"`

// ID of the collection on which the response contents to be filtered.
CollectionID string `json:"collectionID,omitempty"`
}

// GetAllContentResponse response for get all content by content type wallet operation.
type GetAllContentResponse struct {
// contents retrieved from wallet content store.
// map of content ID to content.
Contents map[string]json.RawMessage `json:"contents"`
}

// ContentQueryRequest is request model for querying wallet contents.
type ContentQueryRequest struct {
WalletAuth

// credential query(s) for querying wallet contents.
Query []*wallet.QueryParams `json:"query"`
}

// ContentQueryResponse response for wallet content query.
type ContentQueryResponse struct {
// response presentation(s) containing query results.
Results []*verifiable.Presentation `json:"results"`
}

// IssueRequest is request model for issuing credential from wallet.
type IssueRequest struct {
WalletAuth

// raw credential to be issued from wallet.
Credential json.RawMessage `json:"credential"`

// proof options for issuing credential
ProofOptions *wallet.ProofOptions `json:"proofOptions"`
}

// IssueResponse is response for issue credential interface from wallet.
type IssueResponse struct {
// credential issued.
Credential *verifiable.Credential `json:"credential"`
}

// ProveRequest for producing verifiable presentation from wallet.
// Contains options for proofs and credential. Any combination of credential option can be mixed.
type ProveRequest struct {
WalletAuth

// IDs of credentials already saved in wallet content store.
StoredCredentials []string `json:"storedCredentials"`

// List of raw credentials to be presented.
RawCredentials []json.RawMessage `json:"rawCredentials"`

// Presentation to be proved.
Presentation json.RawMessage `json:"presentation"`

// proof options for issuing credential.
ProofOptions *wallet.ProofOptions `json:"proofOptions"`
}

// ProveResponse contains response presentation from prove operation.
type ProveResponse struct {
// presentation response from prove operation.
Presentation *verifiable.Presentation `json:"presentation"`
}

// VerifyRequest request for verifying a credential or presentation from wallet.
// Any one of the credential option should be used.
type VerifyRequest struct {
WalletAuth

// ID of the credential already saved in wallet content store.
// optional, if provided then this option takes precedence over other options.
StoredCredentialID string `json:"storedCredentialID"`

// List of raw credential to be presented.
// optional, if provided then this option takes precedence over presentation options.
RawCredential json.RawMessage `json:"rawCredential"`

// Presentation to be proved.
// optional, will be used only if other options are not provided.
Presentation json.RawMessage `json:"presentation"`
}

// VerifyResponse is response model for wallet verify operation.
type VerifyResponse struct {
// if true then verification is successful.
Verified bool `json:"verified"`

// error details if verified is false.
Error string `json:"error,omitempty"`
}

// DeriveRequest is request model for deriving a credential from wallet.
type DeriveRequest struct {
WalletAuth

// ID of the credential already saved in wallet content store.
// optional, if provided then this option takes precedence.
StoredCredentialID string `json:"storedCredentialID"`

// List of raw credential to be presented.
// optional, will be used only if other options is not provided.
RawCredential json.RawMessage `json:"rawCredential"`

// DeriveOptions options for deriving credential
*wallet.DeriveOptions `json:"deriveOption"`
}

// DeriveResponse is response for derived credential operation.
type DeriveResponse struct {
// credential derived.
Credential *verifiable.Credential `json:"credential"`
}

// CreateKeyPairRequest is request model for creating key pair from wallet.
type CreateKeyPairRequest struct {
WalletAuth

// type of the key to be created.
KeyType kms.KeyType `json:"keyType,omitempty"`
}

// CreateKeyPairResponse is response model for creating key pair from wallet.
type CreateKeyPairResponse struct {
*wallet.KeyPair
}
1,126 changes: 42 additions & 1,084 deletions pkg/controller/command/vcwallet/command.go

Large diffs are not rendered by default.

2,729 changes: 0 additions & 2,729 deletions pkg/controller/command/vcwallet/command_test.go

Large diffs are not rendered by default.

347 changes: 347 additions & 0 deletions pkg/controller/command/vcwallet/didcomm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,347 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package vcwallet

import (
"encoding/json"
"io"
"time"

"github.com/hyperledger/aries-framework-go/pkg/controller/command"
"github.com/hyperledger/aries-framework-go/pkg/controller/internal/cmdutil"
"github.com/hyperledger/aries-framework-go/pkg/internal/logutil"
"github.com/hyperledger/aries-framework-go/pkg/wallet"
)

// CommandDidComm contains operations provided by verifiable credential wallet controller.
type CommandDidComm struct {
ctx provider
}

// NewDidCommCommand returns new verifiable credential wallet controller command instance.
func NewDidCommCommand(p provider) *CommandDidComm {
cmd := &CommandDidComm{ctx: p}

return cmd
}

// GetHandlers returns list of all commands supported by this controller command.
func (o *CommandDidComm) GetHandlers() []command.Handler {
return []command.Handler{
cmdutil.NewCommandHandler(CommandName, ConnectMethod, o.Connect),
cmdutil.NewCommandHandler(CommandName, ProposePresentationMethod, o.ProposePresentation),
cmdutil.NewCommandHandler(CommandName, PresentProofMethod, o.PresentProof),
cmdutil.NewCommandHandler(CommandName, ProposeCredentialMethod, o.ProposeCredential),
cmdutil.NewCommandHandler(CommandName, RequestCredentialMethod, o.RequestCredential),
cmdutil.NewCommandHandler(CommandName, ResolveCredentialManifestMethod, o.ResolveCredentialManifest),
}
}

// Connect accepts out-of-band invitations and performs DID exchange.
func (o *CommandDidComm) Connect(rw io.Writer, req io.Reader) command.Error {
request := &ConnectRequest{}

err := json.NewDecoder(req).Decode(&request)
if err != nil {
logutil.LogInfo(logger, CommandName, ConnectMethod, err.Error())

return command.NewValidationError(InvalidRequestErrorCode, err)
}

vcWallet, err := wallet.New(request.UserID, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, ConnectMethod, err.Error())

return command.NewExecuteError(DIDConnectErrorCode, err)
}

didComm, err := wallet.NewDidComm(vcWallet, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, ConnectMethod, err.Error())

return command.NewExecuteError(DIDConnectErrorCode, err)
}

connectionID, err := didComm.Connect(request.Auth, request.Invitation,
wallet.WithConnectTimeout(request.Timeout), wallet.WithReuseDID(request.ReuseConnection),
wallet.WithReuseAnyConnection(request.ReuseAnyConnection), wallet.WithMyLabel(request.MyLabel),
wallet.WithRouterConnections(request.RouterConnections...))
if err != nil {
logutil.LogInfo(logger, CommandName, ConnectMethod, err.Error())

return command.NewExecuteError(DIDConnectErrorCode, err)
}

command.WriteNillableResponse(rw, &ConnectResponse{ConnectionID: connectionID}, logger)

logutil.LogDebug(logger, CommandName, ConnectMethod, logSuccess,
logutil.CreateKeyValueString(logUserIDKey, request.UserID),
logutil.CreateKeyValueString(invitationIDString, request.Invitation.ID),
logutil.CreateKeyValueString(LabelString, request.MyLabel),
logutil.CreateKeyValueString(connectionIDString, connectionID))

return nil
}

// ProposePresentation accepts out-of-band invitation and sends message proposing presentation
// from wallet to relying party.
// https://w3c-ccg.github.io/universal-wallet-interop-spec/#proposepresentation
//
// Currently Supporting
// [0454-present-proof-v2](https://github.com/hyperledger/aries-rfcs/tree/master/features/0454-present-proof-v2)
func (o *CommandDidComm) ProposePresentation(rw io.Writer, req io.Reader) command.Error {
request := &ProposePresentationRequest{}

err := json.NewDecoder(req).Decode(&request)
if err != nil {
logutil.LogInfo(logger, CommandName, ProposePresentationMethod, err.Error())

return command.NewValidationError(InvalidRequestErrorCode, err)
}

vcWallet, err := wallet.New(request.UserID, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, ProposePresentationMethod, err.Error())

return command.NewExecuteError(ProposePresentationErrorCode, err)
}

didComm, err := wallet.NewDidComm(vcWallet, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, ProposePresentationMethod, err.Error())

return command.NewExecuteError(ProposePresentationErrorCode, err)
}

msg, err := didComm.ProposePresentation(request.Auth, request.Invitation,
wallet.WithFromDID(request.FromDID), wallet.WithInitiateTimeout(request.Timeout),
wallet.WithConnectOptions(wallet.WithConnectTimeout(request.ConnectionOpts.Timeout),
wallet.WithReuseDID(request.ConnectionOpts.ReuseConnection),
wallet.WithReuseAnyConnection(request.ConnectionOpts.ReuseAnyConnection),
wallet.WithMyLabel(request.ConnectionOpts.MyLabel),
wallet.WithRouterConnections(request.ConnectionOpts.RouterConnections...)))
if err != nil {
logutil.LogInfo(logger, CommandName, ProposePresentationMethod, err.Error())

return command.NewExecuteError(ProposePresentationErrorCode, err)
}

command.WriteNillableResponse(rw, &ProposePresentationResponse{PresentationRequest: msg}, logger)

logutil.LogDebug(logger, CommandName, ProposePresentationMethod, logSuccess,
logutil.CreateKeyValueString(logUserIDKey, request.UserID))

return nil
}

// PresentProof sends present proof message from wallet to relying party.
// https://w3c-ccg.github.io/universal-wallet-interop-spec/#presentproof
//
// Currently Supporting
// [0454-present-proof-v2](https://github.com/hyperledger/aries-rfcs/tree/master/features/0454-present-proof-v2)
//
func (o *CommandDidComm) PresentProof(rw io.Writer, req io.Reader) command.Error {
request := &PresentProofRequest{}

err := json.NewDecoder(req).Decode(&request)
if err != nil {
logutil.LogInfo(logger, CommandName, PresentProofMethod, err.Error())

return command.NewValidationError(InvalidRequestErrorCode, err)
}

vcWallet, err := wallet.New(request.UserID, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, PresentProofMethod, err.Error())

return command.NewExecuteError(PresentProofErrorCode, err)
}

didComm, err := wallet.NewDidComm(vcWallet, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, PresentProofMethod, err.Error())

return command.NewExecuteError(PresentProofErrorCode, err)
}

status, err := didComm.PresentProof(request.Auth, request.ThreadID,
prepareConcludeInteractionOpts(request.WaitForDone, request.Timeout, request.Presentation)...)
if err != nil {
logutil.LogInfo(logger, CommandName, PresentProofMethod, err.Error())

return command.NewExecuteError(PresentProofErrorCode, err)
}

command.WriteNillableResponse(rw, status, logger)

logutil.LogDebug(logger, CommandName, PresentProofMethod, logSuccess,
logutil.CreateKeyValueString(logUserIDKey, request.UserID))

return nil
}

// ProposeCredential sends propose credential message from wallet to issuer.
// https://w3c-ccg.github.io/universal-wallet-interop-spec/#proposecredential
//
// Currently Supporting : 0453-issueCredentialV2
// https://github.com/hyperledger/aries-rfcs/blob/main/features/0453-issue-credential-v2/README.md
//
func (o *CommandDidComm) ProposeCredential(rw io.Writer, req io.Reader) command.Error {
request := &ProposeCredentialRequest{}

err := json.NewDecoder(req).Decode(&request)
if err != nil {
logutil.LogInfo(logger, CommandName, ProposeCredentialMethod, err.Error())

return command.NewValidationError(InvalidRequestErrorCode, err)
}

vcWallet, err := wallet.New(request.UserID, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, ProposeCredentialMethod, err.Error())

return command.NewExecuteError(ProposeCredentialErrorCode, err)
}

didComm, err := wallet.NewDidComm(vcWallet, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, ProposeCredentialMethod, err.Error())

return command.NewExecuteError(ProposeCredentialErrorCode, err)
}

msg, err := didComm.ProposeCredential(request.Auth, request.Invitation,
wallet.WithFromDID(request.FromDID), wallet.WithInitiateTimeout(request.Timeout),
wallet.WithConnectOptions(wallet.WithConnectTimeout(request.ConnectionOpts.Timeout),
wallet.WithReuseDID(request.ConnectionOpts.ReuseConnection),
wallet.WithReuseAnyConnection(request.ConnectionOpts.ReuseAnyConnection),
wallet.WithMyLabel(request.ConnectionOpts.MyLabel),
wallet.WithRouterConnections(request.ConnectionOpts.RouterConnections...)))
if err != nil {
logutil.LogInfo(logger, CommandName, ProposeCredentialMethod, err.Error())

return command.NewExecuteError(ProposeCredentialErrorCode, err)
}

command.WriteNillableResponse(rw, &ProposeCredentialResponse{OfferCredential: msg}, logger)

logutil.LogDebug(logger, CommandName, ProposeCredentialMethod, logSuccess,
logutil.CreateKeyValueString(logUserIDKey, request.UserID))

return nil
}

// RequestCredential sends request credential message from wallet to issuer and
// optionally waits for credential fulfillment.
// https://w3c-ccg.github.io/universal-wallet-interop-spec/#requestcredential
//
// Currently Supporting : 0453-issueCredentialV2
// https://github.com/hyperledger/aries-rfcs/blob/main/features/0453-issue-credential-v2/README.md
//
func (o *CommandDidComm) RequestCredential(rw io.Writer, req io.Reader) command.Error {
request := &RequestCredentialRequest{}

err := json.NewDecoder(req).Decode(&request)
if err != nil {
logutil.LogInfo(logger, CommandName, RequestCredentialMethod, err.Error())

return command.NewValidationError(InvalidRequestErrorCode, err)
}

vcWallet, err := wallet.New(request.UserID, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, RequestCredentialMethod, err.Error())

return command.NewExecuteError(RequestCredentialErrorCode, err)
}

didComm, err := wallet.NewDidComm(vcWallet, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, RequestCredentialMethod, err.Error())

return command.NewExecuteError(RequestCredentialErrorCode, err)
}

status, err := didComm.RequestCredential(request.Auth, request.ThreadID,
prepareConcludeInteractionOpts(request.WaitForDone, request.Timeout, request.Presentation)...)
if err != nil {
logutil.LogInfo(logger, CommandName, RequestCredentialMethod, err.Error())

return command.NewExecuteError(RequestCredentialErrorCode, err)
}

command.WriteNillableResponse(rw, status, logger)

logutil.LogDebug(logger, CommandName, RequestCredentialMethod, logSuccess,
logutil.CreateKeyValueString(logUserIDKey, request.UserID))

return nil
}

// ResolveCredentialManifest resolves given credential manifest by credential fulfillment or credential.
// Supports: https://identity.foundation/credential-manifest/
//
// Writes list of resolved descriptors to writer or returns error if operation fails.
//
func (o *CommandDidComm) ResolveCredentialManifest(rw io.Writer, req io.Reader) command.Error {
request := &ResolveCredentialManifestRequest{}

err := json.NewDecoder(req).Decode(&request)
if err != nil {
logutil.LogInfo(logger, CommandName, ResolveCredentialManifestMethod, err.Error())

return command.NewValidationError(InvalidRequestErrorCode, err)
}

vcWallet, err := wallet.New(request.UserID, o.ctx)
if err != nil {
logutil.LogInfo(logger, CommandName, ResolveCredentialManifestMethod, err.Error())

return command.NewExecuteError(ResolveCredentialManifestErrorCode, err)
}

resolved, err := vcWallet.ResolveCredentialManifest(request.Auth, request.Manifest,
prepareResolveManifestOption(request))
if err != nil {
logutil.LogInfo(logger, CommandName, ResolveCredentialManifestMethod, err.Error())

return command.NewExecuteError(ResolveCredentialManifestErrorCode, err)
}

command.WriteNillableResponse(rw, &ResolveCredentialManifestResponse{Resolved: resolved}, logger)

logutil.LogDebug(logger, CommandName, ResolveCredentialManifestMethod, logSuccess,
logutil.CreateKeyValueString(logUserIDKey, request.UserID))

return nil
}

func prepareConcludeInteractionOpts(waitForDone bool, timeout time.Duration, presentation json.RawMessage) []wallet.ConcludeInteractionOptions { //nolint: lll
var options []wallet.ConcludeInteractionOptions

if waitForDone {
options = append(options, wallet.WaitForDone(timeout))
}

return append(options, wallet.FromRawPresentation(presentation))
}

func prepareResolveManifestOption(rqst *ResolveCredentialManifestRequest) wallet.ResolveManifestOption {
if len(rqst.Fulfillment) > emptyRawLength {
return wallet.ResolveRawFulfillment(rqst.Fulfillment)
}

if len(rqst.Credential) > emptyRawLength {
return wallet.ResolveRawCredential(rqst.DescriptorID, rqst.Credential)
}

if rqst.CredentialID != "" {
return wallet.ResolveCredentialID(rqst.DescriptorID, rqst.CredentialID)
}

return nil
}
982 changes: 982 additions & 0 deletions pkg/controller/command/vcwallet/didcomm_test.go

Large diffs are not rendered by default.

269 changes: 28 additions & 241 deletions pkg/controller/command/vcwallet/models.go
Original file line number Diff line number Diff line change
@@ -11,308 +11,95 @@ import (
"time"

"github.com/hyperledger/aries-framework-go/pkg/client/outofband"
"github.com/hyperledger/aries-framework-go/pkg/controller/command/basewallet"
"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
"github.com/hyperledger/aries-framework-go/pkg/doc/cm"
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
"github.com/hyperledger/aries-framework-go/pkg/kms"
"github.com/hyperledger/aries-framework-go/pkg/wallet"
)

// CreateOrUpdateProfileRequest is request model for
// creating a new wallet profile or updating an existing wallet profile.
type CreateOrUpdateProfileRequest struct {
// Unique identifier to identify wallet user
UserID string `json:"userID"`

// passphrase for local kms for key operations.
// Optional, if this option is provided then wallet for this profile will use local KMS for key operations.
LocalKMSPassphrase string `json:"localKMSPassphrase,omitempty"`

// passphrase for web/remote kms for key operations.
// Optional, if this option is provided then wallet for this profile will use web/remote KMS for key operations.
KeyStoreURL string `json:"keyStoreURL,omitempty"`

// edv configuration for storing wallet contents for this profile
// Optional, if not provided then agent storage provider will be used as store provider.
EDVConfiguration *EDVConfiguration `json:"edvConfiguration,omitempty"`
}
type CreateOrUpdateProfileRequest = basewallet.CreateOrUpdateProfileRequest

// EDVConfiguration contains configuration for EDV settings for profile creation.
type EDVConfiguration struct {
// EDV server URL for storing wallet contents.
ServerURL string `json:"serverURL,omitempty"`

// EDV vault ID for storing the wallet contents.
VaultID string `json:"vaultID,omitempty"`

// Encryption key ID of already existing key in wallet profile kms.
// If profile is using localkms then wallet will create this key set for wallet user.
EncryptionKeyID string `json:"encryptionKID,omitempty"`

// MAC operation key ID of already existing key in wallet profile kms.
// If profile is using localkms then wallet will create this key set for wallet user.
MACKeyID string `json:"macKID,omitempty"`
}
type EDVConfiguration = basewallet.EDVConfiguration

// UnlockWalletRequest contains different options for unlocking wallet.
type UnlockWalletRequest struct {
// user ID of the wallet to be unlocked.
UserID string `json:"userID"`

// passphrase for local kms for key operations.
// Optional, to be used if profile for this wallet user is setup with local KMS.
LocalKMSPassphrase string `json:"localKMSPassphrase,omitempty"`

// WebKMSAuth for authorizing acccess to web/remote kms.
// Optional, to be used if profile for this wallet user is setup with web/remote KMS.
WebKMSAuth *UnlockAuth `json:"webKMSAuth"`

// Options for authorizing access to wallet's EDV content store.
// Optional, to be used only if profile for this wallet user is setup to use EDV as content store.
EDVUnlock *UnlockAuth `json:"edvUnlocks"`

// Time duration in milliseconds after which wallet will expire its unlock status.
Expiry time.Duration `json:"expiry,omitempty"`
}
type UnlockWalletRequest = basewallet.UnlockWalletRequest

// UnlockAuth contains different options for authorizing access to wallet's EDV content store & webkms.
type UnlockAuth struct {
// Http header 'authorization' bearer token to be used.
// Optional, only if required by wallet user (for webkms or edv).
AuthToken string `json:"authToken,omitempty"`

// Http header 'authorization' GNAP token to be used.
// Optional, only if required by wallet user (for webkms or edv).
GNAPToken string `json:"gnapToken,omitempty"`

// Capability if ZCAP sign header feature to be used for authorizing access.
// Optional, can be used only if ZCAP sign header feature is configured with command controller.
Capability string `json:"capability,omitempty"`

// AuthZKeyStoreURL if ZCAP sign header feature to be used for authorizing access.
// Optional, can be used only if ZCAP sign header feature is configured with command controller.
AuthZKeyStoreURL string `json:"authzKeyStoreURL,omitempty"`

// SecretShare if ZCAP sign header feature to be used for authorizing access.
// Optional, can be used only if ZCAP sign header feature is configured with command controller.
SecretShare string `json:"secretShare,omitempty"`
}
type UnlockAuth = basewallet.UnlockAuth

// UnlockWalletResponse contains response for wallet unlock operation.
type UnlockWalletResponse struct {
// Token for granting access to wallet for subsequent wallet operations.
Token string `json:"token,omitempty"`
}
type UnlockWalletResponse = basewallet.UnlockWalletResponse

// LockWalletRequest contains options for locking wallet.
type LockWalletRequest struct {
// user ID of the wallet to be locked.
UserID string `json:"userID"`
}
type LockWalletRequest = basewallet.LockWalletRequest

// LockWalletResponse contains response for wallet lock operation.
type LockWalletResponse struct {
// Closed status of the wallet lock operation.
// if true, wallet is closed successfully
// if false, wallet is already closed or never unlocked.
Closed bool `json:"closed"`
}
type LockWalletResponse = basewallet.LockWalletResponse

// WalletAuth contains wallet auth parameters for performing wallet operations.
type WalletAuth struct {
// Authorization token for performing wallet operations.
Auth string `json:"auth"`

// ID of wallet user.
UserID string `json:"userID"`
}
type WalletAuth = basewallet.WalletAuth

// WalletUser contains wallet user info for performing profile operations.
type WalletUser struct {
// ID of wallet user.
ID string `json:"userID"`
}
type WalletUser = basewallet.WalletUser

// AddContentRequest is request for adding a content to wallet.
type AddContentRequest struct {
WalletAuth

// type of the content to be added to the wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection, key
ContentType wallet.ContentType `json:"contentType"`

// content to be added to wallet content store.
Content json.RawMessage `json:"content"`

// ID of the wallet collection to which this content should belong.
CollectionID string `json:"collectionID"`
}
type AddContentRequest = basewallet.AddContentRequest

// RemoveContentRequest is request for removing a content from wallet.
type RemoveContentRequest struct {
WalletAuth

// type of the content to be removed from the wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection
ContentType wallet.ContentType `json:"contentType"`

// ID of the content to be removed from wallet
ContentID string `json:"contentID"`
}
type RemoveContentRequest = basewallet.RemoveContentRequest

// GetContentRequest is request for getting a content from wallet.
type GetContentRequest struct {
WalletAuth

// type of the content to be returned from wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection
ContentType wallet.ContentType `json:"contentType"`

// ID of the content to be returned from wallet
ContentID string `json:"contentID"`
}
type GetContentRequest = basewallet.GetContentRequest

// GetContentResponse response for get content from wallet operation.
type GetContentResponse struct {
// content retrieved from wallet content store.
Content json.RawMessage `json:"content"`
}
type GetContentResponse = basewallet.GetContentResponse

// GetAllContentRequest is request for getting all contents from wallet for given content type.
type GetAllContentRequest struct {
WalletAuth

// type of the contents to be returned from wallet.
// supported types: collection, credential, didResolutionResponse, metadata, connection
ContentType wallet.ContentType `json:"contentType"`

// ID of the collection on which the response contents to be filtered.
CollectionID string `json:"collectionID,omitempty"`
}
type GetAllContentRequest = basewallet.GetAllContentRequest

// GetAllContentResponse response for get all content by content type wallet operation.
type GetAllContentResponse struct {
// contents retrieved from wallet content store.
// map of content ID to content.
Contents map[string]json.RawMessage `json:"contents"`
}
type GetAllContentResponse = basewallet.GetAllContentResponse

// ContentQueryRequest is request model for querying wallet contents.
type ContentQueryRequest struct {
WalletAuth

// credential query(s) for querying wallet contents.
Query []*wallet.QueryParams `json:"query"`
}
type ContentQueryRequest = basewallet.ContentQueryRequest

// ContentQueryResponse response for wallet content query.
type ContentQueryResponse struct {
// response presentation(s) containing query results.
Results []*verifiable.Presentation `json:"results"`
}
type ContentQueryResponse = basewallet.ContentQueryResponse

// IssueRequest is request model for issuing credential from wallet.
type IssueRequest struct {
WalletAuth

// raw credential to be issued from wallet.
Credential json.RawMessage `json:"credential"`

// proof options for issuing credential
ProofOptions *wallet.ProofOptions `json:"proofOptions"`
}
type IssueRequest = basewallet.IssueRequest

// IssueResponse is response for issue credential interface from wallet.
type IssueResponse struct {
// credential issued.
Credential *verifiable.Credential `json:"credential"`
}
type IssueResponse = basewallet.IssueResponse

// ProveRequest for producing verifiable presentation from wallet.
// Contains options for proofs and credential. Any combination of credential option can be mixed.
type ProveRequest struct {
WalletAuth

// IDs of credentials already saved in wallet content store.
StoredCredentials []string `json:"storedCredentials"`

// List of raw credentials to be presented.
RawCredentials []json.RawMessage `json:"rawCredentials"`

// Presentation to be proved.
Presentation json.RawMessage `json:"presentation"`

// proof options for issuing credential.
ProofOptions *wallet.ProofOptions `json:"proofOptions"`
}
type ProveRequest = basewallet.ProveRequest

// ProveResponse contains response presentation from prove operation.
type ProveResponse struct {
// presentation response from prove operation.
Presentation *verifiable.Presentation `json:"presentation"`
}
type ProveResponse = basewallet.ProveResponse

// VerifyRequest request for verifying a credential or presentation from wallet.
// Any one of the credential option should be used.
type VerifyRequest struct {
WalletAuth

// ID of the credential already saved in wallet content store.
// optional, if provided then this option takes precedence over other options.
StoredCredentialID string `json:"storedCredentialID"`

// List of raw credential to be presented.
// optional, if provided then this option takes precedence over presentation options.
RawCredential json.RawMessage `json:"rawCredential"`

// Presentation to be proved.
// optional, will be used only if other options are not provided.
Presentation json.RawMessage `json:"presentation"`
}
type VerifyRequest = basewallet.VerifyRequest

// VerifyResponse is response model for wallet verify operation.
type VerifyResponse struct {
// if true then verification is successful.
Verified bool `json:"verified"`

// error details if verified is false.
Error string `json:"error,omitempty"`
}
type VerifyResponse = basewallet.VerifyResponse

// DeriveRequest is request model for deriving a credential from wallet.
type DeriveRequest struct {
WalletAuth

// ID of the credential already saved in wallet content store.
// optional, if provided then this option takes precedence.
StoredCredentialID string `json:"storedCredentialID"`

// List of raw credential to be presented.
// optional, will be used only if other options is not provided.
RawCredential json.RawMessage `json:"rawCredential"`

// DeriveOptions options for deriving credential
*wallet.DeriveOptions `json:"deriveOption"`
}
type DeriveRequest = basewallet.DeriveRequest

// DeriveResponse is response for derived credential operation.
type DeriveResponse struct {
// credential derived.
Credential *verifiable.Credential `json:"credential"`
}
type DeriveResponse = basewallet.DeriveResponse

// CreateKeyPairRequest is request model for creating key pair from wallet.
type CreateKeyPairRequest struct {
WalletAuth

// type of the key to be created.
KeyType kms.KeyType `json:"keyType,omitempty"`
}
type CreateKeyPairRequest = basewallet.CreateKeyPairRequest

// CreateKeyPairResponse is response model for creating key pair from wallet.
type CreateKeyPairResponse struct {
*wallet.KeyPair
}
type CreateKeyPairResponse = basewallet.CreateKeyPairResponse

// ConnectRequest is request model for wallet DID connect operation.
type ConnectRequest struct {
22 changes: 13 additions & 9 deletions pkg/controller/rest/vcwallet/operation.go
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ import (
"github.com/gorilla/mux"
"github.com/piprate/json-gold/ld"

"github.com/hyperledger/aries-framework-go/pkg/controller/command/basewallet"
"github.com/hyperledger/aries-framework-go/pkg/controller/command/vcwallet"
"github.com/hyperledger/aries-framework-go/pkg/controller/internal/cmdutil"
"github.com/hyperledger/aries-framework-go/pkg/controller/rest"
@@ -75,16 +76,19 @@ type didCommProvider interface {
}

// Operation contains REST operations provided by verifiable credential wallet.
// Wraps basewallet.Command and vcwallet.CommandDidComm in the same ways as vcwallet.Command.
type Operation struct {
handlers []rest.Handler
command *vcwallet.Command
command *basewallet.Command
didcomm *vcwallet.CommandDidComm
}

// New returns new verfiable credential wallet REST controller.
func New(p provider, config *vcwallet.Config) *Operation {
cmd := vcwallet.New(p, config)
cmd := basewallet.New(p, config)
didcomm := vcwallet.NewDidCommCommand(p)

o := &Operation{command: cmd}
o := &Operation{command: cmd, didcomm: didcomm}

o.registerHandler()

@@ -356,7 +360,7 @@ func (o *Operation) CreateKeyPair(rw http.ResponseWriter, req *http.Request) {
// default: genericError
// 200: connectRes
func (o *Operation) Connect(rw http.ResponseWriter, req *http.Request) {
rest.Execute(o.command.Connect, rw, req.Body)
rest.Execute(o.didcomm.Connect, rw, req.Body)
}

// ProposePresentation swagger:route POST /vcwallet/propose-presentation vcwallet proposePresReq
@@ -372,7 +376,7 @@ func (o *Operation) Connect(rw http.ResponseWriter, req *http.Request) {
// default: genericError
// 200: proposePresRes
func (o *Operation) ProposePresentation(rw http.ResponseWriter, req *http.Request) {
rest.Execute(o.command.ProposePresentation, rw, req.Body)
rest.Execute(o.didcomm.ProposePresentation, rw, req.Body)
}

// PresentProof swagger:route POST /vcwallet/present-proof vcwallet presentProofReq
@@ -387,7 +391,7 @@ func (o *Operation) ProposePresentation(rw http.ResponseWriter, req *http.Reques
// default: genericError
// 200: presentProofRes
func (o *Operation) PresentProof(rw http.ResponseWriter, req *http.Request) {
rest.Execute(o.command.PresentProof, rw, req.Body)
rest.Execute(o.didcomm.PresentProof, rw, req.Body)
}

// ProposeCredential swagger:route POST /vcwallet/propose-credential vcwallet proposeCredReq
@@ -402,7 +406,7 @@ func (o *Operation) PresentProof(rw http.ResponseWriter, req *http.Request) {
// default: genericError
// 200: proposeCredRes
func (o *Operation) ProposeCredential(rw http.ResponseWriter, req *http.Request) {
rest.Execute(o.command.ProposeCredential, rw, req.Body)
rest.Execute(o.didcomm.ProposeCredential, rw, req.Body)
}

// RequestCredential swagger:route POST /vcwallet/request-credential vcwallet requestCredReq
@@ -417,7 +421,7 @@ func (o *Operation) ProposeCredential(rw http.ResponseWriter, req *http.Request)
// default: genericError
// 200: requestCredRes
func (o *Operation) RequestCredential(rw http.ResponseWriter, req *http.Request) {
rest.Execute(o.command.RequestCredential, rw, req.Body)
rest.Execute(o.didcomm.RequestCredential, rw, req.Body)
}

// ResolveCredentialManifest swagger:route POST /vcwallet/resolve-credential-manifest vcwallet resolveCredManifest
@@ -429,7 +433,7 @@ func (o *Operation) RequestCredential(rw http.ResponseWriter, req *http.Request)
// default: genericError
// 200: resolveCredManifest
func (o *Operation) ResolveCredentialManifest(rw http.ResponseWriter, req *http.Request) {
rest.Execute(o.command.ResolveCredentialManifest, rw, req.Body)
rest.Execute(o.didcomm.ResolveCredentialManifest, rw, req.Body)
}

// getIDFromRequest returns ID from request.

0 comments on commit a24b620

Please sign in to comment.