-
Notifications
You must be signed in to change notification settings - Fork 2
/
donor_access.go
138 lines (112 loc) · 3.82 KB
/
donor_access.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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/dynamo"
"github.com/ministryofjustice/opg-modernising-lpa/internal/localize"
"github.com/ministryofjustice/opg-modernising-lpa/internal/notify"
"github.com/ministryofjustice/opg-modernising-lpa/internal/page"
"github.com/ministryofjustice/opg-modernising-lpa/internal/validation"
)
type donorAccessData struct {
App page.AppData
Errors validation.List
Form *donorAccessForm
Donor *actor.DonorProvidedDetails
ShareCode *actor.ShareCodeData
}
func DonorAccess(tmpl template.Template, donorStore DonorStore, shareCodeStore ShareCodeStore, notifyClient NotifyClient, appPublicURL string, randomString func(int) string) Handler {
return func(appData page.AppData, w http.ResponseWriter, r *http.Request, organisation *actor.Organisation, member *actor.Member) error {
donor, err := donorStore.Get(r.Context())
if err != nil {
return err
}
data := &donorAccessData{
App: appData,
Donor: donor,
Form: &donorAccessForm{Email: donor.Donor.Email},
}
shareCodeData, err := shareCodeStore.GetDonor(r.Context())
if err == nil {
data.ShareCode = &shareCodeData
switch page.PostFormString(r, "action") {
case "recall":
if err := shareCodeStore.Delete(r.Context(), shareCodeData); err != nil {
return err
}
return page.Paths.Supporter.ViewLPA.RedirectQuery(w, r, appData, appData.LpaID, url.Values{
"inviteRecalledFor": {shareCodeData.InviteSentTo},
})
case "remove":
if donor.Tasks.PayForLpa.IsCompleted() {
return errors.New("cannot remove LPA access when donor has paid")
}
if err := donorStore.DeleteDonorAccess(r.Context(), shareCodeData); err != nil {
return err
}
return page.Paths.Supporter.ViewLPA.RedirectQuery(w, r, appData, appData.LpaID, url.Values{
"accessRemovedFor": {shareCodeData.InviteSentTo},
})
default:
return tmpl(w, data)
}
}
if !errors.Is(err, dynamo.NotFoundError{}) {
return err
}
if r.Method == http.MethodPost {
data.Form = readDonorAccessForm(r)
data.Errors = data.Form.Validate()
if data.Errors.None() {
if data.Form.Email != donor.Donor.Email {
donor.Donor.Email = data.Form.Email
if err := donorStore.Put(r.Context(), donor); err != nil {
return err
}
}
shareCode := randomString(12)
shareCodeData := actor.ShareCodeData{
LpaOwnerKey: dynamo.LpaOwnerKey(organisation.PK),
LpaKey: dynamo.LpaKey(appData.LpaID),
ActorUID: donor.Donor.UID,
InviteSentTo: data.Form.Email,
}
if err := shareCodeStore.PutDonor(r.Context(), shareCode, shareCodeData); err != nil {
return err
}
if err := notifyClient.SendEmail(r.Context(), data.Form.Email, notify.DonorAccessEmail{
SupporterFullName: member.FullName(),
OrganisationName: organisation.Name,
LpaType: localize.LowerFirst(appData.Localizer.T(donor.Type.String())),
DonorName: donor.Donor.FullName(),
URL: appPublicURL + page.Paths.Start.Format(),
ShareCode: shareCode,
}); err != nil {
return err
}
return page.Paths.Supporter.ViewLPA.RedirectQuery(w, r, appData, appData.LpaID, url.Values{
"inviteSentTo": {data.Form.Email},
})
}
}
return tmpl(w, data)
}
}
type donorAccessForm struct {
Email string
}
func readDonorAccessForm(r *http.Request) *donorAccessForm {
return &donorAccessForm{
Email: page.PostFormString(r, "email"),
}
}
func (f *donorAccessForm) Validate() validation.List {
var errors validation.List
errors.String("email", "email", f.Email,
validation.Empty(),
validation.Email())
return errors
}