[Fixes #1690] AddDefaultUI() throws when using IdentityUser<T>
This commit is contained in:
parent
c7711c2515
commit
971f727ea2
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26730.12
|
||||
VisualStudioVersion = 15.0.27130.2027
|
||||
MinimumVisualStudioVersion = 15.0.26730.03
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0F647068-6602-4E24-B1DC-8ED91481A50A}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnGetAsync(string userId, string code) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class ConfirmEmailModel<TUser> : ConfirmEmailModel where TUser : IdentityUser
|
||||
internal class ConfirmEmailModel<TUser> : ConfirmEmailModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,19 +40,22 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPostConfirmationAsync(string returnUrl = null) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class ExternalLoginModel<TUser> : ExternalLoginModel where TUser : IdentityUser, new()
|
||||
internal class ExternalLoginModel<TUser> : ExternalLoginModel where TUser : class
|
||||
{
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly IUserFactory<TUser> _userFactory;
|
||||
private readonly ILogger<ExternalLoginModel> _logger;
|
||||
|
||||
public ExternalLoginModel(
|
||||
SignInManager<TUser> signInManager,
|
||||
UserManager<TUser> userManager,
|
||||
IUserFactory<TUser> userFactory,
|
||||
ILogger<ExternalLoginModel> logger)
|
||||
{
|
||||
_signInManager = signInManager;
|
||||
_userManager = userManager;
|
||||
_userFactory = userFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +127,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = new TUser { UserName = Input.Email, Email = Input.Email };
|
||||
var user = _userFactory.CreateUser(email: Input.Email, userName: Input.Email);
|
||||
var result = await _userManager.CreateAsync(user);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class ForgotPasswordModel<TUser> : ForgotPasswordModel where TUser : IdentityUser
|
||||
internal class ForgotPasswordModel<TUser> : ForgotPasswordModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly IEmailSender _emailSender;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync(string returnUrl = null) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class LoginModel<TUser> : LoginModel where TUser : IdentityUser
|
||||
internal class LoginModel<TUser> : LoginModel where TUser : class
|
||||
{
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
private readonly ILogger<LoginModel> _logger;
|
||||
|
|
|
|||
|
|
@ -39,14 +39,19 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync(bool rememberMe, string returnUrl = null) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class LoginWith2faModel<TUser> : LoginWith2faModel where TUser : IdentityUser
|
||||
internal class LoginWith2faModel<TUser> : LoginWith2faModel where TUser : class
|
||||
{
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<LoginWith2faModel> _logger;
|
||||
|
||||
public LoginWith2faModel(SignInManager<TUser> signInManager, ILogger<LoginWith2faModel> logger)
|
||||
public LoginWith2faModel(
|
||||
SignInManager<TUser> signInManager,
|
||||
UserManager<TUser> userManager,
|
||||
ILogger<LoginWith2faModel> logger)
|
||||
{
|
||||
_signInManager = signInManager;
|
||||
_userManager = userManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
@ -85,19 +90,21 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
|
||||
var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine);
|
||||
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id);
|
||||
_logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", userId);
|
||||
return LocalRedirect(returnUrl);
|
||||
}
|
||||
else if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id);
|
||||
_logger.LogWarning("User with ID '{UserId}' account locked out.", userId);
|
||||
return RedirectToPage("./Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id);
|
||||
_logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", userId);
|
||||
ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
|
||||
return Page();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,14 +34,19 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync(string returnUrl = null) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class LoginWithRecoveryCodeModel<TUser> : LoginWithRecoveryCodeModel where TUser : IdentityUser
|
||||
internal class LoginWithRecoveryCodeModel<TUser> : LoginWithRecoveryCodeModel where TUser: class
|
||||
{
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<LoginWithRecoveryCodeModel> _logger;
|
||||
|
||||
public LoginWithRecoveryCodeModel(SignInManager<TUser> signInManager, ILogger<LoginWithRecoveryCodeModel> logger)
|
||||
public LoginWithRecoveryCodeModel(
|
||||
SignInManager<TUser> signInManager,
|
||||
UserManager<TUser> userManager,
|
||||
ILogger<LoginWithRecoveryCodeModel> logger)
|
||||
{
|
||||
_signInManager = signInManager;
|
||||
_userManager = userManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
|
@ -76,19 +81,21 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
|
||||
var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
|
||||
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id);
|
||||
_logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", userId);
|
||||
return LocalRedirect(returnUrl ?? Url.Content("~/"));
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id);
|
||||
_logger.LogWarning("User with ID '{UserId}' account locked out.", userId);
|
||||
return RedirectToPage("./Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", user.Id);
|
||||
_logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", userId);
|
||||
ModelState.AddModelError(string.Empty, "Invalid recovery code entered.");
|
||||
return Page();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPost(string returnUrl = null) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class LogoutModel<TUser> : LogoutModel where TUser : IdentityUser
|
||||
internal class LogoutModel<TUser> : LogoutModel where TUser : class
|
||||
{
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
private readonly ILogger<LogoutModel> _logger;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class ChangePasswordModel<TUser> : ChangePasswordModel where TUser : IdentityUser
|
||||
internal class ChangePasswordModel<TUser> : ChangePasswordModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class DeletePersonalDataModel<TUser> : DeletePersonalDataModel where TUser : IdentityUser
|
||||
internal class DeletePersonalDataModel<TUser> : DeletePersonalDataModel where TUser: class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
|
|
@ -77,14 +77,15 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
}
|
||||
|
||||
var result = await _userManager.DeleteAsync(user);
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected error occurred deleteing user with ID '{user.Id}'.");
|
||||
throw new InvalidOperationException($"Unexpected error occurred deleteing user with ID '{userId}'.");
|
||||
}
|
||||
|
||||
await _signInManager.SignOutAsync();
|
||||
|
||||
_logger.LogInformation("User with ID '{UserId}' deleted themselves.", _userManager.GetUserId(User));
|
||||
_logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId);
|
||||
|
||||
return Redirect("~/");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class Disable2faModel<TUser> : Disable2faModel where TUser : IdentityUser
|
||||
internal class Disable2faModel<TUser> : Disable2faModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<Disable2faModel> _logger;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class DownloadPersonalDataModel<TUser> : DownloadPersonalDataModel where TUser : IdentityUser
|
||||
internal class DownloadPersonalDataModel<TUser> : DownloadPersonalDataModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<DownloadPersonalDataModel> _logger;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class EnableAuthenticatorModel<TUser> : EnableAuthenticatorModel where TUser : IdentityUser
|
||||
internal class EnableAuthenticatorModel<TUser> : EnableAuthenticatorModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<EnableAuthenticatorModel> _logger;
|
||||
|
|
@ -102,7 +102,8 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
}
|
||||
|
||||
await _userManager.SetTwoFactorEnabledAsync(user, true);
|
||||
_logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", user.Id);
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
_logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId);
|
||||
|
||||
StatusMessage = "Your authenticator app has been verified.";
|
||||
|
||||
|
|
@ -129,7 +130,9 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
}
|
||||
|
||||
SharedKey = FormatKey(unformattedKey);
|
||||
AuthenticatorUri = GenerateQrCodeUri(user.Email, unformattedKey);
|
||||
|
||||
var email = await _userManager.GetEmailAsync(user);
|
||||
AuthenticatorUri = GenerateQrCodeUri(email, unformattedKey);
|
||||
}
|
||||
|
||||
private string FormatKey(string unformattedKey)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
|
@ -32,17 +33,20 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnGetLinkLoginCallbackAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class ExternalLoginsModel<TUser> : ExternalLoginsModel where TUser : IdentityUser
|
||||
internal class ExternalLoginsModel<TUser> : ExternalLoginsModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
private readonly IUserStore<TUser> _userStore;
|
||||
|
||||
public ExternalLoginsModel(
|
||||
UserManager<TUser> userManager,
|
||||
SignInManager<TUser> signInManager)
|
||||
SignInManager<TUser> signInManager,
|
||||
IUserStore<TUser> userStore)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_userStore = userStore;
|
||||
}
|
||||
|
||||
public override async Task<IActionResult> OnGetAsync()
|
||||
|
|
@ -57,7 +61,14 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
OtherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
|
||||
.Where(auth => CurrentLogins.All(ul => auth.Name != ul.LoginProvider))
|
||||
.ToList();
|
||||
ShowRemoveButton = user.PasswordHash != null || CurrentLogins.Count > 1;
|
||||
|
||||
string passwordHash = null;
|
||||
if (_userStore is IUserPasswordStore<TUser> userPasswordStore)
|
||||
{
|
||||
passwordHash = await userPasswordStore.GetPasswordHashAsync(user, HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
ShowRemoveButton = passwordHash != null || CurrentLogins.Count > 1;
|
||||
return Page();
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +83,8 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
var result = await _userManager.RemoveLoginAsync(user, loginProvider, providerKey);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected error occurred removing external login for user with ID '{user.Id}'.");
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
throw new InvalidOperationException($"Unexpected error occurred removing external login for user with ID '{userId}'.");
|
||||
}
|
||||
|
||||
await _signInManager.RefreshSignInAsync(user);
|
||||
|
|
@ -99,16 +111,17 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user));
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
var info = await _signInManager.GetExternalLoginInfoAsync(userId);
|
||||
if (info == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected error occurred loading external login info for user with ID '{user.Id}'.");
|
||||
throw new InvalidOperationException($"Unexpected error occurred loading external login info for user with ID '{userId}'.");
|
||||
}
|
||||
|
||||
var result = await _userManager.AddLoginAsync(user, info);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected error occurred adding external login for user with ID '{user.Id}'.");
|
||||
throw new InvalidOperationException($"Unexpected error occurred adding external login for user with ID '{userId}'.");
|
||||
}
|
||||
|
||||
// Clear the existing external cookie to ensure a clean login process
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class GenerateRecoveryCodesModel<TUser> : GenerateRecoveryCodesModel where TUser : IdentityUser
|
||||
internal class GenerateRecoveryCodesModel<TUser> : GenerateRecoveryCodesModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<GenerateRecoveryCodesModel> _logger;
|
||||
|
|
@ -45,9 +45,11 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
if (!user.TwoFactorEnabled)
|
||||
var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user);
|
||||
if (!isTwoFactorEnabled)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{user.Id}' because they do not have 2FA enabled.");
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' because they do not have 2FA enabled.");
|
||||
}
|
||||
|
||||
return Page();
|
||||
|
|
@ -61,15 +63,17 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
if (!user.TwoFactorEnabled)
|
||||
var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user);
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
if (!isTwoFactorEnabled)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{user.Id}' as they do not have 2FA enabled.");
|
||||
throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' as they do not have 2FA enabled.");
|
||||
}
|
||||
|
||||
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
|
||||
RecoveryCodes = recoveryCodes.ToArray();
|
||||
|
||||
_logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", user.Id);
|
||||
_logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId);
|
||||
StatusMessage = "You have generated new recovery codes.";
|
||||
return RedirectToPage("./ShowRecoveryCodes");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostSendVerificationEmailAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class IndexModel<TUser> : IndexModel where TUser : IdentityUser
|
||||
internal class IndexModel<TUser> : IndexModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
|
|
@ -65,13 +65,16 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
{
|
||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
var userName = await _userManager.GetUserNameAsync(user);
|
||||
var email = await _userManager.GetEmailAsync(user);
|
||||
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
|
||||
|
||||
Username = user.UserName;
|
||||
Username = userName;
|
||||
|
||||
Input = new InputModel
|
||||
{
|
||||
Email = user.Email,
|
||||
PhoneNumber = user.PhoneNumber
|
||||
Email = email,
|
||||
PhoneNumber = phoneNumber
|
||||
};
|
||||
|
||||
IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user);
|
||||
|
|
@ -92,21 +95,25 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
if (Input.Email != user.Email)
|
||||
var email = await _userManager.GetEmailAsync(user);
|
||||
if (Input.Email != email)
|
||||
{
|
||||
var setEmailResult = await _userManager.SetEmailAsync(user, Input.Email);
|
||||
if (!setEmailResult.Succeeded)
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected error occurred setting email for user with ID '{user.Id}'.");
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
throw new InvalidOperationException($"Unexpected error occurred setting email for user with ID '{userId}'.");
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.PhoneNumber != user.PhoneNumber)
|
||||
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
|
||||
if (Input.PhoneNumber != phoneNumber)
|
||||
{
|
||||
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
|
||||
if (!setPhoneResult.Succeeded)
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected error occurred setting phone number for user with ID '{user.Id}'.");
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
throw new InvalidOperationException($"Unexpected error occurred setting phone number for user with ID '{userId}'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,14 +135,17 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
var email = await _userManager.GetEmailAsync(user);
|
||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var callbackUrl = Url.Page(
|
||||
"/Account/ConfirmEmail",
|
||||
pageHandler: null,
|
||||
values: new { userId = user.Id, code = code },
|
||||
values: new { userId = userId, code = code },
|
||||
protocol: Request.Scheme);
|
||||
await _emailSender.SendEmailAsync(
|
||||
user.Email,
|
||||
email,
|
||||
"Confirm your email",
|
||||
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnGet() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class PersonalDataModel<TUser> : PersonalDataModel where TUser : IdentityUser
|
||||
internal class PersonalDataModel<TUser> : PersonalDataModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<PersonalDataModel> _logger;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class ResetAuthenticatorModel<TUser> : ResetAuthenticatorModel where TUser : IdentityUser
|
||||
internal class ResetAuthenticatorModel<TUser> : ResetAuthenticatorModel where TUser : class
|
||||
{
|
||||
UserManager<TUser> _userManager;
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
|
|
@ -57,7 +57,8 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
|
||||
await _userManager.SetTwoFactorEnabledAsync(user, false);
|
||||
await _userManager.ResetAuthenticatorKeyAsync(user);
|
||||
_logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", user.Id);
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
_logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", userId);
|
||||
|
||||
await _signInManager.RefreshSignInAsync(user);
|
||||
StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key.";
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class SetPasswordModel<TUser> : SetPasswordModel where TUser : IdentityUser
|
||||
internal class SetPasswordModel<TUser> : SetPasswordModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal
|
|||
|
||||
}
|
||||
|
||||
internal class TwoFactorAuthenticationModel<TUser> : TwoFactorAuthenticationModel where TUser : IdentityUser
|
||||
internal class TwoFactorAuthenticationModel<TUser> : TwoFactorAuthenticationModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
|
|
|
|||
|
|
@ -46,9 +46,10 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync(string returnUrl = null) => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class RegisterModel<TUser> : RegisterModel where TUser : IdentityUser, new()
|
||||
internal class RegisterModel<TUser> : RegisterModel where TUser : class
|
||||
{
|
||||
private readonly SignInManager<TUser> _signInManager;
|
||||
private readonly IUserFactory<TUser> _userFactory;
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
private readonly ILogger<LoginModel> _logger;
|
||||
private readonly IEmailSender _emailSender;
|
||||
|
|
@ -56,11 +57,13 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public RegisterModel(
|
||||
UserManager<TUser> userManager,
|
||||
SignInManager<TUser> signInManager,
|
||||
IUserFactory<TUser> userFactory,
|
||||
ILogger<LoginModel> logger,
|
||||
IEmailSender emailSender)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_userFactory = userFactory;
|
||||
_logger = logger;
|
||||
_emailSender = emailSender;
|
||||
}
|
||||
|
|
@ -75,17 +78,18 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
returnUrl = returnUrl ?? Url.Content("~/");
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = new TUser { UserName = Input.Email, Email = Input.Email };
|
||||
var user = _userFactory.CreateUser(email: Input.Email, userName: Input.Email);
|
||||
var result = await _userManager.CreateAsync(user, Input.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation("User created a new account with password.");
|
||||
|
||||
var userId = await _userManager.GetUserIdAsync(user);
|
||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var callbackUrl = Url.Page(
|
||||
"/Account/ConfirmEmail",
|
||||
pageHandler: null,
|
||||
values: new { userId = user.Id, code = code },
|
||||
values: new { userId = userId, code = code },
|
||||
protocol: Request.Scheme);
|
||||
|
||||
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
|
|||
public virtual Task<IActionResult> OnPostAsync() => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal class ResetPasswordModel<TUser> : ResetPasswordModel where TUser : IdentityUser
|
||||
internal class ResetPasswordModel<TUser> : ResetPasswordModel where TUser : class
|
||||
{
|
||||
private readonly UserManager<TUser> _userManager;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an abstraction for instantiating the given user type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type of user.</typeparam>
|
||||
public interface IUserFactory<TUser> where TUser : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an instance of a user and assigns the provided values.
|
||||
/// </summary>
|
||||
/// <param name="email">Email address</param>
|
||||
/// <param name="userName">User name</param>
|
||||
/// <returns>Created user</returns>
|
||||
TUser CreateUser(string email, string userName);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Linq;
|
||||
using Microsoft.AspNetCore.Identity.UI;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
|
|
@ -36,6 +37,13 @@ namespace Microsoft.AspNetCore.Identity
|
|||
.MakeGenericType(builder.UserType));
|
||||
builder.Services.TryAddTransient<IEmailSender, EmailSender>();
|
||||
|
||||
if (TryGetIdentityUserType(builder.UserType, out var primaryKeyType))
|
||||
{
|
||||
var userFactoryType = typeof(IUserFactory<>).MakeGenericType(builder.UserType);
|
||||
var defaultUserFactoryType = typeof(UserFactory<,>).MakeGenericType(builder.UserType, primaryKeyType);
|
||||
builder.Services.TryAddSingleton(userFactoryType, defaultUserFactoryType);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
|
@ -63,5 +71,24 @@ namespace Microsoft.AspNetCore.Identity
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static bool TryGetIdentityUserType(Type userType, out Type primaryKeyType)
|
||||
{
|
||||
primaryKeyType = null;
|
||||
|
||||
var baseType = userType.BaseType;
|
||||
while (baseType != null)
|
||||
{
|
||||
if (baseType.IsGenericType &&
|
||||
baseType.GetGenericTypeDefinition() == typeof(IdentityUser<>))
|
||||
{
|
||||
primaryKeyType = baseType.GetGenericArguments()[0];
|
||||
return true;
|
||||
}
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Identity.UI
|
|||
internal class IdentityDefaultUIConfigureOptions<TUser> :
|
||||
IPostConfigureOptions<RazorPagesOptions>,
|
||||
IPostConfigureOptions<StaticFileOptions>,
|
||||
IPostConfigureOptions<CookieAuthenticationOptions> where TUser : IdentityUser
|
||||
IPostConfigureOptions<CookieAuthenticationOptions> where TUser : class
|
||||
{
|
||||
private const string IdentityUIDefaultAreaName = "Identity";
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
|||
|
||||
namespace Microsoft.AspNetCore.Identity.UI
|
||||
{
|
||||
internal class IdentityPageModelConvention<TUser> : IPageApplicationModelConvention where TUser : IdentityUser
|
||||
internal class IdentityPageModelConvention<TUser> : IPageApplicationModelConvention where TUser : class
|
||||
{
|
||||
public void Apply(PageApplicationModel model)
|
||||
{
|
||||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Identity.UI
|
|||
|
||||
private void ValidateTemplate(Type template)
|
||||
{
|
||||
if(template.IsAbstract || !template.IsGenericTypeDefinition)
|
||||
if (template.IsAbstract || !template.IsGenericTypeDefinition)
|
||||
{
|
||||
throw new InvalidOperationException("Implementation type can't be abstract or non generic.");
|
||||
}
|
||||
|
|
@ -33,11 +33,6 @@ namespace Microsoft.AspNetCore.Identity.UI
|
|||
{
|
||||
throw new InvalidOperationException("Implementation type contains wrong generic arity.");
|
||||
}
|
||||
var argument = genericArguments[0];
|
||||
if (!typeof(IdentityUser).IsAssignableFrom(typeof(TUser)))
|
||||
{
|
||||
throw new InvalidOperationException("Generic implementation type is not compatible.");
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Identity.UI
|
||||
{
|
||||
internal class UserFactory<TUser, TKey> : IUserFactory<TUser>
|
||||
where TUser : IdentityUser<TKey>, new()
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
public TUser CreateUser(string email, string userName)
|
||||
{
|
||||
return new TUser() { Email = email, UserName = userName };
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue