|
|
|
@ -1,14 +1,16 @@ |
|
|
|
using System; |
|
|
|
using System.ComponentModel.DataAnnotations; |
|
|
|
using System.Linq; |
|
|
|
using System.Security.Claims; |
|
|
|
using System.Text; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Microsoft.AspNetCore.Identity; |
|
|
|
using Microsoft.AspNetCore.Mvc; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
using Volo.Abp.Account.Settings; |
|
|
|
using Volo.Abp.Auditing; |
|
|
|
using Volo.Abp.Application.Dtos; |
|
|
|
using Volo.Abp.Identity; |
|
|
|
using Volo.Abp.Settings; |
|
|
|
using Volo.Abp.Uow; |
|
|
|
using Volo.Abp.Validation; |
|
|
|
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|
|
|
|
|
|
|
@ -27,6 +29,12 @@ namespace Volo.Abp.Account.Web.Pages.Account |
|
|
|
[BindProperty] |
|
|
|
public PostInput Input { get; set; } |
|
|
|
|
|
|
|
[BindProperty(SupportsGet = true)] |
|
|
|
public bool IsExternalLogin { get; set; } |
|
|
|
|
|
|
|
[BindProperty(SupportsGet = true)] |
|
|
|
public string ExternalLoginAuthSchema { get; set; } |
|
|
|
|
|
|
|
public RegisterModel(IAccountAppService accountAppService) |
|
|
|
{ |
|
|
|
AccountAppService = accountAppService; |
|
|
|
@ -35,34 +43,141 @@ namespace Volo.Abp.Account.Web.Pages.Account |
|
|
|
public virtual async Task<IActionResult> OnGetAsync() |
|
|
|
{ |
|
|
|
await CheckSelfRegistrationAsync(); |
|
|
|
|
|
|
|
await TrySetEmailAsync(); |
|
|
|
return Page(); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<IActionResult> OnPostAsync() |
|
|
|
private async Task TrySetEmailAsync() |
|
|
|
{ |
|
|
|
ValidateModel(); |
|
|
|
if (IsExternalLogin) |
|
|
|
{ |
|
|
|
var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync(); |
|
|
|
if (externalLoginInfo == null) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (!externalLoginInfo.Principal.Identities.Any()) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
var identity = externalLoginInfo.Principal.Identities.First(); |
|
|
|
var emailClaim = identity.FindFirst(ClaimTypes.Email); |
|
|
|
|
|
|
|
if (emailClaim == null) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
Input = new PostInput {EmailAddress = emailClaim.Value}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<IActionResult> OnPostAsync() |
|
|
|
{ |
|
|
|
await CheckSelfRegistrationAsync(); |
|
|
|
|
|
|
|
var registerDto = new RegisterDto |
|
|
|
var registerDto = new RegisterDto() |
|
|
|
{ |
|
|
|
AppName = "MVC", |
|
|
|
EmailAddress = Input.EmailAddress, |
|
|
|
Password = Input.Password, |
|
|
|
UserName = Input.UserName |
|
|
|
AppName = "MVC" |
|
|
|
}; |
|
|
|
|
|
|
|
var userDto = await AccountAppService.RegisterAsync(registerDto); |
|
|
|
var user = await UserManager.GetByIdAsync(userDto.Id); |
|
|
|
if (IsExternalLogin) |
|
|
|
{ |
|
|
|
var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync(); |
|
|
|
if (externalLoginInfo == null) |
|
|
|
{ |
|
|
|
Logger.LogWarning("External login info is not available"); |
|
|
|
return RedirectToPage("./Login"); |
|
|
|
} |
|
|
|
|
|
|
|
registerDto.EmailAddress = Input.EmailAddress; |
|
|
|
registerDto.UserName = Input.EmailAddress; |
|
|
|
registerDto.Password = GeneratePassword(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ValidateModel(); |
|
|
|
|
|
|
|
await UserManager.SetEmailAsync(user, Input.EmailAddress); |
|
|
|
registerDto.EmailAddress = Input.EmailAddress; |
|
|
|
registerDto.Password = Input.Password; |
|
|
|
registerDto.UserName = Input.UserName; |
|
|
|
} |
|
|
|
|
|
|
|
var userDto = await AccountAppService.RegisterAsync(registerDto); |
|
|
|
var user = await UserManager.GetByIdAsync(userDto.Id); |
|
|
|
await SignInManager.SignInAsync(user, isPersistent: false); |
|
|
|
|
|
|
|
if (IsExternalLogin) |
|
|
|
{ |
|
|
|
await AddToUserLogins(user); |
|
|
|
} |
|
|
|
|
|
|
|
return Redirect(ReturnUrl ?? "~/"); //TODO: How to ensure safety? IdentityServer requires it however it should be checked somehow!
|
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task AddToUserLogins(IdentityUser user) |
|
|
|
{ |
|
|
|
var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync(); |
|
|
|
|
|
|
|
var userLoginAlreadyExists = user.Logins.Any(x => |
|
|
|
x.TenantId == user.TenantId && |
|
|
|
x.LoginProvider == externalLoginInfo.LoginProvider && |
|
|
|
x.ProviderKey == externalLoginInfo.ProviderKey); |
|
|
|
|
|
|
|
if (!userLoginAlreadyExists) |
|
|
|
{ |
|
|
|
user.AddLogin(new UserLoginInfo( |
|
|
|
externalLoginInfo.LoginProvider, |
|
|
|
externalLoginInfo.ProviderKey, |
|
|
|
externalLoginInfo.ProviderDisplayName |
|
|
|
) |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual string GeneratePassword() |
|
|
|
{ |
|
|
|
var random = new Random(); |
|
|
|
var options = UserManager.Options.Password; |
|
|
|
int length = random.Next(options.RequiredLength, IdentityUserConsts.MaxPasswordLength - 1); |
|
|
|
|
|
|
|
bool nonAlphanumeric = options.RequireNonAlphanumeric; |
|
|
|
bool digit = options.RequireDigit; |
|
|
|
bool lowercase = options.RequireLowercase; |
|
|
|
bool uppercase = options.RequireUppercase; |
|
|
|
|
|
|
|
StringBuilder password = new StringBuilder(); |
|
|
|
|
|
|
|
while (password.Length < length) |
|
|
|
{ |
|
|
|
char c = (char)random.Next(32, 126); |
|
|
|
|
|
|
|
password.Append(c); |
|
|
|
|
|
|
|
if (char.IsDigit(c)) |
|
|
|
digit = false; |
|
|
|
else if (char.IsLower(c)) |
|
|
|
lowercase = false; |
|
|
|
else if (char.IsUpper(c)) |
|
|
|
uppercase = false; |
|
|
|
else if (!char.IsLetterOrDigit(c)) |
|
|
|
nonAlphanumeric = false; |
|
|
|
} |
|
|
|
|
|
|
|
if (nonAlphanumeric) |
|
|
|
password.Append((char)random.Next(33, 48)); |
|
|
|
if (digit) |
|
|
|
password.Append((char)random.Next(48, 58)); |
|
|
|
if (lowercase) |
|
|
|
password.Append((char)random.Next(97, 123)); |
|
|
|
if (uppercase) |
|
|
|
password.Append((char)random.Next(65, 91)); |
|
|
|
|
|
|
|
return password.ToString(); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task CheckSelfRegistrationAsync() |
|
|
|
{ |
|
|
|
if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled) || |
|
|
|
|