Fix #4752: validate the username and email.
This commit is contained in:
parent
7f978c7845
commit
4f74962ce2
|
@ -156,129 +156,130 @@
|
|||
private List<SiteTemplate> _templates;
|
||||
private string _template = Constants.DefaultSiteTemplate;
|
||||
private bool _register = true;
|
||||
private string _message = string.Empty;
|
||||
private string _loadingDisplay = "display: none;";
|
||||
private string _message = string.Empty;
|
||||
private string _loadingDisplay = "display: none;";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// include CSS
|
||||
var content = $"<link rel=\"stylesheet\" href=\"{Constants.BootstrapStylesheetUrl}\" integrity=\"{Constants.BootstrapStylesheetIntegrity}\" crossorigin=\"anonymous\" type=\"text/css\"/>";
|
||||
SiteState.AppendHeadContent(content);
|
||||
|
||||
_togglePassword = SharedLocalizer["ShowPassword"];
|
||||
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
||||
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
||||
|
||||
_databases = await DatabaseService.GetDatabasesAsync();
|
||||
if (_databases.Exists(item => item.IsDefault))
|
||||
{
|
||||
_databaseName = _databases.Find(item => item.IsDefault).Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
_databaseName = "LocalDB";
|
||||
}
|
||||
LoadDatabaseConfigComponent();
|
||||
_databases = await DatabaseService.GetDatabasesAsync();
|
||||
if (_databases.Exists(item => item.IsDefault))
|
||||
{
|
||||
_databaseName = _databases.Find(item => item.IsDefault).Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
_databaseName = "LocalDB";
|
||||
}
|
||||
LoadDatabaseConfigComponent();
|
||||
|
||||
_templates = await SiteTemplateService.GetSiteTemplatesAsync();
|
||||
}
|
||||
|
||||
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
_databaseName = (string)eventArgs.Value;
|
||||
_showConnectionString = false;
|
||||
LoadDatabaseConfigComponent();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_message = Localizer["Error.DbConfig.Load"];
|
||||
}
|
||||
}
|
||||
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
_databaseName = (string)eventArgs.Value;
|
||||
_showConnectionString = false;
|
||||
LoadDatabaseConfigComponent();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_message = Localizer["Error.DbConfig.Load"];
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadDatabaseConfigComponent()
|
||||
{
|
||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||
if (database != null)
|
||||
{
|
||||
_databaseConfigType = Type.GetType(database.ControlType);
|
||||
DatabaseConfigComponent = builder =>
|
||||
{
|
||||
builder.OpenComponent(0, _databaseConfigType);
|
||||
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
}
|
||||
private void LoadDatabaseConfigComponent()
|
||||
{
|
||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||
if (database != null)
|
||||
{
|
||||
_databaseConfigType = Type.GetType(database.ControlType);
|
||||
DatabaseConfigComponent = builder =>
|
||||
{
|
||||
builder.OpenComponent(0, _databaseConfigType);
|
||||
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
// include JavaScript
|
||||
var interop = new Interop(JSRuntime);
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.IncludeScript("", Constants.BootstrapScriptUrl, Constants.BootstrapScriptIntegrity, "anonymous", "", "head");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Install()
|
||||
{
|
||||
var connectionString = String.Empty;
|
||||
if (_showConnectionString)
|
||||
{
|
||||
connectionString = _connectionString;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||
{
|
||||
connectionString = databaseConfigControl.GetConnectionString();
|
||||
}
|
||||
}
|
||||
private async Task Install()
|
||||
{
|
||||
var connectionString = String.Empty;
|
||||
if (_showConnectionString)
|
||||
{
|
||||
connectionString = _connectionString;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||
{
|
||||
connectionString = databaseConfigControl.GetConnectionString();
|
||||
}
|
||||
}
|
||||
|
||||
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
||||
{
|
||||
if (await UserService.ValidatePasswordAsync(_hostPassword))
|
||||
{
|
||||
_loadingDisplay = "";
|
||||
StateHasChanged();
|
||||
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
||||
{
|
||||
var result = await UserService.ValidateUserAsync(_hostUsername, _hostEmail, _hostPassword);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_loadingDisplay = "";
|
||||
StateHasChanged();
|
||||
|
||||
Uri uri = new Uri(NavigationManager.Uri);
|
||||
Uri uri = new Uri(NavigationManager.Uri);
|
||||
|
||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||
|
||||
var config = new InstallConfig
|
||||
{
|
||||
DatabaseType = database.DBType,
|
||||
ConnectionString = connectionString,
|
||||
Aliases = uri.Authority,
|
||||
HostUsername = _hostUsername,
|
||||
HostPassword = _hostPassword,
|
||||
HostEmail = _hostEmail,
|
||||
HostName = _hostUsername,
|
||||
TenantName = TenantNames.Master,
|
||||
IsNewTenant = true,
|
||||
SiteName = Constants.DefaultSite,
|
||||
Register = _register,
|
||||
SiteTemplate = _template,
|
||||
RenderMode = RenderModes.Static,
|
||||
Runtime = Runtimes.Server
|
||||
};
|
||||
var config = new InstallConfig
|
||||
{
|
||||
DatabaseType = database.DBType,
|
||||
ConnectionString = connectionString,
|
||||
Aliases = uri.Authority,
|
||||
HostUsername = _hostUsername,
|
||||
HostPassword = _hostPassword,
|
||||
HostEmail = _hostEmail,
|
||||
HostName = _hostUsername,
|
||||
TenantName = TenantNames.Master,
|
||||
IsNewTenant = true,
|
||||
SiteName = Constants.DefaultSite,
|
||||
Register = _register,
|
||||
SiteTemplate = _template,
|
||||
RenderMode = RenderModes.Static,
|
||||
Runtime = Runtimes.Server
|
||||
};
|
||||
|
||||
var installation = await InstallationService.Install(config);
|
||||
if (installation.Success)
|
||||
{
|
||||
NavigationManager.NavigateTo(uri.Scheme + "://" + uri.Authority, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_message = installation.Message;
|
||||
_loadingDisplay = "display: none;";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_message = Localizer["Message.Password.Invalid"];
|
||||
var installation = await InstallationService.Install(config);
|
||||
if (installation.Success)
|
||||
{
|
||||
NavigationManager.NavigateTo(uri.Scheme + "://" + uri.Authority, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_message = installation.Message;
|
||||
_loadingDisplay = "display: none;";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_message = string.Join("<br />", result.Errors.Select(i => i.Value));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -113,6 +113,15 @@ namespace Oqtane.Services
|
|||
/// <returns></returns>
|
||||
Task<User> VerifyTwoFactorAsync(User user, string token);
|
||||
|
||||
/// <summary>
|
||||
/// Validate identity user info.
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
Task<UserValidateResult> ValidateUserAsync(string username, string email, string password);
|
||||
|
||||
/// <summary>
|
||||
/// Validate a users password against the password policy
|
||||
/// </summary>
|
||||
|
|
|
@ -89,6 +89,11 @@ namespace Oqtane.Services
|
|||
return await PostJsonAsync<User>($"{Apiurl}/twofactor?token={token}", user);
|
||||
}
|
||||
|
||||
public async Task<UserValidateResult> ValidateUserAsync(string username, string email, string password)
|
||||
{
|
||||
return await GetJsonAsync<UserValidateResult>($"{Apiurl}/validateuser?username={WebUtility.UrlEncode(username)}&email={WebUtility.UrlEncode(email)}&password={WebUtility.UrlEncode(password)}");
|
||||
}
|
||||
|
||||
public async Task<bool> ValidatePasswordAsync(string password)
|
||||
{
|
||||
return await GetJsonAsync<bool>($"{Apiurl}/validate/{WebUtility.UrlEncode(password)}");
|
||||
|
|
|
@ -347,6 +347,13 @@ namespace Oqtane.Controllers
|
|||
return user;
|
||||
}
|
||||
|
||||
// GET api/<controller>/validate/x
|
||||
[HttpGet("validateuser")]
|
||||
public async Task<UserValidateResult> ValidateUser(string username, string email, string password)
|
||||
{
|
||||
return await _userManager.ValidateUser(username, email, password);
|
||||
}
|
||||
|
||||
// GET api/<controller>/validate/x
|
||||
[HttpGet("validate/{password}")]
|
||||
public async Task<bool> Validate(string password)
|
||||
|
|
41
Oqtane.Server/Managers/InstallUserManager.cs
Normal file
41
Oqtane.Server/Managers/InstallUserManager.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Oqtane.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is only used for user validation during installation process.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser"></typeparam>
|
||||
internal class InstallUserManager<TUser> : UserManager<IdentityUser>
|
||||
{
|
||||
public InstallUserManager(IUserStore<IdentityUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<IdentityUser> passwordHasher, IEnumerable<IUserValidator<IdentityUser>> userValidators, IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<IdentityUser>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<IdentityUser> FindByNameAsync(string userName)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async Task<IdentityUser> FindByEmailAsync(string email)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async Task<string> GetUserIdAsync(IdentityUser user)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ namespace Oqtane.Managers
|
|||
Task<User> ResetPassword(User user, string token);
|
||||
User VerifyTwoFactor(User user, string token);
|
||||
Task<User> LinkExternalAccount(User user, string token, string type, string key, string name);
|
||||
Task<UserValidateResult> ValidateUser(string username, string email, string password);
|
||||
Task<bool> ValidatePassword(string password);
|
||||
Task<Dictionary<string, string>> ImportUsers(int siteId, string filePath, bool notify);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,41 @@ namespace Oqtane.Managers
|
|||
private readonly ILogManager _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IStringLocalizer<UserManager> _localizer;
|
||||
private readonly IUserStore<IdentityUser> _identityStore;
|
||||
private readonly Microsoft.Extensions.Options.IOptions<IdentityOptions> _identityOptionsAccessor;
|
||||
private readonly IPasswordHasher<IdentityUser> _passwordHasher;
|
||||
private readonly IEnumerable<IUserValidator<IdentityUser>> _userValidators;
|
||||
private readonly IEnumerable<IPasswordValidator<IdentityUser>> _passwordValidators;
|
||||
private readonly ILookupNormalizer _identityKeyNormalizer;
|
||||
private readonly IdentityErrorDescriber _identityErrors;
|
||||
private readonly IServiceProvider _identityServices;
|
||||
private readonly Microsoft.Extensions.Logging.ILogger<UserManager<IdentityUser>> _identityLogger;
|
||||
|
||||
public UserManager(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, IProfileRepository profiles, ISettingRepository settings, ISiteRepository sites, ISyncManager syncManager, ILogManager logger, IMemoryCache cache, IStringLocalizer<UserManager> localizer)
|
||||
public UserManager(
|
||||
IUserRepository users,
|
||||
IRoleRepository roles,
|
||||
IUserRoleRepository userRoles,
|
||||
UserManager<IdentityUser> identityUserManager,
|
||||
SignInManager<IdentityUser> identitySignInManager,
|
||||
ITenantManager tenantManager,
|
||||
INotificationRepository notifications,
|
||||
IFolderRepository folders,
|
||||
IProfileRepository profiles,
|
||||
ISettingRepository settings,
|
||||
ISiteRepository sites,
|
||||
ISyncManager syncManager,
|
||||
ILogManager logger,
|
||||
IMemoryCache cache,
|
||||
IStringLocalizer<UserManager> localizer,
|
||||
IUserStore<IdentityUser> store,
|
||||
Microsoft.Extensions.Options.IOptions<IdentityOptions> optionsAccessor,
|
||||
IPasswordHasher<IdentityUser> passwordHasher,
|
||||
IEnumerable<IUserValidator<IdentityUser>> userValidators,
|
||||
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
|
||||
ILookupNormalizer keyNormalizer,
|
||||
IdentityErrorDescriber errors,
|
||||
IServiceProvider services,
|
||||
Microsoft.Extensions.Logging.ILogger<UserManager<IdentityUser>> identityLogger)
|
||||
{
|
||||
_users = users;
|
||||
_roles = roles;
|
||||
|
@ -51,6 +84,15 @@ namespace Oqtane.Managers
|
|||
_logger = logger;
|
||||
_cache = cache;
|
||||
_localizer = localizer;
|
||||
_identityStore = store;
|
||||
_identityOptionsAccessor = optionsAccessor;
|
||||
_passwordHasher = passwordHasher;
|
||||
_userValidators = userValidators;
|
||||
_passwordValidators = passwordValidators;
|
||||
_identityKeyNormalizer = keyNormalizer;
|
||||
_identityErrors = errors;
|
||||
_identityServices = services;
|
||||
_identityLogger = identityLogger;
|
||||
}
|
||||
|
||||
public User GetUser(int userid, int siteid)
|
||||
|
@ -540,6 +582,40 @@ namespace Oqtane.Managers
|
|||
return user;
|
||||
}
|
||||
|
||||
public async Task<UserValidateResult> ValidateUser(string username, string email, string password)
|
||||
{
|
||||
var validateResult = new UserValidateResult { Succeeded = true };
|
||||
var installUserManager = new InstallUserManager<IdentityUser>(_identityStore, _identityOptionsAccessor, _passwordHasher, _userValidators, _passwordValidators, _identityKeyNormalizer, _identityErrors, _identityServices, _identityLogger);
|
||||
|
||||
var user = new IdentityUser { UserName = username, Email = email, EmailConfirmed = true };
|
||||
var userValidator = new UserValidator<IdentityUser>();
|
||||
var userResult = await userValidator.ValidateAsync(installUserManager, user);
|
||||
if (!userResult.Succeeded)
|
||||
{
|
||||
validateResult.Succeeded = false;
|
||||
if(userResult.Errors != null)
|
||||
{
|
||||
validateResult.Errors = userResult.Errors?.ToDictionary(i => i.Code, i => i.Description);
|
||||
}
|
||||
}
|
||||
|
||||
var passwordValidator = new PasswordValidator<IdentityUser>();
|
||||
var passwordResult = await passwordValidator.ValidateAsync(installUserManager, null, password);
|
||||
if (!passwordResult.Succeeded && !validateResult.Errors.ContainsKey("InvalidPassword"))
|
||||
{
|
||||
validateResult.Succeeded = false;
|
||||
if (passwordResult.Errors != null)
|
||||
{
|
||||
foreach (var error in passwordResult.Errors)
|
||||
{
|
||||
validateResult.Errors.Add(error.Code, error.Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return validateResult;
|
||||
}
|
||||
|
||||
public async Task<bool> ValidatePassword(string password)
|
||||
{
|
||||
var validator = new PasswordValidator<IdentityUser>();
|
||||
|
|
15
Oqtane.Shared/Models/UserValidateResult.cs
Normal file
15
Oqtane.Shared/Models/UserValidateResult.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Models
|
||||
{
|
||||
public class UserValidateResult
|
||||
{
|
||||
public bool Succeeded { get; set; }
|
||||
|
||||
public IDictionary<string, string> Errors { get; set; } = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user