Skip to content

Commit

Permalink
MLPAB-1346: Ensure PUTs only apply with the latest version of the str…
Browse files Browse the repository at this point in the history
…uct (#744)
  • Loading branch information
acsauk authored Oct 4, 2023
1 parent 4fd0af5 commit 56a4fa7
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 74 deletions.
16 changes: 10 additions & 6 deletions cmd/event-received/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,17 @@ func Handler(ctx context.Context, event events.CloudWatchEvent) error {
appData := page.AppData{Localizer: bundle.For(localize.En)}

shareCodeSender := page.NewShareCodeSender(app.NewShareCodeStore(dynamoClient), notifyClient, appPublicURL, random.String)
now := time.Now

switch event.DetailType {
case "evidence-received":
return handleEvidenceReceived(ctx, dynamoClient, event)
case "fee-approved":
return handleFeeApproved(ctx, dynamoClient, event, shareCodeSender, appData)
return handleFeeApproved(ctx, dynamoClient, event, shareCodeSender, appData, now)
case "more-evidence-required":
return handleMoreEvidenceRequired(ctx, dynamoClient, event)
return handleMoreEvidenceRequired(ctx, dynamoClient, event, now)
case "fee-denied":
return handleFeeDenied(ctx, dynamoClient, event)
return handleFeeDenied(ctx, dynamoClient, event, now)
default:
return fmt.Errorf("unknown event received: %s", event.DetailType)
}
Expand Down Expand Up @@ -121,7 +122,7 @@ func handleEvidenceReceived(ctx context.Context, client dynamodbClient, event ev
return nil
}

func handleFeeApproved(ctx context.Context, dynamoClient dynamodbClient, event events.CloudWatchEvent, shareCodeSender shareCodeSender, appData page.AppData) error {
func handleFeeApproved(ctx context.Context, dynamoClient dynamodbClient, event events.CloudWatchEvent, shareCodeSender shareCodeSender, appData page.AppData, now func() time.Time) error {
var v uidEvent
if err := json.Unmarshal(event.Detail, &v); err != nil {
return fmt.Errorf("failed to unmarshal 'fee-approved' detail: %w", err)
Expand All @@ -138,6 +139,7 @@ func handleFeeApproved(ctx context.Context, dynamoClient dynamodbClient, event e
}

lpa.Tasks.PayForLpa = actor.PaymentTaskCompleted
lpa.UpdatedAt = now()

if err := dynamoClient.Put(ctx, lpa); err != nil {
return fmt.Errorf("failed to update LPA task status for 'fee-approved': %w", err)
Expand All @@ -150,7 +152,7 @@ func handleFeeApproved(ctx context.Context, dynamoClient dynamodbClient, event e
return nil
}

func handleMoreEvidenceRequired(ctx context.Context, client dynamodbClient, event events.CloudWatchEvent) error {
func handleMoreEvidenceRequired(ctx context.Context, client dynamodbClient, event events.CloudWatchEvent, now func() time.Time) error {
var v uidEvent
if err := json.Unmarshal(event.Detail, &v); err != nil {
return fmt.Errorf("failed to unmarshal 'more-evidence-required' detail: %w", err)
Expand All @@ -171,6 +173,7 @@ func handleMoreEvidenceRequired(ctx context.Context, client dynamodbClient, even
}

lpa.Tasks.PayForLpa = actor.PaymentTaskMoreEvidenceRequired
lpa.UpdatedAt = now()

if err := client.Put(ctx, lpa); err != nil {
return fmt.Errorf("failed to update LPA task status for 'more-evidence-required': %w", err)
Expand All @@ -179,7 +182,7 @@ func handleMoreEvidenceRequired(ctx context.Context, client dynamodbClient, even
return nil
}

func handleFeeDenied(ctx context.Context, client dynamodbClient, event events.CloudWatchEvent) error {
func handleFeeDenied(ctx context.Context, client dynamodbClient, event events.CloudWatchEvent, now func() time.Time) error {
var v uidEvent
if err := json.Unmarshal(event.Detail, &v); err != nil {
return fmt.Errorf("failed to unmarshal 'fee-denied' detail: %w", err)
Expand All @@ -200,6 +203,7 @@ func handleFeeDenied(ctx context.Context, client dynamodbClient, event events.Cl
}

lpa.Tasks.PayForLpa = actor.PaymentTaskDenied
lpa.UpdatedAt = now()

if err := client.Put(ctx, lpa); err != nil {
return fmt.Errorf("failed to update LPA task status for 'fee-denied': %w", err)
Expand Down
63 changes: 39 additions & 24 deletions cmd/event-received/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"testing"
"time"

"github.com/aws/aws-lambda-go/events"
"github.com/ministryofjustice/opg-modernising-lpa/internal/actor"
Expand Down Expand Up @@ -113,6 +114,8 @@ func TestHandleFeeApproved(t *testing.T) {
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`),
}

now := time.Now()

client := newMockDynamodbClient(t)
client.
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Expand All @@ -129,15 +132,15 @@ func TestHandleFeeApproved(t *testing.T) {
return nil
})
client.
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}}).
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}, UpdatedAt: now}).
Return(nil)

shareCodeSender := newMockShareCodeSender(t)
shareCodeSender.
On("SendCertificateProvider", ctx, notify.CertificateProviderInviteEmail, page.AppData{}, false, &page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}}).
On("SendCertificateProvider", ctx, notify.CertificateProviderInviteEmail, page.AppData{}, false, &page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}, UpdatedAt: now}).
Return(nil)

err := handleFeeApproved(ctx, client, event, shareCodeSender, page.AppData{})
err := handleFeeApproved(ctx, client, event, shareCodeSender, page.AppData{}, func() time.Time { return now })
assert.Nil(t, err)
}

Expand All @@ -153,7 +156,7 @@ func TestHandleFeeApprovedWhenDynamoClientOneByUIDError(t *testing.T) {
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Return(expectedError)

err := handleFeeApproved(ctx, client, event, nil, page.AppData{})
err := handleFeeApproved(ctx, client, event, nil, page.AppData{}, time.Now)
assert.Equal(t, fmt.Errorf("failed to resolve uid for 'fee-approved': %w", expectedError), err)
}

Expand All @@ -176,7 +179,7 @@ func TestHandleFeeApprovedWhenDynamoClientGetError(t *testing.T) {
On("One", ctx, "LPA#123", "#DONOR#456", mock.Anything).
Return(expectedError)

err := handleFeeApproved(ctx, client, event, nil, page.AppData{})
err := handleFeeApproved(ctx, client, event, nil, page.AppData{}, time.Now)
assert.Equal(t, fmt.Errorf("failed to get LPA for 'fee-approved': %w", expectedError), err)
}

Expand All @@ -187,6 +190,8 @@ func TestHandleFeeApprovedWhenDynamoClientPutError(t *testing.T) {
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`),
}

now := time.Now()

client := newMockDynamodbClient(t)
client.
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Expand All @@ -203,10 +208,10 @@ func TestHandleFeeApprovedWhenDynamoClientPutError(t *testing.T) {
return nil
})
client.
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}}).
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}, UpdatedAt: now}).
Return(expectedError)

err := handleFeeApproved(ctx, client, event, nil, page.AppData{})
err := handleFeeApproved(ctx, client, event, nil, page.AppData{}, func() time.Time { return now })
assert.Equal(t, fmt.Errorf("failed to update LPA task status for 'fee-approved': %w", expectedError), err)
}

Expand All @@ -217,6 +222,8 @@ func TestHandleFeeApprovedWhenShareCodeSenderError(t *testing.T) {
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`),
}

now := time.Now()

client := newMockDynamodbClient(t)
client.
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Expand All @@ -233,15 +240,15 @@ func TestHandleFeeApprovedWhenShareCodeSenderError(t *testing.T) {
return nil
})
client.
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}}).
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}, UpdatedAt: now}).
Return(nil)

shareCodeSender := newMockShareCodeSender(t)
shareCodeSender.
On("SendCertificateProvider", ctx, notify.CertificateProviderInviteEmail, page.AppData{}, false, &page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}}).
On("SendCertificateProvider", ctx, notify.CertificateProviderInviteEmail, page.AppData{}, false, &page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskCompleted}, UpdatedAt: now}).
Return(expectedError)

err := handleFeeApproved(ctx, client, event, shareCodeSender, page.AppData{})
err := handleFeeApproved(ctx, client, event, shareCodeSender, page.AppData{}, func() time.Time { return now })
assert.Equal(t, fmt.Errorf("failed to send share code to certificate provider for 'fee-approved': %w", expectedError), err)
}

Expand All @@ -252,6 +259,8 @@ func TestHandleMoreEvidenceRequired(t *testing.T) {
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`),
}

now := time.Now()

client := newMockDynamodbClient(t)
client.
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Expand All @@ -268,10 +277,10 @@ func TestHandleMoreEvidenceRequired(t *testing.T) {
return nil
})
client.
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskMoreEvidenceRequired}}).
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskMoreEvidenceRequired}, UpdatedAt: now}).
Return(nil)

err := handleMoreEvidenceRequired(ctx, client, event)
err := handleMoreEvidenceRequired(ctx, client, event, func() time.Time { return now })
assert.Nil(t, err)
}

Expand All @@ -287,7 +296,7 @@ func TestHandleMoreEvidenceRequiredWhenOneByUIDError(t *testing.T) {
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Return(expectedError)

err := handleMoreEvidenceRequired(ctx, client, event)
err := handleMoreEvidenceRequired(ctx, client, event, time.Now)
assert.Equal(t, fmt.Errorf("failed to resolve uid for 'more-evidence-required': %w", expectedError), err)
}

Expand All @@ -307,7 +316,7 @@ func TestHandleMoreEvidenceRequiredWhenPKMissing(t *testing.T) {
return nil
})

err := handleMoreEvidenceRequired(ctx, client, event)
err := handleMoreEvidenceRequired(ctx, client, event, time.Now)

assert.Equal(t, errors.New("PK missing from LPA in response to 'more-evidence-required'"), err)
}
Expand All @@ -331,7 +340,7 @@ func TestHandleMoreEvidenceRequiredWhenGetError(t *testing.T) {
On("One", ctx, "LPA#123", "#DONOR#456", mock.Anything).
Return(expectedError)

err := handleMoreEvidenceRequired(ctx, client, event)
err := handleMoreEvidenceRequired(ctx, client, event, time.Now)
assert.Equal(t, fmt.Errorf("failed to get LPA for 'more-evidence-required': %w", expectedError), err)
}

Expand All @@ -342,6 +351,8 @@ func TestHandleMoreEvidenceRequiredWhenPutError(t *testing.T) {
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`),
}

now := time.Now()

client := newMockDynamodbClient(t)
client.
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Expand All @@ -358,10 +369,10 @@ func TestHandleMoreEvidenceRequiredWhenPutError(t *testing.T) {
return nil
})
client.
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskMoreEvidenceRequired}}).
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskMoreEvidenceRequired}, UpdatedAt: now}).
Return(expectedError)

err := handleMoreEvidenceRequired(ctx, client, event)
err := handleMoreEvidenceRequired(ctx, client, event, func() time.Time { return now })
assert.Equal(t, fmt.Errorf("failed to update LPA task status for 'more-evidence-required': %w", expectedError), err)
}

Expand All @@ -372,6 +383,8 @@ func TestHandleFeeDenied(t *testing.T) {
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`),
}

now := time.Now()

client := newMockDynamodbClient(t)
client.
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Expand All @@ -388,10 +401,10 @@ func TestHandleFeeDenied(t *testing.T) {
return nil
})
client.
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskDenied}}).
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskDenied}, UpdatedAt: now}).
Return(nil)

err := handleFeeDenied(ctx, client, event)
err := handleFeeDenied(ctx, client, event, func() time.Time { return now })
assert.Nil(t, err)
}

Expand All @@ -407,7 +420,7 @@ func TestHandleFeeDeniedWhenOneByUIDError(t *testing.T) {
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Return(expectedError)

err := handleFeeDenied(ctx, client, event)
err := handleFeeDenied(ctx, client, event, time.Now)
assert.Equal(t, fmt.Errorf("failed to resolve uid for 'fee-denied': %w", expectedError), err)
}

Expand All @@ -427,7 +440,7 @@ func TestHandleFeeDeniedWhenPKMissing(t *testing.T) {
return nil
})

err := handleFeeDenied(ctx, client, event)
err := handleFeeDenied(ctx, client, event, time.Now)

assert.Equal(t, errors.New("PK missing from LPA in response to 'fee-denied'"), err)
}
Expand All @@ -451,7 +464,7 @@ func TestHandleFeeDeniedWhenGetError(t *testing.T) {
On("One", ctx, "LPA#123", "#DONOR#456", mock.Anything).
Return(expectedError)

err := handleFeeDenied(ctx, client, event)
err := handleFeeDenied(ctx, client, event, time.Now)
assert.Equal(t, fmt.Errorf("failed to get LPA for 'fee-denied': %w", expectedError), err)
}

Expand All @@ -462,6 +475,8 @@ func TestHandleFeeDeniedWhenPutError(t *testing.T) {
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333"}`),
}

now := time.Now()

client := newMockDynamodbClient(t)
client.
On("OneByUID", ctx, "M-1111-2222-3333", mock.Anything).
Expand All @@ -478,9 +493,9 @@ func TestHandleFeeDeniedWhenPutError(t *testing.T) {
return nil
})
client.
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskDenied}}).
On("Put", ctx, page.Lpa{PK: "LPA#123", SK: "#DONOR#456", Tasks: page.Tasks{PayForLpa: actor.PaymentTaskDenied}, UpdatedAt: now}).
Return(expectedError)

err := handleFeeDenied(ctx, client, event)
err := handleFeeDenied(ctx, client, event, func() time.Time { return now })
assert.Equal(t, fmt.Errorf("failed to update LPA task status for 'fee-denied': %w", expectedError), err)
}
Loading

0 comments on commit 56a4fa7

Please sign in to comment.