diff --git a/Oqtane.Client/Modules/Admin/Register/Index.razor b/Oqtane.Client/Modules/Admin/Register/Index.razor index d8a6dc60..2cf45dc9 100644 --- a/Oqtane.Client/Modules/Admin/Register/Index.razor +++ b/Oqtane.Client/Modules/Admin/Register/Index.razor @@ -16,7 +16,7 @@ - +
@@ -69,6 +69,7 @@ else } @code { + private string _passwordrequirements; private string _username = string.Empty; private ElementReference form; private bool validated = false; @@ -79,44 +80,16 @@ else private string _email = string.Empty; private string _displayname = string.Empty; - //Password construction - private string _minimumlength; - private string _uniquecharacters; - private bool _requiredigit; - private bool _requireupper; - private bool _requirelower; - private bool _requirepunctuation; - private string _passwordconstruction; - public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous; protected override async Task OnInitializedAsync() { - var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); - - _minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6"); - _uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1"); - _requiredigit = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireDigit", "true")); - _requireupper = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireUppercase", "true")); - _requirelower = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireLowercase", "true")); - _requirepunctuation = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", "true")); - - // Replace the placeholders with the actual values of the variables - string digitRequirement = _requiredigit ? Localizer["Password.DigitRequirement"] + ", " : ""; - string uppercaseRequirement = _requireupper ? Localizer["Password.UppercaseRequirement"] + ", " : ""; - string lowercaseRequirement = _requirelower ? Localizer["Password.LowercaseRequirement"] + ", " : ""; - string punctuationRequirement = _requirepunctuation ? Localizer["Password.PunctuationRequirement"] + ", " : ""; - - // Replace the placeholders with the actual values of the variables - string passwordValidationCriteriaTemplate = Localizer["Password.ValidationCriteria"]; - _passwordconstruction = Localizer["Info.Registration.InvalidEmail"] + ". " + string.Format(passwordValidationCriteriaTemplate, - _minimumlength, _uniquecharacters, digitRequirement, uppercaseRequirement, lowercaseRequirement, punctuationRequirement); + _passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId); } protected override void OnParametersSet() { - _togglepassword = SharedLocalizer["ShowPassword"]; - + _togglepassword = SharedLocalizer["ShowPassword"]; } private async Task Register() diff --git a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor index 2dd1303d..b763b08b 100644 --- a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor +++ b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor @@ -23,6 +23,7 @@ else @if (profiles != null && settings != null) { +
@@ -267,6 +268,7 @@ else

@code { + private string _passwordrequirements; private string username = string.Empty; private string _password = string.Empty; private string _passwordtype = "password"; @@ -293,6 +295,8 @@ else { try { + _passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId); + _togglepassword = SharedLocalizer["ShowPassword"]; if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"])) diff --git a/Oqtane.Client/Modules/Admin/Users/Add.razor b/Oqtane.Client/Modules/Admin/Users/Add.razor index f36e78b0..b1c34d4f 100644 --- a/Oqtane.Client/Modules/Admin/Users/Add.razor +++ b/Oqtane.Client/Modules/Admin/Users/Add.razor @@ -12,6 +12,7 @@ @if (profiles != null) { +
@@ -94,6 +95,7 @@ @SharedLocalizer["Cancel"] @code { + private string _passwordrequirements; private string username = string.Empty; private string _password = string.Empty; private string _passwordtype = "password"; @@ -111,6 +113,7 @@ { try { + _passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId); _togglepassword = SharedLocalizer["ShowPassword"]; profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId); settings = new Dictionary(); diff --git a/Oqtane.Client/Modules/Admin/Users/Edit.razor b/Oqtane.Client/Modules/Admin/Users/Edit.razor index fea1a6f0..19fbbdd1 100644 --- a/Oqtane.Client/Modules/Admin/Users/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Users/Edit.razor @@ -21,6 +21,7 @@ else @if (profiles != null) { +
@@ -149,6 +150,7 @@ else @code { + private string _passwordrequirements; private int userid; private string username = string.Empty; private string _password = string.Empty; @@ -183,6 +185,7 @@ else { if (PageState.QueryString.ContainsKey("id")) { + _passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId); _togglepassword = SharedLocalizer["ShowPassword"]; profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId); userid = Int32.Parse(PageState.QueryString["id"]); diff --git a/Oqtane.Client/Resources/Modules/Admin/Register/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Register/Index.resx index bcac3528..9b06fc94 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Register/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Register/Index.resx @@ -177,19 +177,4 @@ Username: - - Passwords Must Have A Minimum Length Of {0} Characters, Including At Least {1} Unique Character(s), {2}{3}{4}{5} To Satisfy Password Compexity Requirements For This Site. - - - At Least One Digit - - - At Least One Lowercase Letter - - - At Least One Punctuation Mark - - - At Least One Uppercase Letter - \ No newline at end of file diff --git a/Oqtane.Client/Services/Interfaces/IUserService.cs b/Oqtane.Client/Services/Interfaces/IUserService.cs index 1a5323e9..01dfa022 100644 --- a/Oqtane.Client/Services/Interfaces/IUserService.cs +++ b/Oqtane.Client/Services/Interfaces/IUserService.cs @@ -135,6 +135,11 @@ namespace Oqtane.Services /// Task LinkUserAsync(User user, string token, string type, string key, string name); - + /// + /// Get password requirements for site + /// + /// ID of a + /// + Task GetPasswordRequirementsAsync(int siteId); } } diff --git a/Oqtane.Client/Services/UserService.cs b/Oqtane.Client/Services/UserService.cs index b74f6e50..8e0e9f94 100644 --- a/Oqtane.Client/Services/UserService.cs +++ b/Oqtane.Client/Services/UserService.cs @@ -96,5 +96,9 @@ namespace Oqtane.Services return await PostJsonAsync($"{Apiurl}/link?token={token}&type={type}&key={key}&name={name}", user); } + public async Task GetPasswordRequirementsAsync(int siteId) + { + return await GetStringAsync($"{Apiurl}/passwordrequirements/{siteId}"); + } } } diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs index b2de0340..7e17e035 100644 --- a/Oqtane.Server/Controllers/UserController.cs +++ b/Oqtane.Server/Controllers/UserController.cs @@ -14,6 +14,10 @@ using Oqtane.Repository; using Oqtane.Security; using Oqtane.Extensions; using Oqtane.Managers; +using Oqtane.Services; +using static System.Runtime.InteropServices.JavaScript.JSType; +using Microsoft.Extensions.Localization; +using Oqtane.Modules.Admin.Roles; namespace Oqtane.Controllers { @@ -27,8 +31,9 @@ namespace Oqtane.Controllers private readonly IUserPermissions _userPermissions; private readonly IJwtManager _jwtManager; private readonly ILogManager _logger; + private readonly IStringLocalizer _localizer; - public UserController(IUserRepository users, ITenantManager tenantManager, IUserManager userManager, ISiteRepository sites, IUserPermissions userPermissions, IJwtManager jwtManager, ILogManager logger) + public UserController(IUserRepository users, ITenantManager tenantManager, IUserManager userManager, ISiteRepository sites, IUserPermissions userPermissions, IJwtManager jwtManager, ILogManager logger, IStringLocalizer localizer) { _users = users; _tenantManager = tenantManager; @@ -37,6 +42,7 @@ namespace Oqtane.Controllers _userPermissions = userPermissions; _jwtManager = jwtManager; _logger = logger; + _localizer = localizer; } // GET api//5?siteid=x @@ -336,5 +342,37 @@ namespace Oqtane.Controllers } return user; } + + // GET api//passwordrequirements/5 + [HttpGet("passwordrequirements/{siteid}")] + public string PasswordRequirements(int siteid) + { + var requirements = ""; + + var site = _sites.GetSite(siteid); + if (site != null && (site.AllowRegistration || User.IsInRole(RoleNames.Registered))) + { + // get settings + var sitesettings = HttpContext.GetSiteSettings(); + var minimumlength = sitesettings.GetValue("IdentityOptions:Password:RequiredLength", "6"); + var uniquecharacters = sitesettings.GetValue("IdentityOptions:Password:RequiredUniqueChars", "1"); + var requiredigit = bool.Parse(sitesettings.GetValue("IdentityOptions:Password:RequireDigit", "true")); + var requireupper = bool.Parse(sitesettings.GetValue("IdentityOptions:Password:RequireUppercase", "true")); + var requirelower = bool.Parse(sitesettings.GetValue("IdentityOptions:Password:RequireLowercase", "true")); + var requirepunctuation = bool.Parse(sitesettings.GetValue("IdentityOptions:Password:RequireNonAlphanumeric", "true")); + + // replace the placeholders with the setting values + string digitRequirement = requiredigit ? _localizer["Password.DigitRequirement"] + ", " : ""; + string uppercaseRequirement = requireupper ? _localizer["Password.UppercaseRequirement"] + ", " : ""; + string lowercaseRequirement = requirelower ? _localizer["Password.LowercaseRequirement"] + ", " : ""; + string punctuationRequirement = requirepunctuation ? _localizer["Password.PunctuationRequirement"] + ", " : ""; + string passwordValidationCriteriaTemplate = _localizer["Password.ValidationCriteria"]; + + // format requirements + requirements = string.Format(passwordValidationCriteriaTemplate, minimumlength, uniquecharacters, digitRequirement, uppercaseRequirement, lowercaseRequirement, punctuationRequirement); + } + + return requirements; + } } } diff --git a/Oqtane.Server/Resources/Controllers/UserController.resx b/Oqtane.Server/Resources/Controllers/UserController.resx new file mode 100644 index 00000000..49c8338e --- /dev/null +++ b/Oqtane.Server/Resources/Controllers/UserController.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + At Least One Digit + + + At Least One Lowercase Letter + + + At Least One Punctuation Mark + + + At Least One Uppercase Letter + + + Passwords Must Have A Minimum Length Of {0} Characters, Including At Least {1} Unique Character(s), {2}{3}{4}{5} To Satisfy Password Compexity Requirements For This Site. + + \ No newline at end of file