Skip to content

Commit

Permalink
Send identity-check-mismatched for donor and certificate provider
Browse files Browse the repository at this point in the history
  • Loading branch information
hawx committed Oct 3, 2024
1 parent 55a1f53 commit a0a6467
Show file tree
Hide file tree
Showing 16 changed files with 532 additions and 28 deletions.
1 change: 1 addition & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ func App(
lpaStoreClient,
lpaStoreResolvingService,
donorStore,
eventClient,
appPublicURL,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import (
"errors"
"net/http"

"github.com/ministryofjustice/opg-modernising-lpa/internal/actor/actoruid"
"github.com/ministryofjustice/opg-modernising-lpa/internal/appcontext"
"github.com/ministryofjustice/opg-modernising-lpa/internal/certificateprovider"
"github.com/ministryofjustice/opg-modernising-lpa/internal/certificateprovider/certificateproviderdata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/event"
"github.com/ministryofjustice/opg-modernising-lpa/internal/identity"
"github.com/ministryofjustice/opg-modernising-lpa/internal/notify"
"github.com/ministryofjustice/opg-modernising-lpa/internal/page"
)

func IdentityWithOneLoginCallback(oneLoginClient OneLoginClient, sessionStore SessionStore, certificateProviderStore CertificateProviderStore, lpaStoreResolvingService LpaStoreResolvingService, notifyClient NotifyClient, lpaStoreClient LpaStoreClient, appPublicURL string) Handler {
func IdentityWithOneLoginCallback(oneLoginClient OneLoginClient, sessionStore SessionStore, certificateProviderStore CertificateProviderStore, lpaStoreResolvingService LpaStoreResolvingService, notifyClient NotifyClient, lpaStoreClient LpaStoreClient, eventClient EventClient, appPublicURL string) Handler {
return func(appData appcontext.Data, w http.ResponseWriter, r *http.Request, certificateProvider *certificateproviderdata.Provided) error {
lpa, err := lpaStoreResolvingService.Get(r.Context())
if err != nil {
Expand Down Expand Up @@ -55,7 +57,32 @@ func IdentityWithOneLoginCallback(oneLoginClient OneLoginClient, sessionStore Se
}

switch certificateProvider.IdentityUserData.Status {
case identity.StatusFailed, identity.StatusInsufficientEvidence, identity.StatusUnknown:
case identity.StatusConfirmed:
if certificateProvider.CertificateProviderIdentityConfirmed(lpa.CertificateProvider.FirstNames, lpa.CertificateProvider.LastName) {
if err := lpaStoreClient.SendCertificateProviderConfirmIdentity(r.Context(), lpa.LpaUID, certificateProvider); err != nil {
return err
}
} else {
if err := eventClient.SendIdentityCheckMismatched(r.Context(), event.IdentityCheckMismatched{
LpaUID: lpa.LpaUID,
ActorUID: actoruid.Prefixed(certificateProvider.UID),
Provided: event.IdentityCheckMismatchedDetails{
FirstNames: lpa.CertificateProvider.FirstNames,
LastName: lpa.CertificateProvider.LastName,
DateOfBirth: certificateProvider.DateOfBirth,
},
Verified: event.IdentityCheckMismatchedDetails{
FirstNames: userData.FirstNames,
LastName: userData.LastName,
DateOfBirth: userData.DateOfBirth,
},
}); err != nil {
return err
}
}

return certificateprovider.PathOneLoginIdentityDetails.Redirect(w, r, appData, certificateProvider.LpaID)
default:
if !lpa.SignedAt.IsZero() {
if err = notifyClient.SendActorEmail(r.Context(), lpa.CorrespondentEmail(), lpa.LpaUID, notify.CertificateProviderFailedIDCheckEmail{
Greeting: notifyClient.EmailGreeting(lpa),
Expand All @@ -69,12 +96,7 @@ func IdentityWithOneLoginCallback(oneLoginClient OneLoginClient, sessionStore Se
}

return certificateprovider.PathUnableToConfirmIdentity.Redirect(w, r, appData, certificateProvider.LpaID)
default:
if err := lpaStoreClient.SendCertificateProviderConfirmIdentity(r.Context(), lpa.LpaUID, certificateProvider); err != nil {
return err
}

return certificateprovider.PathOneLoginIdentityDetails.Redirect(w, r, appData, certificateProvider.LpaID)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import (
"testing"
"time"

"github.com/ministryofjustice/opg-modernising-lpa/internal/actor/actoruid"
"github.com/ministryofjustice/opg-modernising-lpa/internal/certificateprovider"
"github.com/ministryofjustice/opg-modernising-lpa/internal/certificateprovider/certificateproviderdata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/event"
"github.com/ministryofjustice/opg-modernising-lpa/internal/identity"
"github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/notify"
Expand Down Expand Up @@ -64,15 +66,123 @@ func TestGetIdentityWithOneLoginCallback(t *testing.T) {
SendCertificateProviderConfirmIdentity(r.Context(), "lpa-uid", updatedCertificateProvider).
Return(nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, lpaStoreClient, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, lpaStoreClient, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
resp := w.Result()

assert.Nil(t, err)
assert.Equal(t, http.StatusFound, resp.StatusCode)
assert.Equal(t, certificateprovider.PathOneLoginIdentityDetails.Format("lpa-id"), resp.Header.Get("Location"))
}

func TestGetIdentityWithOneLoginCallbackWhenFailedIDCheck(t *testing.T) {
func TestGetIdentityWithOneLoginCallbackWhenIdentityMismatched(t *testing.T) {
now := time.Now()
w := httptest.NewRecorder()
r, _ := http.NewRequest(http.MethodGet, "/?code=a-code", nil)

userInfo := onelogin.UserInfo{CoreIdentityJWT: "an-identity-jwt"}
userData := identity.UserData{Status: identity.StatusConfirmed, FirstNames: "Jonathan", LastName: "Doe", RetrievedAt: now}
actorUID := actoruid.New()

certificateProviderStore := newMockCertificateProviderStore(t)
certificateProviderStore.EXPECT().
Put(r.Context(), &certificateproviderdata.Provided{
LpaID: "lpa-id",
UID: actorUID,
IdentityUserData: userData,
}).
Return(nil)

lpaStoreResolvingService := newMockLpaStoreResolvingService(t)
lpaStoreResolvingService.EXPECT().
Get(r.Context()).
Return(&lpadata.Lpa{LpaUID: "lpa-uid", CertificateProvider: lpadata.CertificateProvider{FirstNames: "John", LastName: "Doe"}}, nil)

sessionStore := newMockSessionStore(t)
sessionStore.EXPECT().
OneLogin(r).
Return(&sesh.OneLoginSession{State: "a-state", Nonce: "a-nonce", Redirect: "/redirect"}, nil)

oneLoginClient := newMockOneLoginClient(t)
oneLoginClient.EXPECT().
Exchange(r.Context(), "a-code", "a-nonce").
Return("id-token", "a-jwt", nil)
oneLoginClient.EXPECT().
UserInfo(r.Context(), "a-jwt").
Return(userInfo, nil)
oneLoginClient.EXPECT().
ParseIdentityClaim(r.Context(), userInfo).
Return(userData, nil)

eventClient := newMockEventClient(t)
eventClient.EXPECT().
SendIdentityCheckMismatched(r.Context(), event.IdentityCheckMismatched{
LpaUID: "lpa-uid",
ActorUID: actoruid.Prefixed(actorUID),
Provided: event.IdentityCheckMismatchedDetails{
FirstNames: "John",
LastName: "Doe",
},
Verified: event.IdentityCheckMismatchedDetails{
FirstNames: "Jonathan",
LastName: "Doe",
},
}).
Return(nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, nil, eventClient, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id", UID: actorUID})
resp := w.Result()

assert.Nil(t, err)
assert.Equal(t, http.StatusFound, resp.StatusCode)
assert.Equal(t, certificateprovider.PathOneLoginIdentityDetails.Format("lpa-id"), resp.Header.Get("Location"))
}

func TestGetIdentityWithOneLoginCallbackWhenIdentityMismatchedEventErrors(t *testing.T) {
now := time.Now()
w := httptest.NewRecorder()
r, _ := http.NewRequest(http.MethodGet, "/?code=a-code", nil)

userInfo := onelogin.UserInfo{CoreIdentityJWT: "an-identity-jwt"}
userData := identity.UserData{Status: identity.StatusConfirmed, FirstNames: "Jonathan", LastName: "Doe", RetrievedAt: now}
actorUID := actoruid.New()

certificateProviderStore := newMockCertificateProviderStore(t)
certificateProviderStore.EXPECT().
Put(mock.Anything, mock.Anything).
Return(nil)

lpaStoreResolvingService := newMockLpaStoreResolvingService(t)
lpaStoreResolvingService.EXPECT().
Get(r.Context()).
Return(&lpadata.Lpa{LpaUID: "lpa-uid", CertificateProvider: lpadata.CertificateProvider{FirstNames: "John", LastName: "Doe"}}, nil)

sessionStore := newMockSessionStore(t)
sessionStore.EXPECT().
OneLogin(r).
Return(&sesh.OneLoginSession{State: "a-state", Nonce: "a-nonce", Redirect: "/redirect"}, nil)

oneLoginClient := newMockOneLoginClient(t)
oneLoginClient.EXPECT().
Exchange(r.Context(), "a-code", "a-nonce").
Return("id-token", "a-jwt", nil)
oneLoginClient.EXPECT().
UserInfo(r.Context(), "a-jwt").
Return(userInfo, nil)
oneLoginClient.EXPECT().
ParseIdentityClaim(r.Context(), userInfo).
Return(userData, nil)

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

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, nil, eventClient, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id", UID: actorUID})

assert.Equal(t, expectedError, err)
}

func TestGetIdentityWithOneLoginCallbackWhenIdentityCheckFailed(t *testing.T) {
w := httptest.NewRecorder()
r, _ := http.NewRequest(http.MethodGet, "/?code=a-code", nil)

Expand Down Expand Up @@ -137,7 +247,7 @@ func TestGetIdentityWithOneLoginCallbackWhenFailedIDCheck(t *testing.T) {
}).
Return(nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, notifyClient, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, notifyClient, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
resp := w.Result()

assert.Nil(t, err)
Expand Down Expand Up @@ -204,7 +314,7 @@ func TestGetIdentityWithOneLoginCallbackWhenSendingEmailError(t *testing.T) {
SendActorEmail(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, notifyClient, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, notifyClient, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
resp := w.Result()

assert.Equal(t, expectedError, err)
Expand Down Expand Up @@ -341,7 +451,7 @@ func TestGetIdentityWithOneLoginCallbackWhenIdentityNotConfirmed(t *testing.T) {
sessionStore := tc.sessionStore(t)
oneLoginClient := tc.oneLoginClient(t)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, tc.certificateProviderStore(t), lpaStoreResolvingService, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, tc.certificateProviderStore(t), lpaStoreResolvingService, nil, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{LpaID: "lpa-id"})
resp := w.Result()

assert.Equal(t, tc.error, err)
Expand All @@ -360,7 +470,7 @@ func TestGetIdentityWithOneLoginCallbackWhenGetLpaStoreResolvingServiceError(t *
Get(r.Context()).
Return(&lpadata.Lpa{CertificateProvider: lpadata.CertificateProvider{}}, expectedError)

err := IdentityWithOneLoginCallback(nil, nil, nil, lpaStoreResolvingService, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{})
err := IdentityWithOneLoginCallback(nil, nil, nil, lpaStoreResolvingService, nil, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{})

assert.Equal(t, expectedError, err)
}
Expand Down Expand Up @@ -396,7 +506,7 @@ func TestGetIdentityWithOneLoginCallbackWhenPutCertificateProviderStoreError(t *
ParseIdentityClaim(mock.Anything, mock.Anything).
Return(identity.UserData{Status: identity.StatusConfirmed}, nil)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{})

assert.Equal(t, expectedError, err)
}
Expand Down Expand Up @@ -437,7 +547,7 @@ func TestGetIdentityWithOneLoginCallbackWhenLpaStoreClientError(t *testing.T) {
SendCertificateProviderConfirmIdentity(mock.Anything, mock.Anything, mock.Anything).
Return(expectedError)

err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, lpaStoreClient, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{})
err := IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, nil, lpaStoreClient, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{})

assert.Equal(t, expectedError, err)
}
Expand All @@ -453,7 +563,7 @@ func TestGetIdentityWithOneLoginCallbackWhenReturning(t *testing.T) {
Get(r.Context()).
Return(&lpadata.Lpa{CertificateProvider: lpadata.CertificateProvider{FirstNames: "first-names", LastName: "last-name"}}, nil)

err := IdentityWithOneLoginCallback(nil, nil, nil, lpaStoreResolvingService, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{
err := IdentityWithOneLoginCallback(nil, nil, nil, lpaStoreResolvingService, nil, nil, nil, "www.example.com")(testAppData, w, r, &certificateproviderdata.Provided{
IdentityUserData: userData,
LpaID: "lpa-id",
})
Expand Down

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

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/ministryofjustice/opg-modernising-lpa/internal/certificateprovider/certificateproviderdata"
"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/event"
"github.com/ministryofjustice/opg-modernising-lpa/internal/identity"
"github.com/ministryofjustice/opg-modernising-lpa/internal/lpastore/lpadata"
"github.com/ministryofjustice/opg-modernising-lpa/internal/notify"
Expand All @@ -33,6 +34,10 @@ type LpaStoreResolvingService interface {
Get(ctx context.Context) (*lpadata.Lpa, error)
}

type EventClient interface {
SendIdentityCheckMismatched(ctx context.Context, e event.IdentityCheckMismatched) error
}

type Logger interface {
InfoContext(ctx context.Context, msg string, args ...any)
WarnContext(ctx context.Context, msg string, args ...any)
Expand Down Expand Up @@ -122,6 +127,7 @@ func Register(
lpaStoreClient LpaStoreClient,
lpaStoreResolvingService LpaStoreResolvingService,
donorStore DonorStore,
eventClient EventClient,
appPublicURL string,
) {
handleRoot := makeHandle(rootMux, errorHandler)
Expand Down Expand Up @@ -161,7 +167,7 @@ func Register(
handleCertificateProvider(certificateprovider.PathIdentityWithOneLogin, page.None,
IdentityWithOneLogin(oneLoginClient, sessionStore, random.String))
handleCertificateProvider(certificateprovider.PathIdentityWithOneLoginCallback, page.None,
IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, notifyClient, lpaStoreClient, appPublicURL))
IdentityWithOneLoginCallback(oneLoginClient, sessionStore, certificateProviderStore, lpaStoreResolvingService, notifyClient, lpaStoreClient, eventClient, appPublicURL))
handleCertificateProvider(certificateprovider.PathOneLoginIdentityDetails, page.None,
OneLoginIdentityDetails(tmpls.Get("onelogin_identity_details.gohtml"), certificateProviderStore, lpaStoreResolvingService))
handleCertificateProvider(certificateprovider.PathUnableToConfirmIdentity, page.None,
Expand Down
Loading

0 comments on commit a0a6467

Please sign in to comment.