@@ -97,6 +103,7 @@
private string _maxlength = "0";
private string _defaultvalue = string.Empty;
private string _options = string.Empty;
+ private string _validation = string.Empty;
private string _isrequired = "False";
private string _isprivate = "False";
private string createdby;
@@ -126,6 +133,7 @@
_maxlength = profile.MaxLength.ToString();
_defaultvalue = profile.DefaultValue;
_options = profile.Options;
+ _validation = profile.Validation;
_isrequired = profile.IsRequired.ToString();
_isprivate = profile.IsPrivate.ToString();
createdby = profile.CreatedBy;
@@ -169,6 +177,7 @@
profile.MaxLength = int.Parse(_maxlength);
profile.DefaultValue = _defaultvalue;
profile.Options = _options;
+ profile.Validation = _validation;
profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired));
profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate));
if (_profileid != -1)
diff --git a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor
index 70aa3487..4c1c22b9 100644
--- a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor
+++ b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor
@@ -1,4 +1,5 @@
@namespace Oqtane.Modules.Admin.UserProfile
+@using System.Text.RegularExpressions;
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IUserService UserService
@@ -227,140 +228,143 @@ else
@code {
- private string username = string.Empty;
- private string _password = string.Empty;
- private string _passwordtype = "password";
- private string _togglepassword = string.Empty;
- private string confirm = string.Empty;
- private bool allowtwofactor = false;
- private string twofactor = "False";
- private string email = string.Empty;
- private string displayname = string.Empty;
- private FileManager filemanager;
- private int folderid = -1;
- private int photofileid = -1;
- private File photo = null;
- private List
profiles;
- private Dictionary settings;
- private string category = string.Empty;
- private string filter = "to";
- private List notifications;
+ private string username = string.Empty;
+ private string _password = string.Empty;
+ private string _passwordtype = "password";
+ private string _togglepassword = string.Empty;
+ private string confirm = string.Empty;
+ private bool allowtwofactor = false;
+ private string twofactor = "False";
+ private string email = string.Empty;
+ private string displayname = string.Empty;
+ private FileManager filemanager;
+ private int folderid = -1;
+ private int photofileid = -1;
+ private File photo = null;
+ private List profiles;
+ private Dictionary settings;
+ private string category = string.Empty;
+ private string filter = "to";
+ private List notifications;
- public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
+ public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
- protected override async Task OnParametersSetAsync()
- {
- try
- {
- _togglepassword = SharedLocalizer["ShowPassword"];
+ protected override async Task OnParametersSetAsync()
+ {
+ try
+ {
+ _togglepassword = SharedLocalizer["ShowPassword"];
- if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"]))
- {
- allowtwofactor = (PageState.Site.Settings["LoginOptions:TwoFactor"] == "true");
- }
+ if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"]))
+ {
+ allowtwofactor = (PageState.Site.Settings["LoginOptions:TwoFactor"] == "true");
+ }
- if (PageState.User != null)
- {
- username = PageState.User.Username;
- twofactor = PageState.User.TwoFactorRequired.ToString();
- email = PageState.User.Email;
- displayname = PageState.User.DisplayName;
+ if (PageState.User != null)
+ {
+ username = PageState.User.Username;
+ twofactor = PageState.User.TwoFactorRequired.ToString();
+ email = PageState.User.Email;
+ displayname = PageState.User.DisplayName;
- // get user folder
- var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
- if (folder != null)
- {
- folderid = folder.FolderId;
- }
+ // get user folder
+ var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
+ if (folder != null)
+ {
+ folderid = folder.FolderId;
+ }
- if (PageState.User.PhotoFileId != null)
- {
- photofileid = PageState.User.PhotoFileId.Value;
- photo = await FileService.GetFileAsync(photofileid);
- }
- else
- {
- photofileid = -1;
- photo = null;
- }
+ if (PageState.User.PhotoFileId != null)
+ {
+ photofileid = PageState.User.PhotoFileId.Value;
+ photo = await FileService.GetFileAsync(photofileid);
+ }
+ else
+ {
+ photofileid = -1;
+ photo = null;
+ }
- profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
- settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
+ profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
+ settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
- await LoadNotificationsAsync();
- }
- else
- {
- AddModuleMessage(Localizer["Message.User.NoLogIn"], MessageType.Warning);
- }
- }
- catch (Exception ex)
- {
- await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
- AddModuleMessage(Localizer["Error.Profile.Load"], MessageType.Error);
- }
- }
+ await LoadNotificationsAsync();
+ }
+ else
+ {
+ AddModuleMessage(Localizer["Message.User.NoLogIn"], MessageType.Warning);
+ }
+ }
+ catch (Exception ex)
+ {
+ await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
+ AddModuleMessage(Localizer["Error.Profile.Load"], MessageType.Error);
+ }
+ }
- private async Task LoadNotificationsAsync()
- {
- notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, filter, PageState.User.UserId);
- notifications = notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
- }
+ private async Task LoadNotificationsAsync()
+ {
+ notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, filter, PageState.User.UserId);
+ notifications = notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
+ }
- private string GetProfileValue(string SettingName, string DefaultValue)
- {
- string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
- if (value.Contains("]"))
- {
- value = value.Substring(value.IndexOf("]") + 1);
- }
- return value;
- }
+ private string GetProfileValue(string SettingName, string DefaultValue)
+ {
+ string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
+ if (value.Contains("]"))
+ {
+ value = value.Substring(value.IndexOf("]") + 1);
+ }
+ return value;
+ }
- private async Task Save()
- {
- try
- {
- if (username != string.Empty && email != string.Empty && ValidateProfiles())
- {
- if (_password == confirm)
- {
- var user = PageState.User;
- user.Username = username;
- user.Password = _password;
- user.TwoFactorRequired = bool.Parse(twofactor);
- user.Email = email;
- user.DisplayName = (displayname == string.Empty ? username : displayname);
- user.PhotoFileId = filemanager.GetFileId();
- if (user.PhotoFileId == -1)
- {
- user.PhotoFileId = null;
- }
- if (user.PhotoFileId != null)
- {
- photofileid = user.PhotoFileId.Value;
- photo = await FileService.GetFileAsync(photofileid);
- }
- else
- {
- photofileid = -1;
- photo = null;
- }
+ private async Task Save()
+ {
+ try
+ {
+ if (username != string.Empty && email != string.Empty && ValidateProfiles())
+ {
+ if (_password == confirm)
+ {
+ var user = PageState.User;
+ user.Username = username;
+ user.Password = _password;
+ user.TwoFactorRequired = bool.Parse(twofactor);
+ user.Email = email;
+ user.DisplayName = (displayname == string.Empty ? username : displayname);
+ user.PhotoFileId = filemanager.GetFileId();
+ if (user.PhotoFileId == -1)
+ {
+ user.PhotoFileId = null;
+ }
+ if (user.PhotoFileId != null)
+ {
+ photofileid = user.PhotoFileId.Value;
+ photo = await FileService.GetFileAsync(photofileid);
+ }
+ else
+ {
+ photofileid = -1;
+ photo = null;
+ }
- user = await UserService.UpdateUserAsync(user);
- if (user != null)
- {
- await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
- await logger.LogInformation("User Profile Saved");
+ user = await UserService.UpdateUserAsync(user);
+ if (user != null)
+ {
+ await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
+ await logger.LogInformation("User Profile Saved");
- AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success);
- StateHasChanged();
- }
- else
- {
- AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
- }
- }
+ AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success);
+ StateHasChanged();
+
+ var interop = new Interop(JSRuntime);
+ await interop.ScrollTo(0, 0, "smooth");
+ }
+ else
+ {
+ AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
+ }
+ }
else
{
AddModuleMessage(Localizer["Message.Password.Invalid"], MessageType.Warning);
@@ -389,10 +393,15 @@ else
}
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{
- if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
+ if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
{
valid = false;
}
+ if (valid == true && !string.IsNullOrEmpty(profile.Validation))
+ {
+ Regex regex = new Regex(profile.Validation);
+ valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success;
+ }
}
}
return valid;
diff --git a/Oqtane.Client/Modules/Admin/Users/Add.razor b/Oqtane.Client/Modules/Admin/Users/Add.razor
index 713dab6e..54c396ee 100644
--- a/Oqtane.Client/Modules/Admin/Users/Add.razor
+++ b/Oqtane.Client/Modules/Admin/Users/Add.razor
@@ -1,4 +1,5 @@
@namespace Oqtane.Modules.Admin.Users
+@using System.Text.RegularExpressions;
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IUserService UserService
@@ -95,8 +96,8 @@
@code {
private string username = string.Empty;
private string _password = string.Empty;
- private string _passwordtype = "password";
- private string _togglepassword = string.Empty;
+ private string _passwordtype = "password";
+ private string _togglepassword = string.Empty;
private string confirm = string.Empty;
private string email = string.Empty;
private string displayname = string.Empty;
@@ -121,15 +122,15 @@
}
}
- private string GetProfileValue(string SettingName, string DefaultValue)
- {
- string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
- if (value.Contains("]"))
- {
- value = value.Substring(value.IndexOf("]") + 1);
- }
- return value;
- }
+ private string GetProfileValue(string SettingName, string DefaultValue)
+ {
+ string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
+ if (value.Contains("]"))
+ {
+ value = value.Substring(value.IndexOf("]") + 1);
+ }
+ return value;
+ }
private async Task SaveUser()
{
@@ -195,9 +196,17 @@
{
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
}
- if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
+ if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{
- valid = false;
+ if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
+ {
+ valid = false;
+ }
+ if (valid == true && !string.IsNullOrEmpty(profile.Validation))
+ {
+ Regex regex = new Regex(profile.Validation);
+ valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success;
+ }
}
}
return valid;
diff --git a/Oqtane.Client/Modules/Admin/Users/Edit.razor b/Oqtane.Client/Modules/Admin/Users/Edit.razor
index af541617..fea1a6f0 100644
--- a/Oqtane.Client/Modules/Admin/Users/Edit.razor
+++ b/Oqtane.Client/Modules/Admin/Users/Edit.razor
@@ -1,4 +1,5 @@
@namespace Oqtane.Modules.Admin.Users
+@using System.Text.RegularExpressions;
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IUserService UserService
@@ -148,124 +149,124 @@ else
@code {
- private int userid;
- private string username = string.Empty;
- private string _password = string.Empty;
- private string _passwordtype = "password";
- private string _togglepassword = string.Empty;
- private string confirm = string.Empty;
- private string email = string.Empty;
- private string displayname = string.Empty;
- private FileManager filemanager;
- private int photofileid = -1;
- private File photo = null;
- private string isdeleted;
- private string lastlogin;
- private string lastipaddress;
+ private int userid;
+ private string username = string.Empty;
+ private string _password = string.Empty;
+ private string _passwordtype = "password";
+ private string _togglepassword = string.Empty;
+ private string confirm = string.Empty;
+ private string email = string.Empty;
+ private string displayname = string.Empty;
+ private FileManager filemanager;
+ private int photofileid = -1;
+ private File photo = null;
+ private string isdeleted;
+ private string lastlogin;
+ private string lastipaddress;
- private List profiles;
- private Dictionary settings;
- private string category = string.Empty;
+ private List profiles;
+ private Dictionary settings;
+ private string category = string.Empty;
- private string createdby;
- private DateTime createdon;
- private string modifiedby;
- private DateTime modifiedon;
- private string deletedby;
- private DateTime? deletedon;
+ private string createdby;
+ private DateTime createdon;
+ private string modifiedby;
+ private DateTime modifiedon;
+ private string deletedby;
+ private DateTime? deletedon;
- public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
+ public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
- protected override async Task OnParametersSetAsync()
- {
- try
- {
- if (PageState.QueryString.ContainsKey("id"))
- {
- _togglepassword = SharedLocalizer["ShowPassword"];
- profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
- userid = Int32.Parse(PageState.QueryString["id"]);
- var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
- if (user != null)
- {
- username = user.Username;
- email = user.Email;
- displayname = user.DisplayName;
- if (user.PhotoFileId != null)
- {
- photofileid = user.PhotoFileId.Value;
- photo = await FileService.GetFileAsync(photofileid);
- }
- else
- {
- photofileid = -1;
- photo = null;
- }
- isdeleted = user.IsDeleted.ToString();
- lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", user.LastLoginOn);
- lastipaddress = user.LastIPAddress;
+ protected override async Task OnParametersSetAsync()
+ {
+ try
+ {
+ if (PageState.QueryString.ContainsKey("id"))
+ {
+ _togglepassword = SharedLocalizer["ShowPassword"];
+ profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
+ userid = Int32.Parse(PageState.QueryString["id"]);
+ var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
+ if (user != null)
+ {
+ username = user.Username;
+ email = user.Email;
+ displayname = user.DisplayName;
+ if (user.PhotoFileId != null)
+ {
+ photofileid = user.PhotoFileId.Value;
+ photo = await FileService.GetFileAsync(photofileid);
+ }
+ else
+ {
+ photofileid = -1;
+ photo = null;
+ }
+ isdeleted = user.IsDeleted.ToString();
+ lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", user.LastLoginOn);
+ lastipaddress = user.LastIPAddress;
- settings = await SettingService.GetUserSettingsAsync(user.UserId);
- createdby = user.CreatedBy;
- createdon = user.CreatedOn;
- modifiedby = user.ModifiedBy;
- modifiedon = user.ModifiedOn;
- deletedby = user.DeletedBy;
- deletedon = user.DeletedOn;
- }
- }
- }
- catch (Exception ex)
- {
- await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
- AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error);
- }
- }
+ settings = await SettingService.GetUserSettingsAsync(user.UserId);
+ createdby = user.CreatedBy;
+ createdon = user.CreatedOn;
+ modifiedby = user.ModifiedBy;
+ modifiedon = user.ModifiedOn;
+ deletedby = user.DeletedBy;
+ deletedon = user.DeletedOn;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
+ AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error);
+ }
+ }
- private string GetProfileValue(string SettingName, string DefaultValue)
- {
- string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
- if (value.Contains("]"))
- {
- value = value.Substring(value.IndexOf("]") + 1);
- }
- return value;
- }
+ private string GetProfileValue(string SettingName, string DefaultValue)
+ {
+ string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
+ if (value.Contains("]"))
+ {
+ value = value.Substring(value.IndexOf("]") + 1);
+ }
+ return value;
+ }
- private async Task SaveUser()
- {
- try
- {
- if (username != string.Empty && email != string.Empty && ValidateProfiles())
- {
- if (_password == confirm)
- {
- var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
- user.SiteId = PageState.Site.SiteId;
- user.Username = username;
- user.Password = _password;
- user.Email = email;
- user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
- user.PhotoFileId = null;
- user.PhotoFileId = filemanager.GetFileId();
- if (user.PhotoFileId == -1)
- {
- user.PhotoFileId = null;
- }
+ private async Task SaveUser()
+ {
+ try
+ {
+ if (username != string.Empty && email != string.Empty && ValidateProfiles())
+ {
+ if (_password == confirm)
+ {
+ var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
+ user.SiteId = PageState.Site.SiteId;
+ user.Username = username;
+ user.Password = _password;
+ user.Email = email;
+ user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
+ user.PhotoFileId = null;
+ user.PhotoFileId = filemanager.GetFileId();
+ if (user.PhotoFileId == -1)
+ {
+ user.PhotoFileId = null;
+ }
- user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
+ user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
- user = await UserService.UpdateUserAsync(user);
- if (user != null)
- {
- await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
- await logger.LogInformation("User Saved {User}", user);
- NavigationManager.NavigateTo(NavigateUrl());
- }
- else
- {
- AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
- }
+ user = await UserService.UpdateUserAsync(user);
+ if (user != null)
+ {
+ await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
+ await logger.LogInformation("User Saved {User}", user);
+ NavigationManager.NavigateTo(NavigateUrl());
+ }
+ else
+ {
+ AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
+ }
}
else
{
@@ -293,9 +294,17 @@ else
{
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
}
- if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
+ if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{
- valid = false;
+ if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
+ {
+ valid = false;
+ }
+ if (valid == true && !string.IsNullOrEmpty(profile.Validation))
+ {
+ Regex regex = new Regex(profile.Validation);
+ valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success;
+ }
}
}
return valid;
diff --git a/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx b/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx
index 720e34f9..8a3a23ca 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx
@@ -183,4 +183,10 @@
Private?
+
+ Optionally provide a regular expression (RegExp) for validating the value entered
+
+
+ Validation:
+
\ No newline at end of file
diff --git a/Oqtane.Server/Migrations/Tenant/04000003_AddProfileValidation.cs b/Oqtane.Server/Migrations/Tenant/04000003_AddProfileValidation.cs
new file mode 100644
index 00000000..c2f46cb5
--- /dev/null
+++ b/Oqtane.Server/Migrations/Tenant/04000003_AddProfileValidation.cs
@@ -0,0 +1,29 @@
+using Microsoft.AspNetCore.Components.Web;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Oqtane.Databases.Interfaces;
+using Oqtane.Migrations.EntityBuilders;
+using Oqtane.Repository;
+
+namespace Oqtane.Migrations.Tenant
+{
+ [DbContext(typeof(TenantDBContext))]
+ [Migration("Tenant.04.00.00.03")]
+ public class AddProfileValidation : MultiDatabaseMigration
+ {
+ public AddProfileValidation(IDatabase database) : base(database)
+ {
+ }
+
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
+ profileEntityBuilder.AddStringColumn("Validation", 200, true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ // not implemented
+ }
+ }
+}
diff --git a/Oqtane.Shared/Models/Profile.cs b/Oqtane.Shared/Models/Profile.cs
index 00c4ea88..e5586a13 100644
--- a/Oqtane.Shared/Models/Profile.cs
+++ b/Oqtane.Shared/Models/Profile.cs
@@ -68,5 +68,10 @@ namespace Oqtane.Models
/// This gives possible values for dropdown input fields.
///
public string Options { get; set; }
+
+ ///
+ /// Optional RegExp validation expression
+ ///
+ public string Validation { get; set; }
}
}