Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions internal/api/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ func runVerifyBeforeUserCreatedHook(
hookReq := &v0hooks.BeforeUserCreatedInput{}
err := call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.BeforeUserCreated, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

u := hookReq.User
require.Equal(t, expUser.ID, u.ID)
Expand Down Expand Up @@ -103,7 +108,12 @@ func runVerifyAfterUserCreatedHook(
hookReq := &v0hooks.AfterUserCreatedInput{}
err := call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.AfterUserCreated, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

u := hookReq.User
require.Equal(t, expUser.ID, u.ID)
Expand Down Expand Up @@ -176,6 +186,12 @@ func signupAndConfirmEmail(
err = call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.SendEmail, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

// verify that the latest user from find user matches OTP
otpHash := crypto.GenerateTokenHash(
expUser.GetEmail(), hookReq.EmailData.Token)
Expand Down Expand Up @@ -285,6 +301,12 @@ func TestE2EHooks(t *testing.T) {
err = call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.SendSMS, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

latestUser, err := models.FindUserByID(inst.Conn, signupUser.ID)
require.NoError(t, err)
require.NotNil(t, latestUser)
Expand Down Expand Up @@ -383,6 +405,12 @@ func TestE2EHooks(t *testing.T) {
err = call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.SendSMS, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

require.Equal(t, currentUser.ID, hookReq.User.ID)
require.Equal(t, currentUser.Aud, hookReq.User.Aud)
require.Equal(t, currentUser.Phone, hookReq.User.Phone)
Expand Down Expand Up @@ -924,6 +952,13 @@ func TestE2EHooks(t *testing.T) {
hookReq := &v0hooks.CustomAccessTokenInput{}
err := call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.CustomizeAccessToken, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

require.Equal(t, currentUser.ID, hookReq.UserID)
require.Equal(t, currentUser.ID.String(), hookReq.Claims.Subject)
}
Expand Down Expand Up @@ -1127,6 +1162,12 @@ func TestE2EHooks(t *testing.T) {
err = call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.SendEmail, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

// hook user matches the signup user
require.Equal(t, signupUser.ID, hookReq.User.ID)
require.Equal(t, signupUser.Aud, hookReq.User.Aud)
Expand Down Expand Up @@ -1240,6 +1281,12 @@ func TestE2EHooks(t *testing.T) {
err = call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.SendEmail, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

// verify there is an ott generated
ott, err := models.FindOneTimeToken(
inst.Conn,
Expand Down Expand Up @@ -1343,6 +1390,12 @@ func TestE2EHooks(t *testing.T) {
err = call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.SendEmail, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

// hook user matches the signup user
require.Equal(t, signupUser.ID, hookReq.User.ID)
require.Equal(t, signupUser.Aud, hookReq.User.Aud)
Expand Down Expand Up @@ -1453,6 +1506,12 @@ func TestE2EHooks(t *testing.T) {
err = call.Unmarshal(hookReq)
require.NoError(t, err)

require.NotNil(t, hookReq.Metadata)
require.NotEmpty(t, hookReq.Metadata.IPAddress)
require.Equal(t, v0hooks.SendEmail, hookReq.Metadata.Name)
require.NotEqual(t, uuid.Nil, hookReq.Metadata.UUID)
require.False(t, hookReq.Metadata.Time.IsZero())

// verify there is an ott generated
ott, err := models.FindOneTimeToken(
inst.Conn,
Expand Down
48 changes: 27 additions & 21 deletions internal/api/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,6 @@ func (ts *HooksTestSuite) TestRunHTTPHook() {
// setup mock requests for hooks
defer gock.OffAll()

input := v0hooks.SendSMSInput{
User: ts.TestUser,
SMS: v0hooks.SMS{
OTP: "123456",
},
}
testURL := "http://localhost:54321/functions/v1/custom-sms-sender"
ts.Config.Hook.SendSMS.URI = testURL

Expand Down Expand Up @@ -126,8 +120,16 @@ func (ts *HooksTestSuite) TestRunHTTPHook() {
ts.Run(tc.description, func() {
req, _ := http.NewRequest("POST", ts.Config.Hook.SendSMS.URI, nil)

input := v0hooks.NewSendSMSInput(
req,
ts.TestUser,
v0hooks.SMS{
OTP: "123456",
},
)

var output v0hooks.SendSMSOutput
err := ts.API.hooksMgr.InvokeHook(ts.API.db, req, &input, &output)
err := ts.API.hooksMgr.InvokeHook(ts.API.db, req, input, &output)

if !tc.expectError {
require.NoError(ts.T(), err)
Expand All @@ -143,12 +145,6 @@ func (ts *HooksTestSuite) TestRunHTTPHook() {
func (ts *HooksTestSuite) TestShouldRetryWithRetryAfterHeader() {
defer gock.OffAll()

input := v0hooks.SendSMSInput{
User: ts.TestUser,
SMS: v0hooks.SMS{
OTP: "123456",
},
}
testURL := "http://localhost:54321/functions/v1/custom-sms-sender"
ts.Config.Hook.SendSMS.URI = testURL

Expand All @@ -169,8 +165,16 @@ func (ts *HooksTestSuite) TestShouldRetryWithRetryAfterHeader() {
req, err := http.NewRequest("POST", "http://localhost:9998/otp", nil)
require.NoError(ts.T(), err)

input := v0hooks.NewSendSMSInput(
req,
ts.TestUser,
v0hooks.SMS{
OTP: "123456",
},
)

var output v0hooks.SendSMSOutput
err = ts.API.hooksMgr.InvokeHook(ts.API.db, req, &input, &output)
err = ts.API.hooksMgr.InvokeHook(ts.API.db, req, input, &output)
require.NoError(ts.T(), err)

// Ensure that all expected HTTP interactions (mocks) have been called
Expand All @@ -180,12 +184,6 @@ func (ts *HooksTestSuite) TestShouldRetryWithRetryAfterHeader() {
func (ts *HooksTestSuite) TestShouldReturnErrorForNonJSONContentType() {
defer gock.OffAll()

input := v0hooks.SendSMSInput{
User: ts.TestUser,
SMS: v0hooks.SMS{
OTP: "123456",
},
}
testURL := "http://localhost:54321/functions/v1/custom-sms-sender"
ts.Config.Hook.SendSMS.URI = testURL

Expand All @@ -198,8 +196,16 @@ func (ts *HooksTestSuite) TestShouldReturnErrorForNonJSONContentType() {
req, err := http.NewRequest("POST", "http://localhost:9999/otp", nil)
require.NoError(ts.T(), err)

input := v0hooks.NewSendSMSInput(
req,
ts.TestUser,
v0hooks.SMS{
OTP: "123456",
},
)

var output v0hooks.SendSMSOutput
err = ts.API.hooksMgr.InvokeHook(ts.API.db, req, &input, &output)
err = ts.API.hooksMgr.InvokeHook(ts.API.db, req, input, &output)
require.Error(ts.T(), err, "Expected an error due to wrong content type")
require.Contains(ts.T(), err.Error(), "Invalid JSON response.")
require.True(ts.T(), gock.IsDone(), "Expected all mocks to have been called")
Expand Down
11 changes: 6 additions & 5 deletions internal/api/mail.go
Original file line number Diff line number Diff line change
Expand Up @@ -860,12 +860,13 @@ func (a *API) sendEmail(r *http.Request, tx *storage.Connection, u *models.User,
emailData.FactorType = params.factorType
}

input := v0hooks.SendEmailInput{
User: u,
EmailData: emailData,
}
input := v0hooks.NewSendEmailInput(
r,
u,
emailData,
)
output := v0hooks.SendEmailOutput{}
return a.hooksMgr.InvokeHook(tx, r, &input, &output)
return a.hooksMgr.InvokeHook(tx, r, input, &output)
}

// Increment email send operations here, since this metric is meant to count number of mail
Expand Down
41 changes: 22 additions & 19 deletions internal/api/mfa.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,16 +408,17 @@ func (a *API) challengePhoneFactor(w http.ResponseWriter, r *http.Request) error
phone := factor.Phone.String()

if config.Hook.SendSMS.Enabled {
input := v0hooks.SendSMSInput{
User: user,
SMS: v0hooks.SMS{
input := v0hooks.NewSendSMSInput(
r,
user,
v0hooks.SMS{
OTP: otp,
SMSType: "mfa",
Phone: phone,
},
}
)
output := v0hooks.SendSMSOutput{}
err := a.hooksMgr.InvokeHook(db, r, &input, &output)
err := a.hooksMgr.InvokeHook(db, r, input, &output)
if err != nil {
return apierrors.NewInternalServerError("error invoking hook")
}
Expand Down Expand Up @@ -648,15 +649,16 @@ func (a *API) verifyTOTPFactor(w http.ResponseWriter, r *http.Request, params *V
})

if config.Hook.MFAVerificationAttempt.Enabled {
input := v0hooks.MFAVerificationAttemptInput{
UserID: user.ID,
FactorID: factor.ID,
FactorType: factor.FactorType,
Valid: valid,
}
input := v0hooks.NewMFAVerificationAttemptInput(
r,
user.ID,
factor.ID,
factor.FactorType,
valid,
)

output := v0hooks.MFAVerificationAttemptOutput{}
err := a.hooksMgr.InvokeHook(nil, r, &input, &output)
err := a.hooksMgr.InvokeHook(nil, r, input, &output)
if err != nil {
return err
}
Expand Down Expand Up @@ -799,15 +801,16 @@ func (a *API) verifyPhoneFactor(w http.ResponseWriter, r *http.Request, params *
valid = subtle.ConstantTimeCompare([]byte(otpCode), []byte(params.Code)) == 1
}
if config.Hook.MFAVerificationAttempt.Enabled {
input := v0hooks.MFAVerificationAttemptInput{
UserID: user.ID,
FactorID: factor.ID,
FactorType: factor.FactorType,
Valid: valid,
}
input := v0hooks.NewMFAVerificationAttemptInput(
r,
user.ID,
factor.ID,
factor.FactorType,
valid,
)

output := v0hooks.MFAVerificationAttemptOutput{}
err := a.hooksMgr.InvokeHook(nil, r, &input, &output)
err := a.hooksMgr.InvokeHook(nil, r, input, &output)
if err != nil {
return err
}
Expand Down
11 changes: 6 additions & 5 deletions internal/api/phone.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,16 @@ func (a *API) sendPhoneConfirmation(r *http.Request, tx *storage.Connection, use
otp = crypto.GenerateOtp(config.Sms.OtpLength)

if config.Hook.SendSMS.Enabled {
input := v0hooks.SendSMSInput{
User: user,
SMS: v0hooks.SMS{
input := v0hooks.NewSendSMSInput(
r,
user,
v0hooks.SMS{
OTP: otp,
Phone: phone,
},
}
)
output := v0hooks.SendSMSOutput{}
err := a.hooksMgr.InvokeHook(tx, r, &input, &output)
err := a.hooksMgr.InvokeHook(tx, r, input, &output)
if err != nil {
return "", err
}
Expand Down
11 changes: 6 additions & 5 deletions internal/api/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,13 @@ func (a *API) ResourceOwnerPasswordGrant(ctx context.Context, w http.ResponseWri
}

if config.Hook.PasswordVerificationAttempt.Enabled {
input := v0hooks.PasswordVerificationAttemptInput{
UserID: user.ID,
Valid: isValidPassword,
}
input := v0hooks.NewPasswordVerificationAttemptInput(
r,
user.ID,
isValidPassword,
)
output := v0hooks.PasswordVerificationAttemptOutput{}
if err := a.hooksMgr.InvokeHook(nil, r, &input, &output); err != nil {
if err := a.hooksMgr.InvokeHook(nil, r, input, &output); err != nil {
return err
}

Expand Down
Loading