diff --git a/Oqtane.Client/Modules/Admin/Themes/Index.razor b/Oqtane.Client/Modules/Admin/Themes/Index.razor
index 198889fe..753451cc 100644
--- a/Oqtane.Client/Modules/Admin/Themes/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Themes/Index.razor
@@ -29,7 +29,7 @@ else
-
+
@if (context.AssemblyName != Constants.ClientId)
{
@@ -79,7 +79,8 @@ else
try
{
_themes = await ThemeService.GetThemesAsync();
- _packages = await PackageService.GetPackagesAsync("theme");
+ var list = _themes.Where(item => !string.IsNullOrEmpty(item.PackageName)).Select(item => item.PackageName).Distinct().ToList();
+ _packages = await PackageService.GetPackagesAsync(list);
}
catch (Exception ex)
{
@@ -100,11 +101,14 @@ else
if (package != null)
{
if (package.ExpiryDate != null && package.ExpiryDate.Value.Date != DateTime.MaxValue.Date)
- {
- link += "" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + " ";
- if (!string.IsNullOrEmpty(package.PaymentUrl))
+ {
+ if (string.IsNullOrEmpty(package.PaymentUrl))
{
- link += " " + SharedLocalizer["Extend"] + " ";
+ link = "" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + " ";
+ }
+ else
+ {
+ link = "" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + " ";
}
}
}
diff --git a/Oqtane.Client/Modules/Admin/UserProfile/Add.razor b/Oqtane.Client/Modules/Admin/UserProfile/Add.razor
index fb3c8209..ceeb2713 100644
--- a/Oqtane.Client/Modules/Admin/UserProfile/Add.razor
+++ b/Oqtane.Client/Modules/Admin/UserProfile/Add.razor
@@ -42,12 +42,6 @@
public override string Title => "Send Notification";
- protected override void OnParametersSet()
- {
- base.OnParametersSet();
- base.SetModuleTitle(Localizer["ModuleTitle.Text"]);
- }
-
private async Task Send()
{
try
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/UserProfile/View.razor b/Oqtane.Client/Modules/Admin/UserProfile/View.razor
index 719b8813..58a3d211 100644
--- a/Oqtane.Client/Modules/Admin/UserProfile/View.razor
+++ b/Oqtane.Client/Modules/Admin/UserProfile/View.razor
@@ -110,11 +110,6 @@
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
public override string Title => "View Notification";
- protected override void OnParametersSet()
- {
- base.OnParametersSet();
- base.SetModuleTitle(Localizer["ModuleTitle.Text"]);
- }
protected override async Task OnInitializedAsync()
{
try
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/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor
index dac92dbe..6957e3e6 100644
--- a/Oqtane.Client/Modules/Admin/Users/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Users/Index.razor
@@ -35,9 +35,9 @@ else
-
SortTable("Username"))">@Localizer["Username"]
-
SortTable("DisplayName"))">@Localizer["Name"]
-
SortTable("LastLoginOn"))">@Localizer["LastLoginOn"]
+
SortTable("Username"))">@Localizer["Username"]
+
SortTable("DisplayName"))">@Localizer["Name"]
+
SortTable("LastLoginOn"))">@Localizer["LastLoginOn"]
@@ -365,124 +365,124 @@ else
}
@code {
- private List allusers;
- private List users;
- private string _search = "";
+ private List allusers;
+ private List users;
+ private string _search = "";
- private string _allowregistration;
- private string _allowsitelogin;
- private string _twofactor;
- private string _cookiename;
+ private string _allowregistration;
+ private string _allowsitelogin;
+ private string _twofactor;
+ private string _cookiename;
- private string _minimumlength;
- private string _uniquecharacters;
- private string _requiredigit;
- private string _requireupper;
- private string _requirelower;
- private string _requirepunctuation;
- private string _maximumfailures;
- private string _lockoutduration;
+ private string _minimumlength;
+ private string _uniquecharacters;
+ private string _requiredigit;
+ private string _requireupper;
+ private string _requirelower;
+ private string _requirepunctuation;
+ private string _maximumfailures;
+ private string _lockoutduration;
- private string _providertype;
- private string _providername;
- private string _authority;
- private string _metadataurl;
- private string _authorizationurl;
- private string _tokenurl;
- private string _userinfourl;
- private string _clientid;
- private string _clientsecret;
- private string _clientsecrettype = "password";
- private string _toggleclientsecret = string.Empty;
- private string _scopes;
- private string _parameters;
- private string _pkce;
- private string _redirecturl;
- private string _identifierclaimtype;
- private string _emailclaimtype;
- private string _roleclaimtype;
- private string _profileclaimtypes;
- private string _domainfilter;
- private string _createusers;
+ private string _providertype;
+ private string _providername;
+ private string _authority;
+ private string _metadataurl;
+ private string _authorizationurl;
+ private string _tokenurl;
+ private string _userinfourl;
+ private string _clientid;
+ private string _clientsecret;
+ private string _clientsecrettype = "password";
+ private string _toggleclientsecret = string.Empty;
+ private string _scopes;
+ private string _parameters;
+ private string _pkce;
+ private string _redirecturl;
+ private string _identifierclaimtype;
+ private string _emailclaimtype;
+ private string _roleclaimtype;
+ private string _profileclaimtypes;
+ private string _domainfilter;
+ private string _createusers;
- private string _secret;
- private string _secrettype = "password";
- private string _togglesecret = string.Empty;
- private string _issuer;
- private string _audience;
- private string _lifetime;
- private string _token;
+ private string _secret;
+ private string _secrettype = "password";
+ private string _togglesecret = string.Empty;
+ private string _issuer;
+ private string _audience;
+ private string _lifetime;
+ private string _token;
private bool isSortedAscending;
private string activeSortColumn;
- public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
+ public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
- protected override async Task OnInitializedAsync()
- {
- await LoadUserSettingsAsync();
- await LoadUsersAsync(true);
+ protected override async Task OnInitializedAsync()
+ {
+ await LoadUserSettingsAsync();
+ await LoadUsersAsync(true);
- var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
- _allowregistration = PageState.Site.AllowRegistration.ToString();
- _allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true");
+ var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
+ _allowregistration = PageState.Site.AllowRegistration.ToString();
+ _allowsitelogin = SettingService.GetSetting(settings, "LoginOptions:AllowSiteLogin", "true");
- if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
- {
- _twofactor = SettingService.GetSetting(settings, "LoginOptions:TwoFactor", "false");
- _cookiename = SettingService.GetSetting(settings, "LoginOptions:CookieName", ".AspNetCore.Identity.Application");
+ if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
+ {
+ _twofactor = SettingService.GetSetting(settings, "LoginOptions:TwoFactor", "false");
+ _cookiename = SettingService.GetSetting(settings, "LoginOptions:CookieName", ".AspNetCore.Identity.Application");
- _minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6");
- _uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1");
- _requiredigit = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireDigit", "true");
- _requireupper = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireUppercase", "true");
- _requirelower = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireLowercase", "true");
- _requirepunctuation = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", "true");
+ _minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6");
+ _uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1");
+ _requiredigit = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireDigit", "true");
+ _requireupper = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireUppercase", "true");
+ _requirelower = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireLowercase", "true");
+ _requirepunctuation = SettingService.GetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", "true");
- _maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5");
- _lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString();
+ _maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5");
+ _lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString();
- _providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", "");
- _providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", "");
- _authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", "");
- _metadataurl = SettingService.GetSetting(settings, "ExternalLogin:MetadataUrl", "");
- _authorizationurl = SettingService.GetSetting(settings, "ExternalLogin:AuthorizationUrl", "");
- _tokenurl = SettingService.GetSetting(settings, "ExternalLogin:TokenUrl", "");
- _userinfourl = SettingService.GetSetting(settings, "ExternalLogin:UserInfoUrl", "");
- _clientid = SettingService.GetSetting(settings, "ExternalLogin:ClientId", "");
- _clientsecret = SettingService.GetSetting(settings, "ExternalLogin:ClientSecret", "");
- _toggleclientsecret = SharedLocalizer["ShowPassword"];
- _scopes = SettingService.GetSetting(settings, "ExternalLogin:Scopes", "");
- _parameters = SettingService.GetSetting(settings, "ExternalLogin:Parameters", "");
- _pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
- _redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
- _identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "sub");
- _emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "email");
- _roleclaimtype = SettingService.GetSetting(settings, "ExternalLogin:RoleClaimType", "");
- _profileclaimtypes = SettingService.GetSetting(settings, "ExternalLogin:ProfileClaimTypes", "");
- _domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
- _createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
+ _providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", "");
+ _providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", "");
+ _authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", "");
+ _metadataurl = SettingService.GetSetting(settings, "ExternalLogin:MetadataUrl", "");
+ _authorizationurl = SettingService.GetSetting(settings, "ExternalLogin:AuthorizationUrl", "");
+ _tokenurl = SettingService.GetSetting(settings, "ExternalLogin:TokenUrl", "");
+ _userinfourl = SettingService.GetSetting(settings, "ExternalLogin:UserInfoUrl", "");
+ _clientid = SettingService.GetSetting(settings, "ExternalLogin:ClientId", "");
+ _clientsecret = SettingService.GetSetting(settings, "ExternalLogin:ClientSecret", "");
+ _toggleclientsecret = SharedLocalizer["ShowPassword"];
+ _scopes = SettingService.GetSetting(settings, "ExternalLogin:Scopes", "");
+ _parameters = SettingService.GetSetting(settings, "ExternalLogin:Parameters", "");
+ _pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
+ _redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
+ _identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "sub");
+ _emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "email");
+ _roleclaimtype = SettingService.GetSetting(settings, "ExternalLogin:RoleClaimType", "");
+ _profileclaimtypes = SettingService.GetSetting(settings, "ExternalLogin:ProfileClaimTypes", "");
+ _domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
+ _createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
- _secret = SettingService.GetSetting(settings, "JwtOptions:Secret", "");
- _togglesecret = SharedLocalizer["ShowPassword"];
- _issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
- _audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
- _lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20");
- }
- }
+ _secret = SettingService.GetSetting(settings, "JwtOptions:Secret", "");
+ _togglesecret = SharedLocalizer["ShowPassword"];
+ _issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
+ _audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
+ _lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20");
+ }
+ }
- private async Task LoadUsersAsync(bool load)
- {
- if (load)
- {
- allusers = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
- if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
- {
- var hosts = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Host);
- allusers.AddRange(hosts);
- allusers = allusers.OrderBy(u => u.User.DisplayName).ToList();
- }
- }
+ private async Task LoadUsersAsync(bool load)
+ {
+ if (load)
+ {
+ allusers = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
+ if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
+ {
+ var hosts = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Host);
+ allusers.AddRange(hosts);
+ allusers = allusers.OrderBy(u => u.User.DisplayName).ToList();
+ }
+ }
users = allusers;
if (!string.IsNullOrEmpty(_search))
diff --git a/Oqtane.Client/Modules/Controls/ActionDialog.razor b/Oqtane.Client/Modules/Controls/ActionDialog.razor
index aeda66ba..9cb5fd7f 100644
--- a/Oqtane.Client/Modules/Controls/ActionDialog.razor
+++ b/Oqtane.Client/Modules/Controls/ActionDialog.razor
@@ -1,6 +1,7 @@
@namespace Oqtane.Modules.Controls
@using System.Text.Json
@inherits LocalizableComponent
+@inject IStringLocalizer SharedLocalizer
@if (_visible)
{
@@ -20,7 +21,7 @@
{
@((MarkupString)_iconSpan) @Text
}
- @Localize("Cancel")
+ @SharedLocalizer["Cancel"]
diff --git a/Oqtane.Client/Modules/Controls/AuditInfo.razor b/Oqtane.Client/Modules/Controls/AuditInfo.razor
index d36e7f9a..acbb3dc6 100644
--- a/Oqtane.Client/Modules/Controls/AuditInfo.razor
+++ b/Oqtane.Client/Modules/Controls/AuditInfo.razor
@@ -64,12 +64,12 @@
if (!String.IsNullOrEmpty(ModifiedBy))
{
- _text += $" {Localizer["by"]} {ModifiedBy} ";
+ _text += $" {Localizer["By"]} {ModifiedBy} ";
}
if (ModifiedOn != null)
{
- _text += $" {Localizer["on"]} {ModifiedOn.Value.ToString(DateTimeFormat)} ";
+ _text += $" {Localizer["On"]} {ModifiedOn.Value.ToString(DateTimeFormat)} ";
}
_text += "";
diff --git a/Oqtane.Client/Modules/Controls/FileManager.razor b/Oqtane.Client/Modules/Controls/FileManager.razor
index 17ed8f81..80426de8 100644
--- a/Oqtane.Client/Modules/Controls/FileManager.razor
+++ b/Oqtane.Client/Modules/Controls/FileManager.razor
@@ -157,6 +157,15 @@
[Parameter]
public EventCallback OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
+ protected override void OnInitialized()
+ {
+ // create unique id for component
+ _guid = Guid.NewGuid().ToString("N");
+ _fileinputid = "FileInput_" + _guid;
+ _progressinfoid = "ProgressInfo_" + _guid;
+ _progressbarid = "ProgressBar_" + _guid;
+ }
+
protected override async Task OnParametersSetAsync()
{
// packages folder is a framework folder for uploading installable nuget packages
@@ -223,12 +232,6 @@
await GetFiles();
- // create unique id for component
- _guid = Guid.NewGuid().ToString("N");
- _fileinputid = "FileInput_" + _guid;
- _progressinfoid = "ProgressInfo_" + _guid;
- _progressbarid = "ProgressBar_" + _guid;
-
_initialized = true;
}
@@ -398,8 +401,8 @@
// reset progress indicators
if (ShowProgress)
{
- await interop.SetElementAttribute(_guid + "ProgressInfo", "style", "display: none;");
- await interop.SetElementAttribute(_guid + "ProgressBar", "style", "display: none;");
+ await interop.SetElementAttribute(_progressinfoid, "style", "display: none;");
+ await interop.SetElementAttribute(_progressbarid, "style", "display: none;");
}
else
{
@@ -435,6 +438,7 @@
{
FileId = file.FileId;
await SetImage();
+ await OnSelect.InvokeAsync(FileId);
await OnUpload.InvokeAsync(FileId);
}
await GetFiles();
@@ -481,7 +485,8 @@
await GetFiles();
FileId = -1;
await SetImage();
- StateHasChanged();
+ await OnSelect.InvokeAsync(FileId);
+ StateHasChanged();
}
catch (Exception ex)
{
diff --git a/Oqtane.Client/Modules/Controls/InputList.razor b/Oqtane.Client/Modules/Controls/InputList.razor
new file mode 100644
index 00000000..25de9fda
--- /dev/null
+++ b/Oqtane.Client/Modules/Controls/InputList.razor
@@ -0,0 +1,50 @@
+@namespace Oqtane.Modules.Controls
+@inherits LocalizableComponent
+
+ OnChange(e))" />
+
+ @foreach(var kvp in DataList)
+ {
+ if (!string.IsNullOrEmpty(kvp.Value))
+ {
+ @Localize(kvp.Value, kvp.Value)
+ }
+ else
+ {
+ @Localize(kvp.Key, kvp.Key)
+ }
+ }
+
+
+@code {
+ private string _id;
+
+ [Parameter]
+ public string Value { get; set; }
+
+ [EditorRequired]
+ [Parameter]
+ public Dictionary DataList { get; set; }
+
+ [EditorRequired]
+ [Parameter]
+ public EventCallback ValueChanged { get; set; }
+
+ protected override void OnInitialized()
+ {
+ // create unique id for component
+ _id = "DataList_" + Guid.NewGuid().ToString("N");
+ }
+
+ protected void OnChange(ChangeEventArgs e)
+ {
+ if (!string.IsNullOrEmpty(e.Value.ToString()))
+ {
+ Value = e.Value.ToString();
+ if (ValueChanged.HasDelegate)
+ {
+ ValueChanged.InvokeAsync(Value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Modules/Controls/RichTextEditor.razor b/Oqtane.Client/Modules/Controls/RichTextEditor.razor
index 2231b02f..ca490d52 100644
--- a/Oqtane.Client/Modules/Controls/RichTextEditor.razor
+++ b/Oqtane.Client/Modules/Controls/RichTextEditor.razor
@@ -5,7 +5,7 @@
-
+
@if (_richfilemanager)
{
diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor
index 6c1b59a4..72a9662c 100644
--- a/Oqtane.Client/Modules/HtmlText/Edit.razor
+++ b/Oqtane.Client/Modules/HtmlText/Edit.razor
@@ -68,12 +68,6 @@
private List _htmltexts;
private string _view = "";
- protected override void OnParametersSet()
- {
- base.OnParametersSet();
- base.SetModuleTitle(Localizer["ModuleTitle.Text"]);
- }
-
protected override async Task OnInitializedAsync()
{
try
diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs
index f1a086e5..41812923 100644
--- a/Oqtane.Client/Modules/ModuleBase.cs
+++ b/Oqtane.Client/Modules/ModuleBase.cs
@@ -9,6 +9,7 @@ using Oqtane.UI;
using System.Collections.Generic;
using Microsoft.JSInterop;
using System.Linq;
+using System.Dynamic;
namespace Oqtane.Modules
{
@@ -280,13 +281,17 @@ namespace Oqtane.Modules
public void SetModuleTitle(string title)
{
- var obj = new { PageModuleId = ModuleState.PageModuleId, Title = title };
+ dynamic obj = new ExpandoObject();
+ obj.PageModuleId = ModuleState.PageModuleId;
+ obj.Title = title;
SiteState.Properties.ModuleTitle = obj;
}
public void SetModuleVisibility(bool visible)
{
- var obj = new { PageModuleId = ModuleState.PageModuleId, Visible = visible };
+ dynamic obj = new ExpandoObject();
+ obj.PageModuleId = ModuleState.PageModuleId;
+ obj.Visible = visible;
SiteState.Properties.ModuleVisibility = obj;
}
diff --git a/Oqtane.Client/Oqtane.Client.csproj b/Oqtane.Client/Oqtane.Client.csproj
index f2f659e1..ecf1b61c 100644
--- a/Oqtane.Client/Oqtane.Client.csproj
+++ b/Oqtane.Client/Oqtane.Client.csproj
@@ -4,7 +4,7 @@
net7.0
Exe
Debug;Release
- 4.0.2
+ 4.0.3
Oqtane
Shaun Walker
.NET Foundation
@@ -12,7 +12,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
https://github.com/oqtane/oqtane.framework
Git
Oqtane
diff --git a/Oqtane.Client/Resources/IconResources.resx b/Oqtane.Client/Resources/IconResources.resx
new file mode 100644
index 00000000..374aa5ff
--- /dev/null
+++ b/Oqtane.Client/Resources/IconResources.resx
@@ -0,0 +1,789 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ Account Login
+
+
+ Account Logout
+
+
+ Action Redo
+
+
+ Action Undo
+
+
+ Align Center
+
+
+ Align Left
+
+
+ Align Right
+
+
+ Aperture
+
+
+ Arrow Bottom
+
+
+ Arrow Circle Bottom
+
+
+ Arrow Circle Left
+
+
+ Arrow Circle Right
+
+
+ Arrow Circle Top
+
+
+ Arrow Left
+
+
+ Arrow Right
+
+
+ Arrow Thick Bottom
+
+
+ Arrow Thick Left
+
+
+ Arrow Thick Right
+
+
+ Arrow Thick Top
+
+
+ Arrow Top
+
+
+ Audio Spectrum
+
+
+ Audio
+
+
+ Badge
+
+
+ Ban
+
+
+ Bar Chart
+
+
+ Basket
+
+
+ Battery Empty
+
+
+ Battery Full
+
+
+ Beaker
+
+
+ Bell
+
+
+ Bluetooth
+
+
+ Bold
+
+
+ Bolt
+
+
+ Book
+
+
+ Bookmark
+
+
+ Box
+
+
+ Briefcase
+
+
+ British Pound
+
+
+ Browser
+
+
+ Brush
+
+
+ Bug
+
+
+ Bullhorn
+
+
+ Calculator
+
+
+ Calendar
+
+
+ Camera Slr
+
+
+ Caret Bottom
+
+
+ Caret Left
+
+
+ Caret Right
+
+
+ Caret Top
+
+
+ Cart
+
+
+ Chat
+
+
+ Check
+
+
+ Chevron Bottom
+
+
+ Chevron Left
+
+
+ Chevron Right
+
+
+ Chevron Top
+
+
+ Circle Check
+
+
+ Circle X
+
+
+ Clipboard
+
+
+ Clock
+
+
+ Cloud Download
+
+
+ Cloud Upload
+
+
+ Cloud
+
+
+ Cloudy
+
+
+ Code
+
+
+ Cog
+
+
+ Collapse Down
+
+
+ Collapse Left
+
+
+ Collapse Right
+
+
+ Collapse Up
+
+
+ Command
+
+
+ Comment Square
+
+
+ Compass
+
+
+ Contrast
+
+
+ Copywriting
+
+
+ Credit Card
+
+
+ Crop
+
+
+ Dashboard
+
+
+ Data Transfer Download
+
+
+ Data Transfer Upload
+
+
+ Delete
+
+
+ Dial
+
+
+ Document
+
+
+ Dollar
+
+
+ Double Quote Sans Left
+
+
+ Double Quote Sans Right
+
+
+ Double Quote Serif Left
+
+
+ Double Quote Serif Right
+
+
+ Droplet
+
+
+ Eject
+
+
+ Elevator
+
+
+ Ellipses
+
+
+ Envelope Closed
+
+
+ Envelope Open
+
+
+ Euro
+
+
+ Excerpt
+
+
+ Expand Down
+
+
+ Expand Left
+
+
+ Expand Right
+
+
+ Expand Up
+
+
+ External Link
+
+
+ Eye
+
+
+ Eyedropper
+
+
+ File
+
+
+ Fire
+
+
+ Flag
+
+
+ Flash
+
+
+ Folder
+
+
+ Fork
+
+
+ Fullscreen Enter
+
+
+ Fullscreen Exit
+
+
+ Globe
+
+
+ Graph
+
+
+ Grid Four Up
+
+
+ Grid Three Up
+
+
+ Grid Two Up
+
+
+ Hard Drive
+
+
+ Header
+
+
+ Headphones
+
+
+ Heart
+
+
+ Home
+
+
+ Image
+
+
+ Inbox
+
+
+ Infinity
+
+
+ Info
+
+
+ Italic
+
+
+ Justify Center
+
+
+ Justify Left
+
+
+ Justify Right
+
+
+ Key
+
+
+ Laptop
+
+
+ Layers
+
+
+ Lightbulb
+
+
+ Link Broken
+
+
+ Link Intact
+
+
+ List Rich
+
+
+ List
+
+
+ Location
+
+
+ Lock Locked
+
+
+ Lock Unlocked
+
+
+ Loop Circular
+
+
+ Loop Square
+
+
+ Loop
+
+
+ Magnifying Glass
+
+
+ Map Marker
+
+
+ Map
+
+
+ Media Pause
+
+
+ Media Play
+
+
+ Media Record
+
+
+ Media Skip Backward
+
+
+ Media Skip Forward
+
+
+ Media Step Backward
+
+
+ Media Step Forward
+
+
+ Media Stop
+
+
+ Medical Cross
+
+
+ Menu
+
+
+ Microphone
+
+
+ Minus
+
+
+ Monitor
+
+
+ Moon
+
+
+ Move
+
+
+ Musical Note
+
+
+ Paperclip
+
+
+ Pencil
+
+
+ People
+
+
+ Person
+
+
+ Phone
+
+
+ Pie Chart
+
+
+ Pin
+
+
+ Play Circle
+
+
+ Plus
+
+
+ Power Standby
+
+
+ Print
+
+
+ Project
+
+
+ Pulse
+
+
+ Puzzle Piece
+
+
+ Question Mark
+
+
+ Rain
+
+
+ Random
+
+
+ Reload
+
+
+ Resize Both
+
+
+ Resize Height
+
+
+ Resize Width
+
+
+ Rss Alt
+
+
+ Rss
+
+
+ Script
+
+
+ Share Boxed
+
+
+ Share
+
+
+ Shield
+
+
+ Signal
+
+
+ Signpost
+
+
+ Sort Ascending
+
+
+ Sort Descending
+
+
+ Spreadsheet
+
+
+ Star
+
+
+ Sun
+
+
+ Tablet
+
+
+ Tag
+
+
+ Tags
+
+
+ Target
+
+
+ Task
+
+
+ Terminal
+
+
+ Text
+
+
+ Thumb Down
+
+
+ Thumb Up
+
+
+ Timer
+
+
+ Transfer
+
+
+ Trash
+
+
+ Underline
+
+
+ Vertical Align Bottom
+
+
+ Vertical Align Center
+
+
+ Vertical Align Top
+
+
+ Video
+
+
+ Volume High
+
+
+ Volume Low
+
+
+ Volume Off
+
+
+ Warning
+
+
+ Wifi
+
+
+ Wrench
+
+
+ X
+
+
+ Yen
+
+
+ Zoom In
+
+
+ Zoom Out
+
+
\ No newline at end of file
diff --git a/Oqtane.Client/Resources/Modules/Admin/Files/Details.resx b/Oqtane.Client/Resources/Modules/Admin/Files/Details.resx
index 65be9d58..9dd02c6d 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Files/Details.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Files/Details.resx
@@ -1,4 +1,4 @@
-
+
Exe
- 4.0.2
+ 4.0.3
Oqtane
Shaun Walker
.NET Foundation
@@ -14,7 +14,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
https://github.com/oqtane/oqtane.framework
Git
Oqtane.Maui
@@ -31,7 +31,7 @@
0E29FC31-1B83-48ED-B6E0-9F3C67B775D4
- 4.0.2
+ 4.0.3
1
14.2
diff --git a/Oqtane.Package/Oqtane.Client.nuspec b/Oqtane.Package/Oqtane.Client.nuspec
index b1214b2d..878d5496 100644
--- a/Oqtane.Package/Oqtane.Client.nuspec
+++ b/Oqtane.Package/Oqtane.Client.nuspec
@@ -2,7 +2,7 @@
Oqtane.Client
- 4.0.2
+ 4.0.3
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,7 +12,7 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
icon.png
oqtane
diff --git a/Oqtane.Package/Oqtane.Framework.nuspec b/Oqtane.Package/Oqtane.Framework.nuspec
index 0d210547..b3ccb5eb 100644
--- a/Oqtane.Package/Oqtane.Framework.nuspec
+++ b/Oqtane.Package/Oqtane.Framework.nuspec
@@ -2,7 +2,7 @@
Oqtane.Framework
- 4.0.2
+ 4.0.3
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -11,8 +11,8 @@
.NET Foundation
false
MIT
- https://github.com/oqtane/oqtane.framework/releases/download/v4.0.2/Oqtane.Framework.4.0.2.Upgrade.zip
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/download/v4.0.3/Oqtane.Framework.4.0.3.Upgrade.zip
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
icon.png
oqtane framework
diff --git a/Oqtane.Package/Oqtane.Server.nuspec b/Oqtane.Package/Oqtane.Server.nuspec
index 650a49f2..b8e56b64 100644
--- a/Oqtane.Package/Oqtane.Server.nuspec
+++ b/Oqtane.Package/Oqtane.Server.nuspec
@@ -2,7 +2,7 @@
Oqtane.Server
- 4.0.2
+ 4.0.3
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,7 +12,7 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
icon.png
oqtane
diff --git a/Oqtane.Package/Oqtane.Shared.nuspec b/Oqtane.Package/Oqtane.Shared.nuspec
index 62a7514a..afa99300 100644
--- a/Oqtane.Package/Oqtane.Shared.nuspec
+++ b/Oqtane.Package/Oqtane.Shared.nuspec
@@ -2,7 +2,7 @@
Oqtane.Shared
- 4.0.2
+ 4.0.3
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,7 +12,7 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
icon.png
oqtane
diff --git a/Oqtane.Package/Oqtane.Updater.nuspec b/Oqtane.Package/Oqtane.Updater.nuspec
index b2c73f3f..81d106e8 100644
--- a/Oqtane.Package/Oqtane.Updater.nuspec
+++ b/Oqtane.Package/Oqtane.Updater.nuspec
@@ -2,7 +2,7 @@
Oqtane.Updater
- 4.0.2
+ 4.0.3
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,7 +12,7 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
icon.png
oqtane
diff --git a/Oqtane.Package/install.ps1 b/Oqtane.Package/install.ps1
index 1981ea2f..6e6a50ca 100644
--- a/Oqtane.Package/install.ps1
+++ b/Oqtane.Package/install.ps1
@@ -1 +1 @@
-Compress-Archive -Path "..\Oqtane.Server\bin\Release\net7.0\publish\*" -DestinationPath "Oqtane.Framework.4.0.2.Install.zip" -Force
\ No newline at end of file
+Compress-Archive -Path "..\Oqtane.Server\bin\Release\net7.0\publish\*" -DestinationPath "Oqtane.Framework.4.0.3.Install.zip" -Force
\ No newline at end of file
diff --git a/Oqtane.Package/upgrade.ps1 b/Oqtane.Package/upgrade.ps1
index 4074dec9..eaaf892a 100644
--- a/Oqtane.Package/upgrade.ps1
+++ b/Oqtane.Package/upgrade.ps1
@@ -1 +1 @@
-Compress-Archive -Path "..\Oqtane.Server\bin\Release\net7.0\publish\*" -DestinationPath "Oqtane.Framework.4.0.2.Upgrade.zip" -Force
\ No newline at end of file
+Compress-Archive -Path "..\Oqtane.Server\bin\Release\net7.0\publish\*" -DestinationPath "Oqtane.Framework.4.0.3.Upgrade.zip" -Force
\ No newline at end of file
diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs
index 636803b1..84a36886 100644
--- a/Oqtane.Server/Controllers/FileController.cs
+++ b/Oqtane.Server/Controllers/FileController.cs
@@ -159,6 +159,48 @@ namespace Oqtane.Controllers
}
}
+ // POST api/
+ [HttpPost]
+ [Authorize(Roles = RoleNames.Registered)]
+ public Models.File Post([FromBody] Models.File file)
+ {
+ var folder = _folders.GetFolder(file.FolderId);
+ if (ModelState.IsValid && folder != null && folder.SiteId == _alias.SiteId)
+ {
+ if (_userPermissions.IsAuthorized(User, folder.SiteId, EntityNames.Folder, file.FolderId, PermissionNames.Edit))
+ {
+ var filepath = _files.GetFilePath(file);
+ if (System.IO.File.Exists(filepath))
+ {
+ file = CreateFile(file.Name, folder.FolderId, filepath);
+ file = _files.AddFile(file);
+ _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.File, file.FileId, SyncEventActions.Create);
+ _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Added {File}", file);
+ }
+ else
+ {
+ _logger.Log(LogLevel.Error, this, LogFunction.Security, "File Does Not Exist At Path {FilePath}", filepath);
+ HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
+ file = null;
+ }
+ }
+ else
+ {
+ _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Post Attempt {File}", file);
+ HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
+ file = null;
+ }
+ }
+ else
+ {
+ _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Post Attempt {File}", file);
+ HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
+ file = null;
+ }
+
+ return file;
+ }
+
// PUT api//5
[HttpPut("{id}")]
[Authorize(Roles = RoleNames.Registered)]
@@ -580,8 +622,9 @@ namespace Oqtane.Controllers
string imagepath = filepath.Replace(Path.GetExtension(filepath), "." + width.ToString() + "x" + height.ToString() + ".png");
if (!System.IO.File.Exists(imagepath) || bool.Parse(recreate))
{
- if ((_userPermissions.IsAuthorized(User, PermissionNames.Edit, file.Folder.PermissionList) ||
- !string.IsNullOrEmpty(file.Folder.ImageSizes) && file.Folder.ImageSizes.ToLower().Split(",").Contains(width.ToString() + "x" + height.ToString())))
+ // user has edit access to folder or folder supports the image size being created
+ if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, file.Folder.PermissionList) ||
+ (!string.IsNullOrEmpty(file.Folder.ImageSizes) && (file.Folder.ImageSizes == "*" || file.Folder.ImageSizes.ToLower().Split(",").Contains(width.ToString() + "x" + height.ToString()))))
{
imagepath = CreateImage(filepath, width, height, mode, position, background, rotate, imagepath);
}
@@ -636,29 +679,43 @@ namespace Oqtane.Controllers
Enum.TryParse(mode, true, out ResizeMode resizemode);
Enum.TryParse(position, true, out AnchorPositionMode anchorpositionmode);
- image.Mutate(x => x
- .AutoOrient() // auto orient the image
- .Rotate(angle)
- .Resize(new ResizeOptions
- {
- Mode = resizemode,
- Position = anchorpositionmode,
- Size = new Size(width, height)
- }));
+ PngEncoder encoder;
if (background != "transparent")
{
image.Mutate(x => x
- .BackgroundColor(Color.ParseHex("#" + background)));
- }
+ .AutoOrient() // auto orient the image
+ .Rotate(angle)
+ .Resize(new ResizeOptions
+ {
+ Mode = resizemode,
+ Position = anchorpositionmode,
+ Size = new Size(width, height),
+ PadColor = Color.ParseHex("#" + background)
+ }));
- PngEncoder encoder = new PngEncoder
+ encoder = new PngEncoder();
+ }
+ else
{
- ColorType = PngColorType.RgbWithAlpha,
- TransparentColorMode = PngTransparentColorMode.Preserve,
- BitDepth = PngBitDepth.Bit8,
- CompressionLevel = PngCompressionLevel.BestSpeed
- };
+ image.Mutate(x => x
+ .AutoOrient() // auto orient the image
+ .Rotate(angle)
+ .Resize(new ResizeOptions
+ {
+ Mode = resizemode,
+ Position = anchorpositionmode,
+ Size = new Size(width, height)
+ }));
+
+ encoder = new PngEncoder
+ {
+ ColorType = PngColorType.RgbWithAlpha,
+ TransparentColorMode = PngTransparentColorMode.Preserve,
+ BitDepth = PngBitDepth.Bit8,
+ CompressionLevel = PngCompressionLevel.BestSpeed
+ };
+ }
image.Save(imagepath, encoder);
}
diff --git a/Oqtane.Server/Controllers/FolderController.cs b/Oqtane.Server/Controllers/FolderController.cs
index 24d252a7..616b24d2 100644
--- a/Oqtane.Server/Controllers/FolderController.cs
+++ b/Oqtane.Server/Controllers/FolderController.cs
@@ -84,10 +84,11 @@ namespace Oqtane.Controllers
}
}
- [HttpGet("{siteId}/{path}")]
+ // GET api//path/x/?path=y
+ [HttpGet("path/{siteId}")]
public Folder GetByPath(int siteId, string path)
{
- var folderPath = WebUtility.UrlDecode(path).Replace("\\", "/");
+ var folderPath = WebUtility.UrlDecode(path).Replace("\\", "/"); // handle legacy path format
folderPath = (folderPath == "/") ? "" : folderPath;
if (!folderPath.EndsWith("/") && folderPath != "")
{
diff --git a/Oqtane.Server/Controllers/InstallationController.cs b/Oqtane.Server/Controllers/InstallationController.cs
index 5c439835..1e4c8716 100644
--- a/Oqtane.Server/Controllers/InstallationController.cs
+++ b/Oqtane.Server/Controllers/InstallationController.cs
@@ -7,9 +7,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Oqtane.Infrastructure;
using Oqtane.Models;
-using Oqtane.Modules;
using Oqtane.Shared;
-using Oqtane.Themes;
using Microsoft.Extensions.Caching.Memory;
using System.Net;
using Oqtane.Repository;
@@ -244,12 +242,15 @@ namespace Oqtane.Controllers
{
try
{
- using (var client = new HttpClient())
+ var url = _configManager.GetSetting("PackageRegistryUrl", Constants.PackageRegistryUrl);
+ if (!string.IsNullOrEmpty(url))
{
- client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
- client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
- Uri uri = new Uri(Constants.PackageRegistryUrl + $"/api/registry/contact/?id={_configManager.GetInstallationId()}&email={WebUtility.UrlEncode(email)}");
- var response = await client.GetAsync(uri).ConfigureAwait(false);
+ using (var client = new HttpClient())
+ {
+ client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
+ client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
+ var response = await client.GetAsync(new Uri(url + $"/api/registry/contact/?id={_configManager.GetInstallationId()}&email={WebUtility.UrlEncode(email)}")).ConfigureAwait(false);
+ }
}
}
catch
diff --git a/Oqtane.Server/Controllers/ModuleDefinitionController.cs b/Oqtane.Server/Controllers/ModuleDefinitionController.cs
index 95380bef..314ec0e3 100644
--- a/Oqtane.Server/Controllers/ModuleDefinitionController.cs
+++ b/Oqtane.Server/Controllers/ModuleDefinitionController.cs
@@ -127,17 +127,26 @@ namespace Oqtane.Controllers
DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", moduleDefinition.Template, Path.DirectorySeparatorChar.ToString());
+ if (!string.IsNullOrEmpty(moduleDefinition.ModuleDefinitionName))
+ {
+ moduleDefinition.ModuleDefinitionName = moduleDefinition.ModuleDefinitionName.Replace("[Owner]", moduleDefinition.Owner).Replace("[Module]", moduleDefinition.Name);
+ }
+ else
+ {
+ moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + ".Module." + moduleDefinition.Name;
+ }
+
if (moduleDefinition.Template.ToLower().Contains("internal"))
{
rootPath = Utilities.PathCombine(rootFolder.FullName, Path.DirectorySeparatorChar.ToString());
- moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ", Oqtane.Client";
- moduleDefinition.ServerManagerType = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
+ moduleDefinition.ModuleDefinitionName = moduleDefinition.ModuleDefinitionName + ", Oqtane.Client";
+ moduleDefinition.ServerManagerType = moduleDefinition.ModuleDefinitionName + ".Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
}
else
{
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName, moduleDefinition.Owner + ".Module." + moduleDefinition.Name, Path.DirectorySeparatorChar.ToString());
- moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ", " + moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Client.Oqtane";
- moduleDefinition.ServerManagerType = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Server.Oqtane";
+ moduleDefinition.ModuleDefinitionName = moduleDefinition.ModuleDefinitionName + ", " + moduleDefinition.ModuleDefinitionName + ".Client.Oqtane";
+ moduleDefinition.ServerManagerType = moduleDefinition.ModuleDefinitionName + ".Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.ModuleDefinitionName + ".Server.Oqtane";
}
ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, moduleDefinition);
@@ -301,7 +310,7 @@ namespace Oqtane.Controllers
}
else
{
- templates.Add(new Template { Name = name, Title = name, Type = "External", Version = "", Location = Utilities.PathCombine(root.Parent.ToString(), Path.DirectorySeparatorChar.ToString()) });
+ templates.Add(new Template { Name = name, Title = name, Type = "External", Version = "", Namespace = "", Location = Utilities.PathCombine(root.Parent.ToString(), Path.DirectorySeparatorChar.ToString()) });
}
}
}
diff --git a/Oqtane.Server/Controllers/PackageController.cs b/Oqtane.Server/Controllers/PackageController.cs
index 4af636f4..7463bff4 100644
--- a/Oqtane.Server/Controllers/PackageController.cs
+++ b/Oqtane.Server/Controllers/PackageController.cs
@@ -38,14 +38,34 @@ namespace Oqtane.Controllers
{
// get packages
List packages = new List();
- if (bool.Parse(_configManager.GetSetting("PackageService", "true")) == true)
+ var url = _configManager.GetSetting("PackageRegistryUrl", Constants.PackageRegistryUrl);
+ if (!string.IsNullOrEmpty(url))
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
- packages = await GetJson>(client, Constants.PackageRegistryUrl + $"/api/registry/packages/?id={_configManager.GetInstallationId()}&type={type.ToLower()}&version={Constants.Version}&search={search}&price={price}&package={package}&sort={sort}");
- }
+ packages = await GetJson>(client, url + $"/api/registry/packages/?id={_configManager.GetInstallationId()}&type={type.ToLower()}&version={Constants.Version}&search={search}&price={price}&package={package}&sort={sort}");
+ }
+ }
+ return packages;
+ }
+
+ // GET: api//list/?names=x,y,z
+ [HttpGet("list")]
+ public async Task> GetPackages(string names)
+ {
+ // get packages
+ List packages = new List();
+ var url = _configManager.GetSetting("PackageRegistryUrl", Constants.PackageRegistryUrl);
+ if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(names))
+ {
+ using (var client = new HttpClient())
+ {
+ client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
+ client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
+ packages = await GetJson>(client, url + $"/api/registry/list/?id={_configManager.GetInstallationId()}&version={Constants.Version}&list={names}");
+ }
}
return packages;
}
@@ -56,14 +76,15 @@ namespace Oqtane.Controllers
{
// get package info
Package package = null;
- if (bool.Parse(_configManager.GetSetting("PackageService", "true")) == true)
+ var url = _configManager.GetSetting("PackageRegistryUrl", Constants.PackageRegistryUrl);
+ if (!string.IsNullOrEmpty(url))
{
var download = (string.IsNullOrEmpty(folder)) ? "false" : "true";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
- package = await GetJson(client, Constants.PackageRegistryUrl + $"/api/registry/package/?id={_configManager.GetInstallationId()}&package={packageid}&version={version}&download={download}");
+ package = await GetJson(client, url + $"/api/registry/package/?id={_configManager.GetInstallationId()}&package={packageid}&version={version}&download={download}");
}
if (package != null)
diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs
index f239eb14..9283aa14 100644
--- a/Oqtane.Server/Controllers/SiteController.cs
+++ b/Oqtane.Server/Controllers/SiteController.cs
@@ -91,7 +91,7 @@ namespace Oqtane.Controllers
site.Pages = new List();
foreach (Page page in _pages.GetPages(site.SiteId))
{
- if (_userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
+ if (!page.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
{
page.Settings = settings.Where(item => item.EntityId == page.PageId)
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
@@ -107,7 +107,7 @@ namespace Oqtane.Controllers
site.Modules = new List();
foreach (PageModule pagemodule in _pageModules.GetPageModules(site.SiteId))
{
- if (_userPermissions.IsAuthorized(User, PermissionNames.View, pagemodule.Module.PermissionList))
+ if (!pagemodule.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, pagemodule.Module.PermissionList))
{
Module module = new Module();
module.SiteId = pagemodule.Module.SiteId;
diff --git a/Oqtane.Server/Controllers/SystemController.cs b/Oqtane.Server/Controllers/SystemController.cs
index ca95428a..471fd81e 100644
--- a/Oqtane.Server/Controllers/SystemController.cs
+++ b/Oqtane.Server/Controllers/SystemController.cs
@@ -52,7 +52,7 @@ namespace Oqtane.Controllers
systeminfo.Add("Logging:LogLevel:Default", _configManager.GetSetting("Logging:LogLevel:Default", "Information"));
systeminfo.Add("Logging:LogLevel:Notify", _configManager.GetSetting("Logging:LogLevel:Notify", "Error"));
systeminfo.Add("UseSwagger", _configManager.GetSetting("UseSwagger", "true"));
- systeminfo.Add("PackageService", _configManager.GetSetting("PackageService", "true"));
+ systeminfo.Add("PackageRegistryUrl", _configManager.GetSetting("PackageRegistryUrl", Constants.PackageRegistryUrl));
break;
case "log":
string log = "";
@@ -74,7 +74,6 @@ namespace Oqtane.Controllers
return systeminfo;
}
-
// GET: api/
[HttpGet("{key}/{value}")]
[Authorize(Roles = RoleNames.Host)]
@@ -94,6 +93,26 @@ namespace Oqtane.Controllers
}
}
+ // GET: api//icons
+ [HttpGet("icons")]
+ public Dictionary Get()
+ {
+ var icons = new Dictionary();
+
+ // use reflection to get list of icons from Icons class
+ Type iconsType = typeof(Icons);
+ System.Reflection.FieldInfo[] fields = iconsType.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetField);
+ foreach (System.Reflection.FieldInfo field in fields)
+ {
+ if (field.FieldType == typeof(string))
+ {
+ icons.Add((string)field.GetValue(null), field.Name); // ie. ("oi oi-home", "Home")
+ }
+ }
+
+ return icons;
+ }
+
private void UpdateSetting(string key, object value)
{
switch (key.ToLower())
diff --git a/Oqtane.Server/Controllers/ThemeController.cs b/Oqtane.Server/Controllers/ThemeController.cs
index 5135ef22..cec332fe 100644
--- a/Oqtane.Server/Controllers/ThemeController.cs
+++ b/Oqtane.Server/Controllers/ThemeController.cs
@@ -173,15 +173,24 @@ namespace Oqtane.Controllers
DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Themes", "Templates", theme.Template, Path.DirectorySeparatorChar.ToString());
+ if (!string.IsNullOrEmpty(theme.ThemeName))
+ {
+ theme.ThemeName = theme.ThemeName.Replace("[Owner]", theme.Owner).Replace("[Theme]", theme.Name);
+ }
+ else
+ {
+ theme.ThemeName = theme.Owner + ".Theme." + theme.Name;
+ }
+
if (theme.Template.ToLower().Contains("internal"))
{
rootPath = Utilities.PathCombine(rootFolder.FullName, Path.DirectorySeparatorChar.ToString());
- theme.ThemeName = theme.Owner + ".Theme." + theme.Name + ", Oqtane.Client";
+ theme.ThemeName = theme.ThemeName + ", Oqtane.Client";
}
else
{
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName, theme.Owner + ".Theme." + theme.Name, Path.DirectorySeparatorChar.ToString());
- theme.ThemeName = theme.Owner + ".Theme." + theme.Name + ", " + theme.Owner + ".Theme." + theme.Name + ".Client.Oqtane";
+ theme.ThemeName = theme.ThemeName + ", " + theme.ThemeName + ".Client.Oqtane";
}
ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, theme);
diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs
index 11345d0e..f26ece36 100644
--- a/Oqtane.Server/Controllers/UserController.cs
+++ b/Oqtane.Server/Controllers/UserController.cs
@@ -14,6 +14,7 @@ using Oqtane.Repository;
using Oqtane.Security;
using Oqtane.Extensions;
using Oqtane.Managers;
+using System.Collections.Generic;
namespace Oqtane.Controllers
{
@@ -61,13 +62,15 @@ namespace Oqtane.Controllers
}
}
- // GET api//name/x?siteid=x
- [HttpGet("name/{name}")]
- public User Get(string name, string siteid)
+ // GET api//name/{name}/{email}?siteid=x
+ [HttpGet("name/{name}/{email}")]
+ public User Get(string name, string email, string siteid)
{
if (int.TryParse(siteid, out int SiteId) && SiteId == _tenantManager.GetAlias().SiteId)
{
- User user = _userManager.GetUser(name, SiteId);
+ name = (name == "-") ? "" : name;
+ email = (email == "-") ? "" : email;
+ User user = _userManager.GetUser(name, email, SiteId);
if (user == null)
{
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
@@ -76,7 +79,7 @@ namespace Oqtane.Controllers
}
else
{
- _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Get Attempt {Username} {SiteId}", name, siteid);
+ _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized User Get Attempt {Username} {Email} {SiteId}", name, email, siteid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
@@ -334,5 +337,23 @@ namespace Oqtane.Controllers
}
return user;
}
+
+ // GET api//passwordrequirements/5
+ [HttpGet("passwordrequirements/{siteid}")]
+ public Dictionary PasswordRequirements(int siteid)
+ {
+ var requirements = new Dictionary();
+
+ var site = _sites.GetSite(siteid);
+ if (site != null && (site.AllowRegistration || User.IsInRole(RoleNames.Registered)))
+ {
+ // get password settings
+ var sitesettings = HttpContext.GetSiteSettings();
+ requirements = sitesettings.Where(item => item.Key.StartsWith("IdentityOptions:Password:"))
+ .ToDictionary(item => item.Key, item => item.Value);
+ }
+
+ return requirements;
+ }
}
}
diff --git a/Oqtane.Server/Infrastructure/Jobs/HostedServiceBase.cs b/Oqtane.Server/Infrastructure/Jobs/HostedServiceBase.cs
index 1c9eb377..be8e8c69 100644
--- a/Oqtane.Server/Infrastructure/Jobs/HostedServiceBase.cs
+++ b/Oqtane.Server/Infrastructure/Jobs/HostedServiceBase.cs
@@ -23,9 +23,6 @@ namespace Oqtane.Infrastructure
_serviceScopeFactory = serviceScopeFactory;
}
- // abstract method must be overridden
- public abstract string ExecuteJob(IServiceProvider provider);
-
// public properties which can be overridden and are used during auto registration of job
public string Name { get; set; } = "";
public string Frequency { get; set; } = "d"; // day
@@ -35,6 +32,17 @@ namespace Oqtane.Infrastructure
public int RetentionHistory { get; set; } = 10;
public bool IsEnabled { get; set; } = false;
+ // one of the following methods must be overridden
+ public virtual string ExecuteJob(IServiceProvider provider)
+ {
+ return "";
+ }
+
+ public virtual Task ExecuteJobAsync(IServiceProvider provider)
+ {
+ return Task.FromResult(string.Empty);
+ }
+
protected async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Yield(); // required so that this method does not block startup
@@ -102,6 +110,7 @@ namespace Oqtane.Infrastructure
// set tenant and execute job
tenantManager.SetTenant(tenant.TenantId);
notes += ExecuteJob(scope.ServiceProvider);
+ notes += await ExecuteJobAsync(scope.ServiceProvider);
}
log.Notes = notes;
log.Succeeded = true;
diff --git a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs
index 04ebe920..777bb912 100644
--- a/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs
+++ b/Oqtane.Server/Infrastructure/Jobs/NotificationJob.cs
@@ -130,7 +130,7 @@ namespace Oqtane.Infrastructure
mailMessage.Subject = notification.Subject;
//body
- mailMessage.Body = notification.Body;
+ mailMessage.Body = notification.Body.Replace("\n", " ");
// encoding
mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;
diff --git a/Oqtane.Server/Managers/Interfaces/IUserManager.cs b/Oqtane.Server/Managers/Interfaces/IUserManager.cs
index ec58c091..82cf7090 100644
--- a/Oqtane.Server/Managers/Interfaces/IUserManager.cs
+++ b/Oqtane.Server/Managers/Interfaces/IUserManager.cs
@@ -7,6 +7,7 @@ namespace Oqtane.Managers
{
User GetUser(int userid, int siteid);
User GetUser(string username, int siteid);
+ User GetUser(string username, string email, int siteid);
Task AddUser(User user);
Task UpdateUser(User user);
Task DeleteUser(int userid, int siteid);
diff --git a/Oqtane.Server/Managers/UserManager.cs b/Oqtane.Server/Managers/UserManager.cs
index 5c2e607d..07304679 100644
--- a/Oqtane.Server/Managers/UserManager.cs
+++ b/Oqtane.Server/Managers/UserManager.cs
@@ -51,7 +51,12 @@ namespace Oqtane.Managers
public User GetUser(string username, int siteid)
{
- User user = _users.GetUser(username);
+ return GetUser(username, "", siteid);
+ }
+
+ public User GetUser(string username, string email, int siteid)
+ {
+ User user = _users.GetUser(username, email);
if (user != null)
{
user.SiteId = siteid;
@@ -138,7 +143,7 @@ namespace Oqtane.Managers
else
{
string url = alias.Protocol + alias.Name;
- string body = "Dear " + user.DisplayName + ",\n\nA User Account Has Been Successfully Created For You. Please Use The Following Link To Access The Site:\n\n" + url + "\n\nThank You!";
+ string body = "Dear " + user.DisplayName + ",\n\nA User Account Has Been Successfully Created For You With The Username " + user.Username + ". Please Visit " + url + " And Use The Login Option To Sign In. If You Do Not Know Your Password, Use The Forgot Password Option On The Login Page To Reset Your Account.\n\nThank You!";
var notification = new Notification(user.SiteId, User, "User Account Notification", body);
_notifications.AddNotification(notification);
}
diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj
index 950d1ebf..cfd7a1e7 100644
--- a/Oqtane.Server/Oqtane.Server.csproj
+++ b/Oqtane.Server/Oqtane.Server.csproj
@@ -3,7 +3,7 @@
net7.0
Debug;Release
- 4.0.2
+ 4.0.3
Oqtane
Shaun Walker
.NET Foundation
@@ -11,7 +11,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
https://github.com/oqtane/oqtane.framework
Git
Oqtane
diff --git a/Oqtane.Server/Repository/Interfaces/IUserRepository.cs b/Oqtane.Server/Repository/Interfaces/IUserRepository.cs
index 89a25bca..89ed4204 100644
--- a/Oqtane.Server/Repository/Interfaces/IUserRepository.cs
+++ b/Oqtane.Server/Repository/Interfaces/IUserRepository.cs
@@ -11,6 +11,7 @@ namespace Oqtane.Repository
User GetUser(int userId);
User GetUser(int userId, bool tracking);
User GetUser(string username);
+ User GetUser(string username, string email);
void DeleteUser(int userId);
}
}
diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
index 99c1e6bf..1607b811 100644
--- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
+++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
@@ -138,14 +138,21 @@ namespace Oqtane.Repository
// sync module assemblies with database
foreach (ModuleDefinition ModuleDefinition in ModuleDefinitions)
{
+ // manage releaseversions in cases where it was not provided or is lower than the module version
+ if (string.IsNullOrEmpty(ModuleDefinition.ReleaseVersions) || (!string.IsNullOrEmpty(ModuleDefinition.Version) && Version.Parse(ModuleDefinition.Version).CompareTo(Version.Parse(ModuleDefinition.ReleaseVersions.Split(',').Last())) > 0))
+ {
+ ModuleDefinition.ReleaseVersions = ModuleDefinition.Version;
+ }
+
ModuleDefinition moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == ModuleDefinition.ModuleDefinitionName).FirstOrDefault();
+
if (moduledefinition == null)
{
- // new module definition
+ // new module definition (version is explicitly not set because it is updated as part of module migrations at startup)
moduledefinition = new ModuleDefinition { ModuleDefinitionName = ModuleDefinition.ModuleDefinitionName };
_db.ModuleDefinition.Add(moduledefinition);
_db.SaveChanges();
- ModuleDefinition.Version = "";
+ ModuleDefinition.Version = "";
}
else
{
@@ -153,16 +160,12 @@ namespace Oqtane.Repository
ModuleDefinition.Name = (!string.IsNullOrEmpty(moduledefinition.Name)) ? moduledefinition.Name : ModuleDefinition.Name;
ModuleDefinition.Description = (!string.IsNullOrEmpty(moduledefinition.Description)) ? moduledefinition.Description : ModuleDefinition.Description;
ModuleDefinition.Categories = (!string.IsNullOrEmpty(moduledefinition.Categories)) ? moduledefinition.Categories : ModuleDefinition.Categories;
- // manage releaseversions in cases where it was not provided or is lower than the module version
- if (string.IsNullOrEmpty(ModuleDefinition.ReleaseVersions) || Version.Parse(ModuleDefinition.Version).CompareTo(Version.Parse(ModuleDefinition.ReleaseVersions.Split(',').Last())) > 0)
- {
- ModuleDefinition.ReleaseVersions = ModuleDefinition.Version;
- }
- ModuleDefinition.Version = moduledefinition.Version;
+
// remove module definition from list as it is already synced
moduledefinitions.Remove(moduledefinition);
}
+ // load db properties
ModuleDefinition.ModuleDefinitionId = moduledefinition.ModuleDefinitionId;
ModuleDefinition.CreatedBy = moduledefinition.CreatedBy;
ModuleDefinition.CreatedOn = moduledefinition.CreatedOn;
diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs
index 72e07bc7..2adff634 100644
--- a/Oqtane.Server/Repository/SiteRepository.cs
+++ b/Oqtane.Server/Repository/SiteRepository.cs
@@ -372,12 +372,15 @@ namespace Oqtane.Repository
page.PermissionList = pageTemplate.PermissionList;
try
{
- if (page.PageId != 0 && pageTemplate.Update)
+ if (page.PageId != 0)
{
- page = _pageRepository.UpdatePage(page);
- if (alias != null)
+ if (pageTemplate.Update)
{
- _logger.Log(LogLevel.Information, "Site Template", LogFunction.Update, "Page Updated {Page}", page);
+ page = _pageRepository.UpdatePage(page);
+ if (alias != null)
+ {
+ _logger.Log(LogLevel.Information, "Site Template", LogFunction.Update, "Page Updated {Page}", page);
+ }
}
}
else
@@ -430,13 +433,20 @@ namespace Oqtane.Repository
pageModule.Module.IsDeleted = false;
try
{
- if (pageModule.ModuleId != 0 && pageTemplate.Update)
+ if (pageModule.ModuleId != 0)
{
- _moduleRepository.UpdateModule(pageModule.Module);
- _pageModuleRepository.UpdatePageModule(pageModule);
- if (alias != null)
+ if (pageTemplate.Update)
{
- _logger.Log(LogLevel.Information, "Site Template", LogFunction.Update, "Page Module Updated {PageModule}", pageModule);
+ _moduleRepository.UpdateModule(pageModule.Module);
+ _pageModuleRepository.UpdatePageModule(pageModule);
+ if (alias != null)
+ {
+ _logger.Log(LogLevel.Information, "Site Template", LogFunction.Update, "Page Module Updated {PageModule}", pageModule);
+ }
+ }
+ else
+ {
+ pageTemplateModule.Content = ""; // do not update content
}
}
else
diff --git a/Oqtane.Server/Repository/ThemeRepository.cs b/Oqtane.Server/Repository/ThemeRepository.cs
index c555580b..a650f7d3 100644
--- a/Oqtane.Server/Repository/ThemeRepository.cs
+++ b/Oqtane.Server/Repository/ThemeRepository.cs
@@ -123,7 +123,7 @@ namespace Oqtane.Repository
if (theme == null)
{
// new theme
- theme = new Theme { ThemeName = Theme.ThemeName };
+ theme = new Theme { ThemeName = Theme.ThemeName, Version = Theme.Version };
_db.Theme.Add(theme);
_db.SaveChanges();
}
@@ -131,6 +131,7 @@ namespace Oqtane.Repository
{
// override user customizable property values
Theme.Name = (!string.IsNullOrEmpty(theme.Name)) ? theme.Name : Theme.Name;
+
// remove theme from list as it is already synced
themes.Remove(theme);
}
@@ -141,6 +142,7 @@ namespace Oqtane.Repository
themecontrol.Name = Theme.Name + " - " + themecontrol.Name;
}
+ // load db properties
Theme.ThemeId = theme.ThemeId;
Theme.CreatedBy = theme.CreatedBy;
Theme.CreatedOn = theme.CreatedOn;
diff --git a/Oqtane.Server/Repository/UserRepository.cs b/Oqtane.Server/Repository/UserRepository.cs
index f5136c74..8320a748 100644
--- a/Oqtane.Server/Repository/UserRepository.cs
+++ b/Oqtane.Server/Repository/UserRepository.cs
@@ -105,7 +105,21 @@ namespace Oqtane.Repository
public User GetUser(string username)
{
- return _db.User.Where(item => item.Username == username).FirstOrDefault();
+ return GetUser(username, "");
+ }
+
+ public User GetUser(string username, string email)
+ {
+ User user = null;
+ if (!string.IsNullOrEmpty(username))
+ {
+ user = _db.User.Where(item => item.Username == username).FirstOrDefault();
+ }
+ if (user == null && !string.IsNullOrEmpty(email))
+ {
+ user = _db.User.Where(item => item.Email == email).FirstOrDefault();
+ }
+ return user;
}
public void DeleteUser(int userId)
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/template.json b/Oqtane.Server/wwwroot/Modules/Templates/External/template.json
index 777da289..493c825e 100644
--- a/Oqtane.Server/wwwroot/Modules/Templates/External/template.json
+++ b/Oqtane.Server/wwwroot/Modules/Templates/External/template.json
@@ -1,5 +1,6 @@
{
"Title": "Default Module Template",
"Type": "External",
- "Version": "4.0.2"
+ "Version": "4.0.3",
+ "Namespace": "[Owner].Module.[Module]"
}
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak
index 03c7d56f..baf59fdd 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak
index 87a45d22..f4a6ccdd 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak
index 1d551e8f..77208775 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak
index 1607b94c..ad62505b 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/template.json b/Oqtane.Server/wwwroot/Themes/Templates/External/template.json
index 04ee5175..7c3b80bb 100644
--- a/Oqtane.Server/wwwroot/Themes/Templates/External/template.json
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/template.json
@@ -1,5 +1,6 @@
{
"Title": "Default Theme Template",
"Type": "External",
- "Version": "4.0.0"
+ "Version": "4.0.3",
+ "Namespace": "[Owner].Theme.[Theme]"
}
diff --git a/Oqtane.Shared/Models/ModuleDefinition.cs b/Oqtane.Shared/Models/ModuleDefinition.cs
index 44f3cd65..5c374667 100644
--- a/Oqtane.Shared/Models/ModuleDefinition.cs
+++ b/Oqtane.Shared/Models/ModuleDefinition.cs
@@ -97,6 +97,10 @@ namespace Oqtane.Models
[NotMapped]
public string ControlTypeRoutes { get; set; }
+ ///
+ /// ReleaseVersions contains a comma delimited list of all official release versions of a module ie "1.0.0,1.0.1"
+ /// Must be set for modules which use SQL scripts or include version-based logic in IInstallable implementations
+ ///
[NotMapped]
public string ReleaseVersions { get; set; }
diff --git a/Oqtane.Shared/Models/Package.cs b/Oqtane.Shared/Models/Package.cs
index 1e424744..8f479a14 100644
--- a/Oqtane.Shared/Models/Package.cs
+++ b/Oqtane.Shared/Models/Package.cs
@@ -33,10 +33,15 @@ namespace Oqtane.Models
public string Description { get; set; }
///
- /// logo
+ /// logo file id
///
public int? LogoFileId { get; set; }
+ ///
+ /// logo url
+ ///
+ public string LogoUrl { get; set; }
+
///
/// License for the Package.
///
diff --git a/Oqtane.Shared/Models/Template.cs b/Oqtane.Shared/Models/Template.cs
index 12859fff..9d667ec2 100644
--- a/Oqtane.Shared/Models/Template.cs
+++ b/Oqtane.Shared/Models/Template.cs
@@ -25,6 +25,11 @@ namespace Oqtane.Models
///
public string Version { get; set; }
+ ///
+ /// namespace (uses tokens)
+ ///
+ public string Namespace { get; set; }
+
///
/// location where template will be created (dynamically set)
///
diff --git a/Oqtane.Shared/Models/User.cs b/Oqtane.Shared/Models/User.cs
index 751b6e01..d7436b4c 100644
--- a/Oqtane.Shared/Models/User.cs
+++ b/Oqtane.Shared/Models/User.cs
@@ -97,7 +97,7 @@ namespace Oqtane.Models
[NotMapped]
public string FolderPath
{
- get => "Users\\" + UserId.ToString() + "\\";
+ get => "Users/" + UserId.ToString() + "/";
}
///
diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj
index 284c399a..7dd6677a 100644
--- a/Oqtane.Shared/Oqtane.Shared.csproj
+++ b/Oqtane.Shared/Oqtane.Shared.csproj
@@ -3,7 +3,7 @@
net7.0
Debug;Release
- 4.0.2
+ 4.0.3
Oqtane
Shaun Walker
.NET Foundation
@@ -11,7 +11,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
https://github.com/oqtane/oqtane.framework
Git
Oqtane
diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs
index 29874f0d..a4c68174 100644
--- a/Oqtane.Shared/Shared/Constants.cs
+++ b/Oqtane.Shared/Shared/Constants.cs
@@ -7,8 +7,8 @@ namespace Oqtane.Shared
{
public class Constants
{
- public static readonly string Version = "4.0.2";
- public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2";
+ public static readonly string Version = "4.0.3";
+ public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3";
public const string PackageId = "Oqtane.Framework";
public const string ClientId = "Oqtane.Client";
public const string UpdaterPackageId = "Oqtane.Updater";
diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs
index cdf0e05e..b5a7493e 100644
--- a/Oqtane.Shared/Shared/Utilities.cs
+++ b/Oqtane.Shared/Shared/Utilities.cs
@@ -1,5 +1,6 @@
using Oqtane.Models;
using System;
+using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
@@ -492,18 +493,51 @@ namespace Oqtane.Shared
public static DateTime? LocalDateAndTimeAsUtc(DateTime? date, string time, TimeZoneInfo localTimeZone = null)
{
- localTimeZone ??= TimeZoneInfo.Local;
- if (date != null)
+ if (date != null && !string.IsNullOrEmpty(time) && TimeSpan.TryParse(time, out TimeSpan timespan))
{
- if (!string.IsNullOrEmpty(time))
- {
- return TimeZoneInfo.ConvertTime(DateTime.Parse(date.Value.Date.ToShortDateString() + " " + time), localTimeZone, TimeZoneInfo.Utc);
- }
- return TimeZoneInfo.ConvertTime(date.Value.Date, localTimeZone, TimeZoneInfo.Utc);
+ return LocalDateAndTimeAsUtc(date.Value.Date.Add(timespan), localTimeZone);
}
return null;
}
+ public static DateTime? LocalDateAndTimeAsUtc(DateTime? date, DateTime? time, TimeZoneInfo localTimeZone = null)
+ {
+ if (date != null)
+ {
+ if (time != null)
+ {
+ return LocalDateAndTimeAsUtc(date.Value.Date.Add(time.Value.TimeOfDay), localTimeZone);
+ }
+ return LocalDateAndTimeAsUtc(date.Value.Date, localTimeZone);
+ }
+ return null;
+ }
+
+ public static DateTime? LocalDateAndTimeAsUtc(DateTime? date, TimeZoneInfo localTimeZone = null)
+ {
+ if (date != null)
+ {
+ localTimeZone ??= TimeZoneInfo.Local;
+ return TimeZoneInfo.ConvertTime(date.Value, localTimeZone, TimeZoneInfo.Utc);
+ }
+ return null;
+ }
+
+ public static DateTime? UtcAsLocalDate(DateTime? dateTime, TimeZoneInfo timeZone = null)
+ {
+ return UtcAsLocalDateAndTime(dateTime, timeZone).date;
+ }
+
+ public static DateTime? UtcAsLocalDateTime(DateTime? dateTime, TimeZoneInfo timeZone = null)
+ {
+ var result = UtcAsLocalDateAndTime(dateTime, timeZone);
+ if (result.date != null && !string.IsNullOrEmpty(result.time) && TimeSpan.TryParse(result.time, out TimeSpan timespan))
+ {
+ result.date = result.date.Value.Add(timespan);
+ }
+ return result.date;
+ }
+
public static (DateTime? date, string time) UtcAsLocalDateAndTime(DateTime? dateTime, TimeZoneInfo timeZone = null)
{
timeZone ??= TimeZoneInfo.Local;
diff --git a/Oqtane.Updater/Oqtane.Updater.csproj b/Oqtane.Updater/Oqtane.Updater.csproj
index e84847c0..69bf2b6a 100644
--- a/Oqtane.Updater/Oqtane.Updater.csproj
+++ b/Oqtane.Updater/Oqtane.Updater.csproj
@@ -3,7 +3,7 @@
net7.0
Exe
- 4.0.2
+ 4.0.3
Oqtane
Shaun Walker
.NET Foundation
@@ -11,7 +11,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2
+ https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3
https://github.com/oqtane/oqtane.framework
Git
Oqtane
diff --git a/README.md b/README.md
index de6ac3a0..b2370579 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Latest Release
-[4.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.1) was released on July 18, 2023 and is primary focused on stabilization. This release includes 68 pull requests by 8 different contributors, pushing the total number of project commits all-time over 3800. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
+[4.0.2](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2) was released on Aug 9, 2023 and is primary focused on stabilization. This release includes 50 pull requests by 9 different contributors, pushing the total number of project commits all-time over 3900. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
[](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json)
@@ -53,7 +53,7 @@ Backlog (TBD)
5.0.0 (Q4 2023)
- [ ] Migration to .NET 8
-4.0.2 ( Aug 2023 )
+[4.0.2](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2) ( Aug 9, 2023 )
- [x] Stabilization improvements
[4.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.1) ( Jul 18, 2023 )