Skip to content

Commit

Permalink
Merge 8881805 into 7111990
Browse files Browse the repository at this point in the history
  • Loading branch information
acsauk authored Feb 27, 2024
2 parents 7111990 + 8881805 commit 728b3c8
Show file tree
Hide file tree
Showing 14 changed files with 460 additions and 36 deletions.
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ repos:
rev: 37.150.1
hooks:
- id: renovate-config-validator
- repo: local
hooks:
- id: stop-only
name: stop-only
entry: yarn run stop-only
language: node
args: [--folder, cypress]

# - repo: https://github.com/Yelp/detect-secrets
# rev: v1.4.0
# hooks:
Expand Down
21 changes: 19 additions & 2 deletions cypress/e2e/supporter/manage-team-members.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ describe('Organisation details', () => {
cy.contains("td", "[email protected]").parent().within(() => {
cy.contains("Kamal Singh")
cy.contains("Invite pending")
cy.contains("a", "Resend invite")
})

cy.contains("td", "[email protected]").parent().within(() => {
cy.contains("Jo Alessi")
cy.contains("Invite pending")
cy.contains("a", "Resend invite")
})

cy.contains("Team members")
Expand All @@ -33,4 +31,23 @@ describe('Organisation details', () => {
cy.contains("Active")
})
});

it('shows resend invite when expired', () => {
cy.visit('/fixtures/supporter?organisation=1&redirect=/manage-organisation/manage-team-members&invitedMembers=1&permission=admin&expireInvites=1');

cy.checkA11yApp();
cy.contains("a", "Manage team members").click()

cy.contains("Invited team members")

cy.contains("td", "[email protected]").parent().within(() => {
cy.contains("button", "Resend invite").click({force: true})
})

cy.url().should("contain", "/manage-organisation/manage-team-members");
cy.checkA11yApp();

cy.contains(".govuk-notification-banner--success", "[email protected]");
cy.get("main").should("not.contain", "Resend invite");
});
});
2 changes: 1 addition & 1 deletion internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func App(
handleRoot(page.Paths.AttorneyFixtures, None,
fixtures.Attorney(tmpls.Get("attorney_fixtures.gohtml"), sessionStore, shareCodeSender, donorStore, certificateProviderStore, attorneyStore))
handleRoot(page.Paths.SupporterFixtures, None,
fixtures.Supporter(sessionStore, organisationStore, donorStore, memberStore))
fixtures.Supporter(sessionStore, organisationStore, donorStore, memberStore, lpaDynamoClient))
handleRoot(page.Paths.DashboardFixtures, None,
fixtures.Dashboard(tmpls.Get("dashboard_fixtures.gohtml"), sessionStore, shareCodeSender, donorStore, certificateProviderStore, attorneyStore))
handleRoot(page.Paths.YourLegalRightsAndResponsibilities, None,
Expand Down
12 changes: 10 additions & 2 deletions internal/app/member_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ func (s *memberStore) CreateMemberInvite(ctx context.Context, organisation *acto
return nil
}

func (s *memberStore) DeleteMemberInvite(ctx context.Context, organisationID, email string) error {
if err := s.dynamoClient.DeleteOne(ctx, organisationKey(organisationID), memberInviteKey(email)); err != nil {
return fmt.Errorf("error deleting member invite: %w", err)
}

return nil
}

func (s *memberStore) Create(ctx context.Context, invite *actor.MemberInvite) error {
data, err := page.SessionDataFromContext(ctx)
if err != nil {
Expand All @@ -73,8 +81,8 @@ func (s *memberStore) Create(ctx context.Context, invite *actor.MemberInvite) er
return fmt.Errorf("error creating organisation member: %w", err)
}

if err := s.dynamoClient.DeleteOne(ctx, invite.PK, invite.SK); err != nil {
return fmt.Errorf("error deleting member invite: %w", err)
if err := s.DeleteMemberInvite(ctx, invite.OrganisationID, invite.Email); err != nil {
return err
}

link := &organisationLink{
Expand Down
4 changes: 2 additions & 2 deletions internal/app/member_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ func TestMemberStoreCreate(t *testing.T) {
invite := &actor.MemberInvite{
PK: "pk",
SK: "sk",
Email: "ab@example.ord",
Email: "ab@example.org",
FirstNames: "a",
LastName: "b",
Permission: actor.Admin,
Expand All @@ -316,7 +316,7 @@ func TestMemberStoreCreate(t *testing.T) {
Return(nil)

dynamoClient.EXPECT().
DeleteOne(ctx, "pk", "sk").
DeleteOne(ctx, "ORGANISATION#org-id", "MEMBERINVITE#YWJAZXhhbXBsZS5vcmc=").
Return(nil)

dynamoClient.EXPECT().
Expand Down
1 change: 1 addition & 0 deletions internal/page/fixtures/donor.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

type DynamoClient interface {
OneByUID(ctx context.Context, uid string, v interface{}) error
Create(ctx context.Context, v interface{}) error
}

type DocumentStore interface {
Expand Down
36 changes: 33 additions & 3 deletions internal/page/fixtures/supporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/base64"
"fmt"
"log"
"net/http"
"strconv"
"strings"
Expand All @@ -25,7 +26,7 @@ type MemberStore interface {
CreateMemberInvite(ctx context.Context, organisation *actor.Organisation, firstNames, lastname, email, code string, permission actor.Permission) error
}

func Supporter(sessionStore sesh.Store, organisationStore OrganisationStore, donorStore DonorStore, memberStore MemberStore) page.Handler {
func Supporter(sessionStore sesh.Store, organisationStore OrganisationStore, donorStore DonorStore, memberStore MemberStore, dynamoClient DynamoClient) page.Handler {
return func(appData page.AppData, w http.ResponseWriter, r *http.Request) error {
var (
invitedMembers = r.FormValue("invitedMembers")
Expand All @@ -35,6 +36,7 @@ func Supporter(sessionStore sesh.Store, organisationStore OrganisationStore, don
redirect = r.FormValue("redirect")
asMember = r.FormValue("asMember")
permission = r.FormValue("permission")
expireInvites = r.FormValue("expireInvites") == "1"

supporterSub = random.String(16)
supporterSessionID = base64.StdEncoding.EncodeToString([]byte(supporterSub))
Expand Down Expand Up @@ -75,15 +77,43 @@ func Supporter(sessionStore sesh.Store, organisationStore OrganisationStore, don

if invitedMembers != "" {
n, err := strconv.Atoi(invitedMembers)
if err != nil {
return fmt.Errorf("invitedMembers should be a number")
}

for i, member := range invitedOrgMemberNames {
if i == n {
break
}

if err = memberStore.CreateMemberInvite(page.ContextWithSessionData(r.Context(), &page.SessionData{OrganisationID: org.ID}), org, member.Firstnames, member.Lastname, strings.ToLower(fmt.Sprintf("%s-%[email protected]", member.Firstnames, member.Lastname)), random.String(12), actor.Admin); err != nil {
return err
email := strings.ToLower(fmt.Sprintf("%s-%[email protected]", member.Firstnames, member.Lastname))

now := time.Now()
if expireInvites {
now = now.Add(time.Hour * -time.Duration(48))
log.Println(now)
}

invite := &actor.MemberInvite{
PK: "ORGANISATION#" + org.ID,
SK: "MEMBERINVITE#" + base64.StdEncoding.EncodeToString([]byte(email)),
CreatedAt: now,
OrganisationID: org.ID,
OrganisationName: org.Name,
Email: email,
FirstNames: member.Firstnames,
LastName: member.Lastname,
Permission: actor.Admin,
ReferenceNumber: random.String(12),
}

if err := dynamoClient.Create(page.ContextWithSessionData(r.Context(), &page.SessionData{OrganisationID: org.ID}), invite); err != nil {
return fmt.Errorf("error creating member invite: %w", err)
}

//if err = memberStore.CreateMemberInvite(page.ContextWithSessionData(r.Context(), &page.SessionData{OrganisationID: org.ID}), org, member.Firstnames, member.Lastname, strings.ToLower(fmt.Sprintf("%s-%[email protected]", member.Firstnames, member.Lastname)), random.String(12), actor.Admin); err != nil {
// return err
//}
}
}

Expand Down
63 changes: 56 additions & 7 deletions internal/page/supporter/manage_team_members.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package supporter

import (
"errors"
"net/http"
"net/url"

"github.com/ministryofjustice/opg-go-common/template"
"github.com/ministryofjustice/opg-modernising-lpa/internal/actor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/notify"
"github.com/ministryofjustice/opg-modernising-lpa/internal/page"
"github.com/ministryofjustice/opg-modernising-lpa/internal/validation"
)
Expand All @@ -15,10 +18,58 @@ type manageTeamMembersData struct {
Organisation *actor.Organisation
InvitedMembers []*actor.MemberInvite
Members []*actor.Member
Form *inviteMemberForm
}

func ManageTeamMembers(tmpl template.Template, memberStore MemberStore) Handler {
func ManageTeamMembers(tmpl template.Template, memberStore MemberStore, randomString func(int) string, notifyClient NotifyClient, appPublicURL string) Handler {
return func(appData page.AppData, w http.ResponseWriter, r *http.Request, organisation *actor.Organisation) error {
data := &manageTeamMembersData{
App: appData,
Organisation: organisation,
}

if r.Method == http.MethodPost {
data.Form = readInviteMemberForm(r)
data.Errors = data.Form.Validate()

if data.Errors.None() {
session, err := page.SessionDataFromContext(r.Context())
if err != nil {
return err
}

if err := memberStore.DeleteMemberInvite(r.Context(), organisation.ID, data.Form.Email); err != nil {
return err
}

inviteCode := randomString(12)
if err := memberStore.CreateMemberInvite(
r.Context(),
organisation,
data.Form.FirstNames,
data.Form.LastName,
data.Form.Email,
inviteCode,
data.Form.Permission,
); err != nil {
return err
}

if err := notifyClient.SendEmail(r.Context(), data.Form.Email, notify.OrganisationMemberInviteEmail{
OrganisationName: organisation.Name,
InviterEmail: session.Email,
InviteCode: inviteCode,
JoinAnOrganisationURL: appPublicURL + page.Paths.Supporter.Start.Format(),
}); err != nil {
return err
}

return page.Paths.Supporter.ManageTeamMembers.RedirectQuery(w, r, appData, url.Values{"inviteSent": {data.Form.Email}})
}

return errors.New("unable to resend invite")
}

invitedMembers, err := memberStore.InvitedMembers(r.Context())
if err != nil {
return err
Expand All @@ -29,11 +80,9 @@ func ManageTeamMembers(tmpl template.Template, memberStore MemberStore) Handler
return err
}

return tmpl(w, &manageTeamMembersData{
App: appData,
Organisation: organisation,
InvitedMembers: invitedMembers,
Members: members,
})
data.InvitedMembers = invitedMembers
data.Members = members

return tmpl(w, data)
}
}
Loading

0 comments on commit 728b3c8

Please sign in to comment.