From 6a769b6dab13fc405af999fbfa68dd19bdf14c14 Mon Sep 17 00:00:00 2001 From: Joshua Hawxwell <m@hawx.me> Date: Tue, 26 Mar 2024 13:36:24 +0000 Subject: [PATCH] Handle certificate-provider-submission-completed event --- .../cloud_watch_event_handler.go | 38 ++++ .../cloud_watch_event_handler_test.go | 168 ++++++++++++++++++ cmd/event-received/factory.go | 1 + .../mock_shareCodeSender_test.go | 48 +++++ 4 files changed, 255 insertions(+) diff --git a/cmd/event-received/cloud_watch_event_handler.go b/cmd/event-received/cloud_watch_event_handler.go index ae98f70700..5e7665882e 100644 --- a/cmd/event-received/cloud_watch_event_handler.go +++ b/cmd/event-received/cloud_watch_event_handler.go @@ -86,6 +86,9 @@ func (h *cloudWatchEventHandler) Handle(ctx context.Context, cloudWatchEvent eve return handleDonorSubmissionCompleted(ctx, h.dynamoClient, cloudWatchEvent, shareCodeSender, appData, lpaStoreClient) + case "certificate-provider-submission-completed": + return handleCertificateProviderSubmissionCompleted(ctx, cloudWatchEvent, h.factory) + default: return fmt.Errorf("unknown cloudwatch event") } @@ -217,8 +220,43 @@ func handleDonorSubmissionCompleted(ctx context.Context, client dynamodbClient, if donor.CertificateProvider.CarryOutBy.IsOnline() { if err := shareCodeSender.SendCertificateProviderInvite(ctx, appData, donor); err != nil { + return fmt.Errorf("failed to send share code to certificate provider: %w", err) + } + } + + return nil +} + +func handleCertificateProviderSubmissionCompleted(ctx context.Context, event events.CloudWatchEvent, factory factory) error { + var v uidEvent + if err := json.Unmarshal(event.Detail, &v); err != nil { + return fmt.Errorf("failed to unmarshal detail: %w", err) + } + + lpaStoreClient, err := factory.LpaStoreClient() + if err != nil { + return err + } + + donor, err := lpaStoreClient.Lpa(ctx, v.UID) + if err != nil { + return fmt.Errorf("failed to retrieve lpa: %w", err) + } + + if donor.CertificateProvider.CarryOutBy.IsPaper() { + shareCodeSender, err := factory.ShareCodeSender(ctx) + if err != nil { return err } + + appData, err := factory.AppData() + if err != nil { + return err + } + + if err := shareCodeSender.SendAttorneys(ctx, appData, donor); err != nil { + return fmt.Errorf("failed to send share codes to attorneys: %w", err) + } } return nil diff --git a/cmd/event-received/cloud_watch_event_handler_test.go b/cmd/event-received/cloud_watch_event_handler_test.go index 628d3a04df..626bb5c882 100644 --- a/cmd/event-received/cloud_watch_event_handler_test.go +++ b/cmd/event-received/cloud_watch_event_handler_test.go @@ -607,5 +607,173 @@ func TestHandleDonorSubmissionCompletedWhenShareCodeSenderError(t *testing.T) { Return(expectedError) err := handleDonorSubmissionCompleted(ctx, client, event, shareCodeSender, appData, lpaStoreClient) + assert.Equal(t, fmt.Errorf("failed to send share code to certificate provider: %w", expectedError), err) +} + +var certificateProviderSubmissionCompletedEvent = events.CloudWatchEvent{ + DetailType: "certificate-provider-submission-completed", + Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`), +} + +func TestHandleCertificateProviderSubmissionCompleted(t *testing.T) { + appData := page.AppData{} + + donor := &actor.DonorProvidedDetails{ + CertificateProvider: actor.CertificateProvider{ + CarryOutBy: actor.Paper, + }, + } + + lpaStoreClient := newMockLpaStoreClient(t) + lpaStoreClient.EXPECT(). + Lpa(ctx, "M-1111-2222-3333"). + Return(donor, nil) + + shareCodeSender := newMockShareCodeSender(t) + shareCodeSender.EXPECT(). + SendAttorneys(ctx, appData, donor). + Return(nil) + + factory := newMockFactory(t) + factory.EXPECT(). + LpaStoreClient(). + Return(lpaStoreClient, nil) + factory.EXPECT(). + ShareCodeSender(ctx). + Return(shareCodeSender, nil) + factory.EXPECT(). + AppData(). + Return(appData, nil) + + err := handleCertificateProviderSubmissionCompleted(ctx, certificateProviderSubmissionCompletedEvent, factory) + assert.Nil(t, err) +} + +func TestHandleCertificateProviderSubmissionCompletedWhenOnline(t *testing.T) { + donor := &actor.DonorProvidedDetails{ + CertificateProvider: actor.CertificateProvider{ + CarryOutBy: actor.Online, + }, + } + + lpaStoreClient := newMockLpaStoreClient(t) + lpaStoreClient.EXPECT(). + Lpa(ctx, "M-1111-2222-3333"). + Return(donor, nil) + + factory := newMockFactory(t) + factory.EXPECT(). + LpaStoreClient(). + Return(lpaStoreClient, nil) + + handler := &cloudWatchEventHandler{factory: factory} + err := handler.Handle(ctx, certificateProviderSubmissionCompletedEvent) + assert.Nil(t, err) +} + +func TestHandleCertificateProviderSubmissionCompletedWhenLpaStoreFactoryErrors(t *testing.T) { + factory := newMockFactory(t) + factory.EXPECT(). + LpaStoreClient(). + Return(nil, expectedError) + + handler := &cloudWatchEventHandler{factory: factory} + err := handler.Handle(ctx, certificateProviderSubmissionCompletedEvent) + assert.Equal(t, expectedError, err) +} + +func TestHandleCertificateProviderSubmissionCompletedWhenLpaStoreErrors(t *testing.T) { + lpaStoreClient := newMockLpaStoreClient(t) + lpaStoreClient.EXPECT(). + Lpa(ctx, "M-1111-2222-3333"). + Return(nil, expectedError) + + factory := newMockFactory(t) + factory.EXPECT(). + LpaStoreClient(). + Return(lpaStoreClient, nil) + + handler := &cloudWatchEventHandler{factory: factory} + err := handler.Handle(ctx, certificateProviderSubmissionCompletedEvent) + assert.Equal(t, fmt.Errorf("failed to retrieve lpa: %w", expectedError), err) +} + +func TestHandleCertificateProviderSubmissionCompletedWhenShareCodeSenderErrors(t *testing.T) { + lpaStoreClient := newMockLpaStoreClient(t) + lpaStoreClient.EXPECT(). + Lpa(ctx, "M-1111-2222-3333"). + Return(&actor.DonorProvidedDetails{ + CertificateProvider: actor.CertificateProvider{ + CarryOutBy: actor.Paper, + }, + }, nil) + + shareCodeSender := newMockShareCodeSender(t) + shareCodeSender.EXPECT(). + SendAttorneys(ctx, mock.Anything, mock.Anything). + Return(expectedError) + + factory := newMockFactory(t) + factory.EXPECT(). + LpaStoreClient(). + Return(lpaStoreClient, nil) + factory.EXPECT(). + ShareCodeSender(ctx). + Return(shareCodeSender, nil) + factory.EXPECT(). + AppData(). + Return(page.AppData{}, nil) + + handler := &cloudWatchEventHandler{factory: factory} + err := handler.Handle(ctx, certificateProviderSubmissionCompletedEvent) + assert.Equal(t, fmt.Errorf("failed to send share codes to attorneys: %w", expectedError), err) +} + +func TestHandleCertificateProviderSubmissionCompletedWhenShareCodeSenderFactoryErrors(t *testing.T) { + lpaStoreClient := newMockLpaStoreClient(t) + lpaStoreClient.EXPECT(). + Lpa(ctx, "M-1111-2222-3333"). + Return(&actor.DonorProvidedDetails{ + CertificateProvider: actor.CertificateProvider{ + CarryOutBy: actor.Paper, + }, + }, nil) + + factory := newMockFactory(t) + factory.EXPECT(). + LpaStoreClient(). + Return(lpaStoreClient, nil) + factory.EXPECT(). + ShareCodeSender(ctx). + Return(nil, expectedError) + + handler := &cloudWatchEventHandler{factory: factory} + err := handler.Handle(ctx, certificateProviderSubmissionCompletedEvent) + assert.Equal(t, expectedError, err) +} + +func TestHandleCertificateProviderSubmissionCompletedWhenAppDataFactoryErrors(t *testing.T) { + lpaStoreClient := newMockLpaStoreClient(t) + lpaStoreClient.EXPECT(). + Lpa(ctx, "M-1111-2222-3333"). + Return(&actor.DonorProvidedDetails{ + CertificateProvider: actor.CertificateProvider{ + CarryOutBy: actor.Paper, + }, + }, nil) + + factory := newMockFactory(t) + factory.EXPECT(). + LpaStoreClient(). + Return(lpaStoreClient, nil) + factory.EXPECT(). + ShareCodeSender(ctx). + Return(nil, nil) + factory.EXPECT(). + AppData(). + Return(page.AppData{}, expectedError) + + handler := &cloudWatchEventHandler{factory: factory} + err := handler.Handle(ctx, certificateProviderSubmissionCompletedEvent) assert.Equal(t, expectedError, err) } diff --git a/cmd/event-received/factory.go b/cmd/event-received/factory.go index 6a0c1968aa..d078e3707c 100644 --- a/cmd/event-received/factory.go +++ b/cmd/event-received/factory.go @@ -38,6 +38,7 @@ type SecretsClient interface { type ShareCodeSender interface { SendCertificateProviderInvite(context.Context, page.AppData, *actor.DonorProvidedDetails) error SendCertificateProviderPrompt(context.Context, page.AppData, *actor.DonorProvidedDetails) error + SendAttorneys(context.Context, page.AppData, *actor.DonorProvidedDetails) error } type UidStore interface { diff --git a/cmd/event-received/mock_shareCodeSender_test.go b/cmd/event-received/mock_shareCodeSender_test.go index 741f9c3366..412ebe1089 100644 --- a/cmd/event-received/mock_shareCodeSender_test.go +++ b/cmd/event-received/mock_shareCodeSender_test.go @@ -25,6 +25,54 @@ func (_m *mockShareCodeSender) EXPECT() *mockShareCodeSender_Expecter { return &mockShareCodeSender_Expecter{mock: &_m.Mock} } +// SendAttorneys provides a mock function with given fields: _a0, _a1, _a2 +func (_m *mockShareCodeSender) SendAttorneys(_a0 context.Context, _a1 page.AppData, _a2 *actor.DonorProvidedDetails) error { + ret := _m.Called(_a0, _a1, _a2) + + if len(ret) == 0 { + panic("no return value specified for SendAttorneys") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, page.AppData, *actor.DonorProvidedDetails) error); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockShareCodeSender_SendAttorneys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendAttorneys' +type mockShareCodeSender_SendAttorneys_Call struct { + *mock.Call +} + +// SendAttorneys is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 page.AppData +// - _a2 *actor.DonorProvidedDetails +func (_e *mockShareCodeSender_Expecter) SendAttorneys(_a0 interface{}, _a1 interface{}, _a2 interface{}) *mockShareCodeSender_SendAttorneys_Call { + return &mockShareCodeSender_SendAttorneys_Call{Call: _e.mock.On("SendAttorneys", _a0, _a1, _a2)} +} + +func (_c *mockShareCodeSender_SendAttorneys_Call) Run(run func(_a0 context.Context, _a1 page.AppData, _a2 *actor.DonorProvidedDetails)) *mockShareCodeSender_SendAttorneys_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(page.AppData), args[2].(*actor.DonorProvidedDetails)) + }) + return _c +} + +func (_c *mockShareCodeSender_SendAttorneys_Call) Return(_a0 error) *mockShareCodeSender_SendAttorneys_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockShareCodeSender_SendAttorneys_Call) RunAndReturn(run func(context.Context, page.AppData, *actor.DonorProvidedDetails) error) *mockShareCodeSender_SendAttorneys_Call { + _c.Call.Return(run) + return _c +} + // SendCertificateProviderInvite provides a mock function with given fields: _a0, _a1, _a2 func (_m *mockShareCodeSender) SendCertificateProviderInvite(_a0 context.Context, _a1 page.AppData, _a2 *actor.DonorProvidedDetails) error { ret := _m.Called(_a0, _a1, _a2)