Merge pull request #4756 from zyhfish/task/fix-4752
Fix #4752: validate the username and email.
This commit is contained in:
commit
6719d242bd
@ -156,129 +156,130 @@
|
|||||||
private List<SiteTemplate> _templates;
|
private List<SiteTemplate> _templates;
|
||||||
private string _template = Constants.DefaultSiteTemplate;
|
private string _template = Constants.DefaultSiteTemplate;
|
||||||
private bool _register = true;
|
private bool _register = true;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private string _loadingDisplay = "display: none;";
|
private string _loadingDisplay = "display: none;";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
// include CSS
|
// include CSS
|
||||||
var content = $"<link rel=\"stylesheet\" href=\"{Constants.BootstrapStylesheetUrl}\" integrity=\"{Constants.BootstrapStylesheetIntegrity}\" crossorigin=\"anonymous\" type=\"text/css\"/>";
|
var content = $"<link rel=\"stylesheet\" href=\"{Constants.BootstrapStylesheetUrl}\" integrity=\"{Constants.BootstrapStylesheetIntegrity}\" crossorigin=\"anonymous\" type=\"text/css\"/>";
|
||||||
SiteState.AppendHeadContent(content);
|
SiteState.AppendHeadContent(content);
|
||||||
|
|
||||||
_togglePassword = SharedLocalizer["ShowPassword"];
|
_togglePassword = SharedLocalizer["ShowPassword"];
|
||||||
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
_databases = await DatabaseService.GetDatabasesAsync();
|
_databases = await DatabaseService.GetDatabasesAsync();
|
||||||
if (_databases.Exists(item => item.IsDefault))
|
if (_databases.Exists(item => item.IsDefault))
|
||||||
{
|
{
|
||||||
_databaseName = _databases.Find(item => item.IsDefault).Name;
|
_databaseName = _databases.Find(item => item.IsDefault).Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_databaseName = "LocalDB";
|
_databaseName = "LocalDB";
|
||||||
}
|
}
|
||||||
LoadDatabaseConfigComponent();
|
LoadDatabaseConfigComponent();
|
||||||
|
|
||||||
_templates = await SiteTemplateService.GetSiteTemplatesAsync();
|
_templates = await SiteTemplateService.GetSiteTemplatesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_databaseName = (string)eventArgs.Value;
|
_databaseName = (string)eventArgs.Value;
|
||||||
_showConnectionString = false;
|
_showConnectionString = false;
|
||||||
LoadDatabaseConfigComponent();
|
LoadDatabaseConfigComponent();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_message = Localizer["Error.DbConfig.Load"];
|
_message = Localizer["Error.DbConfig.Load"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadDatabaseConfigComponent()
|
private void LoadDatabaseConfigComponent()
|
||||||
{
|
{
|
||||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
if (database != null)
|
if (database != null)
|
||||||
{
|
{
|
||||||
_databaseConfigType = Type.GetType(database.ControlType);
|
_databaseConfigType = Type.GetType(database.ControlType);
|
||||||
DatabaseConfigComponent = builder =>
|
DatabaseConfigComponent = builder =>
|
||||||
{
|
{
|
||||||
builder.OpenComponent(0, _databaseConfigType);
|
builder.OpenComponent(0, _databaseConfigType);
|
||||||
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
// include JavaScript
|
// include JavaScript
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
await interop.IncludeScript("", Constants.BootstrapScriptUrl, Constants.BootstrapScriptIntegrity, "anonymous", "", "head");
|
await interop.IncludeScript("", Constants.BootstrapScriptUrl, Constants.BootstrapScriptIntegrity, "anonymous", "", "head");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Install()
|
private async Task Install()
|
||||||
{
|
{
|
||||||
var connectionString = String.Empty;
|
var connectionString = String.Empty;
|
||||||
if (_showConnectionString)
|
if (_showConnectionString)
|
||||||
{
|
{
|
||||||
connectionString = _connectionString;
|
connectionString = _connectionString;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
{
|
{
|
||||||
connectionString = databaseConfigControl.GetConnectionString();
|
connectionString = databaseConfigControl.GetConnectionString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
||||||
{
|
{
|
||||||
if (await UserService.ValidatePasswordAsync(_hostPassword))
|
var result = await UserService.ValidateUserAsync(_hostUsername, _hostEmail, _hostPassword);
|
||||||
{
|
if (result.Succeeded)
|
||||||
_loadingDisplay = "";
|
{
|
||||||
StateHasChanged();
|
_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
|
var config = new InstallConfig
|
||||||
{
|
{
|
||||||
DatabaseType = database.DBType,
|
DatabaseType = database.DBType,
|
||||||
ConnectionString = connectionString,
|
ConnectionString = connectionString,
|
||||||
Aliases = uri.Authority,
|
Aliases = uri.Authority,
|
||||||
HostUsername = _hostUsername,
|
HostUsername = _hostUsername,
|
||||||
HostPassword = _hostPassword,
|
HostPassword = _hostPassword,
|
||||||
HostEmail = _hostEmail,
|
HostEmail = _hostEmail,
|
||||||
HostName = _hostUsername,
|
HostName = _hostUsername,
|
||||||
TenantName = TenantNames.Master,
|
TenantName = TenantNames.Master,
|
||||||
IsNewTenant = true,
|
IsNewTenant = true,
|
||||||
SiteName = Constants.DefaultSite,
|
SiteName = Constants.DefaultSite,
|
||||||
Register = _register,
|
Register = _register,
|
||||||
SiteTemplate = _template,
|
SiteTemplate = _template,
|
||||||
RenderMode = RenderModes.Static,
|
RenderMode = RenderModes.Static,
|
||||||
Runtime = Runtimes.Server
|
Runtime = Runtimes.Server
|
||||||
};
|
};
|
||||||
|
|
||||||
var installation = await InstallationService.Install(config);
|
var installation = await InstallationService.Install(config);
|
||||||
if (installation.Success)
|
if (installation.Success)
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(uri.Scheme + "://" + uri.Authority, true);
|
NavigationManager.NavigateTo(uri.Scheme + "://" + uri.Authority, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = installation.Message;
|
_message = installation.Message;
|
||||||
_loadingDisplay = "display: none;";
|
_loadingDisplay = "display: none;";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.Password.Invalid"];
|
_message = string.Join("<br />", result.Errors.Select(i => !string.IsNullOrEmpty(i.Value) ? i.Value : Localizer[i.Key]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -183,4 +183,7 @@
|
|||||||
<data name="Template" xml:space="preserve">
|
<data name="Template" xml:space="preserve">
|
||||||
<value>Select a site template</value>
|
<value>Select a site template</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.Username.Invalid" xml:space="preserve">
|
||||||
|
<value>The Username Provided Does Not Meet The System Requirement, It Can Only Contains Letters Or Digits.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -113,6 +113,15 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<User> VerifyTwoFactorAsync(User user, string token);
|
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>
|
/// <summary>
|
||||||
/// Validate a users password against the password policy
|
/// Validate a users password against the password policy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -89,6 +89,11 @@ namespace Oqtane.Services
|
|||||||
return await PostJsonAsync<User>($"{Apiurl}/twofactor?token={token}", user);
|
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)
|
public async Task<bool> ValidatePasswordAsync(string password)
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<bool>($"{Apiurl}/validate/{WebUtility.UrlEncode(password)}");
|
return await GetJsonAsync<bool>($"{Apiurl}/validate/{WebUtility.UrlEncode(password)}");
|
||||||
|
@ -347,6 +347,13 @@ namespace Oqtane.Controllers
|
|||||||
return user;
|
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
|
// GET api/<controller>/validate/x
|
||||||
[HttpGet("validate/{password}")]
|
[HttpGet("validate/{password}")]
|
||||||
public async Task<bool> Validate(string password)
|
public async Task<bool> Validate(string password)
|
||||||
|
@ -19,6 +19,7 @@ namespace Oqtane.Managers
|
|||||||
Task<User> ResetPassword(User user, string token);
|
Task<User> ResetPassword(User user, string token);
|
||||||
User VerifyTwoFactor(User user, string token);
|
User VerifyTwoFactor(User user, string token);
|
||||||
Task<User> LinkExternalAccount(User user, string token, string type, string key, string name);
|
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<bool> ValidatePassword(string password);
|
||||||
Task<Dictionary<string, string>> ImportUsers(int siteId, string filePath, bool notify);
|
Task<Dictionary<string, string>> ImportUsers(int siteId, string filePath, bool notify);
|
||||||
}
|
}
|
||||||
|
@ -540,6 +540,30 @@ namespace Oqtane.Managers
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<UserValidateResult> ValidateUser(string username, string email, string password)
|
||||||
|
{
|
||||||
|
var validateResult = new UserValidateResult { Succeeded = true };
|
||||||
|
|
||||||
|
//validate username
|
||||||
|
var allowedChars = _identityUserManager.Options.User.AllowedUserNameCharacters;
|
||||||
|
if (string.IsNullOrWhiteSpace(username) || (!string.IsNullOrEmpty(allowedChars) && username.Any(c => !allowedChars.Contains(c))))
|
||||||
|
{
|
||||||
|
validateResult.Succeeded = false;
|
||||||
|
validateResult.Errors.Add("Message.Username.Invalid", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//validate password
|
||||||
|
var passwordValidator = new PasswordValidator<IdentityUser>();
|
||||||
|
var passwordResult = await passwordValidator.ValidateAsync(_identityUserManager, null, password);
|
||||||
|
if (!passwordResult.Succeeded)
|
||||||
|
{
|
||||||
|
validateResult.Succeeded = false;
|
||||||
|
validateResult.Errors.Add("Message.Password.Invalid", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validateResult;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> ValidatePassword(string password)
|
public async Task<bool> ValidatePassword(string password)
|
||||||
{
|
{
|
||||||
var validator = new PasswordValidator<IdentityUser>();
|
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…
x
Reference in New Issue
Block a user