Fix resend email confirmation (#14118)
This commit is contained in:
parent
b617083148
commit
41195138b1
|
|
@ -207,6 +207,22 @@ namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute]
|
[Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute]
|
||||||
|
public abstract partial class ResendEmailConfirmationModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
||||||
|
{
|
||||||
|
protected ResendEmailConfirmationModel() { }
|
||||||
|
[Microsoft.AspNetCore.Mvc.BindPropertyAttribute]
|
||||||
|
public Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Internal.ResendEmailConfirmationModel.InputModel Input { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
|
||||||
|
public virtual void OnGet() { }
|
||||||
|
public virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Mvc.IActionResult> OnPostAsync() { throw null; }
|
||||||
|
public partial class InputModel
|
||||||
|
{
|
||||||
|
public InputModel() { }
|
||||||
|
[System.ComponentModel.DataAnnotations.EmailAddressAttribute]
|
||||||
|
[System.ComponentModel.DataAnnotations.RequiredAttribute]
|
||||||
|
public string Email { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute]
|
||||||
public partial class ResetPasswordConfirmationModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
public partial class ResetPasswordConfirmationModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
||||||
{
|
{
|
||||||
public ResetPasswordConfirmationModel() { }
|
public ResetPasswordConfirmationModel() { }
|
||||||
|
|
@ -657,6 +673,22 @@ namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute]
|
[Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute]
|
||||||
|
public abstract partial class ResendEmailConfirmationModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
||||||
|
{
|
||||||
|
protected ResendEmailConfirmationModel() { }
|
||||||
|
[Microsoft.AspNetCore.Mvc.BindPropertyAttribute]
|
||||||
|
public Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal.ResendEmailConfirmationModel.InputModel Input { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
|
||||||
|
public virtual void OnGet() { }
|
||||||
|
public virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Mvc.IActionResult> OnPostAsync() { throw null; }
|
||||||
|
public partial class InputModel
|
||||||
|
{
|
||||||
|
public InputModel() { }
|
||||||
|
[System.ComponentModel.DataAnnotations.EmailAddressAttribute]
|
||||||
|
[System.ComponentModel.DataAnnotations.RequiredAttribute]
|
||||||
|
public string Email { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute]
|
||||||
public partial class ResetPasswordConfirmationModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
public partial class ResetPasswordConfirmationModel : Microsoft.AspNetCore.Mvc.RazorPages.PageModel
|
||||||
{
|
{
|
||||||
public ResetPasswordConfirmationModel() { }
|
public ResetPasswordConfirmationModel() { }
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@
|
||||||
<p>
|
<p>
|
||||||
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
|
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<a id="resend-confirmation" asp-page="./ResendEmailConfirmation">Resend email confirmation</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
@page
|
||||||
|
@model ResendEmailConfirmationModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Resend email confirmation";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h2>@ViewData["Title"]</h2>
|
||||||
|
<h4>Enter your email.</h4>
|
||||||
|
<hr />
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<form method="post">
|
||||||
|
<div asp-validation-summary="All" class="text-danger"></div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Input.Email"></label>
|
||||||
|
<input asp-for="Input.Email" class="form-control" />
|
||||||
|
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-default">Resend</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section Scripts {
|
||||||
|
<partial name="_ValidationScriptsPartial" />
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Identity.UI.V3.Pages.Account.Internal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
[AllowAnonymous]
|
||||||
|
[IdentityDefaultUI(typeof(ResendEmailConfirmationModel<>))]
|
||||||
|
public abstract class ResendEmailConfirmationModel : PageModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
[BindProperty]
|
||||||
|
public InputModel Input { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public class InputModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
[EmailAddress]
|
||||||
|
public string Email { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnGet() => throw new NotImplementedException();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ResendEmailConfirmationModel<TUser> : ResendEmailConfirmationModel where TUser : class
|
||||||
|
{
|
||||||
|
private readonly UserManager<TUser> _userManager;
|
||||||
|
private readonly IEmailSender _emailSender;
|
||||||
|
|
||||||
|
public ResendEmailConfirmationModel(UserManager<TUser> userManager, IEmailSender emailSender)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_emailSender = emailSender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IActionResult> OnPostAsync()
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _userManager.FindByEmailAsync(Input.Email);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email.");
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
|
||||||
|
var userId = await _userManager.GetUserIdAsync(user);
|
||||||
|
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||||
|
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
||||||
|
var callbackUrl = Url.Page(
|
||||||
|
"/Account/ConfirmEmail",
|
||||||
|
pageHandler: null,
|
||||||
|
values: new { userId = userId, code = code },
|
||||||
|
protocol: Request.Scheme);
|
||||||
|
await _emailSender.SendEmailAsync(
|
||||||
|
Input.Email,
|
||||||
|
"Confirm your email",
|
||||||
|
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
||||||
|
|
||||||
|
ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email.");
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -41,6 +41,9 @@
|
||||||
<p>
|
<p>
|
||||||
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
|
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<a id="resend-confirmation" asp-page="./ResendEmailConfirmation">Resend email confirmation</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
@page
|
||||||
|
@model ResendEmailConfirmationModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Resend email confirmation";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>@ViewData["Title"]</h1>
|
||||||
|
<h4>Enter your email.</h4>
|
||||||
|
<hr />
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<form method="post">
|
||||||
|
<div asp-validation-summary="All" class="text-danger"></div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Input.Email"></label>
|
||||||
|
<input asp-for="Input.Email" class="form-control" />
|
||||||
|
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Resend</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@section Scripts {
|
||||||
|
<partial name="_ValidationScriptsPartial" />
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Identity.UI.V4.Pages.Account.Internal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
[AllowAnonymous]
|
||||||
|
[IdentityDefaultUI(typeof(ResendEmailConfirmationModel<>))]
|
||||||
|
public abstract class ResendEmailConfirmationModel : PageModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
[BindProperty]
|
||||||
|
public InputModel Input { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public class InputModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
[EmailAddress]
|
||||||
|
public string Email { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnGet() => throw new NotImplementedException();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||||
|
/// directly from your code. This API may change or be removed in future releases.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ResendEmailConfirmationModel<TUser> : ResendEmailConfirmationModel where TUser : class
|
||||||
|
{
|
||||||
|
private readonly UserManager<TUser> _userManager;
|
||||||
|
private readonly IEmailSender _emailSender;
|
||||||
|
|
||||||
|
public ResendEmailConfirmationModel(UserManager<TUser> userManager, IEmailSender emailSender)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_emailSender = emailSender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnGet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IActionResult> OnPostAsync()
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _userManager.FindByEmailAsync(Input.Email);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email.");
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
|
||||||
|
var userId = await _userManager.GetUserIdAsync(user);
|
||||||
|
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||||
|
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
||||||
|
var callbackUrl = Url.Page(
|
||||||
|
"/Account/ConfirmEmail",
|
||||||
|
pageHandler: null,
|
||||||
|
values: new { userId = userId, code = code },
|
||||||
|
protocol: Request.Scheme);
|
||||||
|
await _emailSender.SendEmailAsync(
|
||||||
|
Input.Email,
|
||||||
|
"Confirm your email",
|
||||||
|
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
||||||
|
|
||||||
|
ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email.");
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,12 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<system.webServer>
|
<system.webServer>
|
||||||
<handlers>
|
<handlers>
|
||||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||||
</handlers>
|
</handlers>
|
||||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
|
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false">
|
||||||
|
<environmentVariables>
|
||||||
|
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
|
||||||
|
</environmentVariables>
|
||||||
|
</aspNetCore>
|
||||||
</system.webServer>
|
</system.webServer>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
@ -230,6 +230,33 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
|
||||||
await UserStories.LoginExistingUserAsync(newClient, userName, password);
|
await UserStories.LoginExistingUserAsync(newClient, userName, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CanResendConfirmingEmail()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var emailSender = new ContosoEmailSender();
|
||||||
|
void ConfigureTestServices(IServiceCollection services) => services
|
||||||
|
.SetupTestEmailSender(emailSender)
|
||||||
|
.SetupEmailRequired();
|
||||||
|
|
||||||
|
var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
|
||||||
|
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var newClient = server.CreateClient();
|
||||||
|
|
||||||
|
var userName = $"{Guid.NewGuid()}@example.com";
|
||||||
|
var password = $"!Test.Password1$";
|
||||||
|
|
||||||
|
var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
// Use a new client to simulate a new browser session.
|
||||||
|
await UserStories.ResendConfirmEmailAsync(server.CreateClient(), userName);
|
||||||
|
Assert.Equal(2, emailSender.SentEmails.Count);
|
||||||
|
var email = emailSender.SentEmails.Last();
|
||||||
|
await UserStories.ConfirmEmailAsync(email, newClient);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CanLogInAfterConfirmingEmail_WithGlobalAuthorizeFilter()
|
public async Task CanLogInAfterConfirmingEmail_WithGlobalAuthorizeFilter()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests.Account
|
||||||
{
|
{
|
||||||
private readonly IHtmlFormElement _loginForm;
|
private readonly IHtmlFormElement _loginForm;
|
||||||
private readonly IHtmlAnchorElement _forgotPasswordLink;
|
private readonly IHtmlAnchorElement _forgotPasswordLink;
|
||||||
|
private readonly IHtmlAnchorElement _reconfirmLink;
|
||||||
private readonly IHtmlFormElement _externalLoginForm;
|
private readonly IHtmlFormElement _externalLoginForm;
|
||||||
private readonly IHtmlElement _contosoButton;
|
private readonly IHtmlElement _contosoButton;
|
||||||
private readonly IHtmlElement _loginButton;
|
private readonly IHtmlElement _loginButton;
|
||||||
|
|
@ -26,6 +27,7 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests.Account
|
||||||
_loginForm = HtmlAssert.HasForm("#account", login);
|
_loginForm = HtmlAssert.HasForm("#account", login);
|
||||||
_loginButton = HtmlAssert.HasElement("#login-submit", login);
|
_loginButton = HtmlAssert.HasElement("#login-submit", login);
|
||||||
_forgotPasswordLink = HtmlAssert.HasLink("#forgot-password", login);
|
_forgotPasswordLink = HtmlAssert.HasLink("#forgot-password", login);
|
||||||
|
_reconfirmLink = HtmlAssert.HasLink("#resend-confirmation", login);
|
||||||
if (Context.ContosoLoginEnabled)
|
if (Context.ContosoLoginEnabled)
|
||||||
{
|
{
|
||||||
_externalLoginForm = HtmlAssert.HasForm("#external-account", login);
|
_externalLoginForm = HtmlAssert.HasForm("#external-account", login);
|
||||||
|
|
@ -52,6 +54,14 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests.Account
|
||||||
return new ForgotPassword(Client, forgotPassword, Context);
|
return new ForgotPassword(Client, forgotPassword, Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ResendEmailConfirmation> ClickReconfirmEmailLinkAsync()
|
||||||
|
{
|
||||||
|
var response = await Client.GetAsync(_reconfirmLink.Href);
|
||||||
|
var forgotPassword = await ResponseAssert.IsHtmlDocumentAsync(response);
|
||||||
|
|
||||||
|
return new ResendEmailConfirmation(Client, forgotPassword, Context);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Index> LoginValidUserAsync(string userName, string password)
|
public async Task<Index> LoginValidUserAsync(string userName, string password)
|
||||||
{
|
{
|
||||||
var loggedIn = await SendLoginForm(userName, password);
|
var loggedIn = await SendLoginForm(userName, password);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AngleSharp.Dom.Html;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Account
|
||||||
|
{
|
||||||
|
public class ResendEmailConfirmation : DefaultUIPage
|
||||||
|
{
|
||||||
|
private readonly IHtmlFormElement _resendForm;
|
||||||
|
|
||||||
|
public ResendEmailConfirmation(HttpClient client, IHtmlDocument document, DefaultUIContext context) : base(client, document, context)
|
||||||
|
{
|
||||||
|
_resendForm = HtmlAssert.HasForm(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HttpResponseMessage> ResendAsync(string email)
|
||||||
|
=> Client.SendAsync(_resendForm, new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["Input_Email"] = email
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -194,6 +194,16 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
|
||||||
.WithConfirmedEmail());
|
.WithConfirmedEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static async Task ResendConfirmEmailAsync(HttpClient client, string email)
|
||||||
|
{
|
||||||
|
var index = await Index.CreateAsync(client);
|
||||||
|
var login = await index.ClickLoginLinkAsync();
|
||||||
|
var reconfirm = await login.ClickReconfirmEmailLinkAsync();
|
||||||
|
var response = await reconfirm.ResendAsync(email);
|
||||||
|
ResponseAssert.IsOK(response);
|
||||||
|
Assert.Contains("Verification email sent.", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
internal static async Task<ForgotPasswordConfirmation> ForgotPasswordAsync(HttpClient client, string userName)
|
internal static async Task<ForgotPasswordConfirmation> ForgotPasswordAsync(HttpClient client, string userName)
|
||||||
{
|
{
|
||||||
var index = await Index.CreateAsync(client);
|
var index = await Index.CreateAsync(client);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ namespace Templates.Test.Helpers
|
||||||
public const string LoginUrl = "/Identity/Account/Login";
|
public const string LoginUrl = "/Identity/Account/Login";
|
||||||
public const string RegisterUrl = "/Identity/Account/Register";
|
public const string RegisterUrl = "/Identity/Account/Register";
|
||||||
public const string ForgotPassword = "/Identity/Account/ForgotPassword";
|
public const string ForgotPassword = "/Identity/Account/ForgotPassword";
|
||||||
|
public const string ResendEmailConfirmation = "/Identity/Account/ResendEmailConfirmation";
|
||||||
public const string ExternalArticle = "https://go.microsoft.com/fwlink/?LinkID=532715";
|
public const string ExternalArticle = "https://go.microsoft.com/fwlink/?LinkID=532715";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,7 @@ namespace Templates.Test
|
||||||
PageUrls.PrivacyUrl,
|
PageUrls.PrivacyUrl,
|
||||||
PageUrls.ForgotPassword,
|
PageUrls.ForgotPassword,
|
||||||
PageUrls.RegisterUrl,
|
PageUrls.RegisterUrl,
|
||||||
|
PageUrls.ResendEmailConfirmation,
|
||||||
PageUrls.ExternalArticle,
|
PageUrls.ExternalArticle,
|
||||||
PageUrls.PrivacyUrl }
|
PageUrls.PrivacyUrl }
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ namespace Templates.Test
|
||||||
PageUrls.PrivacyUrl,
|
PageUrls.PrivacyUrl,
|
||||||
PageUrls.ForgotPassword,
|
PageUrls.ForgotPassword,
|
||||||
PageUrls.RegisterUrl,
|
PageUrls.RegisterUrl,
|
||||||
|
PageUrls.ResendEmailConfirmation,
|
||||||
PageUrls.ExternalArticle,
|
PageUrls.ExternalArticle,
|
||||||
PageUrls.PrivacyUrl }
|
PageUrls.PrivacyUrl }
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue