Merge branch 'dev' into Packages

This commit is contained in:
Leigh Pointer
2025-04-22 09:13:15 +02:00
committed by GitHub
10 changed files with 119 additions and 100 deletions

View File

@ -15,7 +15,7 @@
{ {
<div class="container"> <div class="container">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Specify if you want to backup files during the upgrade process. Disabling this option will result in a better experience in some environments." ResourceKey="Backup">Backup Files? </Label> <Label Class="col-sm-3" HelpText="Specify if you want to backup files during the upgrade process. Disabling this option will reduce the time required for the upgrade." ResourceKey="Backup">Backup Files? </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<select id="backup" class="form-select" @bind="@_backup"> <select id="backup" class="form-select" @bind="@_backup">
<option value="True">@SharedLocalizer["Yes"]</option> <option value="True">@SharedLocalizer["Yes"]</option>
@ -24,10 +24,15 @@
</div> </div>
</div> </div>
</div> </div>
<button type="button" class="btn btn-primary" @onclick=@(async () => await Download(Constants.PackageId, @_package.Version))>@SharedLocalizer["Download"] @_package.Version</button> <br />
<button type="button" class="btn btn-success" @onclick="Upgrade">@SharedLocalizer["Upgrade"]</button> @if (!_downloaded)
<br /><br /> {
<ModuleMessage Type="MessageType.Info" Message="Select The Download Button To Download The Framework Upgrade Package And Then Select Upgrade"></ModuleMessage> <button type="button" class="btn btn-primary" @onclick=@(async () => await Download(Constants.PackageId, @_package.Version))>@SharedLocalizer["Download"] @_package.Version</button>
}
else
{
<button type="button" class="btn btn-success" @onclick="Upgrade">@SharedLocalizer["Upgrade"]</button>
}
} }
else else
{ {
@ -43,7 +48,7 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Specify if you want to backup files during the upgrade process. Disabling this option will result in a better experience in some environments." ResourceKey="Backup">Backup Files? </Label> <Label Class="col-sm-3" HelpText="Specify if you want to backup files during the upgrade process. Disabling this option will reduce the time required for the upgrade." ResourceKey="Backup">Backup Files? </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<select id="backup" class="form-select" @bind="@_backup"> <select id="backup" class="form-select" @bind="@_backup">
<option value="True">@SharedLocalizer["Yes"]</option> <option value="True">@SharedLocalizer["Yes"]</option>
@ -52,15 +57,15 @@
</div> </div>
</div> </div>
</div> </div>
<br />
<button type="button" class="btn btn-success" @onclick="Upgrade">@SharedLocalizer["Upgrade"]</button> <button type="button" class="btn btn-success" @onclick="Upgrade">@SharedLocalizer["Upgrade"]</button>
<br /><br />
<ModuleMessage Type="MessageType.Info" Message=@Localizer["MessageUpgrade.Text"]></ModuleMessage>
</TabPanel> </TabPanel>
</TabStrip> </TabStrip>
} }
@code { @code {
private bool _initialized = false; private bool _initialized = false;
private bool _downloaded = false;
private Package _package; private Package _package;
private bool _upgradeavailable = false; private bool _upgradeavailable = false;
private string _backup = "True"; private string _backup = "True";
@ -125,6 +130,7 @@
ShowProgressIndicator(); ShowProgressIndicator();
await PackageService.DownloadPackageAsync(packageid, version); await PackageService.DownloadPackageAsync(packageid, version);
await PackageService.DownloadPackageAsync(Constants.UpdaterPackageId, version); await PackageService.DownloadPackageAsync(Constants.UpdaterPackageId, version);
_downloaded = true;
HideProgressIndicator(); HideProgressIndicator();
AddModuleMessage(Localizer["Success.Framework.Download"], MessageType.Success); AddModuleMessage(Localizer["Success.Framework.Download"], MessageType.Success);
} }

View File

@ -8,9 +8,12 @@
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate> <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container"> <div class="container">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="url" HelpText="The fully qualified Url for this site" ResourceKey="Url">Url:</Label> <Label Class="col-sm-3" For="url" HelpText="An absolute Url for this site" ResourceKey="Url">Url:</Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="url" class="form-control" @bind="@_url" maxlength="500" required /> <div class="input-group">
<input id="url" class="form-control" @bind="@_url" maxlength="500" required />
<button type="button" class="btn btn-primary" @onclick="GenerateUrl">@Localizer["Generate"]</button>
</div>
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
@ -26,64 +29,80 @@
</form> </form>
@code { @code {
private ElementReference form; private ElementReference form;
private bool validated = false; private bool validated = false;
private string _url = string.Empty; private string _url = string.Empty;
private string _mappedurl = string.Empty; private string _mappedurl = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
private async Task SaveUrlMapping() private async Task SaveUrlMapping()
{ {
validated = true; validated = true;
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
if (await interop.FormValid(form)) if (await interop.FormValid(form))
{ {
if (_url != _mappedurl) if (_url != _mappedurl)
{ {
var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/"; var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/";
url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : ""); url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : "");
_url = (_url.StartsWith("/")) ? _url.Substring(1) : _url; _url = (_url.StartsWith("/")) ? _url.Substring(1) : _url;
_url = (!_url.StartsWith("http")) ? url + _url : _url; _url = (!_url.StartsWith("http")) ? url + _url : _url;
if (_url.StartsWith(url)) _mappedurl = _mappedurl.Replace(url, "");
{ _mappedurl = (_mappedurl.StartsWith("/") && _mappedurl != "/") ? _mappedurl.Substring(1) : _mappedurl;
var urlmapping = new UrlMapping();
urlmapping.SiteId = PageState.Site.SiteId;
var route = new Route(_url, PageState.Alias.Path);
urlmapping.Url = route.PagePath;
urlmapping.MappedUrl = _mappedurl.Replace(url, "");
urlmapping.Requests = 0;
urlmapping.CreatedOn = DateTime.UtcNow;
urlmapping.RequestedOn = DateTime.UtcNow;
try if (_url.StartsWith(url))
{ {
urlmapping = await UrlMappingService.AddUrlMappingAsync(urlmapping); var urlmapping = new UrlMapping();
await logger.LogInformation("UrlMapping Saved {UrlMapping}", urlmapping); urlmapping.SiteId = PageState.Site.SiteId;
NavigationManager.NavigateTo(NavigateUrl()); urlmapping.Url = new Route(_url, PageState.Alias.Path).PagePath;
} urlmapping.MappedUrl = _mappedurl;
catch (Exception ex) urlmapping.Requests = 0;
{ urlmapping.CreatedOn = DateTime.UtcNow;
await logger.LogError(ex, "Error Saving UrlMapping {UrlMapping} {Error}", urlmapping, ex.Message); urlmapping.RequestedOn = DateTime.UtcNow;
AddModuleMessage(Localizer["Error.SaveUrlMapping"], MessageType.Error);
} try
} {
else urlmapping = await UrlMappingService.AddUrlMappingAsync(urlmapping);
{ await logger.LogInformation("UrlMapping Saved {UrlMapping}", urlmapping);
AddModuleMessage(Localizer["Message.SaveUrlMapping"], MessageType.Warning); NavigationManager.NavigateTo(NavigateUrl());
} }
} catch (Exception ex)
else {
{ await logger.LogError(ex, "Error Saving UrlMapping {UrlMapping} {Error}", urlmapping, ex.Message);
AddModuleMessage(Localizer["Error.SaveUrlMapping"], MessageType.Error);
}
}
else
{
AddModuleMessage(Localizer["Message.SaveUrlMapping"], MessageType.Warning);
}
}
else
{
AddModuleMessage(Localizer["Message.DuplicateUrlMapping"], MessageType.Warning); AddModuleMessage(Localizer["Message.DuplicateUrlMapping"], MessageType.Warning);
} }
} }
else else
{ {
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
} }
} }
private void GenerateUrl()
{
var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/";
url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : "");
var chars = "abcdefghijklmnopqrstuvwxyz";
Random rnd = new Random();
for (int i = 0; i < 5; i++)
{
url += chars.Substring(rnd.Next(0, chars.Length - 1), 1);
}
_url = url;
}
} }

View File

@ -67,8 +67,11 @@
var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/"; var url = PageState.Uri.Scheme + "://" + PageState.Uri.Authority + "/";
url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : ""); url = url + (!string.IsNullOrEmpty(PageState.Alias.Path) ? PageState.Alias.Path + "/" : "");
_mappedurl = _mappedurl.Replace(url, "");
_mappedurl = (_mappedurl.StartsWith("/") && _mappedurl != "/") ? _mappedurl.Substring(1) : _mappedurl;
var urlmapping = await UrlMappingService.GetUrlMappingAsync(_urlmappingid); var urlmapping = await UrlMappingService.GetUrlMappingAsync(_urlmappingid);
urlmapping.MappedUrl = _mappedurl.Replace(url, ""); urlmapping.MappedUrl = _mappedurl;
urlmapping = await UrlMappingService.UpdateUrlMappingAsync(urlmapping); urlmapping = await UrlMappingService.UpdateUrlMappingAsync(urlmapping);
await logger.LogInformation("UrlMapping Saved {UrlMapping}", urlmapping); await logger.LogInformation("UrlMapping Saved {UrlMapping}", urlmapping);
NavigationManager.NavigateTo(NavigateUrl()); NavigationManager.NavigateTo(NavigateUrl());

View File

@ -124,7 +124,7 @@
<value>Error Downloading Framework Package</value> <value>Error Downloading Framework Package</value>
</data> </data>
<data name="Framework.HelpText" xml:space="preserve"> <data name="Framework.HelpText" xml:space="preserve">
<value>Upload a framework package and select Install to complete the installation</value> <value>Upload A Framework Package (Oqtane.Framework.#.#.#.nupkg) And Then Select Upgrade</value>
</data> </data>
<data name="Framework.Text" xml:space="preserve"> <data name="Framework.Text" xml:space="preserve">
<value>Framework: </value> <value>Framework: </value>
@ -144,9 +144,6 @@
<data name="Message.Text" xml:space="preserve"> <data name="Message.Text" xml:space="preserve">
<value>Framework Is Already Up To Date</value> <value>Framework Is Already Up To Date</value>
</data> </data>
<data name="MessageUpgrade.Text" xml:space="preserve">
<value>Upload A Framework Package (Oqtane.Framework.version.nupkg) And Then Select Upgrade</value>
</data>
<data name="Localhost.Text" xml:space="preserve"> <data name="Localhost.Text" xml:space="preserve">
<value>You Cannot Perform A System Update In A Development Environment</value> <value>You Cannot Perform A System Update In A Development Environment</value>
</data> </data>
@ -157,6 +154,6 @@
<value>Backup Files?</value> <value>Backup Files?</value>
</data> </data>
<data name="Backup.HelpText" xml:space="preserve"> <data name="Backup.HelpText" xml:space="preserve">
<value>Specify if you want to backup files during the upgrade process. Disabling this option will result in a better experience in some environments.</value> <value>Specify if you want to backup files during the upgrade process. Disabling this option will reduce the time required for the upgrade.</value>
</data> </data>
</root> </root>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
@ -121,10 +121,10 @@
<value>Redirect To:</value> <value>Redirect To:</value>
</data> </data>
<data name="MappedUrl.HelpText" xml:space="preserve"> <data name="MappedUrl.HelpText" xml:space="preserve">
<value>A relative or absolute Url where the user will be redirected</value> <value>A relative or absolute Url where the user will be redirected. Use "/" for site root path.</value>
</data> </data>
<data name="Url.HelpText" xml:space="preserve"> <data name="Url.HelpText" xml:space="preserve">
<value>An absolute Url identifying a path to a specific page in the site</value> <value>An absolute Url for this site</value>
</data> </data>
<data name="Url.Text" xml:space="preserve"> <data name="Url.Text" xml:space="preserve">
<value>Url:</value> <value>Url:</value>
@ -141,4 +141,7 @@
<data name="Message.SaveUrlMapping" xml:space="preserve"> <data name="Message.SaveUrlMapping" xml:space="preserve">
<value>The Url must belong to the current site</value> <value>The Url must belong to the current site</value>
</data> </data>
<data name="Generate" xml:space="preserve">
<value>Generate</value>
</data>
</root> </root>

View File

@ -121,7 +121,7 @@
<value>Redirect To:</value> <value>Redirect To:</value>
</data> </data>
<data name="MappedUrl.HelpText" xml:space="preserve"> <data name="MappedUrl.HelpText" xml:space="preserve">
<value>A relative or absolute Url where the user will be redirected</value> <value>A relative or absolute Url where the user will be redirected. Use "/" for site root path.</value>
</data> </data>
<data name="Url.HelpText" xml:space="preserve"> <data name="Url.HelpText" xml:space="preserve">
<value>A relative Url identifying a path to a specific page in the site</value> <value>A relative Url identifying a path to a specific page in the site</value>

View File

@ -343,7 +343,7 @@
var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath); var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath);
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl)) if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
{ {
var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl + route.Query; var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + (!urlMapping.MappedUrl.StartsWith("/") ? "/" : "") + urlMapping.MappedUrl + ((!urlMapping.MappedUrl.Contains("?")) ? route.Query : "");
NavigationManager.NavigateTo(url, false); NavigationManager.NavigateTo(url, false);
return; return;
} }

View File

@ -297,7 +297,7 @@
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl)) if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
{ {
// redirect to mapped url // redirect to mapped url
var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl; var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + (!urlMapping.MappedUrl.StartsWith("/") ? "/" : "") + urlMapping.MappedUrl + ((!urlMapping.MappedUrl.Contains("?")) ? route.Query : "");
NavigationManager.NavigateTo(url, true); NavigationManager.NavigateTo(url, true);
} }
else // no url mapping exists else // no url mapping exists

View File

@ -112,7 +112,7 @@ namespace Oqtane.Pages
url += Request.QueryString.Value.Substring(1); url += Request.QueryString.Value.Substring(1);
} }
return RedirectPermanent(url); return RedirectPermanent(url);
} }
@ -133,10 +133,29 @@ namespace Oqtane.Pages
} }
} }
string etag; string etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16);
string downloadName = file.Name; string downloadName = file.Name;
string filepath = _files.GetFilePath(file); string filepath = _files.GetFilePath(file);
var header = "";
if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch))
{
header = ifNoneMatch.ToString();
}
if (header.Equals(etag))
{
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
return Content(String.Empty);
}
if (!System.IO.File.Exists(filepath))
{
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FilePath}", filepath);
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
return BrokenFile();
}
// evaluate any querystring parameters // evaluate any querystring parameters
bool isRequestingImageManipulation = false; bool isRequestingImageManipulation = false;
@ -165,34 +184,6 @@ namespace Oqtane.Pages
isRequestingImageManipulation = true; isRequestingImageManipulation = true;
} }
if (isRequestingImageManipulation)
{
etag = Utilities.GenerateSimpleHash(Request.QueryString.Value);
}
else
{
etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16);
}
var header = "";
if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch))
{
header = ifNoneMatch.ToString();
}
if (header.Equals(etag))
{
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
return Content(String.Empty);
}
if (!System.IO.File.Exists(filepath))
{
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FilePath}", filepath);
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
return BrokenFile();
}
if (isRequestingImageManipulation) if (isRequestingImageManipulation)
{ {
var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue; var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue;

View File

@ -136,7 +136,7 @@ namespace Oqtane
policy => policy =>
{ {
// allow .NET MAUI client cross origin calls // allow .NET MAUI client cross origin calls
policy.WithOrigins("https://0.0.0.0", "http://0.0.0.0", "app://0.0.0.0") policy.WithOrigins("https://0.0.0.1", "http://0.0.0.1", "app://0.0.0.1")
.AllowAnyHeader().AllowAnyMethod().AllowCredentials(); .AllowAnyHeader().AllowAnyMethod().AllowCredentials();
}); });
}); });