Merge pull request #2403 from sbwalker/dev

Fix #2399 - page paths not being validated for deleted pages
This commit is contained in:
Shaun Walker 2022-09-06 10:52:34 -04:00 committed by GitHub
commit 5b22de589c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 30 additions and 39 deletions

View File

@ -202,7 +202,8 @@
if (hybrid) if (hybrid)
{ {
// hybrid apps utilize an interactive login // hybrid apps utilize an interactive login
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider)); var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider
.GetService(typeof(IdentityAuthenticationStateProvider));
authstateprovider.NotifyAuthenticationChanged(); authstateprovider.NotifyAuthenticationChanged();
NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true)); NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true));
} }

View File

@ -24,7 +24,7 @@
<div class="col-sm-9"> <div class="col-sm-9">
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required> <select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
<option value="-1">&lt;@Localizer["SiteRoot"]&gt;</option> <option value="-1">&lt;@Localizer["SiteRoot"]&gt;</option>
@foreach (Page page in _pageList) @foreach (Page page in PageState.Pages)
{ {
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option> <option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
} }
@ -167,7 +167,6 @@
private List<Theme> _themeList; private List<Theme> _themeList;
private List<ThemeControl> _themes = new List<ThemeControl>(); private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _containers = new List<ThemeControl>(); private List<ThemeControl> _containers = new List<ThemeControl>();
private List<Page> _pageList;
private string _name; private string _name;
private string _title; private string _title;
private string _meta; private string _meta;
@ -201,7 +200,6 @@
_themetype = PageState.Site.DefaultThemeType; _themetype = PageState.Site.DefaultThemeType;
_containers = ThemeService.GetContainerControls(_themeList, _themetype); _containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = PageState.Site.DefaultContainerType; _containertype = PageState.Site.DefaultContainerType;
_pageList = PageState.Pages;
_children = PageState.Pages.Where(item => item.ParentId == null).ToList(); _children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_permissions = string.Empty; _permissions = string.Empty;
ThemeSettings(); ThemeSettings();
@ -307,6 +305,10 @@
} }
if (_path.Contains("/")) if (_path.Contains("/"))
{ {
if (_path.EndsWith("/") && _path != "/")
{
_path = _path.Substring(0, _path.Length - 1);
}
_path = _path.Substring(_path.LastIndexOf("/") + 1); _path = _path.Substring(_path.LastIndexOf("/") + 1);
} }
@ -329,13 +331,8 @@
} }
} }
if (PagePathIsDeleted(page.Path, page.SiteId, _pageList)) var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
{ if (_pages.Any(item => item.Path == page.Path))
AddModuleMessage(string.Format(Localizer["Message.Page.Deleted"], _path), MessageType.Warning);
return;
}
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
{ {
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning); AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
return; return;
@ -427,14 +424,4 @@
NavigationManager.NavigateTo(NavigateUrl()); NavigationManager.NavigateTo(NavigateUrl());
} }
} }
private static bool PagePathIsUnique(string pagePath, int siteId, List<Page> existingPages)
{
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath);
}
private static bool PagePathIsDeleted(string pagePath, int siteId, List<Page> existingPages)
{
return existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath && page.IsDeleted == true);
}
} }

View File

@ -25,7 +25,7 @@
<div class="col-sm-9"> <div class="col-sm-9">
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required> <select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
<option value="-1">&lt;@Localizer["SiteRoot"]&gt;</option> <option value="-1">&lt;@Localizer["SiteRoot"]&gt;</option>
@foreach (Page page in _pageList) @foreach (Page page in PageState.Pages)
{ {
if (page.PageId != _pageId) if (page.PageId != _pageId)
{ {
@ -201,7 +201,6 @@
private List<Theme> _themeList; private List<Theme> _themeList;
private List<ThemeControl> _themes = new List<ThemeControl>(); private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _containers = new List<ThemeControl>(); private List<ThemeControl> _containers = new List<ThemeControl>();
private List<Page> _pageList;
private List<Module> _pageModules; private List<Module> _pageModules;
private int _pageId; private int _pageId;
private string _name; private string _name;
@ -238,7 +237,6 @@
{ {
try try
{ {
_pageList = PageState.Pages;
_children = PageState.Pages.Where(item => item.ParentId == null).ToList(); _children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_themeList = await ThemeService.GetThemesAsync(); _themeList = await ThemeService.GetThemesAsync();
_themes = ThemeService.GetThemeControls(_themeList); _themes = ThemeService.GetThemeControls(_themeList);
@ -435,6 +433,10 @@
} }
if (_path.Contains("/")) if (_path.Contains("/"))
{ {
if (_path.EndsWith("/") && _path != "/")
{
_path = _path.Substring(0, _path.Length - 1);
}
_path = _path.Substring(_path.LastIndexOf("/") + 1); _path = _path.Substring(_path.LastIndexOf("/") + 1);
} }
@ -457,7 +459,8 @@
} }
} }
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList)) var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
if (_pages.Any(item => item.Path == page.Path && item.PageId != page.PageId))
{ {
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning); AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
return; return;
@ -573,9 +576,4 @@
NavigationManager.NavigateTo(NavigateUrl()); NavigationManager.NavigateTo(NavigateUrl());
} }
} }
private static bool PagePathIsUnique(string pagePath, int siteId, int pageId, List<Page> existingPages)
{
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath && page.PageId != pageId);
}
} }

View File

@ -58,7 +58,7 @@
<Row> <Row>
<td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td> <td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td>
<td><ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete"], context.Title)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td> <td><ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete"], context.Title)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
<td>@PageState.Pages.Find(item => item.PageId == context.PageId).Name</td> <td>@_pages.Find(item => item.PageId == context.PageId).Name</td>
<td>@context.Title</td> <td>@context.Title</td>
<td>@context.DeletedBy</td> <td>@context.DeletedBy</td>
<td>@context.DeletedOn</td> <td>@context.DeletedOn</td>

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
@ -160,7 +160,7 @@
<value>Error Loading Pane Layouts For Theme</value> <value>Error Loading Pane Layouts For Theme</value>
</data> </data>
<data name="Message.Page.Exists" xml:space="preserve"> <data name="Message.Page.Exists" xml:space="preserve">
<value>A page with path {0} already exists for the selected parent page. The page path needs to be unique for the selected parent.</value> <value>A page with path '{0}' already exists for this site. Page paths must be unique. You may need to check if a page with this path exists in the Recycle Bin.</value>
</data> </data>
<data name="Message.Required.PageInfo" xml:space="preserve"> <data name="Message.Required.PageInfo" xml:space="preserve">
<value>You Must Provide Page Name, Theme, and Container</value> <value>You Must Provide Page Name, Theme, and Container</value>
@ -228,9 +228,6 @@
<data name="Appearance.Name" xml:space="preserve"> <data name="Appearance.Name" xml:space="preserve">
<value>Appearance</value> <value>Appearance</value>
</data> </data>
<data name="Message.Page.Deleted" xml:space="preserve">
<value>A page with path {0} already exists for the selected parent page in the Recycle Bin. Either recover the page or remove from the Recycle Bin and create it again.</value>
</data>
<data name="Meta.HelpText" xml:space="preserve"> <data name="Meta.HelpText" xml:space="preserve">
<value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value> <value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value>
</data> </data>

View File

@ -151,7 +151,7 @@
<value>Error Loading Pane Layouts For Theme</value> <value>Error Loading Pane Layouts For Theme</value>
</data> </data>
<data name="Mesage.Page.PathExists" xml:space="preserve"> <data name="Mesage.Page.PathExists" xml:space="preserve">
<value>A page with path {0} already exists for the selected parent page. The page path needs to be unique for the selected parent.</value> <value>A page with path '{0}' already exists for this site. Page paths must be unique. You may need to check if a page with this path exists in the Recycle Bin.</value>
</data> </data>
<data name="Message.Required.PageInfo" xml:space="preserve"> <data name="Message.Required.PageInfo" xml:space="preserve">
<value>You Must Provide Page Name, Theme, and Container</value> <value>You Must Provide Page Name, Theme, and Container</value>

View File

@ -12,7 +12,9 @@ namespace Oqtane.Maui;
public static class MauiProgram public static class MauiProgram
{ {
// can be overridden in an appsettings.json in AppDataDirectory // can be overridden in an appsettings.json in AppDataDirectory
static string url = (DeviceInfo.Platform == DevicePlatform.Android) ? "http://10.0.2.2:44357" : "http://localhost:44357"; static string url = (DeviceInfo.Platform == DevicePlatform.Android)
? "http://10.0.2.2:44357"
: "http://localhost:44357";
public static MauiApp CreateMauiApp() public static MauiApp CreateMauiApp()
{ {

View File

@ -51,7 +51,13 @@ namespace Oqtane.Security
protected virtual bool ShouldValidate(AuthorizationFilterContext context) protected virtual bool ShouldValidate(AuthorizationFilterContext context)
{ {
// ignore antiforgery validation if a bearer token was provided // ignore antiforgery validation if a bearer token was provided
if (context.HttpContext.Request.Headers.ContainsKey("Authorization") || context.HttpContext.Request.Headers["User-Agent"] == Constants.MauiUserAgent) if (context.HttpContext.Request.Headers.ContainsKey("Authorization"))
{
return false;
}
// ignore antiforgery validation if client is a MAUI app
if (context.HttpContext.Request.Headers["User-Agent"] == Constants.MauiUserAgent)
{ {
return false; return false;
} }