Merge pull request #4756 from zyhfish/task/fix-4752

Fix #4752: validate the username and email.
This commit is contained in:
Shaun Walker 2024-10-24 09:53:24 -04:00 committed by GitHub
commit 6719d242bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 167 additions and 102 deletions

View File

@ -238,7 +238,8 @@
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 = ""; _loadingDisplay = "";
StateHasChanged(); StateHasChanged();
@ -278,7 +279,7 @@
} }
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

View File

@ -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>

View File

@ -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>

View File

@ -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)}");

View File

@ -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)

View File

@ -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);
} }

View File

@ -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>();

View 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>();
}
}