From 6fb9d77c80fddf9c3a54ba09bfef49fc12b9ef41 Mon Sep 17 00:00:00 2001 From: Seth Back Date: Thu, 10 Mar 2022 10:01:16 -0800 Subject: [PATCH 1/4] update to golang sdk --- go/services/account_service.go | 48 +++++----- go/services/account_service_test.go | 8 +- go/services/credential_service.go | 106 +++++++++------------- go/services/credentialtemplate_service.go | 30 +++--- go/services/provider_service.go | 27 ++++-- go/services/security.go | 3 + go/services/service_base.go | 77 +++++++++------- go/services/service_base_test.go | 31 +++++-- go/services/services.go | 87 ++++++++++-------- go/services/services_test.go | 99 +++++++------------- go/services/trustregistry_service.go | 89 ++++++++++++------ go/services/wallet_service.go | 58 ++++++------ 12 files changed, 354 insertions(+), 309 deletions(-) diff --git a/go/services/account_service.go b/go/services/account_service.go index fdd0f09f6..17dbd686a 100644 --- a/go/services/account_service.go +++ b/go/services/account_service.go @@ -12,14 +12,14 @@ import ( // NewAccountService returns an account servcie with the base service configured // using the provided options -func NewAccountService(options *sdk.ServiceOptions) (AccountService, error) { +func NewAccountService(options *Options) (AccountService, error) { base, err := NewServiceBase(options) if err != nil { return nil, err } - service := &AccountBase{ - ServiceBase: base, - client: sdk.NewAccountClient(base.channel), + service := &accountBase{ + Service: base, + client: sdk.NewAccountClient(base.GetChannel()), } return service, nil @@ -29,9 +29,9 @@ func NewAccountService(options *sdk.ServiceOptions) (AccountService, error) { type AccountService interface { Service // SignIn returns an encoded auth token - SignIn(userContext context.Context, details *sdk.AccountDetails, inviteCode, ecosystemID string) (string, sdk.ConfirmationMethod, error) + SignIn(userContext context.Context, request *sdk.SignInRequest) (string, sdk.ConfirmationMethod, error) // Unprotect takes an authtoken that has been protected using a pin code - // and returns an ulocked token + // and returns an unlocked token Unprotect(authtoken, securityCode string) (string, error) // Protect will apply the given security code blind to the provided token Protect(authtoken, securityCode string) (string, error) @@ -43,37 +43,35 @@ type AccountService interface { RevokeDevice(userContext context.Context, request *sdk.RevokeDeviceRequest) (*sdk.RevokeDeviceResponse, error) } -// AccountBase implements the AccountService interface -type AccountBase struct { - *ServiceBase +type accountBase struct { + Service client sdk.AccountClient } // SignIn to a given account -func (a *AccountBase) SignIn(userContext context.Context, details *sdk.AccountDetails, inviteCode, ecosystemID string) (string, sdk.ConfirmationMethod, error) { - if details == nil { - details = &sdk.AccountDetails{} - } - - if len(ecosystemID) == 0 { - ecosystemID = a.options.DefaultEcosystem +func (a *accountBase) SignIn(userContext context.Context, request *sdk.SignInRequest) (string, sdk.ConfirmationMethod, error) { + if len(request.EcosystemId) == 0 { + request.EcosystemId = a.GetServiceOptions().DefaultEcosystem } - response, err := a.client.SignIn(userContext, &sdk.SignInRequest{Details: details, InvitationCode: inviteCode, EcosystemId: ecosystemID}) + resp, err := a.client.SignIn(userContext, request) if err != nil { return "", sdk.ConfirmationMethod_None, err } - tkn, err := ProfileToToken(response.Profile) + tkn, err := ProfileToToken(resp.Profile) if err != nil { return "", sdk.ConfirmationMethod_None, err } - return tkn, response.ConfirmationMethod, nil + return tkn, resp.ConfirmationMethod, nil } // Unprotect an authtoken using the given security code -func (a *AccountBase) Unprotect(authtoken, securityCode string) (string, error) { +// +// This method can be called multiple times on an individual token +// to "unwrap" the blindings that have been applied +func (a *accountBase) Unprotect(authtoken, securityCode string) (string, error) { profile, err := ProfileFromToken(authtoken) if err != nil { return "", err @@ -101,8 +99,8 @@ func (a *AccountBase) Unprotect(authtoken, securityCode string) (string, error) // Protect an authtoken with the given security code. Must be unprotected before use // // This method can be called as many times as you want, but each code must be "unwrapped" -// in the reverse order before use -func (a *AccountBase) Protect(authtoken, securityCode string) (string, error) { +// by calling Unprotect in the reverse order before use +func (a *accountBase) Protect(authtoken, securityCode string) (string, error) { profile, err := ProfileFromToken(authtoken) if err != nil { return "", err @@ -128,7 +126,7 @@ func (a *AccountBase) Protect(authtoken, securityCode string) (string, error) { } // GetInfo associated with a given wallet -func (a *AccountBase) GetInfo(userContext context.Context) (*sdk.InfoResponse, error) { +func (a *accountBase) GetInfo(userContext context.Context) (*sdk.InfoResponse, error) { request := &sdk.InfoRequest{} md, err := a.GetMetadataContext(userContext, request) if err != nil { @@ -142,7 +140,7 @@ func (a *AccountBase) GetInfo(userContext context.Context) (*sdk.InfoResponse, e } // ListDevices that can access the cloud wallet -func (a *AccountBase) ListDevices(userContext context.Context, request *sdk.ListDevicesRequest) (*sdk.ListDevicesResponse, error) { +func (a *accountBase) ListDevices(userContext context.Context, request *sdk.ListDevicesRequest) (*sdk.ListDevicesResponse, error) { md, err := a.GetMetadataContext(userContext, request) if err != nil { return nil, err @@ -155,7 +153,7 @@ func (a *AccountBase) ListDevices(userContext context.Context, request *sdk.List } // RevokeDevice from the cloud wallet -func (a *AccountBase) RevokeDevice(userContext context.Context, request *sdk.RevokeDeviceRequest) (*sdk.RevokeDeviceResponse, error) { +func (a *accountBase) RevokeDevice(userContext context.Context, request *sdk.RevokeDeviceRequest) (*sdk.RevokeDeviceResponse, error) { md, err := a.GetMetadataContext(userContext, request) if err != nil { return nil, err diff --git a/go/services/account_service_test.go b/go/services/account_service_test.go index bfeba21e5..437f0a88d 100644 --- a/go/services/account_service_test.go +++ b/go/services/account_service_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + sdk "github.com/trinsic-id/sdk/go/proto" ) func TestProtectUnprotectProfile(t *testing.T) { @@ -19,7 +20,8 @@ func TestProtectUnprotectProfile(t *testing.T) { if !assert2.Nil(err) { return } - profile, _, err := accountService.SignIn(context.Background(), nil, "", "default") + + profile, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{}) if !assert2.Nil(err) { return } @@ -35,7 +37,7 @@ func TestProtectUnprotectProfile(t *testing.T) { } t.Run("Protected profile should fail", func(t *testing.T) { - accountService.SetProfile(protectedProfile) + accountService.SetToken(protectedProfile) info2, err2 := accountService.GetInfo(context.Background()) if !assert2.NotNil(err2) { t.FailNow() @@ -46,7 +48,7 @@ func TestProtectUnprotectProfile(t *testing.T) { }) t.Run("Unprotected profile should work", func(t *testing.T) { - accountService.SetProfile(unprotectedProfile) + accountService.SetToken(unprotectedProfile) info2, err2 := accountService.GetInfo(context.Background()) if !assert2.Nil(err2) { t.FailNow() diff --git a/go/services/credential_service.go b/go/services/credential_service.go index b35716e8c..f1f299318 100644 --- a/go/services/credential_service.go +++ b/go/services/credential_service.go @@ -2,7 +2,6 @@ package services import ( "context" - "encoding/json" "fmt" sdk "github.com/trinsic-id/sdk/go/proto" @@ -10,117 +9,102 @@ import ( type Document map[string]interface{} -func NewCredentialService(options *sdk.ServiceOptions) (CredentialService, error) { +// NewCredentialService returns a credential service with the base service configured +// using the provided options +func NewCredentialService(options *Options) (CredentialService, error) { base, err := NewServiceBase(options) if err != nil { return nil, err } - service := &CredentialBase{ - ServiceBase: base, - client: sdk.NewVerifiableCredentialClient(base.channel), + service := &credentialBase{ + Service: base, + client: sdk.NewVerifiableCredentialClient(base.GetChannel()), } return service, nil } +// CredentialsService defines the interface for interacting with credentials type CredentialService interface { Service - IssueCredential(userContext context.Context, document Document) (Document, error) + // IssueCredential using a document json + IssueCredential(userContext context.Context, request *sdk.IssueRequest) (*sdk.IssueResponse, error) + // IssueFromTemplate issues a credential using a template IssueFromTemplate(userContext context.Context, request *sdk.IssueFromTemplateRequest) (*sdk.IssueFromTemplateResponse, error) + // CheckStatus of the credential CheckStatus(userContext context.Context, request *sdk.CheckStatusRequest) (*sdk.CheckStatusResponse, error) + // UpdateStatus of the credential (i.e. revoke) UpdateStatus(userContext context.Context, request *sdk.UpdateStatusRequest) (*sdk.UpdateStatusResponse, error) - CreateProof(userContext context.Context, documentId string, revealDocument Document) (Document, error) - VerifyProof(userContext context.Context, proofDocument Document) (bool, error) - Send(userContext context.Context, document Document, email string) error + // CreateProof using either a credential in a cloud wallet or based on the json document provided + CreateProof(userContext context.Context, request *sdk.CreateProofRequest) (*sdk.CreateProofResponse, error) + // VerifyProof presentation + VerifyProof(userContext context.Context, request *sdk.VerifyProofRequest) (bool, error) + // Send a credential to another use's wallet + Send(userContext context.Context, request *sdk.SendRequest) error } -type CredentialBase struct { - *ServiceBase +type credentialBase struct { + Service client sdk.VerifiableCredentialClient } -func (c *CredentialBase) IssueCredential(userContext context.Context, document Document) (Document, error) { - jsonBytes, err := json.Marshal(document) +func (c *credentialBase) IssueCredential(userContext context.Context, request *sdk.IssueRequest) (*sdk.IssueResponse, error) { + md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err } - issueRequest := &sdk.IssueRequest{ - DocumentJson: string(jsonBytes), - } - md, err := c.GetMetadataContext(userContext, issueRequest) - if err != nil { - return nil, err - } - response, err := c.client.Issue(md, issueRequest) - if err != nil { - return nil, err - } - var doc map[string]interface{} - err = json.Unmarshal([]byte(response.SignedDocumentJson), &doc) + response, err := c.client.Issue(md, request) if err != nil { return nil, err } - return doc, nil + + return response, nil } -func (c *CredentialBase) IssueFromTemplate(userContext context.Context, request *sdk.IssueFromTemplateRequest) (*sdk.IssueFromTemplateResponse, error) { +func (c *credentialBase) IssueFromTemplate(userContext context.Context, request *sdk.IssueFromTemplateRequest) (*sdk.IssueFromTemplateResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err } + response, err := c.client.IssueFromTemplate(md, request) if err != nil { return nil, err } + return response, nil } -func (c *CredentialBase) CreateProof(userContext context.Context, documentId string, revealDocument Document) (Document, error) { - jsonString, err := json.Marshal(revealDocument) - if err != nil { - return nil, err - } - request := &sdk.CreateProofRequest{ - Proof: &sdk.CreateProofRequest_ItemId{ItemId: documentId}, - RevealDocumentJson: string(jsonString), - } +func (c *credentialBase) CreateProof(userContext context.Context, request *sdk.CreateProofRequest) (*sdk.CreateProofResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err } - proof, err := c.client.CreateProof(md, request) - if err != nil { - return nil, err - } - var proofMap map[string]interface{} - err = json.Unmarshal([]byte(proof.ProofDocumentJson), &proofMap) + + response, err := c.client.CreateProof(md, request) if err != nil { return nil, err } - return proofMap, nil + + return response, nil } -func (c *CredentialBase) VerifyProof(userContext context.Context, proofDocument Document) (bool, error) { - jsonString, err := json.Marshal(proofDocument) - if err != nil { - return false, err - } - request := &sdk.VerifyProofRequest{ - ProofDocumentJson: string(jsonString), - } +func (c *credentialBase) VerifyProof(userContext context.Context, request *sdk.VerifyProofRequest) (bool, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return false, err } + proof, err := c.client.VerifyProof(md, request) if err != nil { return false, err } + return proof.IsValid, nil } -func (c *CredentialBase) CheckStatus(userContext context.Context, request *sdk.CheckStatusRequest) (*sdk.CheckStatusResponse, error) { +func (c *credentialBase) CheckStatus(userContext context.Context, request *sdk.CheckStatusRequest) (*sdk.CheckStatusResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err @@ -132,7 +116,7 @@ func (c *CredentialBase) CheckStatus(userContext context.Context, request *sdk.C return response, nil } -func (c *CredentialBase) UpdateStatus(userContext context.Context, request *sdk.UpdateStatusRequest) (*sdk.UpdateStatusResponse, error) { +func (c *credentialBase) UpdateStatus(userContext context.Context, request *sdk.UpdateStatusRequest) (*sdk.UpdateStatusResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err @@ -147,24 +131,16 @@ func (c *CredentialBase) UpdateStatus(userContext context.Context, request *sdk. return response, fmt.Errorf("error - did not run to completion %s", response.Status) } -func (c *CredentialBase) Send(userContext context.Context, document Document, email string) error { - jsonString, err := json.Marshal(document) - if err != nil { - return err - } - request := &sdk.SendRequest{ - DeliveryMethod: &sdk.SendRequest_Email{ - Email: email, - }, - DocumentJson: string(jsonString), - } +func (c *credentialBase) Send(userContext context.Context, request *sdk.SendRequest) error { md, err := c.GetMetadataContext(userContext, request) if err != nil { return err } + _, err = c.client.Send(md, request) if err != nil { return err } + return nil } diff --git a/go/services/credentialtemplate_service.go b/go/services/credentialtemplate_service.go index 1fca63243..1ecafa0ba 100644 --- a/go/services/credentialtemplate_service.go +++ b/go/services/credentialtemplate_service.go @@ -6,34 +6,42 @@ import ( sdk "github.com/trinsic-id/sdk/go/proto" ) -func NewCredentialTemplateService(options *sdk.ServiceOptions) (CredentialTemplateService, error) { +// NewCredentialTemplateService returns a credential template servcie with the base service configured +// using the provided options +func NewCredentialTemplateService(options *Options) (CredentialTemplateService, error) { base, err := NewServiceBase(options) if err != nil { return nil, err } - service := &CredentialTemplateBase{ - ServiceBase: base, - client: sdk.NewCredentialTemplatesClient(base.channel), + service := &credentialTemplateBase{ + Service: base, + client: sdk.NewCredentialTemplatesClient(base.GetChannel()), } return service, nil } +// CredentialTemplateService defines the interface for interacting with credentials templates type CredentialTemplateService interface { Service + // Create a credential template Create(userContext context.Context, request *sdk.CreateCredentialTemplateRequest) (*sdk.CreateCredentialTemplateResponse, error) + // Get a specific credential template Get(userContext context.Context, request *sdk.GetCredentialTemplateRequest) (*sdk.GetCredentialTemplateResponse, error) + // List available credential templates List(userContext context.Context, request *sdk.ListCredentialTemplatesRequest) (*sdk.ListCredentialTemplatesResponse, error) + // Search for a template Search(userContext context.Context, request *sdk.SearchCredentialTemplatesRequest) (*sdk.SearchCredentialTemplatesResponse, error) + // Delete a template Delete(userContext context.Context, request *sdk.DeleteCredentialTemplateRequest) (*sdk.DeleteCredentialTemplateResponse, error) } -type CredentialTemplateBase struct { - *ServiceBase +type credentialTemplateBase struct { + Service client sdk.CredentialTemplatesClient } -func (c *CredentialTemplateBase) Create(userContext context.Context, request *sdk.CreateCredentialTemplateRequest) (*sdk.CreateCredentialTemplateResponse, error) { +func (c *credentialTemplateBase) Create(userContext context.Context, request *sdk.CreateCredentialTemplateRequest) (*sdk.CreateCredentialTemplateResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err @@ -45,7 +53,7 @@ func (c *CredentialTemplateBase) Create(userContext context.Context, request *sd return response, nil } -func (c *CredentialTemplateBase) Get(userContext context.Context, request *sdk.GetCredentialTemplateRequest) (*sdk.GetCredentialTemplateResponse, error) { +func (c *credentialTemplateBase) Get(userContext context.Context, request *sdk.GetCredentialTemplateRequest) (*sdk.GetCredentialTemplateResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err @@ -57,7 +65,7 @@ func (c *CredentialTemplateBase) Get(userContext context.Context, request *sdk.G return response, nil } -func (c *CredentialTemplateBase) List(userContext context.Context, request *sdk.ListCredentialTemplatesRequest) (*sdk.ListCredentialTemplatesResponse, error) { +func (c *credentialTemplateBase) List(userContext context.Context, request *sdk.ListCredentialTemplatesRequest) (*sdk.ListCredentialTemplatesResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err @@ -69,7 +77,7 @@ func (c *CredentialTemplateBase) List(userContext context.Context, request *sdk. return response, nil } -func (c *CredentialTemplateBase) Search(userContext context.Context, request *sdk.SearchCredentialTemplatesRequest) (*sdk.SearchCredentialTemplatesResponse, error) { +func (c *credentialTemplateBase) Search(userContext context.Context, request *sdk.SearchCredentialTemplatesRequest) (*sdk.SearchCredentialTemplatesResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err @@ -81,7 +89,7 @@ func (c *CredentialTemplateBase) Search(userContext context.Context, request *sd return response, nil } -func (c *CredentialTemplateBase) Delete(userContext context.Context, request *sdk.DeleteCredentialTemplateRequest) (*sdk.DeleteCredentialTemplateResponse, error) { +func (c *credentialTemplateBase) Delete(userContext context.Context, request *sdk.DeleteCredentialTemplateRequest) (*sdk.DeleteCredentialTemplateResponse, error) { md, err := c.GetMetadataContext(userContext, request) if err != nil { return nil, err diff --git a/go/services/provider_service.go b/go/services/provider_service.go index ef0335ecd..fd6bf74fc 100644 --- a/go/services/provider_service.go +++ b/go/services/provider_service.go @@ -7,33 +7,40 @@ import ( sdk "github.com/trinsic-id/sdk/go/proto" ) -func NewProviderService(options *sdk.ServiceOptions) (ProviderService, error) { +// NewProviderService returns a provider servcie with the base service configured +// using the provided options +func NewProviderService(options *Options) (ProviderService, error) { base, err := NewServiceBase(options) if err != nil { return nil, err } - service := &ProviderBase{ - ServiceBase: base, - client: sdk.NewProviderClient(base.channel), + service := &providerBase{ + Service: base, + client: sdk.NewProviderClient(base.GetChannel()), } return service, nil } +// ProviderService wraps all the functions for interacting with providers (ecosystems) type ProviderService interface { Service + // InviteParticipant to the ecosystem InviteParticipant(userContext context.Context, request *sdk.InviteRequest) (*sdk.InviteResponse, error) + // InvitationStatus returns the status of the invitation InvitationStatus(userContext context.Context, request *sdk.InvitationStatusRequest) (*sdk.InvitationStatusResponse, error) + // CreateEcosystem creates a new ecosystem CreateEcosystem(ctx context.Context, request *sdk.CreateEcosystemRequest) (*sdk.CreateEcosystemResponse, error) + // GenerateToken returns an authToken that can be used for interacting with the ecosystem GenerateToken(ctx context.Context, description string) (string, error) } -type ProviderBase struct { - *ServiceBase +type providerBase struct { + Service client sdk.ProviderClient } -func (p *ProviderBase) InviteParticipant(ctx context.Context, request *sdk.InviteRequest) (*sdk.InviteResponse, error) { +func (p *providerBase) InviteParticipant(ctx context.Context, request *sdk.InviteRequest) (*sdk.InviteResponse, error) { if request == nil || request.Details == nil || len(request.Details.Email) == 0 { return nil, errors.New("must provide email to invite") } @@ -51,7 +58,7 @@ func (p *ProviderBase) InviteParticipant(ctx context.Context, request *sdk.Invit return response, nil } -func (p *ProviderBase) InvitationStatus(ctx context.Context, request *sdk.InvitationStatusRequest) (*sdk.InvitationStatusResponse, error) { +func (p *providerBase) InvitationStatus(ctx context.Context, request *sdk.InvitationStatusRequest) (*sdk.InvitationStatusResponse, error) { md, err := p.GetMetadataContext(ctx, request) if err != nil { return nil, err @@ -65,7 +72,7 @@ func (p *ProviderBase) InvitationStatus(ctx context.Context, request *sdk.Invita return response, nil } -func (p *ProviderBase) CreateEcosystem(ctx context.Context, request *sdk.CreateEcosystemRequest) (*sdk.CreateEcosystemResponse, error) { +func (p *providerBase) CreateEcosystem(ctx context.Context, request *sdk.CreateEcosystemRequest) (*sdk.CreateEcosystemResponse, error) { resp, err := p.client.CreateEcosystem(ctx, request) if err != nil { return nil, err @@ -74,7 +81,7 @@ func (p *ProviderBase) CreateEcosystem(ctx context.Context, request *sdk.CreateE return resp, nil } -func (p *ProviderBase) GenerateToken(ctx context.Context, description string) (string, error) { +func (p *providerBase) GenerateToken(ctx context.Context, description string) (string, error) { req := &sdk.GenerateTokenRequest{Description: description} md, err := p.GetMetadataContext(ctx, req) diff --git a/go/services/security.go b/go/services/security.go index 92eff1e29..c9b7e80a7 100644 --- a/go/services/security.go +++ b/go/services/security.go @@ -11,13 +11,16 @@ import ( "google.golang.org/protobuf/proto" ) +// SecurityProvider defines the required functionality to provide authentication to the api type SecurityProvider interface { GetAuthHeader(profile *sdk.AccountProfile, message proto.Message) (string, error) } +// OberonSecurityProvider implements the SecurityProvider interface and provides oberon token functionality type OberonSecurityProvider struct { } +// GetAuthHeader returns an authentication header with a correctly formatted oberon token func (o OberonSecurityProvider) GetAuthHeader(profile *sdk.AccountProfile, message proto.Message) (string, error) { if profile != nil && profile.Protection.Enabled { return "", fmt.Errorf("the token must be unprotected before use") diff --git a/go/services/service_base.go b/go/services/service_base.go index 7397dba7f..1d12c1662 100644 --- a/go/services/service_base.go +++ b/go/services/service_base.go @@ -14,63 +14,78 @@ import ( "google.golang.org/protobuf/proto" ) -func NewServiceBase(options *sdk.ServiceOptions) (*ServiceBase, error) { - conn, err := NewServiceConnection(options) - if err != nil { - return nil, err +// NewServiceBase returns a base service which is the foundation +// for all the other services +func NewServiceBase(options *Options) (Service, error) { + if options.Channel == nil { + conn, err := NewServiceConnection(options.ServiceOptions) + if err != nil { + return nil, err + } + + options.Channel = conn } - return &ServiceBase{ + return &serviceBase{ options: options, - channel: conn, securityProvider: &OberonSecurityProvider{}, }, nil } -type ServiceBase struct { - options *sdk.ServiceOptions - channel *grpc.ClientConn - securityProvider SecurityProvider -} - +// Service defines functionality common to all services type Service interface { + // GetMetadatContext returns a context with the required grpc metadata embedded in it GetMetadataContext(userContext context.Context, message proto.Message) (context.Context, error) + // BuildMetdata builds the required grpc metadata BuildMetadata(message proto.Message) (metadata.MD, error) - SetProfile(token string) - GetProfile() string + // SetToken assigns the given auth token to the service. This token will be used for + // make all api calls + SetToken(token string) + // GetToken returns the auth token currently assigned to this service or an empty string + // if none is set + GetToken() string + // GetProfile returns the account profile associated with this service, or null if none + GetProfile() *sdk.AccountProfile + // GetServiceOptions returns the set of ServiceOptions the service is using GetServiceOptions() *sdk.ServiceOptions - SetChannel(channel *grpc.ClientConn) + // GetChannel returns the grpc client connect GetChannel() *grpc.ClientConn } -func (s *ServiceBase) GetChannel() *grpc.ClientConn { - return s.channel +type serviceBase struct { + options *Options + securityProvider SecurityProvider +} + +func (s *serviceBase) GetChannel() *grpc.ClientConn { + return s.options.Channel } -func (s *ServiceBase) SetChannel(channel *grpc.ClientConn) { - s.channel = channel +func (s *serviceBase) SetToken(authtoken string) { + s.options.ServiceOptions.AuthToken = authtoken } -func (s *ServiceBase) SetProfile(authtoken string) { - s.options.AuthToken = authtoken +func (s *serviceBase) GetToken() string { + return s.options.ServiceOptions.AuthToken } -func (s *ServiceBase) GetProfile() string { - if s.options != nil { - return s.options.AuthToken +func (s *serviceBase) GetProfile() *sdk.AccountProfile { + if s.options != nil && len(s.options.ServiceOptions.AuthToken) != 0 { + profile, _ := ProfileFromToken(s.options.ServiceOptions.AuthToken) + return profile } - return "" + return nil } -func (s *ServiceBase) GetServiceOptions() *sdk.ServiceOptions { - return s.options +func (s *serviceBase) GetServiceOptions() *sdk.ServiceOptions { + return s.options.ServiceOptions } // GetMetadataContext returns a new context with grpc metadata containing authentication headers // // This call will return an error if the auth token is not set -func (s *ServiceBase) GetMetadataContext(userContext context.Context, message proto.Message) (context.Context, error) { +func (s *serviceBase) GetMetadataContext(userContext context.Context, message proto.Message) (context.Context, error) { if userContext == nil { return nil, errors.New("userContext cannot be nil") } @@ -86,12 +101,12 @@ func (s *ServiceBase) GetMetadataContext(userContext context.Context, message pr // BuildMetadata builds grpc metadata with the authentication header configured. // // This call will return an error if the auth token is not set -func (s *ServiceBase) BuildMetadata(message proto.Message) (metadata.MD, error) { - if len(s.options.AuthToken) == 0 { +func (s *serviceBase) BuildMetadata(message proto.Message) (metadata.MD, error) { + if len(s.options.ServiceOptions.AuthToken) == 0 { return nil, errors.New("cannot call authenticated endpoint: auth token must be set in service options") } - profile, err := ProfileFromToken(s.options.AuthToken) + profile, err := ProfileFromToken(s.options.ServiceOptions.AuthToken) if err != nil { return nil, err } diff --git a/go/services/service_base_test.go b/go/services/service_base_test.go index 87ed712c9..8c989fb86 100644 --- a/go/services/service_base_test.go +++ b/go/services/service_base_test.go @@ -28,7 +28,7 @@ func TestServiceBase(t *testing.T) { base, err := NewServiceBase(opts) assert.Nil(err) - assert.Equal(opts, base.GetServiceOptions()) + assert.Equal(opts.ServiceOptions, base.GetServiceOptions()) // Did we get a default grpc connection? conn := base.GetChannel() @@ -36,15 +36,30 @@ func TestServiceBase(t *testing.T) { assert.Equal(connectivity.Idle, conn.GetState(), "new grpc connection state should be idle") assert.Equal("127.0.0.1:1234", conn.Target()) - // Can we replace the grpc connection + // Can we specify a grp connection? nconn, err := grpc.Dial("192.168.1.1:4321", grpc.WithInsecure()) assert.Nil(err) if !assert.NotNil(nconn) { return } - base.SetChannel(nconn) - assert.Equal("192.168.1.1:4321", base.channel.Target(), "new grpc connection should be set") + opts, err = NewServiceOptions( + WithOptions(&sdk.ServiceOptions{ + ServerEndpoint: "127.0.0.1", + ServerPort: 1234, + DefaultEcosystem: "test"}, + ), + WithChannel(nconn), + ) + + if !assert.Nil(err) { + return + } + + base, err = NewServiceBase(opts) + assert.Nil(err) + assert.Equal(opts.ServiceOptions, base.GetServiceOptions()) + assert.Equal("192.168.1.1:4321", base.GetChannel().Target(), "new grpc connection should be set") // we should have an empty auth profile assert.Empty(base.GetProfile(), "auth Profile should be empty") @@ -68,8 +83,8 @@ func TestServiceBase(t *testing.T) { assert.Equal("EgoxMjM0NTY3ODkwGgoxMjM0NTY3ODkwIgIIAQ", tkn) // Set new profile - base.SetProfile(tkn) - assert.Equal(tkn, base.options.AuthToken, "auth token should have been replaced") + base.SetToken(tkn) + assert.Equal(tkn, base.GetServiceOptions().AuthToken, "auth token should have been replaced") // Must Unprotect token _, err = base.GetMetadataContext(context.Background(), &sdk.AccountDetails{}) @@ -79,8 +94,8 @@ func TestServiceBase(t *testing.T) { // use test vector (valid unprotected token) testToken := "CiVodHRwczovL3RyaW5zaWMuaWQvc2VjdXJpdHkvdjEvb2Jlcm9uEnAKKnVybjp0cmluc2ljOndhbGxldHM6SlZkS0pHcWs1YnFzRmtNTGJKTHZwSxIkYmFiM2Y5ZTgtOTIyYS00ZjEwLWI5MmMtMmYyZTM0MmUwNDQzIhx1cm46dHJpbnNpYzplY29zeXN0ZW1zOlRlc3QxGjCFcgwYBFmtbNn4Y2D37yIiChzzNLfods2vo37H6wf65vAYFZ3FqbtMNe6MKX14LQQiAA" - base.SetProfile(testToken) - assert.Equal(testToken, base.options.AuthToken, "auth token should have been replaced") + base.SetToken(testToken) + assert.Equal(testToken, base.GetServiceOptions().AuthToken, "auth token should have been replaced") // Sets the authorization header to oberon md, err := base.BuildMetadata(&sdk.AccountDetails{}) diff --git a/go/services/services.go b/go/services/services.go index 6ce20237d..5900b66cf 100644 --- a/go/services/services.go +++ b/go/services/services.go @@ -6,37 +6,45 @@ import ( "strings" sdk "github.com/trinsic-id/sdk/go/proto" + "google.golang.org/grpc" _ "google.golang.org/protobuf/types/known/structpb" ) +//Options for configuring the sdk +type Options struct { + ServiceOptions *sdk.ServiceOptions + Channel *grpc.ClientConn +} + // NewServiceOptions returns a service options configuration with the provided options set -func NewServiceOptions(opts ...Option) (*sdk.ServiceOptions, error) { - so := &sdk.ServiceOptions{} +func NewServiceOptions(opts ...Option) (*Options, error) { + options := &Options{ + ServiceOptions: &sdk.ServiceOptions{ + DefaultEcosystem: "default", + }, + } // Default to production - WithProductionEnv()(so) - - // with the default ecosystem set - so.DefaultEcosystem = "default" + WithProductionEnv()(options) // set user defined options for _, o := range opts { - err := o(so) + err := o(options) if err != nil { return nil, err } } - return so, nil + return options, nil } // Option function for setting options when configuring the service -type Option func(*sdk.ServiceOptions) error +type Option func(*Options) error // WithAuthToken sets a specific account token to use func WithAuthToken(token string) Option { - return func(s *sdk.ServiceOptions) error { - s.AuthToken = token + return func(s *Options) error { + s.ServiceOptions.AuthToken = token return nil } @@ -47,20 +55,20 @@ func WithAuthToken(token string) Option { // This value will be added to calls that reqire an ecosystemID to be set // if no value is provided func WithDefaultEcosystem(ecosystemID string) Option { - return func(s *sdk.ServiceOptions) error { - s.DefaultEcosystem = ecosystemID + return func(s *Options) error { + s.ServiceOptions.DefaultEcosystem = ecosystemID return nil } } // WithOptions will replace the current options with the one provided func WithOptions(serviceOptions *sdk.ServiceOptions) Option { - return func(s *sdk.ServiceOptions) error { - s.AuthToken = serviceOptions.AuthToken - s.ServerPort = serviceOptions.ServerPort - s.ServerEndpoint = serviceOptions.ServerEndpoint - s.ServerUseTls = serviceOptions.ServerUseTls - s.DefaultEcosystem = serviceOptions.DefaultEcosystem + return func(s *Options) error { + s.ServiceOptions.AuthToken = serviceOptions.AuthToken + s.ServiceOptions.ServerPort = serviceOptions.ServerPort + s.ServiceOptions.ServerEndpoint = serviceOptions.ServerEndpoint + s.ServiceOptions.ServerUseTls = serviceOptions.ServerUseTls + s.ServiceOptions.DefaultEcosystem = serviceOptions.DefaultEcosystem return nil } @@ -68,10 +76,10 @@ func WithOptions(serviceOptions *sdk.ServiceOptions) Option { // WithDevEnv will configure the server to use the trinsic development environment func WithDevEnv() Option { - return func(s *sdk.ServiceOptions) error { - s.ServerEndpoint = "dev-internal.trinsic.cloud" - s.ServerPort = 443 - s.ServerUseTls = true + return func(s *Options) error { + s.ServiceOptions.ServerEndpoint = "dev-internal.trinsic.cloud" + s.ServiceOptions.ServerPort = 443 + s.ServiceOptions.ServerUseTls = true return nil } @@ -79,10 +87,10 @@ func WithDevEnv() Option { // WithStagingEnv will configure the server to use the trinsic staging environment func WithStagingEnv() Option { - return func(s *sdk.ServiceOptions) error { - s.ServerEndpoint = "staging-internal.trinsic.cloud" - s.ServerPort = 443 - s.ServerUseTls = true + return func(s *Options) error { + s.ServiceOptions.ServerEndpoint = "staging-internal.trinsic.cloud" + s.ServiceOptions.ServerPort = 443 + s.ServiceOptions.ServerUseTls = true return nil } @@ -90,10 +98,10 @@ func WithStagingEnv() Option { // WithProductionEnv will configure the server to use the trinsic production environment func WithProductionEnv() Option { - return func(s *sdk.ServiceOptions) error { - s.ServerEndpoint = "prod.trinsic.cloud" - s.ServerPort = 443 - s.ServerUseTls = true + return func(s *Options) error { + s.ServiceOptions.ServerEndpoint = "prod.trinsic.cloud" + s.ServiceOptions.ServerPort = 443 + s.ServiceOptions.ServerUseTls = true return nil } @@ -101,22 +109,29 @@ func WithProductionEnv() Option { // WithProductionEnv will configure the server to use the trinsic production environment func WithTestEnv() Option { - return func(s *sdk.ServiceOptions) error { - s.ServerEndpoint = os.Getenv("TEST_SERVER_ENDPOINT") + return func(s *Options) error { + s.ServiceOptions.ServerEndpoint = os.Getenv("TEST_SERVER_ENDPOINT") port, err := strconv.Atoi(os.Getenv("TEST_SERVER_PORT")) if err != nil || port <= 0 { port = 443 } - s.ServerPort = int32(port) + s.ServiceOptions.ServerPort = int32(port) useTLS := os.Getenv("TEST_SERVER_USE_TLS") if len(useTLS) != 0 && strings.Compare(strings.ToLower(useTLS), "false") != 0 { - s.ServerUseTls = true + s.ServiceOptions.ServerUseTls = true } else { - s.ServerUseTls = false + s.ServiceOptions.ServerUseTls = false } return nil } } + +func WithChannel(conn *grpc.ClientConn) Option { + return func(s *Options) error { + s.Channel = conn + return nil + } +} diff --git a/go/services/services_test.go b/go/services/services_test.go index 968d7d408..fb19e4581 100644 --- a/go/services/services_test.go +++ b/go/services/services_test.go @@ -35,56 +35,31 @@ func TestServiceOptions(t *testing.T) { opts, err := NewServiceOptions() assert.Nil(err) - prodOpts := &sdk.ServiceOptions{} + prodOpts := &Options{ServiceOptions: &sdk.ServiceOptions{}} err = WithProductionEnv()(prodOpts) assert.Nil(err, "production options should return") - prodOpts.DefaultEcosystem = "default" + prodOpts.ServiceOptions.DefaultEcosystem = "default" assert.Equal(prodOpts, opts, "should default to production env") - assert.Equal("prod.trinsic.cloud", opts.ServerEndpoint, "incorrect prod url") + assert.Equal("prod.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect prod url") err = WithAuthToken("test token")(opts) assert.Nil(err, "should not error on test token") - assert.Equal("test token", opts.AuthToken, "test token not applied") + assert.Equal("test token", opts.ServiceOptions.AuthToken, "test token not applied") err = WithDevEnv()(opts) assert.Nil(err, "should not error on dev env") - assert.Equal("dev-internal.trinsic.cloud", opts.ServerEndpoint, "incorrect dev url") + assert.Equal("dev-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect dev url") err = WithStagingEnv()(opts) assert.Nil(err, "should not error on staging env") - assert.Equal("staging-internal.trinsic.cloud", opts.ServerEndpoint, "incorrect staging url") + assert.Equal("staging-internal.trinsic.cloud", opts.ServiceOptions.ServerEndpoint, "incorrect staging url") err = WithDefaultEcosystem("test1")(opts) assert.Nil(err, "should not error on setting default ecosystem") - assert.Equal("test1", opts.DefaultEcosystem, "default ecosystem not updated") - - // // Grab config from env - // os.Setenv("TEST_SERVER_ENDPOINT", "test.ing") - // os.Setenv("TEST_SERVER_PORT", "1234") - // os.Setenv("TEST_SERVER_USE_TLS", "true") - - // err = WithTestEnv()(opts) - // assert.Nil(err, "should not error on test env") - // assert.Equal("test.ing", opts.ServerEndpoint) - // assert.Equal(int32(1234), opts.ServerPort) - // assert.True(opts.ServerUseTls) - - // // Respect false for flag - // os.Setenv("TEST_SERVER_USE_TLS", "false") - // err = WithTestEnv()(opts) - // assert.Nil(err, "should not error on test env") - // assert.False(opts.ServerUseTls) + assert.Equal("test1", opts.ServiceOptions.DefaultEcosystem, "default ecosystem not updated") } -// func GetTestServerChannel() *grpc.ClientConn { -// channel, err := CreateChannel(CreateChannelUrlFromConfig(TrinsicTestConfig()), true) -// if err != nil { -// panic(err) -// } -// return channel -// } - func TestVaccineCredentialsDemo(t *testing.T) { assert2 := assert.New(t) @@ -104,6 +79,8 @@ func TestVaccineCredentialsDemo(t *testing.T) { return } + opts.Channel = accountService.GetChannel() + // if !accountService.GetChannel().WaitForStateChange(context.Background(), connectivity.Ready) { // t.Fail() // } @@ -111,19 +88,19 @@ func TestVaccineCredentialsDemo(t *testing.T) { // SETUP ACTORS // Create 3 different profiles for each participant in the scenario // setupActors() { - allison, _, err := accountService.SignIn(context.Background(), nil, "", "") + allison, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{}) failError(t, "error creating profile", err) if !assert2.NotNil(allison) { return } - clinic, _, err := accountService.SignIn(context.Background(), nil, "", "") + clinic, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{}) failError(t, "error creating profile", err) if !assert2.NotNil(clinic) { return } - airline, _, err := accountService.SignIn(context.Background(), nil, "", "") + airline, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{}) failError(t, "error creating profile", err) if !assert2.NotNil(airline) { return @@ -138,25 +115,20 @@ func TestVaccineCredentialsDemo(t *testing.T) { // var allison = WalletProfile.Parser.ParseFrom(File.ReadAllBytes("allison.bin")); // } - walletService, err := CreateWalletService(opts) + walletService, err := NewWalletService(opts) failError(t, "error creating wallet service", err) - walletService.SetChannel(accountService.GetChannel()) credentialService, err := NewCredentialService(opts) failError(t, "error creating credential service", err) - credentialService.SetChannel(accountService.GetChannel()) // ISSUE CREDENTIAL // Sign a credential as the clinic and send it to Allison // issueCredential() { fileContent, err := ioutil.ReadFile(GetVaccineCertUnsignedPath()) failError(t, "error reading file", err) - var credentialJson Document - err = json.Unmarshal(fileContent, &credentialJson) - failError(t, "error parsing JSON", err) - credentialService.SetProfile(clinic) - credential, err := credentialService.IssueCredential(context.Background(), credentialJson) + credentialService.SetToken(clinic) + credential, err := credentialService.IssueCredential(context.Background(), &sdk.IssueRequest{DocumentJson: string(fileContent)}) failError(t, "error issuing credential", err) fmt.Printf("Credential:%s\n", credential) // } @@ -164,9 +136,9 @@ func TestVaccineCredentialsDemo(t *testing.T) { // STORE CREDENTIAL // Alice stores the credential in her cloud wallet. // storeCredential() { - walletService.SetProfile(allison) + walletService.SetToken(allison) failError(t, "error setting profile", err) - itemId, err := walletService.InsertItem(context.Background(), credential) + itemId, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson}) failError(t, "error inserting item", err) fmt.Println("item id", itemId) // } @@ -176,7 +148,7 @@ func TestVaccineCredentialsDemo(t *testing.T) { // The venue has communicated with Allison the details of the credential // that they require expressed as a JSON-LD frame. // shareCredential() { - walletService.SetProfile(allison) + walletService.SetToken(allison) failError(t, "error reading file", err) fileContent2, err := ioutil.ReadFile(GetVaccineCertFramePath()) @@ -185,8 +157,13 @@ func TestVaccineCredentialsDemo(t *testing.T) { err = json.Unmarshal(fileContent2, &proofRequestJson) failError(t, "error parsing JSON", err) - credentialService.SetProfile(allison) - credentialProof, err := credentialService.CreateProof(context.Background(), itemId, proofRequestJson) + req := &sdk.CreateProofRequest{ + RevealDocumentJson: string(fileContent2), + Proof: &sdk.CreateProofRequest_ItemId{ItemId: itemId}, + } + + credentialService.SetToken(allison) + credentialProof, err := credentialService.CreateProof(context.Background(), req) failError(t, "error creating proof", err) fmt.Println("Credential proof", credentialProof) // } @@ -194,9 +171,9 @@ func TestVaccineCredentialsDemo(t *testing.T) { // VERIFY CREDENTIAL // The airline verifies the credential // verifyCredential() { - walletService.SetProfile(airline) + walletService.SetToken(airline) failError(t, "error setting profile", err) - valid, err := credentialService.VerifyProof(context.Background(), credentialProof) + valid, err := credentialService.VerifyProof(context.Background(), &sdk.VerifyProofRequest{ProofDocumentJson: credential.SignedDocumentJson}) failError(t, "error verifying proof", err) fmt.Println("Validation result", valid) if valid != true { @@ -211,13 +188,12 @@ func TestTrustRegistryDemo(t *testing.T) { return } - opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken)) + opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken), WithChannel(channel)) if !assert2.Nil(err) { return } service, _ := NewTrustRegistryService(opts) - service.SetChannel(channel) // register issuer didUri := "did:example:test" @@ -261,7 +237,7 @@ func TestTrustRegistryDemo(t *testing.T) { } assert2.Equal(sdk.RegistrationStatus_CURRENT, verifierStatus, "verifier status should be current") - ecosystemList, err := service.SearchRegistry(context.Background(), "") + ecosystemList, err := service.SearchRegistry(context.Background(), nil) if !assert2.Nil(err) { return } @@ -273,17 +249,17 @@ func createAccountAndSignIn(t *testing.T) (*assert.Assertions, *grpc.ClientConn, assert2 := assert.New(t) opts, err := NewServiceOptions(WithTestEnv()) if !assert2.Nil(err) { - return nil, nil, "", err + return assert2, nil, "", err } // Open in background accountService, err := NewAccountService(opts) if !assert2.Nil(err) { - return nil, nil, "", err + return assert2, nil, "", err } - authtoken, _, err := accountService.SignIn(context.Background(), nil, "", "") + authtoken, _, err := accountService.SignIn(context.Background(), &sdk.SignInRequest{}) if !assert2.Nil(err) { fmt.Println(err) - return nil, nil, "", err + return assert2, nil, "", err } return assert2, accountService.GetChannel(), authtoken, nil } @@ -309,7 +285,7 @@ func TestEcosystemDemo(t *testing.T) { return } - opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken)) + opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken), WithChannel(channel)) if !assert2.Nil(err) { return } @@ -319,8 +295,6 @@ func TestEcosystemDemo(t *testing.T) { return } - service.SetChannel(channel) - actualCreate, err := service.CreateEcosystem(context.Background(), &sdk.CreateEcosystemRequest{ Name: "Test-Ecosystem", Description: "My ecosystem", @@ -348,7 +322,7 @@ func TestTemplatesDemo(t *testing.T) { return } - opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken)) + opts, err := NewServiceOptions(WithTestEnv(), WithAuthToken(authtoken), WithChannel(channel)) if !assert2.Nil(err) { return } @@ -357,15 +331,12 @@ func TestTemplatesDemo(t *testing.T) { if !assert2.Nil(err) { return } - templateService.SetChannel(channel) credentialService, err := NewCredentialService(opts) if !assert2.Nil(err) { return } - credentialService.SetChannel(channel) - // create example template templateRequest := &sdk.CreateCredentialTemplateRequest{Name: "My Example Credential", AllowAdditionalFields: false, Fields: make(map[string]*sdk.TemplateField)} templateRequest.Fields["firstName"] = &sdk.TemplateField{Description: "Given name"} diff --git a/go/services/trustregistry_service.go b/go/services/trustregistry_service.go index 57547996a..1987c22e9 100644 --- a/go/services/trustregistry_service.go +++ b/go/services/trustregistry_service.go @@ -8,162 +8,191 @@ import ( sdk "github.com/trinsic-id/sdk/go/proto" ) -func NewTrustRegistryService(options *sdk.ServiceOptions) (TrustRegistryService, error) { +// NewTrustRegistryService returns a trust registry servcie with the base service configured +// using the provided options +func NewTrustRegistryService(options *Options) (TrustRegistryService, error) { base, err := NewServiceBase(options) if err != nil { return nil, err } - service := &TrustRegistryBase{ - ServiceBase: base, - client: sdk.NewTrustRegistryClient(base.channel), + service := &trustRegistryBase{ + Service: base, + client: sdk.NewTrustRegistryClient(base.GetChannel()), } return service, nil } +// TrustRegistryService defines the interface for interacting with trust registries type TrustRegistryService interface { Service - RegisterGovernanceFramework(userContext context.Context, governanceFramework string, description string) error + // RegisterGovernanceFramework in the ecosystem + RegisterGovernanceFramework(userContext context.Context, request *sdk.AddFrameworkRequest) error + // RemoveGovernanceFramework from the ecosystem RemoveGovernanceFramework(userContext context.Context, request *sdk.RemoveFrameworkRequest) (*sdk.RemoveFrameworkResponse, error) + // RegisterIssuer to issue the given credentials within the governance framework RegisterIssuer(userContext context.Context, request *sdk.RegisterIssuerRequest) error + // UnregisterIssuer from issuing given credentials within the governance framework UnregisterIssuer(userContext context.Context, request *sdk.UnregisterIssuerRequest) error + // RegisterVerifier in the given governance framework RegisterVerifier(userContext context.Context, request *sdk.RegisterVerifierRequest) error + // UnregisterVerifier in the given governance framework UnregisterVerifier(userContext context.Context, request *sdk.UnregisterVerifierRequest) error + // CheckIssuerStatus indicates whether the given issuer is authorized to issue credentials + // within the given framework CheckIssuerStatus(userContext context.Context, request *sdk.CheckIssuerStatusRequest) (sdk.RegistrationStatus, error) + // CheckVerifierStatus indicates whether the given verifier is authorized to verify credentials + // within the given framework CheckVerifierStatus(userContext context.Context, request *sdk.CheckVerifierStatusRequest) (sdk.RegistrationStatus, error) - SearchRegistry(userContext context.Context, query string) (*sdk.SearchRegistryResponse, error) + // SearchRegistry for frameworks, issues, and verifiers + SearchRegistry(userContext context.Context, request *sdk.SearchRegistryRequest) (*sdk.SearchRegistryResponse, error) + // FetchData from the provided governance framework FetchData(userContext context.Context, request *sdk.FetchDataRequest) (sdk.TrustRegistry_FetchDataClient, error) } -type TrustRegistryBase struct { - *ServiceBase +type trustRegistryBase struct { + Service client sdk.TrustRegistryClient } -func (t *TrustRegistryBase) RegisterGovernanceFramework(userContext context.Context, governanceFramework string, description string) error { +func (t *trustRegistryBase) RegisterGovernanceFramework(userContext context.Context, request *sdk.AddFrameworkRequest) error { // Verify that it is a valid uri - _, err := url.Parse(governanceFramework) + _, err := url.Parse(request.GovernanceFramework.TrustRegistryUri) if err != nil { return err } - request := &sdk.AddFrameworkRequest{ - GovernanceFramework: &sdk.GovernanceFramework{ - GovernanceFrameworkUri: governanceFramework, - TrustRegistryUri: "", - Description: description, - }, - } + md, err := t.GetMetadataContext(userContext, request) if err != nil { return err } + _, err = t.client.AddFramework(md, request) if err != nil { return err } + return nil } -func (t *TrustRegistryBase) RegisterIssuer(userContext context.Context, request *sdk.RegisterIssuerRequest) error { +func (t *trustRegistryBase) RegisterIssuer(userContext context.Context, request *sdk.RegisterIssuerRequest) error { md, err := t.GetMetadataContext(userContext, request) if err != nil { return err } + response, err := t.client.RegisterIssuer(md, request) if err != nil { return err } + if response.Status != sdk.ResponseStatus_SUCCESS { return fmt.Errorf("cannot register issuer: code %s", response.Status) } + return nil } -func (t *TrustRegistryBase) UnregisterIssuer(userContext context.Context, request *sdk.UnregisterIssuerRequest) error { +func (t *trustRegistryBase) UnregisterIssuer(userContext context.Context, request *sdk.UnregisterIssuerRequest) error { panic("implement me") } -func (t *TrustRegistryBase) RegisterVerifier(userContext context.Context, request *sdk.RegisterVerifierRequest) error { +func (t *trustRegistryBase) RegisterVerifier(userContext context.Context, request *sdk.RegisterVerifierRequest) error { md, err := t.GetMetadataContext(userContext, request) if err != nil { return err } + response, err := t.client.RegisterVerifier(md, request) if err != nil { return err } + if response.Status != sdk.ResponseStatus_SUCCESS { return fmt.Errorf("cannot register verifier: code %s", response.Status) } + return nil } -func (t *TrustRegistryBase) UnregisterVerifier(userContext context.Context, request *sdk.UnregisterVerifierRequest) error { +func (t *trustRegistryBase) UnregisterVerifier(userContext context.Context, request *sdk.UnregisterVerifierRequest) error { panic("implement me") } -func (t *TrustRegistryBase) CheckIssuerStatus(userContext context.Context, request *sdk.CheckIssuerStatusRequest) (sdk.RegistrationStatus, error) { +func (t *trustRegistryBase) CheckIssuerStatus(userContext context.Context, request *sdk.CheckIssuerStatusRequest) (sdk.RegistrationStatus, error) { md, err := t.GetMetadataContext(userContext, request) if err != nil { return sdk.RegistrationStatus_NOT_FOUND, err } + response, err := t.client.CheckIssuerStatus(md, request) if err != nil { return sdk.RegistrationStatus_NOT_FOUND, err } + return response.Status, nil } -func (t *TrustRegistryBase) CheckVerifierStatus(userContext context.Context, request *sdk.CheckVerifierStatusRequest) (sdk.RegistrationStatus, error) { +func (t *trustRegistryBase) CheckVerifierStatus(userContext context.Context, request *sdk.CheckVerifierStatusRequest) (sdk.RegistrationStatus, error) { md, err := t.GetMetadataContext(userContext, request) if err != nil { return sdk.RegistrationStatus_NOT_FOUND, err } + response, err := t.client.CheckVerifierStatus(md, request) if err != nil { return sdk.RegistrationStatus_NOT_FOUND, err } + return response.Status, nil } -func (t *TrustRegistryBase) SearchRegistry(userContext context.Context, query string) (*sdk.SearchRegistryResponse, error) { - if query == "" { - query = "SELECT * FROM c" +func (t *trustRegistryBase) SearchRegistry(userContext context.Context, request *sdk.SearchRegistryRequest) (*sdk.SearchRegistryResponse, error) { + if request == nil { + request = &sdk.SearchRegistryRequest{} } - request := &sdk.SearchRegistryRequest{ - Query: query, + + if request.Query == "" { + request.Query = "SELECT * FROM c" } + md, err := t.GetMetadataContext(userContext, request) if err != nil { return nil, err } + response, err := t.client.SearchRegistry(md, request) if err != nil { return nil, err } + return response, nil } -func (t *TrustRegistryBase) RemoveGovernanceFramework(userContext context.Context, request *sdk.RemoveFrameworkRequest) (*sdk.RemoveFrameworkResponse, error) { +func (t *trustRegistryBase) RemoveGovernanceFramework(userContext context.Context, request *sdk.RemoveFrameworkRequest) (*sdk.RemoveFrameworkResponse, error) { md, err := t.GetMetadataContext(userContext, request) if err != nil { return nil, err } + response, err := t.client.RemoveFramework(md, request) if err != nil { return nil, err } + return response, nil } -func (t *TrustRegistryBase) FetchData(userContext context.Context, request *sdk.FetchDataRequest) (sdk.TrustRegistry_FetchDataClient, error) { +func (t *trustRegistryBase) FetchData(userContext context.Context, request *sdk.FetchDataRequest) (sdk.TrustRegistry_FetchDataClient, error) { md, err := t.GetMetadataContext(userContext, request) if err != nil { return nil, err } + response, err := t.client.FetchData(md, request) if err != nil { return nil, err } + return response, nil } diff --git a/go/services/wallet_service.go b/go/services/wallet_service.go index 43b97d930..e53df43af 100644 --- a/go/services/wallet_service.go +++ b/go/services/wallet_service.go @@ -2,78 +2,84 @@ package services import ( "context" - "encoding/json" sdk "github.com/trinsic-id/sdk/go/proto" ) -func CreateWalletService(options *sdk.ServiceOptions) (WalletService, error) { +// NewWalletService returns a wallet service with the base service configured +// using the provided options +func NewWalletService(options *Options) (WalletService, error) { base, err := NewServiceBase(options) if err != nil { return nil, err } - service := &WalletBase{ - ServiceBase: base, - client: sdk.NewUniversalWalletClient(base.channel), + service := &walletBase{ + Service: base, + client: sdk.NewUniversalWalletClient(base.GetChannel()), } return service, nil } +// WalletService defines the interface for interacting with wallet type WalletService interface { Service - Search(userContext context.Context, query string) (*sdk.SearchResponse, error) - InsertItem(userContext context.Context, item Document) (string, error) - DeleteItem(userContext context.Context, request *sdk.DeleteItemRequest) (*sdk.DeleteItemResponse, error) + Search(userContext context.Context, request *sdk.SearchRequest) (*sdk.SearchResponse, error) + InsertItem(userContext context.Context, request *sdk.InsertItemRequest) (string, error) + DeleteItem(userContext context.Context, request *sdk.DeleteItemRequest) error } -type WalletBase struct { - *ServiceBase +type walletBase struct { + Service client sdk.UniversalWalletClient } -func (w *WalletBase) Search(userContext context.Context, query string) (*sdk.SearchResponse, error) { - request := &sdk.SearchRequest{ - Query: query, +func (w *walletBase) Search(userContext context.Context, request *sdk.SearchRequest) (*sdk.SearchResponse, error) { + if request == nil { + request = &sdk.SearchRequest{} + } + + if len(request.Query) == 0 { + request.Query = "SELECT * FROM c" } + md, err := w.GetMetadataContext(userContext, request) if err != nil { return nil, err } + response, err := w.client.Search(md, request) if err != nil { return nil, err } + return response, nil } -func (w *WalletBase) InsertItem(userContext context.Context, item Document) (string, error) { - jsonString, err := json.Marshal(item) - if err != nil { - return "", err - } - request := &sdk.InsertItemRequest{ - ItemJson: string(jsonString), - } +func (w *walletBase) InsertItem(userContext context.Context, request *sdk.InsertItemRequest) (string, error) { md, err := w.GetMetadataContext(userContext, request) if err != nil { return "", err } + response, err := w.client.InsertItem(md, request) if err != nil { return "", err } + return response.ItemId, nil } -func (w *WalletBase) DeleteItem(userContext context.Context, request *sdk.DeleteItemRequest) (*sdk.DeleteItemResponse, error) { +func (w *walletBase) DeleteItem(userContext context.Context, request *sdk.DeleteItemRequest) error { md, err := w.GetMetadataContext(userContext, request) if err != nil { - return nil, err + return err } - response, err := w.client.DeleteItem(md, request) + + _, err = w.client.DeleteItem(md, request) if err != nil { - return nil, err + return err } - return response, nil + + return nil } From 43b6f0fa0618a39e372cdd060f294e4d1ef3002b Mon Sep 17 00:00:00 2001 From: Seth Back Date: Thu, 10 Mar 2022 10:04:39 -0800 Subject: [PATCH 2/4] remove document type --- go/services/credential_service.go | 2 -- go/services/services_test.go | 3 --- 2 files changed, 5 deletions(-) diff --git a/go/services/credential_service.go b/go/services/credential_service.go index f1f299318..c9f4987bb 100644 --- a/go/services/credential_service.go +++ b/go/services/credential_service.go @@ -7,8 +7,6 @@ import ( sdk "github.com/trinsic-id/sdk/go/proto" ) -type Document map[string]interface{} - // NewCredentialService returns a credential service with the base service configured // using the provided options func NewCredentialService(options *Options) (CredentialService, error) { diff --git a/go/services/services_test.go b/go/services/services_test.go index fb19e4581..4c3149f08 100644 --- a/go/services/services_test.go +++ b/go/services/services_test.go @@ -153,9 +153,6 @@ func TestVaccineCredentialsDemo(t *testing.T) { fileContent2, err := ioutil.ReadFile(GetVaccineCertFramePath()) failError(t, "error reading file", err) - var proofRequestJson Document - err = json.Unmarshal(fileContent2, &proofRequestJson) - failError(t, "error parsing JSON", err) req := &sdk.CreateProofRequest{ RevealDocumentJson: string(fileContent2), From 16bee5d7b83c6afbd17a931b6965d6f03a83bcfc Mon Sep 17 00:00:00 2001 From: Seth Back Date: Thu, 10 Mar 2022 10:14:44 -0800 Subject: [PATCH 3/4] fix lint --- go/services/credential_service.go | 2 +- go/services/services.go | 6 ++--- go/services/services_test.go | 40 +++++++++++++++---------------- go/services/storage.go | 13 +++++----- 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/go/services/credential_service.go b/go/services/credential_service.go index c9f4987bb..f9d712ab4 100644 --- a/go/services/credential_service.go +++ b/go/services/credential_service.go @@ -22,7 +22,7 @@ func NewCredentialService(options *Options) (CredentialService, error) { return service, nil } -// CredentialsService defines the interface for interacting with credentials +// CredentialService defines the interface for interacting with credentials type CredentialService interface { Service // IssueCredential using a document json diff --git a/go/services/services.go b/go/services/services.go index 5900b66cf..b8a25c4fa 100644 --- a/go/services/services.go +++ b/go/services/services.go @@ -7,7 +7,6 @@ import ( sdk "github.com/trinsic-id/sdk/go/proto" "google.golang.org/grpc" - _ "google.golang.org/protobuf/types/known/structpb" ) //Options for configuring the sdk @@ -50,7 +49,7 @@ func WithAuthToken(token string) Option { } } -// WithEcosystem will set the default ecosystem used for each of the calls +// WithDefaultEcosystem will set the default ecosystem used for each of the calls // // This value will be added to calls that reqire an ecosystemID to be set // if no value is provided @@ -107,7 +106,7 @@ func WithProductionEnv() Option { } } -// WithProductionEnv will configure the server to use the trinsic production environment +// WithTestEnv will configure the server to use the trinsic production environment func WithTestEnv() Option { return func(s *Options) error { s.ServiceOptions.ServerEndpoint = os.Getenv("TEST_SERVER_ENDPOINT") @@ -129,6 +128,7 @@ func WithTestEnv() Option { } } +// WithChannel will use the provided grpc channel instead of creating a default func WithChannel(conn *grpc.ClientConn) Option { return func(s *Options) error { s.Channel = conn diff --git a/go/services/services_test.go b/go/services/services_test.go index 4c3149f08..bca30fe75 100644 --- a/go/services/services_test.go +++ b/go/services/services_test.go @@ -138,9 +138,9 @@ func TestVaccineCredentialsDemo(t *testing.T) { // storeCredential() { walletService.SetToken(allison) failError(t, "error setting profile", err) - itemId, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson}) + itemID, err := walletService.InsertItem(context.Background(), &sdk.InsertItemRequest{ItemJson: credential.SignedDocumentJson}) failError(t, "error inserting item", err) - fmt.Println("item id", itemId) + fmt.Println("item id", itemID) // } // SHARE CREDENTIAL @@ -156,7 +156,7 @@ func TestVaccineCredentialsDemo(t *testing.T) { req := &sdk.CreateProofRequest{ RevealDocumentJson: string(fileContent2), - Proof: &sdk.CreateProofRequest_ItemId{ItemId: itemId}, + Proof: &sdk.CreateProofRequest_ItemId{ItemId: itemID}, } credentialService.SetToken(allison) @@ -193,31 +193,31 @@ func TestTrustRegistryDemo(t *testing.T) { service, _ := NewTrustRegistryService(opts) // register issuer - didUri := "did:example:test" - typeUri := "https://schema.org/Card" - frameworkUri := "https://example.com" + didURI := "did:example:test" + typeURI := "https://schema.org/Card" + frameworkURI := "https://example.com" err = service.RegisterIssuer(context.Background(), &sdk.RegisterIssuerRequest{ - Authority: &sdk.RegisterIssuerRequest_DidUri{DidUri: didUri}, - CredentialTypeUri: typeUri, - GovernanceFrameworkUri: frameworkUri, + Authority: &sdk.RegisterIssuerRequest_DidUri{DidUri: didURI}, + CredentialTypeUri: typeURI, + GovernanceFrameworkUri: frameworkURI, }) if !assert2.Nil(err) { return } err = service.RegisterVerifier(context.Background(), &sdk.RegisterVerifierRequest{ - Authority: &sdk.RegisterVerifierRequest_DidUri{DidUri: didUri}, - PresentationTypeUri: typeUri, - GovernanceFrameworkUri: frameworkUri, + Authority: &sdk.RegisterVerifierRequest_DidUri{DidUri: didURI}, + PresentationTypeUri: typeURI, + GovernanceFrameworkUri: frameworkURI, }) if !assert2.Nil(err) { return } issuerStatus, err := service.CheckIssuerStatus(context.Background(), &sdk.CheckIssuerStatusRequest{ - GovernanceFrameworkUri: frameworkUri, - Member: &sdk.CheckIssuerStatusRequest_DidUri{DidUri: didUri}, - CredentialTypeUri: typeUri, + GovernanceFrameworkUri: frameworkURI, + Member: &sdk.CheckIssuerStatusRequest_DidUri{DidUri: didURI}, + CredentialTypeUri: typeURI, }) if !assert2.Nil(err) { return @@ -225,9 +225,9 @@ func TestTrustRegistryDemo(t *testing.T) { assert2.Equal(sdk.RegistrationStatus_CURRENT, issuerStatus, "Issuer status should be current") verifierStatus, err := service.CheckVerifierStatus(context.Background(), &sdk.CheckVerifierStatusRequest{ - GovernanceFrameworkUri: frameworkUri, - Member: &sdk.CheckVerifierStatusRequest_DidUri{DidUri: didUri}, - PresentationTypeUri: typeUri, + GovernanceFrameworkUri: frameworkURI, + Member: &sdk.CheckVerifierStatusRequest_DidUri{DidUri: didURI}, + PresentationTypeUri: typeURI, }) if !assert2.Nil(err) { return @@ -363,7 +363,7 @@ func TestTemplatesDemo(t *testing.T) { return } - credentialJson, err := credentialService.IssueFromTemplate(context.Background(), &sdk.IssueFromTemplateRequest{ + credentialJSON, err := credentialService.IssueFromTemplate(context.Background(), &sdk.IssueFromTemplateRequest{ TemplateId: template.Data.Id, ValuesJson: string(valuesString), }) @@ -371,7 +371,7 @@ func TestTemplatesDemo(t *testing.T) { return } var jsonDocument = make(map[string]interface{}) - err = json.Unmarshal([]byte(credentialJson.DocumentJson), &jsonDocument) + err = json.Unmarshal([]byte(credentialJSON.DocumentJson), &jsonDocument) if !assert2.Nil(err) { return } diff --git a/go/services/storage.go b/go/services/storage.go index b76480ed1..5cffbb324 100644 --- a/go/services/storage.go +++ b/go/services/storage.go @@ -2,29 +2,30 @@ package services import sdk "github.com/trinsic-id/sdk/go/proto" +// ProfileProvider defines the interface for interacting with stored profiles type ProfileProvider interface { Get(name string) (sdk.AccountProfile, error) Save(name string, profile sdk.AccountProfile) error } -type FileProfileProvider struct { +type fileProfileProvider struct { } -type KeychainProfileProvider struct { +type keychainProfileProvider struct { } -func (f FileProfileProvider) Get(name string) (sdk.AccountProfile, error) { +func (f fileProfileProvider) Get(name string) (sdk.AccountProfile, error) { panic("implement me") } -func (f FileProfileProvider) Save(name string, profile *sdk.AccountProfile) error { +func (f fileProfileProvider) Save(name string, profile *sdk.AccountProfile) error { panic("implement me") } -func (k KeychainProfileProvider) Get(name string) (sdk.AccountProfile, error) { +func (k keychainProfileProvider) Get(name string) (sdk.AccountProfile, error) { panic("implement me") } -func (k KeychainProfileProvider) Save(name string, profile *sdk.AccountProfile) error { +func (k keychainProfileProvider) Save(name string, profile *sdk.AccountProfile) error { panic("implement me") } From c7aec5235f1718ae0e811184848b5191f6085894 Mon Sep 17 00:00:00 2001 From: Seth Back Date: Thu, 10 Mar 2022 10:32:58 -0800 Subject: [PATCH 4/4] update comments --- go/services/services.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go/services/services.go b/go/services/services.go index b8a25c4fa..bbd301a39 100644 --- a/go/services/services.go +++ b/go/services/services.go @@ -106,7 +106,8 @@ func WithProductionEnv() Option { } } -// WithTestEnv will configure the server to use the trinsic production environment +// WithTestEnv will configure the server to use the environment provided by environment variables +// falling back to trinsic production environment if necessary func WithTestEnv() Option { return func(s *Options) error { s.ServiceOptions.ServerEndpoint = os.Getenv("TEST_SERVER_ENDPOINT")