From 2f2840e39eda2477aa5b8e7277879f6e91b5550f Mon Sep 17 00:00:00 2001 From: hiranya911 Date: Mon, 30 Mar 2020 14:58:13 -0700 Subject: [PATCH 1/2] feat(auth): Added GenerateEmailVerificationLinkAsync() API --- .../Auth/EmailActionRequestTest.cs | 74 +++++++++++++++++++ .../Auth/EmailActionLinkRequest.cs | 7 ++ .../FirebaseAdmin/Auth/FirebaseAuth.cs | 51 +++++++++++++ 3 files changed, 132 insertions(+) diff --git a/FirebaseAdmin/FirebaseAdmin.Tests/Auth/EmailActionRequestTest.cs b/FirebaseAdmin/FirebaseAdmin.Tests/Auth/EmailActionRequestTest.cs index 5447e92f..7dd680a2 100644 --- a/FirebaseAdmin/FirebaseAdmin.Tests/Auth/EmailActionRequestTest.cs +++ b/FirebaseAdmin/FirebaseAdmin.Tests/Auth/EmailActionRequestTest.cs @@ -96,6 +96,11 @@ public void NoEmail() var handler = new MockMessageHandler() { Response = GenerateEmailLinkResponse }; var auth = this.CreateFirebaseAuth(handler); + Assert.ThrowsAsync( + async () => await auth.GenerateEmailVerificationLinkAsync(null)); + Assert.ThrowsAsync( + async () => await auth.GenerateEmailVerificationLinkAsync(string.Empty)); + Assert.ThrowsAsync( async () => await auth.GeneratePasswordResetLinkAsync(null)); Assert.ThrowsAsync( @@ -110,10 +115,79 @@ public void InvalidActionCodeSettings(ActionCodeSettings settings) var auth = this.CreateFirebaseAuth(handler); var email = "user@example.com"; + Assert.ThrowsAsync( + async () => await auth.GenerateEmailVerificationLinkAsync(email, settings)); + Assert.ThrowsAsync( async () => await auth.GeneratePasswordResetLinkAsync(email, settings)); } + [Fact] + public async Task EmailVerificationLink() + { + var handler = new MockMessageHandler() { Response = GenerateEmailLinkResponse }; + var auth = this.CreateFirebaseAuth(handler); + + var link = await auth.GenerateEmailVerificationLinkAsync("user@example.com"); + + Assert.Equal("https://mock-oob-link.for.auth.tests", link); + + var request = NewtonsoftJsonSerializer.Instance.Deserialize>( + handler.LastRequestBody); + Assert.Equal(3, request.Count); + Assert.Equal("user@example.com", request["email"]); + Assert.Equal("VERIFY_EMAIL", request["requestType"]); + Assert.True((bool)request["returnOobLink"]); + this.AssertRequest(handler.Requests[0]); + } + + [Fact] + public async Task EmailVerificationLinkWithSettings() + { + var handler = new MockMessageHandler() { Response = GenerateEmailLinkResponse }; + var auth = this.CreateFirebaseAuth(handler); + + var link = await auth.GenerateEmailVerificationLinkAsync( + "user@example.com", ActionCodeSettings); + + Assert.Equal("https://mock-oob-link.for.auth.tests", link); + + var request = NewtonsoftJsonSerializer.Instance.Deserialize>( + handler.LastRequestBody); + Assert.Equal(10, request.Count); + Assert.Equal("user@example.com", request["email"]); + Assert.Equal("VERIFY_EMAIL", request["requestType"]); + Assert.True((bool)request["returnOobLink"]); + + Assert.Equal(ActionCodeSettings.Url, request["continueUrl"]); + Assert.True((bool)request["canHandleCodeInApp"]); + Assert.Equal(ActionCodeSettings.DynamicLinkDomain, request["dynamicLinkDomain"]); + Assert.Equal(ActionCodeSettings.IosBundleId, request["iOSBundleId"]); + Assert.Equal(ActionCodeSettings.AndroidPackageName, request["androidPackageName"]); + Assert.Equal( + ActionCodeSettings.AndroidMinimumVersion, request["androidMinimumVersion"]); + Assert.True((bool)request["androidInstallApp"]); + this.AssertRequest(handler.Requests[0]); + } + + [Fact] + public async Task EmailVerificationLinkUnexpectedResponse() + { + var handler = new MockMessageHandler() { Response = "{}" }; + var auth = this.CreateFirebaseAuth(handler); + + var exception = await Assert.ThrowsAsync( + async () => await auth.GenerateEmailVerificationLinkAsync("user@example.com")); + + Assert.Equal(ErrorCode.Unknown, exception.ErrorCode); + Assert.Equal(AuthErrorCode.UnexpectedResponse, exception.AuthErrorCode); + Assert.Equal( + $"Failed to generate email action link for: user@example.com", + exception.Message); + Assert.NotNull(exception.HttpResponse); + Assert.Null(exception.InnerException); + } + [Fact] public async Task PasswordResetLink() { diff --git a/FirebaseAdmin/FirebaseAdmin/Auth/EmailActionLinkRequest.cs b/FirebaseAdmin/FirebaseAdmin/Auth/EmailActionLinkRequest.cs index a2fc6dc2..ab29db98 100644 --- a/FirebaseAdmin/FirebaseAdmin/Auth/EmailActionLinkRequest.cs +++ b/FirebaseAdmin/FirebaseAdmin/Auth/EmailActionLinkRequest.cs @@ -19,6 +19,7 @@ namespace FirebaseAdmin.Auth { internal sealed class EmailActionLinkRequest { + private const string VerifyEmail = "VERIFY_EMAIL"; private const string PasswordReset = "PASSWORD_RESET"; private EmailActionLinkRequest(string type, string email, ActionCodeSettings settings) @@ -74,6 +75,12 @@ private EmailActionLinkRequest(string type, string email, ActionCodeSettings set [JsonProperty("androidInstallApp")] internal bool? AndroidInstallApp { get; } + internal static EmailActionLinkRequest EmailVerificationLinkRequest( + string email, ActionCodeSettings settings) + { + return new EmailActionLinkRequest(VerifyEmail, email, settings); + } + internal static EmailActionLinkRequest PasswordResetLinkRequest( string email, ActionCodeSettings settings) { diff --git a/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs b/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs index 7ebb16d7..81fa8303 100644 --- a/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs +++ b/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs @@ -552,6 +552,57 @@ public PagedAsyncEnumerable ListUsersAs return userManager.ListUsers(options); } + /// + /// Generates the out-of-band email action link for email verification flows for the specified + /// email address. + /// + /// If an error occurs while generating the link. + /// The email of the user to be verified. + /// A task that completes with the email verification link. + public async Task GenerateEmailVerificationLinkAsync(string email) + { + return await this.GenerateEmailVerificationLinkAsync(email, null) + .ConfigureAwait(false); + } + + /// + /// Generates the out-of-band email action link for email verification flows for the specified + /// email address. + /// + /// If an error occurs while generating the link. + /// The email of the user to be verifed. + /// The action code settings object which defines whether + /// the link is to be handled by a mobile app and the additional state information to be + /// passed in the deep link.. + /// A task that completes with the email verification link. + public async Task GenerateEmailVerificationLinkAsync( + string email, ActionCodeSettings settings) + { + return await this.GenerateEmailVerificationLinkAsync(email, settings, default(CancellationToken)) + .ConfigureAwait(false); + } + + /// + /// Generates the out-of-band email action link for email verification flows for the specified + /// email address. + /// + /// If an error occurs while generating the link. + /// The email of the user to be verified. + /// The action code settings object which defines whether + /// the link is to be handled by a mobile app and the additional state information to be + /// passed in the deep link.. + /// A cancellation token to monitor the asynchronous + /// operation. + /// A task that completes with the email verification reset link. + public async Task GenerateEmailVerificationLinkAsync( + string email, ActionCodeSettings settings, CancellationToken cancellationToken) + { + var userManager = this.IfNotDeleted(() => this.userManager.Value); + var request = EmailActionLinkRequest.EmailVerificationLinkRequest(email, settings); + return await userManager.GenerateEmailActionLinkAsync(request, cancellationToken) + .ConfigureAwait(false); + } + /// /// Generates the out-of-band email action link for password reset flows for the specified /// email address. From dc85a074269907bab1ef13ccf02992738054e1a7 Mon Sep 17 00:00:00 2001 From: hiranya911 Date: Thu, 2 Apr 2020 15:17:48 -0700 Subject: [PATCH 2/2] Updated API docs --- FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs b/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs index 81fa8303..80cc87fd 100644 --- a/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs +++ b/FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs @@ -571,9 +571,9 @@ public async Task GenerateEmailVerificationLinkAsync(string email) /// /// If an error occurs while generating the link. /// The email of the user to be verifed. - /// The action code settings object which defines whether + /// The action code settings object that defines whether /// the link is to be handled by a mobile app and the additional state information to be - /// passed in the deep link.. + /// passed in the deep link. /// A task that completes with the email verification link. public async Task GenerateEmailVerificationLinkAsync( string email, ActionCodeSettings settings) @@ -588,9 +588,9 @@ public async Task GenerateEmailVerificationLinkAsync( /// /// If an error occurs while generating the link. /// The email of the user to be verified. - /// The action code settings object which defines whether + /// The action code settings object that defines whether /// the link is to be handled by a mobile app and the additional state information to be - /// passed in the deep link.. + /// passed in the deep link. /// A cancellation token to monitor the asynchronous /// operation. /// A task that completes with the email verification reset link.