Compare commits

...

82 Commits

Author SHA1 Message Date
03b6abe5ec Merge pull request #4149 from oqtane/master
5.1.1 release
2024-04-16 13:34:15 -04:00
4479304f3f Merge pull request #4148 from oqtane/dev
5.1.1 release
2024-04-16 13:33:51 -04:00
ed83405254 Merge pull request #4147 from sbwalker/dev
fix SiteMap path issue
2024-04-16 13:04:39 -04:00
b815d945d9 fix SiteMap path issue 2024-04-16 13:04:25 -04:00
2b8e024f48 Merge pull request #4146 from sbwalker/dev
include .NET MAUI CORS policy for static files
2024-04-16 12:36:53 -04:00
2a0399b98d include .NET MAUI CORS policy for static files, add support for [wwwroot] in content 2024-04-16 12:36:31 -04:00
4e333e2d75 Merge pull request #4145 from sbwalker/dev
fix SiteRouter issue when running on .NET MAUI
2024-04-16 08:03:16 -04:00
4f25b7bbbe fix SiteRouter issue when running on .NET MAUI 2024-04-16 08:02:59 -04:00
3678db649b Merge pull request #4144 from sbwalker/dev
fixes for #4134 - Rich Text Editor
2024-04-15 08:54:30 -04:00
9d8b1fd99b fixes for #4134 - Rich Text Editor 2024-04-15 08:54:23 -04:00
7b62c06be3 Merge pull request #4140 from sbwalker/dev
convert Quill's empty content to empty string
2024-04-12 15:11:01 -04:00
bc978a91e3 convert Quill's empty content to empty string 2024-04-12 15:10:47 -04:00
611ba97b60 Merge pull request #4139 from sbwalker/dev
more changes for #4134 - ensure HTML content is preserved
2024-04-12 14:58:27 -04:00
39dff1ea7c more changes for #4134 - ensure HTML content is preserved 2024-04-12 14:58:14 -04:00
bcf7bcba1d Merge pull request #4137 from sbwalker/dev
fix #4134 - RichTextEditor scenarios
2024-04-12 13:25:59 -04:00
8f00730189 fix #4134 - RichTextEditor scenarios 2024-04-12 13:25:44 -04:00
1dde79ace2 Merge pull request #4136 from zyhfish/bug/fix-issue-4121
Fix #4121: avoid nested square bracket issue.
2024-04-12 11:04:25 -04:00
Ben
5954fb91be Fix #4121: avoid nested square bracket issue. 2024-04-12 21:56:49 +08:00
e192383662 Merge pull request #4135 from leigh-pointer/TokenRep
InitializeTokenReplace not setting the correct PackageReference
2024-04-12 07:41:40 -04:00
4a20fad4e5 InitializeTokenReplace not setting the correct PackageReference
For completeness.
2024-04-12 12:21:44 +02:00
a469e0864e Merge pull request #4132 from sbwalker/dev
move RichTextEditor script registration to Body
2024-04-11 15:27:09 -04:00
cfce2bdbd9 move RichTextEditor script registration to Body 2024-04-11 15:26:55 -04:00
529b5c0a00 Merge pull request #4130 from sbwalker/dev
prepare for 5.1.1 release
2024-04-11 14:28:12 -04:00
7cc5787779 prepare for 5.1.1 release 2024-04-11 14:27:59 -04:00
48eeb279e2 Merge pull request #4129 from sbwalker/dev
add Process info to System Info to indicate if process is 32 bit or 64 bit
2024-04-11 13:34:25 -04:00
d67566252a add Process info to System Info to indicate if process is 32 bit or 64 bit 2024-04-11 13:34:06 -04:00
8a2d79e17d Merge pull request #4127 from sbwalker/dev
fix issue where active tab not set correctly when rich text editor disabled
2024-04-11 09:16:57 -04:00
17370dff54 fix issue where active tab not set correctly when rich text editor disabled 2024-04-11 09:16:39 -04:00
f08a8e7634 Merge pull request #4126 from sbwalker/dev
fix https://github.com/oqtane/oqtane.blogs/issues/44 - rich text editor throwing exception in specific scenario
2024-04-11 09:04:00 -04:00
83543bbddc fix https://github.com/oqtane/oqtane.blogs/issues/44 - rich text editor throwing exception in specific scenario 2024-04-11 09:03:41 -04:00
b898c90f41 Merge pull request #4125 from leigh-pointer/ImageSharpUpdate
ImageSharp update from 3.1.3 to 3.1.4
2024-04-11 07:44:51 -04:00
1ec927cf4f ImageSharp update from 3.1.3 to 3.1.4 2024-04-11 11:11:05 +02:00
aef21ba9d5 Merge pull request #4124 from sbwalker/dev
update theme and module templates to .NET SDK 8.0.4
2024-04-10 16:29:35 -04:00
0b31709aee update theme and module templates to .NEt SDK 8.0.4 2024-04-10 16:29:16 -04:00
7c3433256a Merge pull request #4123 from sbwalker/dev
update to .NET SDK 8.0.4
2024-04-10 16:24:40 -04:00
c79c638f35 update to .NET SDK 8.0.4 2024-04-10 16:24:23 -04:00
a148941a39 Merge pull request #4119 from sbwalker/dev
fix #4109 - fix resx key in SqlServerConfig (credit @mmisu)
2024-04-09 08:06:31 -04:00
23abe26b0b fix #4109 - fix resx key in SqlServerConfig (credit @mmisu) 2024-04-09 08:06:12 -04:00
8f21d6dde0 Merge pull request #4112 from mdmontesinos/dev
fix #4103 - Visual Studio build acceleration breaks Oqtane Module build process
2024-04-08 14:32:09 -04:00
b74a6c9e03 Merge pull request #4118 from sbwalker/dev
removing StreamRendering attribute as recent SDK seems to have resolved earlier rendering issues
2024-04-08 14:31:52 -04:00
b63f73ef93 removing StreamRendering attribute as recent SDK seems to have resolved earlier rendering issues 2024-04-08 14:31:12 -04:00
1f0b369a15 Disable Accelerate Builds for Package project in Module template 2024-04-06 08:37:48 +02:00
7a43473513 Disable Accelerate Builds for Package project in Theme template 2024-04-06 08:36:13 +02:00
07f367a2a5 Merge pull request #4111 from sbwalker/dev
fix #4108 - content lost when adding image to RichTextEditor
2024-04-05 16:07:15 -04:00
c52ad68d92 fix #4108 - content lost when adding image to RichTextEditor 2024-04-05 16:07:01 -04:00
85467dbd2a Merge pull request #4106 from sbwalker/dev
update text in component to be consistent with resx
2024-04-04 12:01:01 -04:00
aa767846f0 update text in component to be consistent with resx 2024-04-04 12:00:52 -04:00
6d3ad15d20 Merge pull request #4105 from sbwalker/dev
modify #4099 - fix localization and use Delete rather than Clear in API methods for consistency with rest of framework
2024-04-04 11:58:22 -04:00
7b95db4d13 modify #4099 - fix localization and use Delete rather than Clear in API methods for consistency with rest of framework 2024-04-04 11:58:05 -04:00
160b3ff655 Merge pull request #4099 from zyhfish/task/fix-3625
Fix #3625: add the clear logs function.
2024-04-04 08:26:41 -04:00
Ben
757a39a75e update code by review result. 2024-04-03 22:27:39 +08:00
Ben
4c08a527be Fix #3625: add the clear logs function. 2024-04-03 09:21:13 +08:00
578b7b0512 Update issue templates 2024-04-02 16:43:43 -04:00
45e0259099 Update issue templates 2024-04-02 16:41:52 -04:00
1ac1933ec1 Update issue templates 2024-04-02 16:37:54 -04:00
43353e89bb Merge pull request #4098 from sbwalker/dev
fix ThemeSettings SetSetting() references to not specify IsPrivate property
2024-04-02 10:53:24 -04:00
010e4610f7 fix ThemeSettings SetSetting() references to not specify IsPrivate property 2024-04-02 10:53:07 -04:00
ba38853406 Merge pull request #4097 from sbwalker/dev
fix SiteMap so that it supports page Urls
2024-04-02 08:45:03 -04:00
4944a9e51e fix SiteMap so that it supports page Urls 2024-04-02 08:44:51 -04:00
73ad97859c Merge pull request #4093 from sbwalker/dev
fix #4091 - double slash generated for home page path ("/") and urlparameters
2024-04-01 15:11:38 -04:00
e600da229c fix #4091 - double slash generated for home page path ("/") and urlparameters 2024-04-01 15:11:20 -04:00
273b4f20db Merge pull request #4090 from sbwalker/dev
fix #4088 - redirect to login if not authenticated
2024-04-01 12:01:04 -04:00
9843dccdf0 fix #4088 - redirect to login if not authenticated 2024-04-01 12:00:53 -04:00
60ae1ec1e8 Merge pull request #4089 from W6HBR/dev
Fix incorrect parameter passed from ProfileService to ProfileController
2024-04-01 09:53:48 -04:00
650c6670f2 Fix incorrect parameter passed from ProfileService.cs to ProfileController.cs
ProfileService was passing SiteId instead of ProfileId which was causing updates to profile entries to fail with "Unauthorized Profile Put Attempt".
2024-03-31 10:08:19 -07:00
d6dcba7a60 Merge pull request #4083 from sbwalker/dev
use Constants.RequestVerificationToken rather than magic string
2024-03-29 11:19:33 -04:00
5b3849082f use Constants.RequestVerificationToken rather than magic string 2024-03-29 11:19:21 -04:00
5de988a2e6 Merge pull request #4082 from sbwalker/dev
remove changes to allow path to support urls - urls should be specified as redirects
2024-03-29 10:15:42 -04:00
26220b2f54 remove changes to allow path to support urls - urls should be specified as redirects 2024-03-29 10:15:24 -04:00
8d8436f1f1 Merge pull request #4081 from sbwalker/dev
set active tab correctly in RichTextEditor for scenarios where rich text editor is disabled
2024-03-29 07:50:27 -04:00
93057d9449 set active tab correctly in RichTextEditor for scenarios where rich text editor is disabled 2024-03-29 07:50:03 -04:00
b2419abdc8 Merge pull request #4079 from sbwalker/dev
fix #4073 - OIDC/OAuth2 flow with static rendering
2024-03-28 16:12:15 -04:00
9f654918ae fix #4073 - OIDC/OAuth2 flow with static rendering 2024-03-28 16:12:02 -04:00
cb086fe08d Merge pull request #4077 from zyhfish/task/fix-issue-4074
Fix #4074: use the correct property value.
2024-03-28 14:23:46 -04:00
1482166ba3 Merge pull request #4078 from sbwalker/dev
fix #4075 - auth cookie being rejected under some scenarios - change from Strict to Lax to match latest .NET Identity configuration
2024-03-28 14:23:31 -04:00
6b8dd9bf03 fix #4075 - auth cookie being rejected under some scenarios - change from Strict to Lax to match latest .NET Identity configuration 2024-03-28 14:23:13 -04:00
Ben
a8af9da249 Fix #4074: use the correct property value. 2024-03-28 22:18:30 +08:00
e410f82fdb Update README.md 2024-03-27 15:01:47 -04:00
4f70f228f1 Update README.md 2024-03-27 10:43:55 -04:00
ddc97b99fa Update README.md 2024-03-27 10:37:03 -04:00
5f42918cc9 Update README.md 2024-03-27 10:09:39 -04:00
e6dfe6fe89 Update README.md 2024-03-27 08:57:52 -04:00
62 changed files with 526 additions and 469 deletions

26
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@ -0,0 +1,26 @@
---
name: Bug Report
about: Create a bug report to help us improve the product
title: "[BUG] "
labels: ''
assignees: ''
---
### Oqtane Info
Version - #.#.#
Render Mode - Static
Interactivity - Server
Database - SQL Server
### Describe the bug
### Expected Behavior
### Steps To Reproduce
### Anything else?

View File

@ -0,0 +1,20 @@
---
name: Enhancement Request
about: 'Suggest a product enhancement '
title: "[ENH] "
labels: ''
assignees: ''
---
### Oqtane Info
Version - #.#.#
Render Mode - Static
Interactivity - Server
Database - SQL Server
### Describe the enhancement
### Anything else?

View File

@ -86,47 +86,48 @@ else
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="SaveSiteSettings">@SharedLocalizer["Save"]</button>
<button type="button" class="btn btn-success" @onclick="SaveSiteSettings">@SharedLocalizer["Save"]</button>
<ActionDialog Header="Clear Events" Message="Are You Sure You Wish To Remove All Log Events?" Action="DeleteLogs" Class="btn btn-danger" OnClick="@(async () => await DeleteLogs())" ResourceKey="DeleteLogs" />
</TabPanel>
</TabStrip>
}
@code {
private string _level = "-";
private string _function = "-";
private string _rows = "10";
private int _page = 1;
private List<Log> _logs;
private int _retention = 30;
private string _level = "-";
private string _function = "-";
private string _rows = "10";
private int _page = 1;
private List<Log> _logs;
private int _retention = 30;
public override string UrlParametersTemplate => "/{level}/{function}/{rows}/{page}";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
public override string UrlParametersTemplate => "/{level}/{function}/{rows}/{page}";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnParametersSetAsync()
{
try
{
if (UrlParameters.ContainsKey("level"))
{
_level = UrlParameters["level"];
}
if (UrlParameters.ContainsKey("function"))
{
_function = UrlParameters["function"];
}
if (UrlParameters.ContainsKey("rows"))
{
_rows = UrlParameters["rows"];
}
if (UrlParameters.ContainsKey("page") && int.TryParse(UrlParameters["page"], out int page))
{
_page = page;
}
protected override async Task OnParametersSetAsync()
{
try
{
if (UrlParameters.ContainsKey("level"))
{
_level = UrlParameters["level"];
}
if (UrlParameters.ContainsKey("function"))
{
_function = UrlParameters["function"];
}
if (UrlParameters.ContainsKey("rows"))
{
_rows = UrlParameters["rows"];
}
if (UrlParameters.ContainsKey("page") && int.TryParse(UrlParameters["page"], out int page))
{
_page = page;
}
await GetLogs();
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
_retention = int.Parse( SettingService.GetSetting(settings, "LogRetention", "30"));
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
_retention = int.Parse( SettingService.GetSetting(settings, "LogRetention", "30"));
}
catch (Exception ex)
{
@ -213,22 +214,37 @@ else
return classname;
}
private async Task SaveSiteSettings()
{
try
{
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
settings = SettingService.SetSetting(settings, "LogRetention", _retention.ToString(), true);
private async Task SaveSiteSettings()
{
try
{
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
settings = SettingService.SetSetting(settings, "LogRetention", _retention.ToString(), true);
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Site Settings {Error}", ex.Message);
AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error);
}
}
AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Site Settings {Error}", ex.Message);
AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error);
}
}
private async Task DeleteLogs()
{
try
{
await LogService.DeleteLogsAsync(PageState.Site.SiteId);
await GetLogs();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Logs {Error}", ex.Message);
AddModuleMessage(Localizer["Error.DeleteLogs"], MessageType.Error);
}
}
private void OnPageChange(int page)
{

View File

@ -385,45 +385,34 @@
page.ParentId = Int32.Parse(_parentid);
}
// path can be a link to an external url
if (!_path.Contains("://"))
if (string.IsNullOrEmpty(_path))
{
if (string.IsNullOrEmpty(_path))
{
_path = _name;
}
_path = _name;
}
(_path, string parameters) = Utilities.ParsePath(_path);
if (_path.Contains("/"))
if (_path.Contains("/"))
{
if (_path.EndsWith("/") && _path != "/")
{
if (_path.EndsWith("/") && _path != "/")
{
_path = _path.Substring(0, _path.Length - 1);
}
_path = _path.Substring(_path.LastIndexOf("/") + 1);
_path = _path.Substring(0, _path.Length - 1);
}
if (_parentid == "-1")
{
page.Path = Utilities.GetFriendlyUrl(_path);
}
else
{
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
if (parent.Path == string.Empty)
{
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
}
else
{
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
}
}
page.Path += parameters;
_path = _path.Substring(_path.LastIndexOf("/") + 1);
}
if (_parentid == "-1")
{
page.Path = Utilities.GetFriendlyUrl(_path);
}
else
{
page.Path = _path;
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
if (parent.Path == string.Empty)
{
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
}
else
{
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
}
}
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
@ -497,14 +486,7 @@
}
else
{
if (!page.Path.Contains("://"))
{
NavigationManager.NavigateTo(page.Path); // redirect to new page created
}
else
{
NavigationManager.NavigateTo(NavigateUrl("admin/pages"));
}
NavigationManager.NavigateTo(page.Path); // redirect to new page created
}
}
else

View File

@ -380,7 +380,7 @@
}
else
{
if (_path.Contains("/") & !_path.Contains("://"))
if (_path.Contains("/"))
{
_path = _path.Substring(_path.LastIndexOf("/") + 1);
}
@ -529,45 +529,34 @@
_page.ParentId = Int32.Parse(_parentid);
}
// path can be a link to an external url
if (!_path.Contains("://"))
if (string.IsNullOrEmpty(_path))
{
if (string.IsNullOrEmpty(_path))
{
_path = _name;
}
_path = _name;
}
(_path, string parameters) = Utilities.ParsePath(_path);
if (_path.Contains("/"))
if (_path.Contains("/"))
{
if (_path.EndsWith("/") && _path != "/")
{
if (_path.EndsWith("/") && _path != "/")
{
_path = _path.Substring(0, _path.Length - 1);
}
_path = _path.Substring(_path.LastIndexOf("/") + 1);
_path = _path.Substring(0, _path.Length - 1);
}
if (_parentid == "-1")
{
_page.Path = Utilities.GetFriendlyUrl(_path);
}
else
{
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == _page.ParentId);
if (parent.Path == string.Empty)
{
_page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
}
else
{
_page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
}
}
_page.Path += parameters;
_path = _path.Substring(_path.LastIndexOf("/") + 1);
}
if (_parentid == "-1")
{
_page.Path = Utilities.GetFriendlyUrl(_path);
}
else
{
_page.Path = _path;
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == _page.ParentId);
if (parent.Path == string.Empty)
{
_page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
}
else
{
_page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
}
}
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
@ -658,14 +647,7 @@
}
else
{
if (!_page.Path.Contains("://"))
{
NavigationManager.NavigateTo(NavigateUrl(), true); // redirect to page being edited
}
else
{
NavigationManager.NavigateTo(NavigateUrl("admin/pages"));
}
NavigationManager.NavigateTo(NavigateUrl(), true); // redirect to page being edited
}
}
else

View File

@ -26,6 +26,12 @@
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="process" HelpText="Indicates if the current process is 32 bit or 64 bit" ResourceKey="Process">Process: </Label>
<div class="col-sm-9">
<input id="process" class="form-control" @bind="@_process" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="machinename" HelpText="Machine Name" ResourceKey="MachineName">Machine Name: </Label>
<div class="col-sm-9">
@ -62,12 +68,6 @@
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="tickcount" HelpText="Amount Of Time The Service Has Been Available And Operational" ResourceKey="TickCount">Service Uptime: </Label>
<div class="col-sm-9">
<input id="tickcount" class="form-control" @bind="@_tickcount" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="workingset" HelpText="Memory Allocation Of Service (in MB)" ResourceKey="WorkingSet">Memory Allocation: </Label>
<div class="col-sm-9">
@ -165,13 +165,13 @@
private string _version = string.Empty;
private string _clrversion = string.Empty;
private string _osversion = string.Empty;
private string _machinename = string.Empty;
private string _process = string.Empty;
private string _machinename = string.Empty;
private string _ipaddress = string.Empty;
private string _environment = string.Empty;
private string _contentrootpath = string.Empty;
private string _webrootpath = string.Empty;
private string _servertime = string.Empty;
private string _tickcount = string.Empty;
private string _workingset = string.Empty;
private string _installationid = string.Empty;
@ -192,13 +192,13 @@
{
_clrversion = systeminfo["CLRVersion"].ToString();
_osversion = systeminfo["OSVersion"].ToString();
_machinename = systeminfo["MachineName"].ToString();
_process = systeminfo["Process"].ToString();
_machinename = systeminfo["MachineName"].ToString();
_ipaddress = systeminfo["IPAddress"].ToString();
_environment = systeminfo["Environment"].ToString();
_contentrootpath = systeminfo["ContentRootPath"].ToString();
_webrootpath = systeminfo["WebRootPath"].ToString();
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
_tickcount = TimeSpan.FromMilliseconds(Convert.ToInt64(systeminfo["TickCount"].ToString())).ToString();
_workingset = (Convert.ToInt64(systeminfo["WorkingSet"].ToString()) / 1000000).ToString() + " MB";
}

View File

@ -54,7 +54,7 @@ else
<div class="modal-header">
<h5 class="modal-title">@Header</h5>
<form method="post" @formname="@($"ActionDialogCloseForm{Id}")" @onsubmit="DisplayModal" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="btn-close" aria-label="Close"></button>
</form>
</div>
@ -65,12 +65,12 @@ else
@if (!string.IsNullOrEmpty(Action))
{
<form method="post" @formname="@($"ActionDialogConfirmForm{Id}")" @onsubmit="Confirm" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="@Class">@((MarkupString)_iconSpan) @Text</button>
</form>
}
<form method="post" @formname="@($"ActionDialogCancelForm{Id}")" @onsubmit="DisplayModal" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="btn btn-secondary">@SharedLocalizer["Cancel"]</button>
</form>
</div>
@ -88,7 +88,7 @@ else
else
{
<form method="post" @formname="@($"ActionDialogActionForm{Id}")" @onsubmit="DisplayModal" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="@Class">@((MarkupString)_iconSpan) @Text</button>
</form>
}

View File

@ -99,7 +99,7 @@
if (!string.IsNullOrEmpty(Text))
{
_text = Localize(nameof(Text), _text);
_text = Localize(nameof(Text), Text);
}
else
{

View File

@ -13,7 +13,7 @@
<NavLink class="ms-2" href="@NavigateUrl("admin/log")">View Details</NavLink>
}
<form method="post" @onsubmit="DismissModal" @formname="@_formname" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="btn-close" aria-label="Close"></button>
</form>
}

View File

@ -73,7 +73,7 @@
@if (!string.IsNullOrEmpty(SearchProperties))
{
<form method="post" autocomplete="off" @formname="PagerForm" @onsubmit="Search" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<div class="input-group my-3">
<input type="text" id="pagersearch" name="_search" class="form-control" placeholder=@string.Format(Localizer["SearchPlaceholder"], FormatSearchProperties()) @bind="@_search" />
<button type="submit" class="btn btn-primary">@SharedLocalizer["Search"]</button>

View File

@ -63,8 +63,7 @@
</span>
}
</div>
<div @ref="@_editorElement">
</div>
<div @ref="@_editorElement"></div>
</div>
</div>
</TabPanel>
@ -91,11 +90,11 @@
</div>
@if (ReadOnly)
{
<textarea id="rawhtmleditor" class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10" readonly></textarea>
<textarea id="@_rawhtmlid" class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10" readonly></textarea>
}
else
{
<textarea id="rawhtmleditor" class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10"></textarea>
<textarea id="@_rawhtmlid" class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10"></textarea>
}
</TabPanel>
}
@ -104,17 +103,25 @@
</div>
@code {
private bool _initialized = false;
private RichTextEditorInterop interop;
private FileManager _fileManager;
private string _activetab = "Rich";
private ElementReference _editorElement;
private ElementReference _toolBar;
private bool _richfilemanager = false;
private FileManager _fileManager;
private string _richhtml = string.Empty;
private string _originalrichhtml = string.Empty;
private bool _rawfilemanager = false;
private string _rawhtmlid = "RawHtmlEditor_" + Guid.NewGuid().ToString("N");
private string _rawhtml = string.Empty;
private string _originalrawhtml = string.Empty;
private string _message = string.Empty;
private string _activetab = "Rich";
private bool _contentchanged = false;
[Parameter]
public string Content { get; set; }
@ -123,7 +130,7 @@
public bool ReadOnly { get; set; } = false;
[Parameter]
public string Placeholder { get; set; } = "Enter Your Content...";
public string Placeholder { get; set; }
[Parameter]
public bool AllowFileManagement { get; set; } = true;
@ -146,20 +153,29 @@
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js", Location = ResourceLocation.Body },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js", Location = ResourceLocation.Body },
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js", Location = ResourceLocation.Body }
};
protected override void OnInitialized()
{
interop = new RichTextEditorInterop(JSRuntime);
if (string.IsNullOrEmpty(Placeholder))
{
Placeholder = Localizer["Placeholder"];
}
}
protected override void OnParametersSet()
{
_richhtml = Content;
_rawhtml = Content;
_originalrawhtml = _rawhtml; // preserve for comparison later
_originalrichhtml = "";
_contentchanged = true; // identifies when Content parameter has changed
// Quill wraps content in <p> tags which can be used as a signal to set the active tab
if (!string.IsNullOrEmpty(Content) && !Content.StartsWith("<p>") && AllowRawHtml)
if (!AllowRichText)
{
_activetab = "Raw";
}
@ -171,8 +187,6 @@
if (AllowRichText)
{
var interop = new RichTextEditorInterop(JSRuntime);
if (firstRender)
{
await interop.CreateEditor(
@ -182,15 +196,38 @@
Placeholder,
Theme,
DebugLevel);
}
await interop.LoadEditorContent(_editorElement, _richhtml);
await interop.LoadEditorContent(_editorElement, _richhtml);
if (string.IsNullOrEmpty(_originalrichhtml))
{
// preserve a copy of the rich text content (Quill sanitizes content so we need to retrieve it from the editor)
// preserve a copy of the content (Quill sanitizes content so we need to retrieve it from the editor as it may have been modified)
_originalrichhtml = await interop.GetHtml(_editorElement);
_initialized = true;
}
else
{
if (_initialized)
{
if (_contentchanged)
{
// reload editor if Content passed to component has changed
await interop.LoadEditorContent(_editorElement, _richhtml);
_originalrichhtml = await interop.GetHtml(_editorElement);
}
else
{
// preserve changed content on re-render event
var richhtml = await interop.GetHtml(_editorElement);
if (richhtml != _richhtml)
{
_richhtml = richhtml;
await interop.LoadEditorContent(_editorElement, _richhtml);
}
}
}
}
_contentchanged = false;
}
}
@ -218,23 +255,27 @@
else
{
var richhtml = "";
if (AllowRichText)
{
// return rich text content if it has changed
var interop = new RichTextEditorInterop(JSRuntime);
richhtml = await interop.GetHtml(_editorElement);
}
// rich text value will only be blank if AllowRichText is disabled or the JS Interop method failed
if (richhtml != _originalrichhtml && !string.IsNullOrEmpty(richhtml) && !string.IsNullOrEmpty(_originalrichhtml))
{
return richhtml;
}
else
{
// return original raw html content
return _originalrawhtml;
}
}
if (richhtml != _originalrichhtml && !string.IsNullOrEmpty(richhtml))
{
// convert Quill's empty content to empty string
if (richhtml == "<p><br></p>")
{
richhtml = string.Empty;
}
return richhtml;
}
else
{
// return original raw html content
return _originalrawhtml;
}
}
}
public async Task InsertRichImage()
@ -245,7 +286,6 @@
var file = _fileManager.GetFile();
if (file != null)
{
var interop = new RichTextEditorInterop(JSRuntime);
await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name));
_richhtml = await interop.GetHtml(_editorElement);
_richfilemanager = false;
@ -271,7 +311,7 @@
if (file != null)
{
var interop = new Interop(JSRuntime);
int pos = await interop.GetCaretPosition("rawhtmleditor");
int pos = await interop.GetCaretPosition(_rawhtmlid);
var image = "<img src=\"" + file.Url + "\" alt=\"" + ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name) + "\" class=\"img-fluid\">";
_rawhtml = _rawhtml.Substring(0, pos) + image + _rawhtml.Substring(pos);
_rawfilemanager = false;

View File

@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<Configurations>Debug;Release</Configurations>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -12,7 +12,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>
@ -22,9 +22,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
</ItemGroup>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -153,7 +153,7 @@
<data name="Integrated" xml:space="preserve">
<value>Integrated</value>
</data>
<data name="Encryption,Text" xml:space="preserve">
<data name="Encryption.Text" xml:space="preserve">
<value>Encryption:</value>
</data>
<data name="Encryption.HelpText" xml:space="preserve">

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -210,4 +210,16 @@
<data name="Success.SaveSiteSettings" xml:space="preserve">
<value>Settings Saved Successfully</value>
</data>
<data name="DeleteLogs.Header" xml:space="preserve">
<value>Clear Events</value>
</data>
<data name="DeleteLogs.Message" xml:space="preserve">
<value>Are You Sure You Wish To Remove All Log Events?</value>
</data>
<data name="DeleteLogs.Text" xml:space="preserve">
<value>Clear Events</value>
</data>
<data name="Error.DeleteLogs" xml:space="preserve">
<value>Error Deleting Log Events</value>
</data>
</root>

View File

@ -255,12 +255,6 @@
<data name="MachineName.Text" xml:space="preserve">
<value>Machine Name:</value>
</data>
<data name="TickCount.HelpText" xml:space="preserve">
<value>Amount Of Time The Service Has Been Available And Operational</value>
</data>
<data name="TickCount.Text" xml:space="preserve">
<value>Service Uptime:</value>
</data>
<data name="WebRootPath.HelpText" xml:space="preserve">
<value>Server Web Root Path</value>
</data>
@ -294,4 +288,10 @@
<data name="Error.ClearLog" xml:space="preserve">
<value>Ann Error Occurred Clearing The System Log</value>
</data>
<data name="Process.HelpText" xml:space="preserve">
<value>Indicates if the current process is 32 bit or 64 bit</value>
</data>
<data name="Process.Text" xml:space="preserve">
<value>Process: </value>
</data>
</root>

View File

@ -126,4 +126,7 @@
<data name="Message.Require.Image" xml:space="preserve">
<value>You Must Select An Image To Insert</value>
</data>
<data name="Placeholder" xml:space="preserve">
<value>Enter Your Content...</value>
</data>
</root>

View File

@ -29,6 +29,13 @@ namespace Oqtane.Services
/// <returns></returns>
Task<Log> GetLogAsync(int logId);
/// <summary>
/// Clear the entire logs of the given site.
/// </summary>
/// <param name="siteId"></param>
/// <returns></returns>
Task DeleteLogsAsync(int siteId);
/// <summary>
/// Creates a new log entry
/// </summary>

View File

@ -35,6 +35,11 @@ namespace Oqtane.Services
return await GetJsonAsync<Log>($"{Apiurl}/{logId}");
}
public async Task DeleteLogsAsync(int siteId)
{
await DeleteAsync($"{Apiurl}?siteid={siteId}");
}
public async Task Log(int? pageId, int? moduleId, int? userId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args)
{
await Log(null, pageId, moduleId, userId, category, feature, function, level, exception, message, args);

View File

@ -33,7 +33,7 @@ namespace Oqtane.Services
public async Task<Profile> UpdateProfileAsync(Profile profile)
{
return await PutJsonAsync<Profile>($"{Apiurl}/{profile.SiteId}", profile);
return await PutJsonAsync<Profile>($"{Apiurl}/{profile.ProfileId}", profile);
}
public async Task DeleteProfileAsync(int profileId)
{

View File

@ -9,7 +9,7 @@
<div class="modal-header">
<h5 class="modal-title"><ModuleTitle /></h5>
<form method="post" class="app-form-inline" @formname="AdminContainerForm" @onsubmit="@CloseModal" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="btn-close" aria-label="Close"></button>
</form>
</div>

View File

@ -12,7 +12,7 @@
@if (_showEditMode || (PageState.Page.IsPersonalizable && PageState.User != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered)))
{
<form method="post" class="app-form-inline" @formname="EditModeForm" @onsubmit="@(async () => await ToggleEditMode(PageState.EditMode))" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
@if (PageState.EditMode)
{
<button type="submit" class="btn @ButtonClass active" aria-pressed="true" autocomplete="off">

View File

@ -16,7 +16,7 @@
else
{
<form method="post" class="app-form-inline" action="@logouturl" @formname="LogoutForm">
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="hidden" name="returnurl" value="@returnurl" />
<button type="submit" class="btn btn-primary">@Localizer["Logout"]</button>
</form>

View File

@ -121,15 +121,15 @@
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
if (_login != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login, true);
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
}
if (_register != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Register", _register, true);
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Register", _register);
}
if (_footer != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer, true);
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer);
}
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
}

View File

@ -3,8 +3,6 @@
@using Oqtane.Shared
@inject SiteState SiteState
@implements IDisposable
@* the following StreamRendering attribute is required - if it is removed the framework will not render the content in static rendering *@
@attribute [StreamRendering]
@if (!string.IsNullOrEmpty(_title))
{

View File

@ -1,13 +1,13 @@
@namespace Oqtane.UI
@inject SiteState SiteState
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Interactive)
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
{
<StreamRenderingDisabled ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
}
else
{
<StreamRenderingEnabled ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="@InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, PageState.Site.Prerender)" />
}
@code {

View File

@ -3,8 +3,6 @@
@inject IInstallationService InstallationService
@inject IJSRuntime JSRuntime
@inject SiteState SiteState
@* the following StreamRendering attribute is required - if it is removed the framework will not render the content in static rendering *@
@attribute [StreamRendering]
@if (_initialized)
{

View File

@ -124,12 +124,20 @@
{
if (querystring.ContainsKey("reload") && querystring["reload"] == "post")
{
// post back so that the cookies are set correctly - required on any change to the principal
var interop = new Interop(JSRuntime);
var fields = new { returnurl = "/" + NavigationManager.ToBaseRelativePath(_absoluteUri) };
string url = Utilities.TenantUrl(SiteState.Alias, "/pages/external/");
await interop.SubmitForm(url, fields);
return;
if (PageState.RenderMode == RenderModes.Interactive)
{
// post back so that the cookies are set correctly - required on any change to the principal
var interop = new Interop(JSRuntime);
var fields = new { returnurl = "/" + NavigationManager.ToBaseRelativePath(_absoluteUri) };
string url = Utilities.TenantUrl(SiteState.Alias, "/pages/external/");
await interop.SubmitForm(url, fields);
return;
}
else
{
NavigationManager.NavigateTo(_absoluteUri.Replace("?reload=post", "").Replace("&reload=post", ""), true);
return;
}
}
else
{
@ -163,9 +171,9 @@
visitorId = PageState.VisitorId;
}
if (PageState.RenderMode == RenderModes.Interactive)
if (PageState != null && PageState.RenderMode == RenderModes.Interactive)
{
// process any sync events (for synchrozing the client application with the server)
// process any sync events (for synchronizing the client application with the server)
var sync = await SyncService.GetSyncEventsAsync(lastsyncdate);
lastsyncdate = sync.SyncDate;
if (sync.SyncEvents.Any())
@ -243,105 +251,97 @@
}
}
if (page != null)
// check if user is authorized to view page
if (page != null && UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList) && (Utilities.IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate) || UserSecurity.IsAuthorized(user, PermissionNames.Edit, page.PermissionList)))
{
// check if user is authorized to view page
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList) && (Utilities.IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate) || UserSecurity.IsAuthorized(user, PermissionNames.Edit, page.PermissionList)))
// edit mode
if (user != null)
{
// edit mode
if (user != null)
if (querystring.ContainsKey("editmode") && querystring["edit"] == "true")
{
if (querystring.ContainsKey("editmode") && querystring["edit"] == "true")
editmode = true;
}
else
{
editmode = (page.PageId == ((user.Settings.ContainsKey("CP-editmode")) ? int.Parse(user.Settings["CP-editmode"]) : -1));
if (!editmode)
{
editmode = true;
}
else
{
editmode = (page.PageId == ((user.Settings.ContainsKey("CP-editmode")) ? int.Parse(user.Settings["CP-editmode"]) : -1));
if (!editmode)
{
var userSettings = new Dictionary<string, string> { { "CP-editmode", "-1" } };
await SettingService.UpdateUserSettingsAsync(userSettings, user.UserId);
}
var userSettings = new Dictionary<string, string> { { "CP-editmode", "-1" } };
await SettingService.UpdateUserSettingsAsync(userSettings, user.UserId);
}
}
// load additional metadata for current page
page = ProcessPage(page, site, user, SiteState.Alias);
}
// load additional metadata for modules
(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
// load additional metadata for current page
page = ProcessPage(page, site, user, SiteState.Alias);
// populate page state (which acts as a client-side cache for subsequent requests)
_pagestate = new PageState
// load additional metadata for modules
(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
// populate page state (which acts as a client-side cache for subsequent requests)
_pagestate = new PageState
{
Alias = SiteState.Alias,
Site = site,
Page = page,
User = user,
Uri = new Uri(_absoluteUri, UriKind.Absolute),
Route = route,
QueryString = querystring,
UrlParameters = route.UrlParameters,
ModuleId = moduleid,
Action = action,
EditMode = editmode,
LastSyncDate = lastsyncdate,
RenderMode = RenderMode,
Runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime),
VisitorId = visitorId,
RemoteIPAddress = SiteState.RemoteIPAddress,
ReturnUrl = returnurl,
IsInternalNavigation = _isInternalNavigation,
RenderId = Guid.NewGuid(),
Refresh = false
};
OnStateChange?.Invoke(_pagestate);
if (PageState.RenderMode == RenderModes.Interactive)
{
await ScrollToFragment(_pagestate.Uri);
}
}
else
{
if (page == null)
{
// check for url mapping
var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath);
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
{
Alias = SiteState.Alias,
Site = site,
Page = page,
User = user,
Uri = new Uri(_absoluteUri, UriKind.Absolute),
Route = route,
QueryString = querystring,
UrlParameters = route.UrlParameters,
ModuleId = moduleid,
Action = action,
EditMode = editmode,
LastSyncDate = lastsyncdate,
RenderMode = RenderMode,
Runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime),
VisitorId = visitorId,
RemoteIPAddress = SiteState.RemoteIPAddress,
ReturnUrl = returnurl,
IsInternalNavigation = _isInternalNavigation,
RenderId = Guid.NewGuid(),
Refresh = false
};
OnStateChange?.Invoke(_pagestate);
if (PageState.RenderMode == RenderModes.Interactive)
{
await ScrollToFragment(_pagestate.Uri);
var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl + route.Query;
NavigationManager.NavigateTo(url, false);
return;
}
}
else
{
// Need to redirect 404 as page doesnot exist in a Permission or Timeframe
if (route.PagePath != "404")
{
// redirect to 404 page
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", ""));
}
}
}
else // page not found
{
// look for url mapping
var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath);
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
{
var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl + route.Query;
NavigationManager.NavigateTo(url, false);
}
else // not mapped
{
if (user == null)
{
// redirect to login page if user not logged in as they may need to be authenticated
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery)));
return;
}
else
{
if (route.PagePath != "404")
{
// redirect to 404 page
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", ""));
}
else
{
// redirect to home page as a fallback
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", ""));
}
}
}
// page not found or user does not have sufficient access
if (route.PagePath != "404")
{
// redirect to 404 page
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", ""));
}
else
{
// redirect to home page as a fallback
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", ""));
}
}
}

View File

@ -1,21 +0,0 @@
@attribute [StreamRendering(false)]
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
}
else
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="@InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, PageState.Site.Prerender)" />
}
@code {
[Parameter]
public SiteState SiteState { get; set; }
[Parameter]
public PageState PageState { get; set; }
[Parameter]
public Module ModuleState { get; set; }
}

View File

@ -1,21 +0,0 @@
@attribute [StreamRendering(true)]
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
}
else
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="@InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, PageState.Site.Prerender)" />
}
@code {
[Parameter]
public SiteState SiteState { get; set; }
[Parameter]
public PageState PageState { get; set; }
[Parameter]
public Module ModuleState { get; set; }
}

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
@ -34,7 +34,7 @@
<ItemGroup>
<PackageReference Include="EFCore.NamingConventions" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.4" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
</ItemGroup>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
@ -33,7 +33,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
</ItemGroup>
<ItemGroup>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -10,7 +10,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
@ -33,7 +33,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.4" />
</ItemGroup>
<ItemGroup>

View File

@ -6,7 +6,7 @@
<!-- <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> -->
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
<OutputType>Exe</OutputType>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -14,7 +14,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane.Maui</RootNamespace>
@ -31,7 +31,7 @@
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
<!-- Versions -->
<ApplicationDisplayVersion>5.1.0</ApplicationDisplayVersion>
<ApplicationDisplayVersion>5.1.1</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
@ -65,15 +65,15 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.4" />
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.10" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="8.0.10" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.20" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.20" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="8.0.20" />
</ItemGroup>
<ItemGroup>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Client</id>
<version>5.1.0</version>
<version>5.1.1</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Framework</id>
<version>5.1.0</version>
<version>5.1.1</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -11,8 +11,8 @@
<copyright>.NET Foundation</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v5.1.0/Oqtane.Framework.5.1.0.Upgrade.zip</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</releaseNotes>
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v5.1.1/Oqtane.Framework.5.1.1.Upgrade.zip</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane framework</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Server</id>
<version>5.1.0</version>
<version>5.1.1</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Shared</id>
<version>5.1.0</version>
<version>5.1.1</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Oqtane.Updater</id>
<version>5.1.0</version>
<version>5.1.1</version>
<authors>Shaun Walker</authors>
<owners>.NET Foundation</owners>
<title>Oqtane Framework</title>
@ -12,7 +12,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</releaseNotes>
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</releaseNotes>
<icon>icon.png</icon>
<tags>oqtane</tags>
</metadata>

View File

@ -1 +1 @@
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.0.Install.zip" -Force
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.1.Install.zip" -Force

View File

@ -1 +1 @@
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.0.Upgrade.zip" -Force
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.1.Upgrade.zip" -Force

View File

@ -76,5 +76,20 @@ namespace Oqtane.Controllers
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
}
[HttpDelete]
[Authorize(Roles = RoleNames.Admin)]
public void Delete(string siteId)
{
if (int.TryParse(siteId, out int parsedSiteId) && parsedSiteId == _alias.SiteId)
{
_logs.DeleteLogs(parsedSiteId, 0); // specifying zero for age results in all logs being deleted
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Log Delete Attempt {SiteId}", siteId);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
}
}
}

View File

@ -365,8 +365,8 @@ namespace Oqtane.Controllers
{
{ "FrameworkVersion", moduleDefinition.Version },
{ "ClientReference", $"<PackageReference Include=\"Oqtane.Client\" Version=\"{moduleDefinition.Version}\" />" },
{ "ServerReference", $"<PackageReference Include=\"Oqtane.Client\" Version=\"{moduleDefinition.Version}\" />" },
{ "SharedReference", $"<PackageReference Include=\"Oqtane.Client\" Version=\"{moduleDefinition.Version}\" />" },
{ "ServerReference", $"<PackageReference Include=\"Oqtane.Server\" Version=\"{moduleDefinition.Version}\" />" },
{ "SharedReference", $"<PackageReference Include=\"Oqtane.Shared\" Version=\"{moduleDefinition.Version}\" />" },
};
});
}

View File

@ -34,6 +34,7 @@ namespace Oqtane.Controllers
case "environment":
systeminfo.Add("CLRVersion", Environment.Version.ToString());
systeminfo.Add("OSVersion", Environment.OSVersion.ToString());
systeminfo.Add("Process", (Environment.Is64BitProcess) ? "64 Bit" : "32 Bit");
systeminfo.Add("MachineName", Environment.MachineName);
systeminfo.Add("WorkingSet", Environment.WorkingSet.ToString());
systeminfo.Add("TickCount", Environment.TickCount64.ToString());

View File

@ -157,7 +157,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Events.OnRedirectToLogin = context =>
{

View File

@ -93,6 +93,7 @@ namespace Oqtane.Infrastructure
}
var result = new StringBuilder();
source = source.Replace("[[", "[$_["); //avoid nested square bracket issue.
foreach (Match match in this.TokenizerRegex.Matches(source))
{
var key = match.Result("${key}");
@ -126,7 +127,7 @@ namespace Oqtane.Infrastructure
result.Append(match.Result("${text}"));
}
}
result.Replace("[$_", "["); //restore the changes.
return result.ToString();
}

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Configurations>Debug;Release</Configurations>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -11,7 +11,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>
@ -33,19 +33,19 @@
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.3">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.4" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.3" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.4" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.4" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.8" />
</ItemGroup>
<ItemGroup>

View File

@ -47,14 +47,23 @@ namespace Oqtane.Pages
var sitemap = new List<Sitemap>();
// build site map
var rooturl = _alias.Protocol + (string.IsNullOrEmpty(_alias.Path) ? _alias.Name : _alias.Name.Substring(0, _alias.Name.IndexOf("/")));
var moduleDefinitions = _moduleDefinitions.GetModuleDefinitions(_alias.SiteId).ToList();
var pageModules = _pageModules.GetPageModules(_alias.SiteId);
foreach (var page in _pages.GetPages(_alias.SiteId))
{
if (_userPermissions.IsAuthorized(null, PermissionNames.View, page.PermissionList) && page.IsNavigation)
{
var rooturl = _alias.Protocol + (string.IsNullOrEmpty(_alias.Path) ? _alias.Name : _alias.Name.Substring(0, _alias.Name.IndexOf("/")));
sitemap.Add(new Sitemap { Url = rooturl + Utilities.NavigateUrl(_alias.Path, page.Path, ""), ModifiedOn = DateTime.UtcNow });
var pageurl = rooturl;
if (string.IsNullOrEmpty(page.Url))
{
pageurl += Utilities.NavigateUrl(_alias.Path, page.Path, "");
}
else
{
pageurl += (page.Url.StartsWith("/") ? "" : "/") + page.Url;
}
sitemap.Add(new Sitemap { Url = pageurl, ModifiedOn = DateTime.UtcNow });
foreach (var pageModule in pageModules.Where(item => item.PageId == page.PageId))
{

View File

@ -59,14 +59,14 @@ namespace Oqtane.Repository
// delete logs in batches of 100 records
var count = 0;
var purgedate = DateTime.UtcNow.AddDays(-age);
var logs = db.Log.Where(item => item.SiteId == siteId && item.Level != "Error" && item.LogDate < purgedate)
var logs = db.Log.Where(item => item.SiteId == siteId && item.LogDate < purgedate)
.OrderBy(item => item.LogDate).Take(100).ToList();
while (logs.Count > 0)
{
count += logs.Count;
db.Log.RemoveRange(logs);
db.SaveChanges();
logs = db.Log.Where(item => item.SiteId == siteId && item.Level != "Error" && item.LogDate < purgedate)
logs = db.Log.Where(item => item.SiteId == siteId && item.LogDate < purgedate)
.OrderBy(item => item.LogDate).Take(100).ToList();
}
return count;

View File

@ -22,6 +22,7 @@ using Oqtane.UI;
using OqtaneSSR.Extensions;
using Microsoft.AspNetCore.Components.Authorization;
using Oqtane.Providers;
using Microsoft.AspNetCore.Cors.Infrastructure;
namespace Oqtane
{
@ -135,7 +136,7 @@ namespace Oqtane
{
// allow .NET MAUI client cross origin calls
policy.WithOrigins("https://0.0.0.0", "http://0.0.0.0", "app://0.0.0.0")
.AllowAnyHeader().AllowCredentials();
.AllowAnyHeader().AllowAnyMethod().AllowCredentials();
});
});
@ -169,7 +170,7 @@ namespace Oqtane
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISyncManager sync, ILogger<Startup> logger)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISyncManager sync, ICorsService corsService, ICorsPolicyProvider corsPolicyProvider, ILogger<Startup> logger)
{
if (!string.IsNullOrEmpty(_configureServicesErrors))
{
@ -198,7 +199,16 @@ namespace Oqtane
app.UseOqtaneLocalization();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
OnPrepareResponse = (ctx) =>
{
var policy = corsPolicyProvider.GetPolicyAsync(ctx.Context, Constants.MauiCorsPolicy)
.ConfigureAwait(false).GetAwaiter().GetResult();
corsService.ApplyResult(corsService.EvaluatePolicy(ctx.Context, policy), ctx.Context.Response);
}
});
app.UseExceptionMiddleWare();
app.UseTenantResolution();
app.UseJwtAuthorization();

View File

@ -13,9 +13,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.4" />
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />

View File

@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<AccelerateBuildsInVisualStudio>false</AccelerateBuildsInVisualStudio>
</PropertyGroup>
<ItemGroup>

View File

@ -19,10 +19,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.4" />
</ItemGroup>
<ItemGroup>

View File

@ -108,12 +108,12 @@
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
if (_login != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login, true);
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
}
if (_register != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Register", _register, true);
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Register", _register);
}
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
}

View File

@ -12,9 +12,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.4" />
</ItemGroup>
<ItemGroup>

View File

@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<AccelerateBuildsInVisualStudio>false</AccelerateBuildsInVisualStudio>
</PropertyGroup>
<ItemGroup>

View File

@ -35,6 +35,9 @@ app {
}
/* Action Dialog */
.app-actiondialog{
position: absolute;
}
.app-actiondialog .modal {
position: fixed; /* Stay in place */
z-index: 9999; /* Sit on top */

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Configurations>Debug;Release</Configurations>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -11,7 +11,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>
@ -19,8 +19,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.3" />

View File

@ -4,8 +4,8 @@ namespace Oqtane.Shared
{
public class Constants
{
public static readonly string Version = "5.1.0";
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,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0";
public static readonly string Version = "5.1.1";
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,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.1.1";
public const string PackageId = "Oqtane.Framework";
public const string ClientId = "Oqtane.Client";
public const string UpdaterPackageId = "Oqtane.Updater";

View File

@ -21,86 +21,50 @@ namespace Oqtane.Shared
return $"{type.Namespace}, {assemblyName}";
}
public static (string UrlParameters, string Querystring, string Fragment) ParseParameters(string url)
public static (string UrlParameters, string Querystring, string Fragment) ParseParameters(string parameters)
{
// /path/urlparameters
// /urlparameters /urlparameters?Id=1 /urlparameters#5 /urlparameters?Id=1#5 /urlparameters?reload#5
// Id=1 Id=1#5 reload#5 reload
// #5
if (!url.Contains("://"))
{
if (!url.StartsWith("/")) // urlparameters always start with "/"
{
url = ((!url.StartsWith("#")) ? "?" : "/") + url;
}
url = Constants.PackageRegistryUrl + url; // create absolute url
}
var uri = new Uri(url);
// create absolute url to convert to Uri
parameters = (!parameters.StartsWith("/") && !parameters.StartsWith("#") ? "?" : "") + parameters;
parameters = Constants.PackageRegistryUrl + parameters;
var uri = new Uri(parameters);
var querystring = uri.Query.Replace("?", "");
var fragment = uri.Fragment.Replace("#", "");
var urlparameters = uri.LocalPath;
urlparameters = (urlparameters == "/") ? "" : urlparameters;
if (urlparameters.Contains(Constants.UrlParametersDelimiter))
{
urlparameters = urlparameters.Substring(urlparameters.IndexOf(Constants.UrlParametersDelimiter) + 1);
}
return (urlparameters, querystring, fragment);
}
public static (string Path, string Parameters) ParsePath(string url)
{
url = ((!url.StartsWith("/") && !url.Contains("://")) ? "/" : "") + url;
(string path, string querystring, string fragment) = ParseParameters(url);
var uriBuilder = new UriBuilder
{
Path = path,
Query = querystring,
Fragment = fragment
};
return (uriBuilder.Path, uriBuilder.Uri.Query + uriBuilder.Uri.Fragment);
}
public static string NavigateUrl(string alias, string path, string parameters)
{
string querystring = "";
string fragment = "";
if (!string.IsNullOrEmpty(parameters))
{
// parse path
(path, _) = ParsePath(path);
// parse parameters
(string urlparameters, string querystring, string fragment) = ParseParameters(parameters);
// add urlparameters to path
(string urlparameters, querystring, fragment) = ParseParameters(parameters);
if (!string.IsNullOrEmpty(urlparameters))
{
if (urlparameters.StartsWith("/")) urlparameters = urlparameters.Remove(0, 1);
path += $"/{Constants.UrlParametersDelimiter}/{urlparameters}";
path += (path.EndsWith("/") ? "" : "/") + $"{Constants.UrlParametersDelimiter}/{urlparameters.Substring(1)}";
}
// build url
var uriBuilder = new UriBuilder
{
Path = !string.IsNullOrEmpty(alias)
? (!string.IsNullOrEmpty(path)) ? $"{alias}{path}": $"{alias}"
: $"{path}",
Query = querystring,
Fragment = fragment
};
path = uriBuilder.Uri.PathAndQuery;
}
else
// build url
var uriBuilder = new UriBuilder
{
path = ((!string.IsNullOrEmpty(alias)) ? alias + (!path.StartsWith("/") ? "/" : "") : "") + path;
}
Path = !string.IsNullOrEmpty(alias)
? (!string.IsNullOrEmpty(path)) ? $"{alias}{path}": $"{alias}"
: $"{path}",
Query = querystring,
Fragment = fragment
};
return path;
return uriBuilder.Uri.PathAndQuery;
}
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
@ -185,6 +149,7 @@ namespace Oqtane.Shared
break;
case "render":
content = content.Replace(Constants.FileUrl, alias?.BaseUrl + aliasUrl + Constants.FileUrl);
content = content.Replace("[wwwroot]", alias?.BaseUrl + aliasUrl + "/");
// legacy
content = content.Replace("[siteroot]", UrlCombine("Content", "Tenants", alias.TenantId.ToString(), "Sites", alias.SiteId.ToString()));
content = content.Replace(Constants.ContentUrl, alias.Path + Constants.ContentUrl);

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<Version>5.1.0</Version>
<Version>5.1.1</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -11,7 +11,7 @@
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0</PackageReleaseNotes>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<RootNamespace>Oqtane</RootNamespace>

View File

@ -1,6 +1,6 @@
# Latest Release
[5.0.2](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2) was released on Jan 25, 2024 and is a stabilization release targeted at .NET 8. This release includes 51 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 4600. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
[5.1.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0) was released on Mar 27, 2024 and is a major release providing Static Server Rendering support for Blazor in .NET 8. This release includes 263 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 5100. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json)
@ -63,8 +63,12 @@ Backlog (TBD)
- [ ] Folder Providers
- [ ] Generative AI Integration
5.1.0 (Q1 2024)
- [ ] Full Stack Blazor (Static Server-Side Rendering)
5.1.1 (Apr 2024)
- [ ] Stabilization improvements
[5.1.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0) (Mar 27, 2024)
- [x] Migration to the new unified Blazor approach in .NET 8 (ie. blazor.web.js)
- [x] Static Server Rendering (SSR) support
[5.0.2](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2) (Jan 25, 2024)
- [x] Stabilization improvements