diff --git a/auth/email_action_links.go b/auth/email_action_links.go index 6b649254..e62aac54 100644 --- a/auth/email_action_links.go +++ b/auth/email_action_links.go @@ -32,6 +32,7 @@ type ActionCodeSettings struct { AndroidMinimumVersion string `json:"androidMinimumVersion,omitempty"` AndroidInstallApp bool `json:"androidInstallApp,omitempty"` DynamicLinkDomain string `json:"dynamicLinkDomain,omitempty"` + SendEmailLink bool `json:"-"` } func (settings *ActionCodeSettings) toMap() (map[string]interface{}, error) { @@ -39,8 +40,8 @@ func (settings *ActionCodeSettings) toMap() (map[string]interface{}, error) { return nil, errors.New("URL must not be empty") } - url, err := url.Parse(settings.URL) - if err != nil || url.Scheme == "" || url.Host == "" { + parsedURL, err := url.Parse(settings.URL) + if err != nil || parsedURL.Scheme == "" || parsedURL.Host == "" { return nil, fmt.Errorf("malformed url string: %q", settings.URL) } @@ -58,6 +59,9 @@ func (settings *ActionCodeSettings) toMap() (map[string]interface{}, error) { if err := json.Unmarshal(b, &result); err != nil { return nil, err } + // Since SendEmailLink defaults to false, we will always set "returnOobLink" to true by default. + // This means no email is sent out in the default case + result["returnOobLink"] = !settings.SendEmailLink return result, nil } @@ -114,9 +118,8 @@ func (c *baseClient) generateEmailActionLink( } payload := map[string]interface{}{ - "requestType": linkType, - "email": email, - "returnOobLink": true, + "requestType": linkType, + "email": email, } if settings != nil { settingsMap, err := settings.toMap() diff --git a/auth/email_action_links_test.go b/auth/email_action_links_test.go index 876f3300..a71591dd 100644 --- a/auth/email_action_links_test.go +++ b/auth/email_action_links_test.go @@ -20,6 +20,7 @@ import ( "fmt" "net/http" "reflect" + "strconv" "testing" "firebase.google.com/go/v4/errorutils" @@ -98,9 +99,8 @@ func TestEmailVerificationLink(t *testing.T) { } want := map[string]interface{}{ - "requestType": "VERIFY_EMAIL", - "email": testEmail, - "returnOobLink": true, + "requestType": "VERIFY_EMAIL", + "email": testEmail, } if err := checkActionLinkRequest(want, s); err != nil { t.Fatalf("EmailVerificationLink() %v", err) @@ -111,24 +111,32 @@ func TestEmailVerificationLinkWithSettings(t *testing.T) { s := echoServer(testActionLinkResponse, t) defer s.Close() - link, err := s.Client.EmailVerificationLinkWithSettings(context.Background(), testEmail, testActionCodeSettings) - if err != nil { - t.Fatal(err) - } - if link != testActionLink { - t.Errorf("EmailVerificationLinkWithSettings() = %q; want = %q", link, testActionLink) - } + cases := []string{"true", "false", ""} + testActionCodeSettingsCustom, testActionCodeSettingsMapCustom := getCopiesOfTestSettings(testActionCodeSettings, + testActionCodeSettingsMap) + for _, caseStr := range cases { + if returnOobLink, err := strconv.ParseBool(caseStr); err == nil { + testActionCodeSettingsCustom.SendEmailLink = !returnOobLink + testActionCodeSettingsMapCustom["returnOobLink"] = returnOobLink + } + link, err := s.Client.EmailVerificationLinkWithSettings(context.Background(), testEmail, testActionCodeSettingsCustom) + if err != nil { + t.Fatal(err) + } + if link != testActionLink { + t.Errorf("EmailVerificationLinkWithSettings() = %q; want = %q", link, testActionLink) + } - want := map[string]interface{}{ - "requestType": "VERIFY_EMAIL", - "email": testEmail, - "returnOobLink": true, - } - for k, v := range testActionCodeSettingsMap { - want[k] = v - } - if err := checkActionLinkRequest(want, s); err != nil { - t.Fatalf("EmailVerificationLinkWithSettings() %v", err) + want := map[string]interface{}{ + "requestType": "VERIFY_EMAIL", + "email": testEmail, + } + for k, v := range testActionCodeSettingsMapCustom { + want[k] = v + } + if err := checkActionLinkRequest(want, s); err != nil { + t.Fatalf("EmailVerificationLinkWithSettings() %v", err) + } } } @@ -145,9 +153,8 @@ func TestPasswordResetLink(t *testing.T) { } want := map[string]interface{}{ - "requestType": "PASSWORD_RESET", - "email": testEmail, - "returnOobLink": true, + "requestType": "PASSWORD_RESET", + "email": testEmail, } if err := checkActionLinkRequest(want, s); err != nil { t.Fatalf("PasswordResetLink() %v", err) @@ -158,24 +165,30 @@ func TestPasswordResetLinkWithSettings(t *testing.T) { s := echoServer(testActionLinkResponse, t) defer s.Close() - link, err := s.Client.PasswordResetLinkWithSettings(context.Background(), testEmail, testActionCodeSettings) - if err != nil { - t.Fatal(err) - } - if link != testActionLink { - t.Errorf("PasswordResetLinkWithSettings() = %q; want = %q", link, testActionLink) - } + cases := []bool{true, false} + testActionCodeSettingsCustom, testActionCodeSettingsMapCustom := getCopiesOfTestSettings(testActionCodeSettings, + testActionCodeSettingsMap) + for _, returnOobLink := range cases { + testActionCodeSettingsCustom.SendEmailLink = !returnOobLink + testActionCodeSettingsMapCustom["returnOobLink"] = returnOobLink + link, err := s.Client.PasswordResetLinkWithSettings(context.Background(), testEmail, testActionCodeSettingsCustom) + if err != nil { + t.Fatal(err) + } + if link != testActionLink { + t.Errorf("PasswordResetLinkWithSettings() = %q; want = %q", link, testActionLink) + } - want := map[string]interface{}{ - "requestType": "PASSWORD_RESET", - "email": testEmail, - "returnOobLink": true, - } - for k, v := range testActionCodeSettingsMap { - want[k] = v - } - if err := checkActionLinkRequest(want, s); err != nil { - t.Fatalf("PasswordResetLinkWithSettings() %v", err) + want := map[string]interface{}{ + "requestType": "PASSWORD_RESET", + "email": testEmail, + } + for k, v := range testActionCodeSettingsMapCustom { + want[k] = v + } + if err := checkActionLinkRequest(want, s); err != nil { + t.Fatalf("PasswordResetLinkWithSettings() %v", err) + } } } @@ -204,24 +217,29 @@ func TestEmailSignInLink(t *testing.T) { s := echoServer(testActionLinkResponse, t) defer s.Close() - link, err := s.Client.EmailSignInLink(context.Background(), testEmail, testActionCodeSettings) - if err != nil { - t.Fatal(err) - } - if link != testActionLink { - t.Errorf("EmailSignInLink() = %q; want = %q", link, testActionLink) - } - - want := map[string]interface{}{ - "requestType": "EMAIL_SIGNIN", - "email": testEmail, - "returnOobLink": true, - } - for k, v := range testActionCodeSettingsMap { - want[k] = v - } - if err := checkActionLinkRequest(want, s); err != nil { - t.Fatalf("EmailSignInLink() %v", err) + cases := []bool{true, false} + testActionCodeSettingsCustom, testActionCodeSettingsMapCustom := getCopiesOfTestSettings(testActionCodeSettings, + testActionCodeSettingsMap) + for _, returnOobLink := range cases { + testActionCodeSettingsCustom.SendEmailLink = !returnOobLink + testActionCodeSettingsMapCustom["returnOobLink"] = returnOobLink + link, err := s.Client.EmailSignInLink(context.Background(), testEmail, testActionCodeSettingsCustom) + if err != nil { + t.Fatal(err) + } + if link != testActionLink { + t.Errorf("EmailSignInLink() = %q; want = %q", link, testActionLink) + } + want := map[string]interface{}{ + "requestType": "EMAIL_SIGNIN", + "email": testEmail, + } + for k, v := range testActionCodeSettingsMapCustom { + want[k] = v + } + if err := checkActionLinkRequest(want, s); err != nil { + t.Fatalf("EmailSignInLink() %v", err) + } } } @@ -333,3 +351,22 @@ func checkActionLinkRequestWithURL(want map[string]interface{}, wantURL string, } return nil } + +func getCopiesOfTestSettings(testSettings *ActionCodeSettings, + testSettingsMap map[string]interface{}) (*ActionCodeSettings, map[string]interface{}) { + testActionCodeSettingsCustom := &ActionCodeSettings{ + URL: testSettings.URL, + HandleCodeInApp: testSettings.HandleCodeInApp, + IOSBundleID: testSettings.IOSBundleID, + AndroidPackageName: testSettings.AndroidPackageName, + AndroidMinimumVersion: testSettings.AndroidMinimumVersion, + AndroidInstallApp: testSettings.AndroidInstallApp, + DynamicLinkDomain: testSettings.DynamicLinkDomain, + SendEmailLink: testSettings.SendEmailLink, + } + testActionCodeSettingsMapCustom := map[string]interface{}{} + for k, v := range testSettingsMap { + testActionCodeSettingsMapCustom[k] = v + } + return testActionCodeSettingsCustom, testActionCodeSettingsMapCustom +} diff --git a/auth/tenant_mgt_test.go b/auth/tenant_mgt_test.go index 77c26851..8881fce1 100644 --- a/auth/tenant_mgt_test.go +++ b/auth/tenant_mgt_test.go @@ -503,9 +503,8 @@ func TestTenantEmailVerificationLink(t *testing.T) { } want := map[string]interface{}{ - "requestType": "VERIFY_EMAIL", - "email": testEmail, - "returnOobLink": true, + "requestType": "VERIFY_EMAIL", + "email": testEmail, } if err := checkActionLinkRequestWithURL(want, wantEmailActionURL, s); err != nil { t.Fatalf("EmailVerificationLink() %v", err) @@ -530,9 +529,8 @@ func TestTenantPasswordResetLink(t *testing.T) { } want := map[string]interface{}{ - "requestType": "PASSWORD_RESET", - "email": testEmail, - "returnOobLink": true, + "requestType": "PASSWORD_RESET", + "email": testEmail, } if err := checkActionLinkRequestWithURL(want, wantEmailActionURL, s); err != nil { t.Fatalf("PasswordResetLink() %v", err) @@ -548,24 +546,30 @@ func TestTenantEmailSignInLink(t *testing.T) { t.Fatalf("AuthForTenant() = %v", err) } - link, err := client.EmailSignInLink(context.Background(), testEmail, testActionCodeSettings) - if err != nil { - t.Fatal(err) - } - if link != testActionLink { - t.Errorf("EmailSignInLink() = %q; want = %q", link, testActionLink) - } + cases := []bool{true, false} + testActionCodeSettingsCustom, testActionCodeSettingsMapCustom := getCopiesOfTestSettings(testActionCodeSettings, + testActionCodeSettingsMap) + for _, returnOobLink := range cases { + testActionCodeSettingsCustom.SendEmailLink = !returnOobLink + testActionCodeSettingsMapCustom["returnOobLink"] = returnOobLink + link, err := client.EmailSignInLink(context.Background(), testEmail, testActionCodeSettingsCustom) + if err != nil { + t.Fatal(err) + } + if link != testActionLink { + t.Errorf("EmailSignInLink() = %q; want = %q", link, testActionLink) + } - want := map[string]interface{}{ - "requestType": "EMAIL_SIGNIN", - "email": testEmail, - "returnOobLink": true, - } - for k, v := range testActionCodeSettingsMap { - want[k] = v - } - if err := checkActionLinkRequestWithURL(want, wantEmailActionURL, s); err != nil { - t.Fatalf("EmailSignInLink() %v", err) + want := map[string]interface{}{ + "requestType": "EMAIL_SIGNIN", + "email": testEmail, + } + for k, v := range testActionCodeSettingsMapCustom { + want[k] = v + } + if err := checkActionLinkRequestWithURL(want, wantEmailActionURL, s); err != nil { + t.Fatalf("EmailSignInLink() %v", err) + } } }