Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MLPAB-1743: Create a new LPA as a supporter #1017

Merged
merged 19 commits into from
Feb 7, 2024
Merged
12 changes: 12 additions & 0 deletions cypress/e2e/supporter/dashboard.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
describe('Dashboard', () => {
beforeEach(() => {
cy.visit('/fixtures/supporter?redirect=/supporter-dashboard&organisation=1');
});

it('can create a new LPA', () => {
cy.checkA11yApp();
cy.contains('button', 'Make a new LPA').click();

cy.url().should('contain', '/your-details');
});
});
8 changes: 7 additions & 1 deletion internal/app/donor_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,14 @@ func (s *donorStore) Get(ctx context.Context) (*actor.DonorProvidedDetails, erro
return nil, errors.New("donorStore.Get requires LpaID and SessionID")
}

sk := donorKey(data.SessionID)

if data.OrganisationID != "" {
sk = organisationKey(data.OrganisationID)
}

var donor *actor.DonorProvidedDetails
err = s.dynamoClient.One(ctx, lpaKey(data.LpaID), donorKey(data.SessionID), &donor)
err = s.dynamoClient.One(ctx, lpaKey(data.LpaID), sk, &donor)
return donor, err
}

Expand Down
32 changes: 25 additions & 7 deletions internal/app/donor_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,34 @@ func TestDonorStoreGetAnyWhenDataStoreError(t *testing.T) {
}

func TestDonorStoreGet(t *testing.T) {
ctx := page.ContextWithSessionData(context.Background(), &page.SessionData{LpaID: "an-id", SessionID: "456"})
testCases := map[string]struct {
sessionData *page.SessionData
expectedSK string
}{
"donor": {
sessionData: &page.SessionData{LpaID: "an-id", SessionID: "456"},
expectedSK: "#DONOR#456",
},
"organisation": {
sessionData: &page.SessionData{LpaID: "an-id", SessionID: "456", OrganisationID: "789"},
expectedSK: "ORGANISATION#789",
},
}

dynamoClient := newMockDynamoClient(t)
dynamoClient.ExpectOne(ctx, "LPA#an-id", "#DONOR#456", &actor.DonorProvidedDetails{LpaID: "an-id"}, nil)
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
ctx := page.ContextWithSessionData(context.Background(), tc.sessionData)

donorStore := &donorStore{dynamoClient: dynamoClient, uuidString: func() string { return "10100000" }}
dynamoClient := newMockDynamoClient(t)
dynamoClient.ExpectOne(ctx, "LPA#an-id", tc.expectedSK, &actor.DonorProvidedDetails{LpaID: "an-id"}, nil)

lpa, err := donorStore.Get(ctx)
assert.Nil(t, err)
assert.Equal(t, &actor.DonorProvidedDetails{LpaID: "an-id"}, lpa)
donorStore := &donorStore{dynamoClient: dynamoClient, uuidString: func() string { return "10100000" }}

lpa, err := donorStore.Get(ctx)
assert.Nil(t, err)
assert.Equal(t, &actor.DonorProvidedDetails{LpaID: "an-id"}, lpa)
})
}
}

func TestDonorStoreGetWithSessionMissing(t *testing.T) {
Expand Down
43 changes: 37 additions & 6 deletions internal/app/organisation_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
now func() time.Time
}

func (s *organisationStore) Create(ctx context.Context, name string) error {
func (s *organisationStore) Create(ctx context.Context, name string) (*actor.Organisation, error) {
data, err := page.SessionDataFromContext(ctx)
if err != nil {
return err
return nil, err
}

if data.SessionID == "" {
return errors.New("organisationStore.Create requires SessionID")
return nil, errors.New("organisationStore.Create requires SessionID")
}

organisationID := s.uuidString()
Expand All @@ -38,7 +38,7 @@
}

if err := s.dynamoClient.Create(ctx, organisation); err != nil {
return fmt.Errorf("error creating organisation: %w", err)
return nil, fmt.Errorf("error creating organisation: %w", err)
}

member := &actor.Member{
Expand All @@ -48,10 +48,10 @@
}

if err := s.dynamoClient.Create(ctx, member); err != nil {
return fmt.Errorf("error creating organisation member: %w", err)
return nil, fmt.Errorf("error creating organisation member: %w", err)
}

return nil
return organisation, nil
}

func (s *organisationStore) Get(ctx context.Context) (*actor.Organisation, error) {
Expand Down Expand Up @@ -98,6 +98,37 @@
return nil
}

func (s *organisationStore) CreateLPA(ctx context.Context, organisationID string) (*actor.DonorProvidedDetails, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving this here for now. We could probably modify donorStore.Create() but I didn't want to have to think through the LpaLink implications until we need it for the dashboard.

data, err := page.SessionDataFromContext(ctx)
if err != nil {
return nil, err
}

if data.SessionID == "" {
return nil, errors.New("donorStore.Create requires SessionID")
}

lpaID := s.uuidString()

donor := &actor.DonorProvidedDetails{
PK: lpaKey(lpaID),
SK: organisationKey(organisationID),
LpaID: lpaID,
CreatedAt: s.now(),
Version: 1,
}

if donor.Hash, err = donor.GenerateHash(); err != nil {
return nil, err

Check warning on line 122 in internal/app/organisation_store.go

View check run for this annotation

Codecov / codecov/patch

internal/app/organisation_store.go#L122

Added line #L122 was not covered by tests
}

if err := s.dynamoClient.Create(ctx, donor); err != nil {
return nil, err
}

return donor, err
}

func organisationKey(s string) string {
return "ORGANISATION#" + s
}
Expand Down
74 changes: 71 additions & 3 deletions internal/app/organisation_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,15 @@ func TestOrganisationStoreCreate(t *testing.T) {

organisationStore := &organisationStore{dynamoClient: dynamoClient, now: testNowFn, uuidString: func() string { return "a-uuid" }}

err := organisationStore.Create(ctx, "A name")
organisation, err := organisationStore.Create(ctx, "A name")
assert.Nil(t, err)
assert.Equal(t, &actor.Organisation{
PK: "ORGANISATION#a-uuid",
SK: "ORGANISATION#a-uuid",
ID: "a-uuid",
CreatedAt: testNow,
Name: "A name",
}, organisation)
}

func TestOrganisationStoreCreateWithSessionMissing(t *testing.T) {
Expand All @@ -47,8 +54,9 @@ func TestOrganisationStoreCreateWithSessionMissing(t *testing.T) {
t.Run(name, func(t *testing.T) {
organisationStore := &organisationStore{}

err := organisationStore.Create(ctx, "A name")
organisation, err := organisationStore.Create(ctx, "A name")
assert.Error(t, err)
assert.Nil(t, organisation)
})
}
}
Expand Down Expand Up @@ -84,8 +92,9 @@ func TestOrganisationStoreCreateWhenErrors(t *testing.T) {
dynamoClient := makeMockDynamoClient(t)
organisationStore := &organisationStore{dynamoClient: dynamoClient, now: testNowFn, uuidString: func() string { return "a-uuid" }}

err := organisationStore.Create(ctx, "A name")
organisation, err := organisationStore.Create(ctx, "A name")
assert.ErrorIs(t, err, expectedError)
assert.Nil(t, organisation)
})
}
}
Expand Down Expand Up @@ -211,3 +220,62 @@ func TestOrganisationStoreCreateMemberInviteWhenErrors(t *testing.T) {
err := organisationStore.CreateMemberInvite(ctx, &actor.Organisation{}, "[email protected]", "abcde")
assert.ErrorIs(t, err, expectedError)
}

func TestOrganisationStoreCreateLPA(t *testing.T) {
ctx := page.ContextWithSessionData(context.Background(), &page.SessionData{SessionID: "an-id"})
expectedDonor := &actor.DonorProvidedDetails{
PK: "LPA#a-uuid",
SK: "ORGANISATION#an-id",
LpaID: "a-uuid",
CreatedAt: testNow,
Version: 1,
}
expectedDonor.Hash, _ = expectedDonor.GenerateHash()

dynamoClient := newMockDynamoClient(t)
dynamoClient.EXPECT().
Create(ctx, expectedDonor).
Return(nil)

organisationStore := &organisationStore{dynamoClient: dynamoClient, now: testNowFn, uuidString: func() string { return "a-uuid" }}

donor, err := organisationStore.CreateLPA(ctx, "an-id")

assert.Nil(t, err)
assert.Equal(t, expectedDonor, donor)
}

func TestOrganisationStoreCreateLPAWithSessionMissing(t *testing.T) {
ctx := page.ContextWithSessionData(context.Background(), &page.SessionData{SessionID: ""})

organisationStore := &organisationStore{dynamoClient: nil, now: testNowFn, uuidString: func() string { return "a-uuid" }}

_, err := organisationStore.CreateLPA(ctx, "an-id")

assert.NotNil(t, err)
}

func TestOrganisationStoreCreateLPAMissingSessionID(t *testing.T) {
ctx := context.Background()

organisationStore := &organisationStore{dynamoClient: nil, now: testNowFn, uuidString: func() string { return "a-uuid" }}

_, err := organisationStore.CreateLPA(ctx, "an-id")

assert.Equal(t, page.SessionMissingError{}, err)
}

func TestOrganisationStoreCreateLPAWhenDynamoError(t *testing.T) {
ctx := page.ContextWithSessionData(context.Background(), &page.SessionData{SessionID: "an-id"})

dynamoClient := newMockDynamoClient(t)
dynamoClient.EXPECT().
Create(ctx, mock.Anything).
Return(expectedError)

organisationStore := &organisationStore{dynamoClient: dynamoClient, now: testNowFn, uuidString: func() string { return "a-uuid" }}

_, err := organisationStore.CreateLPA(ctx, "an-id")

assert.Equal(t, expectedError, err)
}
5 changes: 3 additions & 2 deletions internal/page/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import (
)

type SessionData struct {
SessionID string
LpaID string
SessionID string
LpaID string
OrganisationID string
}

type SessionMissingError struct{}
Expand Down
16 changes: 12 additions & 4 deletions internal/page/donor/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,22 +436,30 @@ func makeLpaHandle(mux *http.ServeMux, store sesh.Store, defaultOptions page.Han
appData.ActorType = actor.TypeDonor
appData.AppPublicURL = appPublicURL

donorSession, err := sesh.Login(store, r)
loginSession, err := sesh.Login(store, r)
if err != nil {
http.Redirect(w, r, page.Paths.Start.Format(), http.StatusFound)
return
}

appData.SessionID = donorSession.SessionID()

appData.SessionID = loginSession.SessionID()
sessionData, err := page.SessionDataFromContext(ctx)

if err == nil {
sessionData.SessionID = appData.SessionID
ctx = page.ContextWithSessionData(ctx, sessionData)

appData.LpaID = sessionData.LpaID
} else {
ctx = page.ContextWithSessionData(ctx, &page.SessionData{SessionID: appData.SessionID, LpaID: appData.LpaID})
sessionData = &page.SessionData{SessionID: appData.SessionID, LpaID: appData.LpaID}
ctx = page.ContextWithSessionData(ctx, sessionData)
}

if loginSession.OrganisationID != "" {
appData.IsSupporter = true
appData.OrganisationName = loginSession.OrganisationName

sessionData.OrganisationID = loginSession.OrganisationID
}

appData.Page = path.Format(appData.LpaID)
Expand Down
Loading
Loading