Merge pull request #48 from sbwalker/master

Improved page reload efficiency, refactored NavigateUrl and EditUrl helpers, added antiforgery token and returnurl to Logout scenario, fixed PageModule service call api url, modified rendering engine to allow for component differentiation
This commit is contained in:
Shaun Walker 2019-08-02 15:52:47 -04:00 committed by GitHub
commit 4969838a15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 231 additions and 173 deletions

View File

@ -73,7 +73,8 @@ private async Task Login()
{
// client-side Blazor
authstateprovider.NotifyAuthenticationChanged();
UriHelper.NavigateTo(NavigateUrl(ReturnUrl, true));
PageState.Reload = Constants.ReloadPage;
UriHelper.NavigateTo(NavigateUrl(ReturnUrl));
}
}
else
@ -85,6 +86,6 @@ private async Task Login()
private void Cancel()
{
string ReturnUrl = PageState.QueryString["returnurl"];
UriHelper.NavigateTo(NavigateUrl(ReturnUrl));
UriHelper.NavigateTo(ReturnUrl);
}
}

View File

@ -104,6 +104,7 @@
pagemodule.ContainerType = containertype;
await PageModuleService.UpdatePageModuleAsync(pagemodule);
UriHelper.NavigateTo(NavigateUrl(true));
PageState.Reload = Constants.ReloadPage;
UriHelper.NavigateTo(NavigateUrl());
}
}

View File

@ -170,6 +170,7 @@
p.ViewPermissions = viewpermissions;
p.EditPermissions = editpermissions;
await PageService.AddPageAsync(p);
UriHelper.NavigateTo(NavigateUrl(path, true));
PageState.Reload = Constants.ReloadSite;
UriHelper.NavigateTo(NavigateUrl(path));
}
}

View File

@ -157,6 +157,7 @@
private async Task DeletePage()
{
await PageService.DeletePageAsync(Int32.Parse(PageState.QueryString["id"]));
UriHelper.NavigateTo(NavigateUrl("", true));
PageState.Reload = Constants.ReloadSite;
UriHelper.NavigateTo(NavigateUrl());
}
}

View File

@ -16,7 +16,7 @@
<input type="password" name="Password" class="form-control" placeholder="Password" @bind="@Password" />
</div>
<button type="button" class="btn btn-primary" @onclick="@RegisterUser">Register</button>
<NavLink class="btn btn-secondary" href="/">Cancel</NavLink>
<button type="button" class="btn btn-secondary" @onclick="@Cancel">Cancel</button>
</div>
@code {
@ -36,4 +36,9 @@ private async Task RegisterUser()
await UserService.AddUserAsync(user);
UriHelper.NavigateTo("");
}
private void Cancel()
{
UriHelper.NavigateTo(NavigateUrl("")); // navigate to home
}
}

View File

@ -57,6 +57,7 @@
htmltext.Content = content;
await htmltextservice.AddHtmlTextAsync(htmltext);
}
UriHelper.NavigateTo(NavigateUrl(true));
PageState.Reload = Constants.ReloadPage;
UriHelper.NavigateTo(NavigateUrl());
}
}

View File

@ -20,32 +20,37 @@ namespace Oqtane.Modules
public string NavigateUrl()
{
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return Utilities.NavigateUrl(PageState, reload);
return NavigateUrl(PageState.Page.Path);
}
public string NavigateUrl(string path)
{
return Utilities.NavigateUrl(PageState, path);
}
public string NavigateUrl(string path, bool reload)
{
return Utilities.NavigateUrl(PageState, path, reload);
return Utilities.NavigateUrl(PageState.Alias.Path, path);
}
public string EditUrl(string action)
{
return Utilities.EditUrl(PageState, ModuleState, action, "");
return EditUrl(ModuleState.ModuleId, action);
}
public string EditUrl(string action, string parameters)
{
return Utilities.EditUrl(PageState, ModuleState, action, parameters);
return EditUrl(ModuleState.ModuleId, action, parameters);
}
public string EditUrl(int moduleid, string action)
{
return EditUrl(moduleid, action, "");
}
public string EditUrl(int moduleid, string action, string parameters)
{
return EditUrl(PageState.Page.Path, moduleid, action, parameters);
}
public string EditUrl(string path, int moduleid, string action, string parameters)
{
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
}
}
}

View File

@ -23,7 +23,7 @@ namespace Oqtane.Services
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "PageModule", urihelper.GetAbsoluteUri()); }
get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "PageModule"); }
}
public async Task<List<PageModule>> GetPageModulesAsync()

View File

@ -13,5 +13,9 @@
public const string AllUsersRole = "All Users";
public const string AdminRole = "Administrators";
public const int ReloadApplication = 3;
public const int ReloadSite = 2;
public const int ReloadPage = 1;
}
}

View File

@ -20,21 +20,26 @@
protected override void OnInit()
{
DynamicComponent = builder =>
{
if (ModuleState != null)
{
Type containerType = Type.GetType(container);
if (containerType != null)
{
builder.OpenComponent(0, containerType);
builder.OpenComponent(ModuleState.ModuleId, containerType); // set sequence to moduleid so that component tree is able to differentiate
builder.CloseComponent();
}
else
{
// container does not exist with type specified
}
}
};
}
protected override Task OnParametersSetAsync()
{
if (PageState.Page.PageId == Module.PageId)
{
ModuleState = Module; // passed in from Pane component
container = ModuleState.ContainerType;
@ -42,6 +47,7 @@
{
container = Constants.DefaultAdminContainer;
}
}
return Task.CompletedTask;
}
}

View File

@ -24,7 +24,7 @@
Type moduleType = Type.GetType(typename);
if (moduleType != null)
{
builder.OpenComponent(0, moduleType);
builder.OpenComponent(ModuleState.ModuleId, moduleType); // set sequence to moduleid so that component tree is able to differentiate
builder.CloseComponent();
}
else

View File

@ -19,5 +19,6 @@ namespace Oqtane.Shared
public Dictionary<string, string> QueryString { get; set; }
public int ModuleId { get; set; }
public string Control { get; set; }
public int Reload { get; set; }
}
}

View File

@ -41,7 +41,7 @@
DynamicComponent = builder =>
{
if (pagestate != null)
if (PageState != null)
{
builder.OpenComponent(0, Type.GetType(Constants.DefaultPage));
builder.CloseComponent();
@ -75,38 +75,54 @@
List<Module> modules;
int moduleid = -1;
string control = "";
int reload = 0;
bool reload = false;
if (PageState == null)
if (PageState != null)
{
reload = PageState.Reload;
}
if (PageState == null || reload == Constants.ReloadApplication)
{
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
themes = await ThemeService.GetThemesAsync();
aliases = await AliasService.GetAliasesAsync();
alias = null;
}
else
{
moduledefinitions = PageState.ModuleDefinitions;
themes = PageState.Themes;
aliases = PageState.Aliases;
alias = PageState.Alias;
}
// check if site has changed
if (alias == null || GetAlias(_absoluteUri, aliases).Name != alias.Name)
{
alias = GetAlias(_absoluteUri, aliases);
SiteState.Alias = alias; // set state for services
reload = true;
reload = Constants.ReloadSite;
}
if (PageState == null || reload == true)
if (PageState == null || reload <= Constants.ReloadSite)
{
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
themes = await ThemeService.GetThemesAsync();
site = await SiteService.GetSiteAsync(alias.SiteId);
}
else
{
moduledefinitions = PageState.ModuleDefinitions;
themes = PageState.Themes;
site = PageState.Site;
}
if (site != null || reload == true)
if (site != null)
{
if (PageState == null || reload >= Constants.ReloadSite)
{
pages = await PageService.GetPagesAsync(site.SiteId);
}
else
{
pages = PageState.Pages;
}
// get Url path and querystring
string path = new Uri(_absoluteUri).PathAndQuery.Substring(1);
@ -148,13 +164,23 @@
// remove trailing slash so it can be used as a key for Pages
if (path.EndsWith("/")) path = path.Substring(0, path.Length - 1);
if (querystring.ContainsKey("reload"))
if (PageState == null || reload >= Constants.ReloadPage)
{
reload = true;
page = pages.Where(item => item.Path == path).FirstOrDefault();
}
else
{
page = PageState.Page;
}
// check if page has changed
if (page.Path != path)
{
page = pages.Where(item => item.Path == path).FirstOrDefault();
reload = Constants.ReloadPage;
}
user = null;
if (PageState == null || reload == true)
if (PageState == null || reload >= Constants.ReloadPage)
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
if (authState.User.Identity.IsAuthenticated)
@ -167,29 +193,6 @@
user = PageState.User;
}
if (PageState == null || reload == true)
{
pages = await PageService.GetPagesAsync(site.SiteId);
}
else
{
pages = PageState.Pages;
}
if (PageState == null || reload == true)
{
page = pages.Where(item => item.Path == path).FirstOrDefault();
}
else
{
page = PageState.Page;
}
if (page.Path != path)
{
page = pages.Where(item => item.Path == path).FirstOrDefault();
reload = true;
}
if (page != null)
{
// check if user is authorized to view page
@ -211,10 +214,10 @@
if (PageState != null && (PageState.ModuleId != pagestate.ModuleId || PageState.Control != pagestate.Control))
{
reload = true;
reload = Constants.ReloadPage;
}
if (PageState == null || reload == true)
if (PageState == null || reload >= Constants.ReloadPage)
{
modules = await ModuleService.GetModulesAsync(page.PageId);
modules = ProcessModules(modules, moduledefinitions, pagestate.Control, page.Panes);
@ -224,6 +227,7 @@
modules = PageState.Modules;
}
pagestate.Modules = modules;
pagestate.Reload = 0;
OnStateChange?.Invoke(pagestate);
}

View File

@ -5,52 +5,37 @@ namespace Oqtane.Shared
{
public class Utilities
{
public static string NavigateUrl(PageState pagestate)
{
return NavigateUrl(pagestate, pagestate.Page.Path, false);
}
public static string NavigateUrl(PageState pagestate, bool reload)
public static string NavigateUrl(string alias, string path)
{
return NavigateUrl(pagestate, pagestate.Page.Path, reload);
string url = "";
if (alias != "")
{
url += alias + "/";
}
public static string NavigateUrl(PageState pagestate, string path)
if (path != "")
{
return NavigateUrl(pagestate, path, false);
url += path + "/";
}
public static string NavigateUrl(PageState pagestate, string path, bool reload)
if (!url.StartsWith("/"))
{
string url = pagestate.Alias.Path + "/" + path;
if (reload)
{
if (url.Contains("?"))
{
url += "&reload=true";
}
else
{
url += "?reload=true";
}
url = "/" + url;
}
return url;
}
public static string EditUrl(PageState pagestate, Module modulestate, string action)
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
{
return EditUrl(pagestate, modulestate, action, "");
string url = NavigateUrl(alias, path);
if ( url == "/" )
{
url = "";
}
public static string EditUrl(PageState pagestate, Module modulestate, string action, string parameters)
if (moduleid != -1)
{
string url = pagestate.Alias.Path;
if (pagestate.Page.Path != "")
{
url += "/" + pagestate.Page.Path;
url += "/" + moduleid.ToString();
}
url += "/" + modulestate.ModuleId.ToString();
if (action != "")
if (moduleid != -1 && action != "")
{
url += "/" + action;
}
@ -58,6 +43,10 @@ namespace Oqtane.Shared
{
url += "?" + parameters;
}
if (!url.StartsWith("/"))
{
url = "/" + url;
}
return url;
}

View File

@ -16,32 +16,38 @@ namespace Oqtane.Themes
public string NavigateUrl()
{
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return Utilities.NavigateUrl(PageState, reload);
return NavigateUrl(PageState.Page.Path);
}
public string NavigateUrl(string path)
{
return Utilities.NavigateUrl(PageState, path);
}
public string NavigateUrl(string path, bool reload)
{
return Utilities.NavigateUrl(PageState, path, reload);
return Utilities.NavigateUrl(PageState.Alias.Path, path);
}
public string EditUrl(string action)
{
return Utilities.EditUrl(PageState, ModuleState, action, "");
return EditUrl(ModuleState.ModuleId, action);
}
public string EditUrl(string action, string parameters)
{
return Utilities.EditUrl(PageState, ModuleState, action, parameters);
}
return EditUrl(ModuleState.ModuleId, action, parameters);
}
public string EditUrl(int moduleid, string action)
{
return EditUrl(moduleid, action, "");
}
public string EditUrl(int moduleid, string action, string parameters)
{
return EditUrl(PageState.Page.Path, moduleid, action, parameters);
}
public string EditUrl(string path, int moduleid, string action, string parameters)
{
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
}
}
}

View File

@ -119,7 +119,9 @@
pagemodule.Order = 0;
pagemodule.ContainerType = containertype;
await PageModuleService.AddPageModuleAsync(pagemodule);
UriHelper.NavigateTo(NavigateUrl(true));
PageState.Reload = Constants.ReloadPage;
UriHelper.NavigateTo(NavigateUrl());
}
private string PageUrl(string action)
@ -130,13 +132,13 @@
switch (action)
{
case "Add":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action;
url = EditUrl("admin/pages", pagemanagementmoduleid, action, "");
break;
case "Edit":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action + "&id=" + PageState.Page.PageId.ToString();
url = EditUrl("admin/pages", pagemanagementmoduleid, action, "id=" + PageState.Page.PageId.ToString());
break;
case "Delete":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action + "&id=" + PageState.Page.PageId.ToString();
url = EditUrl("admin/pages", pagemanagementmoduleid, action, "id=" + PageState.Page.PageId.ToString());
break;
}
}

View File

@ -26,7 +26,12 @@
@code {
private void LoginUser()
{
UriHelper.NavigateTo(NavigateUrl("login?returnurl=" + PageState.Page.Path));
string returnurl = PageState.Alias.Path;
if (PageState.Page.Path != "/")
{
returnurl += "/" + PageState.Page.Path;
}
UriHelper.NavigateTo("login?returnurl=" + returnurl);
}
private async Task LogoutUser()
@ -38,13 +43,16 @@
{
// server-side Blazor
var interop = new Interop(jsRuntime);
await interop.SubmitForm("/logout/", "");
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
var fields = new { __RequestVerificationToken = antiforgerytoken, returnurl = (PageState.Alias.Path + "/" + PageState.Page.Path) };
await interop.SubmitForm("/logout/", fields);
}
else
{
// client-side Blazor
authstateprovider.NotifyAuthenticationChanged();
UriHelper.NavigateTo(NavigateUrl("login", true));
PageState.Reload = Constants.ReloadPage;
UriHelper.NavigateTo(NavigateUrl());
}
}
}

View File

@ -1,6 +1,7 @@
@using Oqtane.Themes
@using Oqtane.Services
@using Oqtane.Models
@using Oqtane.Shared
@inherits ContainerBase
@inject IUriHelper UriHelper
@inject IUserService UserService
@ -58,7 +59,7 @@
pagemodule.Order = ModuleState.Order;
pagemodule.ContainerType = ModuleState.ContainerType;
string path = PageState.Page.Path + "?reload=true";
string url = NavigateUrl();
switch (action)
{
case "up":
@ -70,8 +71,7 @@
await PageModuleService.UpdatePageModuleAsync(pagemodule);
break;
case "settings":
if (path == "") { path += "/"; }
path = PageState.Page.Path + "?mid=" + pagemodule.ModuleId.ToString() + "&ctl=Settings";
url = EditUrl(pagemodule.ModuleId, "Settings");
break;
case "delete":
await PageModuleService.DeletePageModuleAsync(pagemodule.PageModuleId);
@ -81,7 +81,8 @@
await PageModuleService.UpdatePageModuleAsync(pagemodule);
break;
}
UriHelper.NavigateTo(NavigateUrl(path));
PageState.Reload = Constants.ReloadPage;
UriHelper.NavigateTo(url);
}
public class ActionViewModel

View File

@ -12,22 +12,12 @@ namespace Oqtane.Themes
public string NavigateUrl()
{
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return Utilities.NavigateUrl(PageState, reload);
return NavigateUrl(PageState.Page.Path);
}
public string NavigateUrl(string path)
{
return Utilities.NavigateUrl(PageState, path);
}
public string NavigateUrl(string path, bool reload)
{
return Utilities.NavigateUrl(PageState, path, reload);
return Utilities.NavigateUrl(PageState.Alias.Path, path);
}
}

View File

@ -10,22 +10,27 @@ namespace Oqtane.Themes
public string NavigateUrl()
{
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return Utilities.NavigateUrl(PageState, reload);
return NavigateUrl(PageState.Page.Path);
}
public string NavigateUrl(string path)
{
return Utilities.NavigateUrl(PageState, path);
return Utilities.NavigateUrl(PageState.Alias.Path, path);
}
public string NavigateUrl(string path, bool reload)
public string EditUrl(int moduleid, string action)
{
return Utilities.NavigateUrl(PageState, path, reload);
return EditUrl(moduleid, action, "");
}
public string EditUrl(int moduleid, string action, string parameters)
{
return EditUrl(PageState.Page.Path, moduleid, action, parameters);
}
public string EditUrl(string path, int moduleid, string action, string parameters)
{
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
}
}
}

View File

@ -46,7 +46,12 @@ namespace Oqtane.Pages
await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
}
return LocalRedirect(Url.Content("~/" + returnurl));
string url = "~/";
if (returnurl != "/")
{
url = Url.Content("~/" + returnurl);
}
return LocalRedirect(url);
}
}
}

View File

@ -12,15 +12,19 @@ using Oqtane.Models;
namespace Oqtane.Pages
{
[IgnoreAntiforgeryToken(Order = 1001)]
[AllowAnonymous]
public class LogoutModel : PageModel
{
public async Task<IActionResult> OnPostAsync()
public async Task<IActionResult> OnPostAsync(string returnurl)
{
await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme);
return LocalRedirect(Url.Content("~/"));
string url = "~/";
if (returnurl != "/")
{
url = Url.Content("~/" + returnurl);
}
return LocalRedirect(url);
}
}
}

View File

@ -183,6 +183,12 @@ GO
INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType])
VALUES (13, 2, N'Page2', N'page2', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-home', N'Top;Bottom', N'All Users', N'Administrators', NULL, 1, 1, N'')
GO
INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType])
VALUES (14, 2, N'Login', N'login', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'All Users', N'Administrators', NULL, 1, 0, N'')
GO
INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType])
VALUES (15, 2, N'Register', N'register', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'All Users', N'Administrators', NULL, 1, 0, N'')
GO
SET IDENTITY_INSERT [dbo].[Page] OFF
GO
@ -239,6 +245,12 @@ GO
INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions])
VALUES (17, 2, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators')
GO
INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions])
VALUES (18, 2, N'Oqtane.Client.Modules.Admin.Login, Oqtane.Client', N'All Users', N'Administrators')
GO
INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions])
VALUES (19, 2, N'Oqtane.Client.Modules.Admin.Register, Oqtane.Client', N'All Users', N'Administrators')
GO
SET IDENTITY_INSERT [dbo].[Module] OFF
GO
@ -295,6 +307,12 @@ GO
INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType])
VALUES (17, 13, 17, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client')
GO
INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType])
VALUES (18, 14, 18, N'Login', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client')
GO
INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType])
VALUES (19, 15, 19, N'Register', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client')
GO
SET IDENTITY_INSERT [dbo].[PageModule] OFF
GO