Skip to content

Commit

Permalink
Emit lpa-access-granted when an lpa is registered
Browse files Browse the repository at this point in the history
  • Loading branch information
hawx committed Dec 11, 2024
1 parent 8742bdd commit 5bbe1e1
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 12 deletions.
46 changes: 46 additions & 0 deletions cmd/event-received/lpastore_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ package main

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"time"

"github.com/aws/aws-lambda-go/events"
"github.com/ministryofjustice/opg-modernising-lpa/internal/dashboard/dashboarddata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo"
"github.com/ministryofjustice/opg-modernising-lpa/internal/event"
)

type lpastoreEventHandler struct{}
Expand All @@ -24,6 +28,14 @@ func (h *lpastoreEventHandler) Handle(ctx context.Context, factory factory, clou
}

switch v.ChangeType {
case "REGISTER":
lpaStoreClient, err := factory.LpaStoreClient()
if err != nil {
return fmt.Errorf("could not create LpaStoreClient: %w", err)
}

return handleRegister(ctx, factory.DynamoClient(), lpaStoreClient, factory.EventClient(), v)

case "STATUTORY_WAITING_PERIOD":
return handleStatutoryWaitingPeriod(ctx, factory.DynamoClient(), factory.Now(), v)

Expand All @@ -38,6 +50,40 @@ func (h *lpastoreEventHandler) Handle(ctx context.Context, factory factory, clou
return fmt.Errorf("unknown lpastore event")
}

func handleRegister(ctx context.Context, client dynamodbClient, lpaStoreClient LpaStoreClient, eventClient EventClient, v lpaUpdatedEvent) error {
lpa, err := lpaStoreClient.Lpa(ctx, v.UID)
if err != nil {
return fmt.Errorf("error getting lpa: %w", err)
}

var links []dashboarddata.LpaLink
if err := client.AllByLpaUIDAndPartialSK(ctx, v.UID, dynamo.SubKey(""), &links); err != nil {
return fmt.Errorf("error getting all subs for uid: %w", err)
}

data := event.LpaAccessGranted{
UID: v.UID,
LpaType: lpa.Type.String(),
}

for _, link := range links {
if !link.ActorType.IsDonor() &&
!link.ActorType.IsAttorney() && !link.ActorType.IsReplacementAttorney() &&
!link.ActorType.IsTrustCorporation() && !link.ActorType.IsReplacementTrustCorporation() {
continue
}

sub, _ := base64.StdEncoding.DecodeString(link.UserSub())

data.Actors = append(data.Actors, event.LpaAccessGrantedActor{
SubjectID: string(sub),
ActorUID: link.UID.String(),
})
}

return eventClient.SendLpaAccessGranted(ctx, data)
}

func handleStatutoryWaitingPeriod(ctx context.Context, client dynamodbClient, now func() time.Time, event lpaUpdatedEvent) error {
donor, err := getDonorByLpaUID(ctx, client, event.UID)
if err != nil {
Expand Down
133 changes: 133 additions & 0 deletions cmd/event-received/lpastore_event_handler_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package main

import (
"encoding/base64"
"encoding/json"
"fmt"
"testing"

"github.com/aws/aws-lambda-go/events"
"github.com/ministryofjustice/opg-modernising-lpa/internal/actor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/actor/actoruid"
"github.com/ministryofjustice/opg-modernising-lpa/internal/dashboard/dashboarddata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo"
"github.com/ministryofjustice/opg-modernising-lpa/internal/event"
"github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
Expand All @@ -31,6 +37,133 @@ func TestLpaStoreEventHandlerHandleLpaUpdatedWhenChangeTypeNotExpected(t *testin
assert.Nil(t, err)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedRegister(t *testing.T) {
v := &events.CloudWatchEvent{
DetailType: "lpa-updated",
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333","changeType":"REGISTER"}`),
}

lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(ctx, "M-1111-2222-3333").
Return(&lpadata.Lpa{Type: lpadata.LpaTypePersonalWelfare}, nil)

donorUID := actoruid.New()
attorneyUID := actoruid.New()
replacementTrustCorporationUID := actoruid.New()

client := newMockDynamodbClient(t)
client.EXPECT().
AllByLpaUIDAndPartialSK(ctx, "M-1111-2222-3333", dynamo.SubKey(""), mock.Anything).
Return(nil).
SetData([]dashboarddata.LpaLink{{
SK: dynamo.SubKey(base64.StdEncoding.EncodeToString([]byte("donor-sub"))),
UID: donorUID,
ActorType: actor.TypeDonor,
}, {
SK: dynamo.SubKey(base64.StdEncoding.EncodeToString([]byte("attorney-sub"))),
UID: attorneyUID,
ActorType: actor.TypeAttorney,
}, {
SK: dynamo.SubKey(base64.StdEncoding.EncodeToString([]byte("certificate-provided-sub"))),
UID: actoruid.New(),
ActorType: actor.TypeCertificateProvider,
}, {
SK: dynamo.SubKey(base64.StdEncoding.EncodeToString([]byte("replacement-trust-sub"))),
UID: replacementTrustCorporationUID,
ActorType: actor.TypeReplacementTrustCorporation,
}})

eventClient := newMockEventClient(t)
eventClient.EXPECT().
SendLpaAccessGranted(ctx, event.LpaAccessGranted{
UID: "M-1111-2222-3333",
LpaType: "personal-welfare",
Actors: []event.LpaAccessGrantedActor{{
SubjectID: "donor-sub",
ActorUID: donorUID.String(),
}, {
SubjectID: "attorney-sub",
ActorUID: attorneyUID.String(),
}, {
SubjectID: "replacement-trust-sub",
ActorUID: replacementTrustCorporationUID.String(),
}},
}).
Return(nil)

factory := newMockFactory(t)
factory.EXPECT().DynamoClient().Return(client)
factory.EXPECT().LpaStoreClient().Return(lpaStoreClient, nil)
factory.EXPECT().EventClient().Return(eventClient)

handler := &lpastoreEventHandler{}

err := handler.Handle(ctx, factory, v)
assert.Nil(t, err)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedRegisterWhenErrorCreatingLpaStore(t *testing.T) {
v := &events.CloudWatchEvent{
DetailType: "lpa-updated",
Detail: json.RawMessage(`{"uid":"M-1111-2222-3333","changeType":"REGISTER"}`),
}

factory := newMockFactory(t)
factory.EXPECT().LpaStoreClient().Return(nil, expectedError)

handler := &lpastoreEventHandler{}

err := handler.Handle(ctx, factory, v)
assert.ErrorIs(t, err, expectedError)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedRegisterWhenLpaStoreErrors(t *testing.T) {
lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(nil, expectedError)

err := handleRegister(ctx, nil, lpaStoreClient, nil, lpaUpdatedEvent{})
assert.ErrorIs(t, err, expectedError)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedRegisterWhenDynamoErrors(t *testing.T) {
lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(&lpadata.Lpa{}, nil)

client := newMockDynamodbClient(t)
client.EXPECT().
AllByLpaUIDAndPartialSK(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)

err := handleRegister(ctx, client, lpaStoreClient, nil, lpaUpdatedEvent{})
assert.ErrorIs(t, err, expectedError)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedRegisterWhenEventClientErrors(t *testing.T) {
lpaStoreClient := newMockLpaStoreClient(t)
lpaStoreClient.EXPECT().
Lpa(mock.Anything, mock.Anything).
Return(&lpadata.Lpa{}, nil)

client := newMockDynamodbClient(t)
client.EXPECT().
AllByLpaUIDAndPartialSK(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(nil).
SetData([]dashboarddata.LpaLink{})

eventClient := newMockEventClient(t)
eventClient.EXPECT().
SendLpaAccessGranted(mock.Anything, mock.Anything).
Return(expectedError)

err := handleRegister(ctx, client, lpaStoreClient, eventClient, lpaUpdatedEvent{})
assert.ErrorIs(t, err, expectedError)
}

func TestLpaStoreEventHandlerHandleLpaUpdatedStatutoryWaitingPeriod(t *testing.T) {
event := &events.CloudWatchEvent{
DetailType: "lpa-updated",
Expand Down
1 change: 1 addition & 0 deletions cmd/event-received/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ type DocumentStore interface {
type EventClient interface {
SendApplicationUpdated(ctx context.Context, event event.ApplicationUpdated) error
SendCertificateProviderStarted(ctx context.Context, event event.CertificateProviderStarted) error
SendLpaAccessGranted(ctx context.Context, event event.LpaAccessGranted) error
}

type ScheduledStore interface {
Expand Down
47 changes: 47 additions & 0 deletions cmd/event-received/mock_EventClient_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion cmd/event-received/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ func (c *mockDynamodbClient_OneByUID_Call) SetData(data any) {
}

func (c *mockDynamodbClient_One_Call) SetData(data any) {
c.Run(func(ctx context.Context, pk dynamo.PK, sk dynamo.SK, v interface{}) {
c.Run(func(_ context.Context, _ dynamo.PK, _ dynamo.SK, v interface{}) {
b, _ := attributevalue.Marshal(data)
attributevalue.Unmarshal(b, v)
})
}

func (c *mockDynamodbClient_AllByLpaUIDAndPartialSK_Call) SetData(data any) {
c.Run(func(_ context.Context, _ string, _ dynamo.SK, v interface{}) {
b, _ := attributevalue.Marshal(data)
attributevalue.Unmarshal(b, v)
})
Expand Down
23 changes: 13 additions & 10 deletions internal/attorney/attorneypage/mock_Handler_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions internal/attorney/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func (s *Store) Create(ctx context.Context, shareCode sharecodedata.Link, email
Create(dashboarddata.LpaLink{
PK: dynamo.LpaKey(data.LpaID),
SK: dynamo.SubKey(data.SessionID),
UID: shareCode.ActorUID,
DonorKey: shareCode.LpaOwnerKey,
ActorType: actor.TypeAttorney,
UpdatedAt: s.now(),
Expand Down
1 change: 1 addition & 0 deletions internal/attorney/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func TestAttorneyStoreCreate(t *testing.T) {
PK: dynamo.LpaKey("123"),
SK: dynamo.SubKey("456"),
DonorKey: dynamo.LpaOwnerKey(dynamo.DonorKey("donor")),
UID: uid,
ActorType: actor.TypeAttorney,
UpdatedAt: now,
},
Expand Down
1 change: 1 addition & 0 deletions internal/certificateprovider/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func (s *Store) Create(ctx context.Context, shareCode sharecodedata.Link, email
PK: dynamo.LpaKey(data.LpaID),
SK: dynamo.SubKey(data.SessionID),
DonorKey: shareCode.LpaOwnerKey,
UID: shareCode.ActorUID,
ActorType: actor.TypeCertificateProvider,
UpdatedAt: s.now(),
}).
Expand Down
1 change: 1 addition & 0 deletions internal/certificateprovider/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func TestCertificateProviderStoreCreate(t *testing.T) {
PK: dynamo.LpaKey("lpa-id"),
SK: dynamo.SubKey("session-id"),
DonorKey: shareCode.LpaOwnerKey,
UID: uid,
ActorType: actor.TypeCertificateProvider,
UpdatedAt: testNow,
},
Expand Down
Loading

0 comments on commit 5bbe1e1

Please sign in to comment.