Skip to content

Commit

Permalink
Expire identity check after 6 months
Browse files Browse the repository at this point in the history
  • Loading branch information
hawx committed Aug 30, 2024
1 parent cb53906 commit be6bf48
Show file tree
Hide file tree
Showing 37 changed files with 1,451 additions and 45 deletions.
1 change: 1 addition & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ packages:
github.com/ministryofjustice/opg-modernising-lpa/internal/pay:
github.com/ministryofjustice/opg-modernising-lpa/internal/place:
github.com/ministryofjustice/opg-modernising-lpa/internal/s3:
github.com/ministryofjustice/opg-modernising-lpa/internal/scheduled:
github.com/ministryofjustice/opg-modernising-lpa/internal/search:
github.com/ministryofjustice/opg-modernising-lpa/internal/secrets:
github.com/ministryofjustice/opg-modernising-lpa/internal/sesh:
Expand Down
15 changes: 15 additions & 0 deletions cmd/mlpa/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/ministryofjustice/opg-go-common/template"
"github.com/ministryofjustice/opg-modernising-lpa/internal/actor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/app"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo"
"github.com/ministryofjustice/opg-modernising-lpa/internal/event"
"github.com/ministryofjustice/opg-modernising-lpa/internal/lambda"
Expand All @@ -37,6 +38,7 @@ import (
"github.com/ministryofjustice/opg-modernising-lpa/internal/pay"
"github.com/ministryofjustice/opg-modernising-lpa/internal/place"
"github.com/ministryofjustice/opg-modernising-lpa/internal/s3"
"github.com/ministryofjustice/opg-modernising-lpa/internal/scheduled"
"github.com/ministryofjustice/opg-modernising-lpa/internal/search"
"github.com/ministryofjustice/opg-modernising-lpa/internal/secrets"
"github.com/ministryofjustice/opg-modernising-lpa/internal/sesh"
Expand Down Expand Up @@ -357,6 +359,19 @@ func run(ctx context.Context, logger *slog.Logger) error {
handler = telemetry.WrapHandler(mux)
}

// TODO: move others out of app/app.go to here, maybe it makes more sense? The
// only negative is the number of arguments that will be added.
donorStore := donor.NewStore(lpasDynamoClient, eventClient, logger, searchClient)
scheduledStore := scheduled.NewStore(lpasDynamoClient)

runner := scheduled.NewRunner(logger, scheduledStore, donorStore, notifyClient)
go func() {
if err := runner.Run(ctx); err != nil {
logger.Error("runner error", slog.Any("err", err))
os.Exit(1)
}
}()

server := &http.Server{
Addr: ":" + port,
Handler: page.Recover(tmpls.Get("error-500.gohtml"), logger, bundle, handler),
Expand Down
19 changes: 11 additions & 8 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/ministryofjustice/opg-modernising-lpa/internal/pay"
"github.com/ministryofjustice/opg-modernising-lpa/internal/place"
"github.com/ministryofjustice/opg-modernising-lpa/internal/random"
"github.com/ministryofjustice/opg-modernising-lpa/internal/scheduled"
"github.com/ministryofjustice/opg-modernising-lpa/internal/search"
"github.com/ministryofjustice/opg-modernising-lpa/internal/sesh"
"github.com/ministryofjustice/opg-modernising-lpa/internal/sharecode"
Expand All @@ -48,22 +49,22 @@ type Logger interface {
}

type DynamoClient interface {
One(ctx context.Context, pk dynamo.PK, sk dynamo.SK, v interface{}) error
OneByPK(ctx context.Context, pk dynamo.PK, v interface{}) error
OneByPartialSK(ctx context.Context, pk dynamo.PK, partialSK dynamo.SK, v interface{}) error
AllByKeys(ctx context.Context, keys []dynamo.Keys) ([]map[string]dynamodbtypes.AttributeValue, error)
AllByPartialSK(ctx context.Context, pk dynamo.PK, partialSK dynamo.SK, v interface{}) error
LatestForActor(ctx context.Context, sk dynamo.SK, v interface{}) error
AllBySK(ctx context.Context, sk dynamo.SK, v interface{}) error
AllByKeys(ctx context.Context, keys []dynamo.Keys) ([]map[string]dynamodbtypes.AttributeValue, error)
AllKeysByPK(ctx context.Context, pk dynamo.PK) ([]dynamo.Keys, error)
Put(ctx context.Context, v interface{}) error
BatchPut(ctx context.Context, items []interface{}) error
Create(ctx context.Context, v interface{}) error
DeleteKeys(ctx context.Context, keys []dynamo.Keys) error
DeleteOne(ctx context.Context, pk dynamo.PK, sk dynamo.SK) error
Update(ctx context.Context, pk dynamo.PK, sk dynamo.SK, values map[string]dynamodbtypes.AttributeValue, expression string) error
BatchPut(ctx context.Context, items []interface{}) error
LatestForActor(ctx context.Context, sk dynamo.SK, v interface{}) error
One(ctx context.Context, pk dynamo.PK, sk dynamo.SK, v interface{}) error
OneByPK(ctx context.Context, pk dynamo.PK, v interface{}) error
OneByPartialSK(ctx context.Context, pk dynamo.PK, partialSK dynamo.SK, v interface{}) error
OneBySK(ctx context.Context, sk dynamo.SK, v interface{}) error
OneByUID(ctx context.Context, uid string, v interface{}) error
Put(ctx context.Context, v interface{}) error
Update(ctx context.Context, pk dynamo.PK, sk dynamo.SK, values map[string]dynamodbtypes.AttributeValue, expression string) error
WriteTransaction(ctx context.Context, transaction *dynamo.Transaction) error
}

Expand Down Expand Up @@ -107,6 +108,7 @@ func App(
organisationStore := supporter.NewOrganisationStore(lpaDynamoClient)
memberStore := supporter.NewMemberStore(lpaDynamoClient)
voucherStore := voucher.NewStore(lpaDynamoClient)
scheduledStore := scheduled.NewStore(lpaDynamoClient)
progressTracker := task.ProgressTracker{Localizer: localizer}

shareCodeSender := sharecode.NewSender(shareCodeStore, notifyClient, appPublicURL, random.String, eventClient)
Expand Down Expand Up @@ -247,6 +249,7 @@ func App(
shareCodeStore,
progressTracker,
lpaStoreResolvingService,
scheduledStore,
)

return withAppData(page.ValidateCsrf(rootMux, sessionStore, random.String, errorHandler), localizer, lang)
Expand Down
8 changes: 8 additions & 0 deletions internal/donor/donordata/provided.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,14 @@ func (l *Provided) Under18ActorDetails() []Under18ActorDetails {
return data
}

func (l *Provided) CorrespondentEmail() string {
if l.Correspondent.Email == "" {
return l.Donor.Email
}

return l.Correspondent.Email
}

func (l *Provided) ActorAddresses() []place.Address {
var addresses []place.Address

Expand Down
13 changes: 12 additions & 1 deletion internal/donor/donorpage/identity_with_one_login_callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (
"github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo"
"github.com/ministryofjustice/opg-modernising-lpa/internal/identity"
"github.com/ministryofjustice/opg-modernising-lpa/internal/scheduled"
"github.com/ministryofjustice/opg-modernising-lpa/internal/task"
)

func IdentityWithOneLoginCallback(oneLoginClient OneLoginClient, sessionStore SessionStore, donorStore DonorStore) Handler {
func IdentityWithOneLoginCallback(oneLoginClient OneLoginClient, sessionStore SessionStore, donorStore DonorStore, scheduledStore ScheduledStore) Handler {
return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, provided *donordata.Provided) error {
if provided.DonorIdentityConfirmed() {
return donor.PathOneLoginIdentityDetails.Redirect(w, r, appData, provided)
Expand Down Expand Up @@ -59,6 +61,15 @@ func IdentityWithOneLoginCallback(oneLoginClient OneLoginClient, sessionStore Se
case identity.StatusInsufficientEvidence:
return donor.PathUnableToConfirmIdentity.Redirect(w, r, appData, provided)
default:
if err := scheduledStore.Put(r.Context(), scheduled.Row{
At: userData.RetrievedAt.AddDate(0, 6, 0),
Action: scheduled.ActionCancelDonorIdentity,
TargetPK: dynamo.WrapPK(provided.PK),
TargetSK: dynamo.WrapSK(provided.SK),
}); err != nil {
return err
}

return donor.PathOneLoginIdentityDetails.Redirect(w, r, appData, provided)
}
}
Expand Down
28 changes: 22 additions & 6 deletions internal/donor/donorpage/identity_with_one_login_callback_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (

"github.com/ministryofjustice/opg-modernising-lpa/internal/donor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/dynamo"
"github.com/ministryofjustice/opg-modernising-lpa/internal/identity"
"github.com/ministryofjustice/opg-modernising-lpa/internal/onelogin"
"github.com/ministryofjustice/opg-modernising-lpa/internal/scheduled"
"github.com/ministryofjustice/opg-modernising-lpa/internal/sesh"
"github.com/ministryofjustice/opg-modernising-lpa/internal/task"
"github.com/stretchr/testify/assert"
Expand All @@ -25,6 +27,8 @@ func TestGetIdentityWithOneLoginCallback(t *testing.T) {
userInfo := onelogin.UserInfo{CoreIdentityJWT: "an-identity-jwt"}
userData := identity.UserData{Status: identity.StatusConfirmed, FirstNames: "John", LastName: "Doe", RetrievedAt: now}
updatedDonor := &donordata.Provided{
PK: dynamo.LpaKey("hey"),
SK: dynamo.LpaOwnerKey(dynamo.DonorKey("oh")),
LpaID: "lpa-id",
Donor: donordata.Donor{FirstNames: "John", LastName: "Doe"},
DonorIdentityUserData: userData,
Expand Down Expand Up @@ -52,7 +56,19 @@ func TestGetIdentityWithOneLoginCallback(t *testing.T) {
ParseIdentityClaim(r.Context(), userInfo).
Return(userData, nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore)(testAppData, w, r, &donordata.Provided{
scheduledStore := newMockScheduledStore(t)
scheduledStore.EXPECT().
Put(r.Context(), scheduled.Row{
At: now.AddDate(0, 6, 0),
Action: scheduled.ActionCancelDonorIdentity,
TargetPK: dynamo.WrapPK(dynamo.LpaKey("hey")),
TargetSK: dynamo.WrapSK(dynamo.LpaOwnerKey(dynamo.DonorKey("oh"))),
}).
Return(nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore, scheduledStore)(testAppData, w, r, &donordata.Provided{
PK: dynamo.LpaKey("hey"),
SK: dynamo.LpaOwnerKey(dynamo.DonorKey("oh")),
LpaID: "lpa-id",
Donor: donordata.Donor{FirstNames: "John", LastName: "Doe"},
})
Expand Down Expand Up @@ -182,7 +198,7 @@ func TestGetIdentityWithOneLoginCallbackWhenIdentityNotConfirmed(t *testing.T) {
sessionStore := tc.sessionStore(t)
oneLoginClient := tc.oneLoginClient(t)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, tc.donorStore(t))(testAppData, w, r, &donordata.Provided{})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, tc.donorStore(t), nil)(testAppData, w, r, &donordata.Provided{})
resp := w.Result()

assert.Equal(t, tc.error, err)
Expand Down Expand Up @@ -222,7 +238,7 @@ func TestGetIdentityWithOneLoginCallbackWhenInsufficientEvidenceReturnCodeClaimP
ParseIdentityClaim(mock.Anything, mock.Anything).
Return(identity.UserData{Status: identity.StatusInsufficientEvidence}, nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore)(testAppData, w, r, &donordata.Provided{
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore, nil)(testAppData, w, r, &donordata.Provided{
Donor: donordata.Donor{FirstNames: "John", LastName: "Doe"},
LpaID: "lpa-id",
})
Expand Down Expand Up @@ -264,7 +280,7 @@ func TestGetIdentityWithOneLoginCallbackWhenAnyOtherReturnCodeClaimPresent(t *te
ParseIdentityClaim(mock.Anything, mock.Anything).
Return(identity.UserData{Status: identity.StatusFailed}, nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore)(testAppData, w, r, &donordata.Provided{
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore, nil)(testAppData, w, r, &donordata.Provided{
Donor: donordata.Donor{FirstNames: "John", LastName: "Doe"},
LpaID: "lpa-id",
})
Expand Down Expand Up @@ -301,7 +317,7 @@ func TestGetIdentityWithOneLoginCallbackWhenPutDonorStoreError(t *testing.T) {
ParseIdentityClaim(mock.Anything, mock.Anything).
Return(identity.UserData{Status: identity.StatusConfirmed}, nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore)(testAppData, w, r, &donordata.Provided{})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore, nil)(testAppData, w, r, &donordata.Provided{})

assert.Equal(t, expectedError, err)
}
Expand All @@ -312,7 +328,7 @@ func TestGetIdentityWithOneLoginCallbackWhenReturning(t *testing.T) {
now := time.Date(2012, time.January, 1, 2, 3, 4, 5, time.UTC)
userData := identity.UserData{Status: identity.StatusConfirmed, FirstNames: "first-name", LastName: "last-name", RetrievedAt: now}

err := IdentityWithOneLoginCallback(nil, nil, nil)(testAppData, w, r, &donordata.Provided{
err := IdentityWithOneLoginCallback(nil, nil, nil, nil)(testAppData, w, r, &donordata.Provided{
LpaID: "lpa-id",
Donor: donordata.Donor{FirstNames: "first-name", LastName: "last-name"},
DonorIdentityUserData: userData,
Expand Down
84 changes: 84 additions & 0 deletions internal/donor/donorpage/mock_ScheduledStore_test.go

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

10 changes: 9 additions & 1 deletion internal/donor/donorpage/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/ministryofjustice/opg-modernising-lpa/internal/pay"
"github.com/ministryofjustice/opg-modernising-lpa/internal/place"
"github.com/ministryofjustice/opg-modernising-lpa/internal/random"
"github.com/ministryofjustice/opg-modernising-lpa/internal/scheduled"
"github.com/ministryofjustice/opg-modernising-lpa/internal/sesh"
"github.com/ministryofjustice/opg-modernising-lpa/internal/sharecode"
"github.com/ministryofjustice/opg-modernising-lpa/internal/sharecode/sharecodedata"
Expand Down Expand Up @@ -158,6 +159,10 @@ type ShareCodeStore interface {
Get(ctx context.Context, actorType actor.Type, code string) (sharecodedata.Link, error)
}

type ScheduledStore interface {
Put(ctx context.Context, row scheduled.Row) error
}

type ErrorHandler func(http.ResponseWriter, *http.Request, error)

type ProgressTracker interface {
Expand Down Expand Up @@ -187,6 +192,7 @@ func Register(
shareCodeStore ShareCodeStore,
progressTracker ProgressTracker,
lpaStoreResolvingService LpaStoreResolvingService,
scheduledStore ScheduledStore,
) {
payer := Pay(logger, sessionStore, donorStore, payClient, random.String, appPublicURL)

Expand Down Expand Up @@ -382,7 +388,7 @@ func Register(
handleWithDonor(donor.PathIdentityWithOneLogin, page.CanGoBack,
IdentityWithOneLogin(oneLoginClient, sessionStore, random.String))
handleWithDonor(donor.PathIdentityWithOneLoginCallback, page.CanGoBack,
IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore))
IdentityWithOneLoginCallback(oneLoginClient, sessionStore, donorStore, scheduledStore))
handleWithDonor(donor.PathOneLoginIdentityDetails, page.CanGoBack,
OneLoginIdentityDetails(tmpls.Get("onelogin_identity_details.gohtml"), donorStore))
handleWithDonor(donor.PathRegisterWithCourtOfProtection, page.None,
Expand All @@ -404,6 +410,8 @@ func Register(
Guidance(tmpls.Get("we_have_contacted_voucher.gohtml")))
handleWithDonor(donor.PathWhatYouCanDoNow, page.CanGoBack,
WhatYouCanDoNow(tmpls.Get("what_you_can_do_now.gohtml"), donorStore))
handleWithDonor(donor.PathWhatYouCanDoNowExpired, page.CanGoBack,
WhatYouCanDoNow(tmpls.Get("what_you_can_do_now_expired.gohtml"), donorStore))
handleWithDonor(donor.PathWhatHappensNextRegisteringWithCourtOfProtection, page.None,
Guidance(tmpls.Get("what_happens_next_registering_with_court_of_protection.gohtml")))

Expand Down
4 changes: 2 additions & 2 deletions internal/donor/donorpage/register_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/ministryofjustice/opg-modernising-lpa/internal/date"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor"
"github.com/ministryofjustice/opg-modernising-lpa/internal/donor/donordata"
lpastore "github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore"
"github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore"
"github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/onelogin"
"github.com/ministryofjustice/opg-modernising-lpa/internal/page"
Expand All @@ -27,7 +27,7 @@ import (

func TestRegister(t *testing.T) {
mux := http.NewServeMux()
Register(mux, &slog.Logger{}, template.Templates{}, &mockSessionStore{}, &mockDonorStore{}, &onelogin.Client{}, &place.Client{}, "http://example.org", &pay.Client{}, &mockShareCodeSender{}, &mockWitnessCodeSender{}, nil, &mockCertificateProviderStore{}, &mockNotifyClient{}, &mockEvidenceReceivedStore{}, &mockDocumentStore{}, &mockEventClient{}, &mockDashboardStore{}, &mockLpaStoreClient{}, &mockShareCodeStore{}, &mockProgressTracker{}, &lpastore.ResolvingService{})
Register(mux, &slog.Logger{}, template.Templates{}, &mockSessionStore{}, &mockDonorStore{}, &onelogin.Client{}, &place.Client{}, "http://example.org", &pay.Client{}, &mockShareCodeSender{}, &mockWitnessCodeSender{}, nil, &mockCertificateProviderStore{}, &mockNotifyClient{}, &mockEvidenceReceivedStore{}, &mockDocumentStore{}, &mockEventClient{}, &mockDashboardStore{}, &mockLpaStoreClient{}, &mockShareCodeStore{}, &mockProgressTracker{}, &lpastore.ResolvingService{}, &mockScheduledStore{})

assert.Implements(t, (*http.Handler)(nil), mux)
}
Expand Down
3 changes: 3 additions & 0 deletions internal/donor/donorpage/task_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ func taskListSignSection(provided *donordata.Provided) taskListSection {
case identity.StatusFailed:
signPath = donor.PathRegisterWithCourtOfProtection

case identity.StatusExpired:
signPath = donor.PathWhatYouCanDoNowExpired

case identity.StatusInsufficientEvidence:
if !provided.SignedAt.IsZero() {
signPath = donor.PathYouHaveSubmittedYourLpa
Expand Down
1 change: 1 addition & 0 deletions internal/donor/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const (
PathWhatHappensNextRegisteringWithCourtOfProtection = Path("/what-happens-next-registering-with-court-of-protection")
PathWhatIsVouching = Path("/what-is-vouching")
PathWhatYouCanDoNow = Path("/what-you-can-do-now")
PathWhatYouCanDoNowExpired = Path("/what-you-can-do-now-expired")
PathWhenCanTheLpaBeUsed = Path("/when-can-the-lpa-be-used")
PathWhichFeeTypeAreYouApplyingFor = Path("/which-fee-type-are-you-applying-for")
PathWithdrawThisLpa = Path("/withdraw-this-lpa")
Expand Down
Loading

0 comments on commit be6bf48

Please sign in to comment.