From 32a2d164c32e52521e9c0bf8cb2ca0696870f273 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 29 Jul 2019 21:45:08 -0400 Subject: [PATCH 01/44] Replace querystring routes with conventional routes --- Oqtane.Client/Shared/SiteRouter.razor | 554 +++++++++++++------------- Oqtane.Client/Shared/Utilities.cs | 11 +- 2 files changed, 292 insertions(+), 273 deletions(-) diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index b8ec1bd2..c61e3002 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -26,325 +26,339 @@ @code { -[CascadingParameter] PageState PageState { get; set; } + [CascadingParameter] PageState PageState { get; set; } -[Parameter] Action OnStateChange { get; set; } + [Parameter] Action OnStateChange { get; set; } -PageState pagestate; -RenderFragment DynamicComponent { get; set; } + PageState pagestate; + RenderFragment DynamicComponent { get; set; } -string _absoluteUri; -bool _navigationInterceptionEnabled; + string _absoluteUri; + bool _navigationInterceptionEnabled; -protected override void OnInit() -{ - _absoluteUri = UriHelper.GetAbsoluteUri(); - UriHelper.OnLocationChanged += OnLocationChanged; - - DynamicComponent = builder => + protected override void OnInit() { - if (pagestate != null) + _absoluteUri = UriHelper.GetAbsoluteUri(); + UriHelper.OnLocationChanged += OnLocationChanged; + + DynamicComponent = builder => { - builder.OpenComponent(0, Type.GetType(Constants.DefaultPage)); - builder.CloseComponent(); - } - }; -} - -public void Dispose() -{ - UriHelper.OnLocationChanged -= OnLocationChanged; -} - -protected override async Task OnParametersSetAsync() -{ - if (PageState == null) - { - await Refresh(); - } -} - -private async Task Refresh() -{ - List moduledefinitions; - List themes; - List aliases; - Alias alias; - Site site; - List pages; - Page page; - User user; - List modules; - - bool reload = false; - if (PageState == null) - { - aliases = await AliasService.GetAliasesAsync(); - alias = null; - } - else - { - aliases = PageState.Aliases; - alias = PageState.Alias; - } - if (alias == null || GetAlias(_absoluteUri, aliases).Name != alias.Name) - { - alias = GetAlias(_absoluteUri, aliases); - SiteState.Alias = alias; // set state for services - reload = true; - } - if (PageState == null || reload == true) - { - 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) - { - string path = new Uri(_absoluteUri).PathAndQuery.Substring(1); - if (path.EndsWith("/")) { path = path.Substring(0, path.Length - 1); } - if (alias.Path != "") - { - path = path.Replace(alias.Path, ""); - if (path.StartsWith("/")) { path = path.Substring(1); } - } - Dictionary querystring = ParseQueryString(path); - - if (querystring.ContainsKey("reload")) - { - reload = true; - } - - user = null; - if (PageState == null || reload == true) - { - var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); - if (authState.User.Identity.IsAuthenticated) + if (pagestate != null) { - user = await UserService.GetUserAsync(authState.User.Identity.Name); + builder.OpenComponent(0, Type.GetType(Constants.DefaultPage)); + builder.CloseComponent(); } + }; + } + + public void Dispose() + { + UriHelper.OnLocationChanged -= OnLocationChanged; + } + + protected override async Task OnParametersSetAsync() + { + if (PageState == null) + { + await Refresh(); + } + } + + private async Task Refresh() + { + List moduledefinitions; + List themes; + List aliases; + Alias alias; + Site site; + List pages; + Page page; + User user; + List modules; + int moduleid = -1; + string control = ""; + + bool reload = false; + if (PageState == null) + { + aliases = await AliasService.GetAliasesAsync(); + alias = null; } else { - user = PageState.User; + aliases = PageState.Aliases; + alias = PageState.Alias; } - - if (PageState == null || reload == true) + if (alias == null || GetAlias(_absoluteUri, aliases).Name != alias.Name) { - pages = await PageService.GetPagesAsync(site.SiteId); - } - else - { - pages = PageState.Pages; - } - - if (path.IndexOf("?") != -1) - { - path = path.Substring(0, path.IndexOf("?")); - } - - 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(); + alias = GetAlias(_absoluteUri, aliases); + SiteState.Alias = alias; // set state for services reload = true; } - - if (page != null) + if (PageState == null || reload == true) { - // check if user is authorized to view page - if (UserService.IsAuthorized(user, page.ViewPermissions)) + 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) + { + string path = new Uri(_absoluteUri).PathAndQuery.Substring(1); + if (path.EndsWith("/")) { path = path.Substring(0, path.Length - 1); } + if (alias.Path != "") { - pagestate = new PageState(); - pagestate.ModuleDefinitions = moduledefinitions; - pagestate.Themes = themes; - pagestate.Aliases = aliases; - pagestate.Alias = alias; - pagestate.Site = site; - pagestate.Pages = pages; - pagestate.Page = page; - pagestate.User = user; - pagestate.Uri = new Uri(_absoluteUri, UriKind.Absolute); - pagestate.QueryString = querystring; - pagestate.ModuleId = -1; - pagestate.Control = ""; + path = path.Replace(alias.Path, ""); + if (path.StartsWith("/")) { path = path.Substring(1); } + } + Dictionary querystring = ParseQueryString(path); - if (querystring.ContainsKey("mid")) - { - pagestate.ModuleId = int.Parse(querystring["mid"]); - } - if (querystring.ContainsKey("ctl")) - { - pagestate.Control = querystring["ctl"]; - } - if (PageState != null && (PageState.ModuleId != pagestate.ModuleId || PageState.Control != pagestate.Control)) - { - reload = true; - } + if (querystring.ContainsKey("reload")) + { + reload = true; + } - if (PageState == null || reload == true) + user = null; + if (PageState == null || reload == true) + { + var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + if (authState.User.Identity.IsAuthenticated) { - modules = await ModuleService.GetModulesAsync(page.PageId); - modules = ProcessModules(modules, moduledefinitions, pagestate.Control, page.Panes); + user = await UserService.GetUserAsync(authState.User.Identity.Name); } - else - { - modules = PageState.Modules; - } - pagestate.Modules = modules; - - OnStateChange?.Invoke(pagestate); } else { - // user is not authorized to view page + user = PageState.User; } - } - else - { - // page does not exist - } - } - else - { - // site does not exist - } -} -private async void OnLocationChanged(object sender, LocationChangedEventArgs args) -{ - _absoluteUri = args.Location; - await Refresh(); -} - -Task IHandleAfterRender.OnAfterRenderAsync() -{ - if (!_navigationInterceptionEnabled && ComponentContext.IsConnected) - { - _navigationInterceptionEnabled = true; - return NavigationInterception.EnableNavigationInterceptionAsync(); - } - return Task.CompletedTask; -} - -private Dictionary ParseQueryString(string path) -{ - Dictionary querystring = new Dictionary(); - if (path.IndexOf("?") != -1) - { - foreach (string kvp in path.Substring(path.IndexOf("?") + 1).Split('&')) - { - if (kvp != "") + if (PageState == null || reload == true) { - if (kvp.Contains("=")) + pages = await PageService.GetPagesAsync(site.SiteId); + } + else + { + pages = PageState.Pages; + } + + // format path so that it can be located in the pages collection + if (path.IndexOf("?") != -1) + { + // remove querystring from path + path = path.Substring(0, path.IndexOf("?")); + } + // remove admin route elements from path + string[] segments = path.Split('/'); + int result; + // admin routes are in the form of path/moduleid/control or path/moduleid + if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result)) + { + control = segments[segments.Length - 1]; + moduleid = result; + path = path.Replace("/" + moduleid.ToString() + "/" + control, ""); + } + else + { + if (segments.Length >= 1 && int.TryParse(segments[segments.Length - 1], out result)) { - string[] pair = kvp.Split('='); - querystring.Add(pair[0], pair[1]); + moduleid = result; + path = path.Replace("/" + moduleid.ToString(), ""); + } + } + + 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 + if (UserService.IsAuthorized(user, page.ViewPermissions)) + { + pagestate = new PageState(); + pagestate.ModuleDefinitions = moduledefinitions; + pagestate.Themes = themes; + pagestate.Aliases = aliases; + pagestate.Alias = alias; + pagestate.Site = site; + pagestate.Pages = pages; + pagestate.Page = page; + pagestate.User = user; + pagestate.Uri = new Uri(_absoluteUri, UriKind.Absolute); + pagestate.QueryString = querystring; + pagestate.ModuleId = moduleid; + pagestate.Control = control; + + if (PageState != null && (PageState.ModuleId != pagestate.ModuleId || PageState.Control != pagestate.Control)) + { + reload = true; + } + + if (PageState == null || reload == true) + { + modules = await ModuleService.GetModulesAsync(page.PageId); + modules = ProcessModules(modules, moduledefinitions, pagestate.Control, page.Panes); + } + else + { + modules = PageState.Modules; + } + pagestate.Modules = modules; + + OnStateChange?.Invoke(pagestate); } else { - querystring.Add(kvp, "true"); // default querystring when no value is provided + // user is not authorized to view page } } - } - } - return querystring; -} - -private List ProcessModules(List modules, List moduledefinitions, string control, string panes) -{ - ModuleDefinition moduledefinition; - - if (control == "") - { - control = Constants.DefaultControl; - } - - Dictionary paneindex = new Dictionary(); - foreach (Module module in modules) - { - // set the type based on the template and action - moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault(); - if (moduledefinition != null) - { - string typename = moduledefinition.ControlTypeTemplate; - if (moduledefinition.ControlTypeRoutes != "") + else { - foreach (string route in moduledefinition.ControlTypeRoutes.Split(';')) - { - if (route.StartsWith(control + "=")) - { - typename = route.Replace(control + "=", ""); - } - } + // page does not exist } - module.ModuleType = typename.Replace("{Control}", control); - } - - // ensure module's pane exists in current page and if not, assign it to the Admin pane - if (!panes.Contains(module.Pane)) - { - module.Pane = Constants.AdminPane; - } - - // calculate module position within pane - if (paneindex.ContainsKey(module.Pane)) - { - paneindex[module.Pane] += 1; } else { - paneindex.Add(module.Pane, 0); + // site does not exist } - module.PaneModuleIndex = paneindex[module.Pane]; } - foreach (Module module in modules) + private async void OnLocationChanged(object sender, LocationChangedEventArgs args) { - module.PaneModuleCount = paneindex[module.Pane] + 1; + _absoluteUri = args.Location; + await Refresh(); } - return modules; -} -private Alias GetAlias(string absoluteUri, List aliases) -{ + Task IHandleAfterRender.OnAfterRenderAsync() + { + if (!_navigationInterceptionEnabled && ComponentContext.IsConnected) + { + _navigationInterceptionEnabled = true; + return NavigationInterception.EnableNavigationInterceptionAsync(); + } + return Task.CompletedTask; + } - string aliasname; - Alias alias = null; - Uri uri = new Uri(absoluteUri); + private Dictionary ParseQueryString(string path) + { + Dictionary querystring = new Dictionary(); + if (path.IndexOf("?") != -1) + { + foreach (string kvp in path.Substring(path.IndexOf("?") + 1).Split('&')) + { + if (kvp != "") + { + if (kvp.Contains("=")) + { + string[] pair = kvp.Split('='); + querystring.Add(pair[0], pair[1]); + } + else + { + querystring.Add(kvp, "true"); // default querystring when no value is provided + } + } + } + } + return querystring; + } - if (uri.Segments.Count() > 1) + private List ProcessModules(List modules, List moduledefinitions, string control, string panes) { - // check if first path segment is an alias ( ie. a subfolder - www.domain.com/subfolder ) - aliasname = uri.Authority + "/" + uri.Segments[1]; - if (aliasname.EndsWith("/")) { aliasname = aliasname.Substring(0, aliasname.Length - 1); } - alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault(); + ModuleDefinition moduledefinition; + + if (control == "") + { + control = Constants.DefaultControl; + } + + Dictionary paneindex = new Dictionary(); + foreach (Module module in modules) + { + // set the type based on the template and action + moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault(); + if (moduledefinition != null) + { + string typename = moduledefinition.ControlTypeTemplate; + if (moduledefinition.ControlTypeRoutes != "") + { + foreach (string route in moduledefinition.ControlTypeRoutes.Split(';')) + { + if (route.StartsWith(control + "=")) + { + typename = route.Replace(control + "=", ""); + } + } + } + module.ModuleType = typename.Replace("{Control}", control); + } + + // ensure module's pane exists in current page and if not, assign it to the Admin pane + if (!panes.Contains(module.Pane)) + { + module.Pane = Constants.AdminPane; + } + + // calculate module position within pane + if (paneindex.ContainsKey(module.Pane)) + { + paneindex[module.Pane] += 1; + } + else + { + paneindex.Add(module.Pane, 0); + } + module.PaneModuleIndex = paneindex[module.Pane]; + } + + foreach (Module module in modules) + { + module.PaneModuleCount = paneindex[module.Pane] + 1; + } + return modules; } - if (alias == null) + + private Alias GetAlias(string absoluteUri, List aliases) { - aliasname = uri.Authority; - alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault(); + + string aliasname; + Alias alias = null; + Uri uri = new Uri(absoluteUri); + + if (uri.Segments.Count() > 1) + { + // check if first path segment is an alias ( ie. a subfolder - www.domain.com/subfolder ) + aliasname = uri.Authority + "/" + uri.Segments[1]; + if (aliasname.EndsWith("/")) { aliasname = aliasname.Substring(0, aliasname.Length - 1); } + alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault(); + } + if (alias == null) + { + aliasname = uri.Authority; + alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault(); + } + if (alias == null && aliases.Count > 0) + { + // use first alias if Uri does not exist + alias = aliases.FirstOrDefault(); + } + alias.Scheme = uri.Scheme; + return alias; } - if (alias == null && aliases.Count > 0) - { - // use first alias if Uri does not exist - alias = aliases.FirstOrDefault(); - } - alias.Scheme = uri.Scheme; - return alias; -} } \ No newline at end of file diff --git a/Oqtane.Client/Shared/Utilities.cs b/Oqtane.Client/Shared/Utilities.cs index 9de11332..b038c322 100644 --- a/Oqtane.Client/Shared/Utilities.cs +++ b/Oqtane.Client/Shared/Utilities.cs @@ -44,14 +44,19 @@ namespace Oqtane.Shared public static string EditUrl(PageState pagestate, Module modulestate, string action, string parameters) { - string url = pagestate.Alias.Path + "/" + pagestate.Page.Path + "?mid=" + modulestate.ModuleId.ToString(); + string url = pagestate.Alias.Path; + if (pagestate.Page.Path != "") + { + url += "/" + pagestate.Page.Path; + } + url += "/" + modulestate.ModuleId.ToString(); if (action != "") { - url += "&ctl=" + action; + url += "/" + action; } if (!string.IsNullOrEmpty(parameters)) { - url += "&" + parameters; + url += "?" + parameters; } return url; } From c9783c3b2fd3d27d79d1ebbb4bbbedf1c82b3e36 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 31 Jul 2019 16:05:36 -0400 Subject: [PATCH 02/44] Enhancement to support audit fields on entities --- Oqtane.Client/Modules/HtmlText/Edit.razor | 2 +- Oqtane.Client/Shared/SiteRouter.razor | 65 ++++++++-------- .../HtmlText/Repository/HtmlTextContext.cs | 5 +- Oqtane.Server/Repository/AliasRepository.cs | 4 +- Oqtane.Server/Repository/ContextBase.cs | 33 --------- Oqtane.Server/Repository/DBContextBase.cs | 74 +++++++++++++++++++ .../{MasterContext.cs => MasterDBContext.cs} | 4 +- Oqtane.Server/Repository/ModuleRepository.cs | 4 +- .../Repository/PageModuleRepository.cs | 4 +- Oqtane.Server/Repository/PageRepository.cs | 4 +- Oqtane.Server/Repository/SiteRepository.cs | 4 +- Oqtane.Server/Repository/TenantContext.cs | 41 ---------- Oqtane.Server/Repository/TenantDBContext.cs | 21 ++++++ Oqtane.Server/Repository/TenantRepository.cs | 4 +- Oqtane.Server/Repository/TenantResolver.cs | 4 +- Oqtane.Server/Repository/UserRepository.cs | 4 +- Oqtane.Server/Scripts/Tenant.sql | 42 ++++++----- Oqtane.Server/Startup.cs | 12 +-- Oqtane.Shared/Models/HtmlTextInfo.cs | 9 ++- Oqtane.Shared/Models/IAuditable.cs | 12 +++ Oqtane.Shared/Models/Site.cs | 11 ++- 21 files changed, 213 insertions(+), 150 deletions(-) delete mode 100644 Oqtane.Server/Repository/ContextBase.cs create mode 100644 Oqtane.Server/Repository/DBContextBase.cs rename Oqtane.Server/Repository/{MasterContext.cs => MasterDBContext.cs} (61%) delete mode 100644 Oqtane.Server/Repository/TenantContext.cs create mode 100644 Oqtane.Server/Repository/TenantDBContext.cs create mode 100644 Oqtane.Shared/Models/IAuditable.cs diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor index 63c4b2f3..099a9c21 100644 --- a/Oqtane.Client/Modules/HtmlText/Edit.razor +++ b/Oqtane.Client/Modules/HtmlText/Edit.razor @@ -57,6 +57,6 @@ htmltext.Content = content; await htmltextservice.AddHtmlTextAsync(htmltext); } - UriHelper.NavigateTo(NavigateUrl(), true); + UriHelper.NavigateTo(NavigateUrl(true)); } } diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index c61e3002..cde8bd28 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -109,14 +109,46 @@ } if (site != null || reload == true) { + // get Url path and querystring string path = new Uri(_absoluteUri).PathAndQuery.Substring(1); - if (path.EndsWith("/")) { path = path.Substring(0, path.Length - 1); } + + // parse querystring and remove + Dictionary querystring = new Dictionary(); + if (path.IndexOf("?") != -1) + { + querystring = ParseQueryString(path); + path = path.Substring(0, path.IndexOf("?")); + } + + // format path and remove alias + path = path.Replace("//", "/"); + if (!path.EndsWith("/")) { path += "/"; } if (alias.Path != "") { - path = path.Replace(alias.Path, ""); - if (path.StartsWith("/")) { path = path.Substring(1); } + path = path.Replace(alias.Path + "/", ""); } - Dictionary querystring = ParseQueryString(path); + + // extract admin route elements from path + string[] segments = path.Split('/'); + int result; + if (segments.Length >= 3 && int.TryParse(segments[segments.Length - 3], out result)) + { + // path has moduleid and control specification ie. page/moduleid/control/ + control = segments[segments.Length - 2]; + moduleid = result; + path = path.Replace(moduleid.ToString() + "/" + control + "/", ""); + } + else + { + if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result)) + { + // path has only moduleid specification ie. page/moduleid/ + moduleid = result; + path = path.Replace(moduleid.ToString() + "/", ""); + } + } + // 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")) { @@ -146,31 +178,6 @@ pages = PageState.Pages; } - // format path so that it can be located in the pages collection - if (path.IndexOf("?") != -1) - { - // remove querystring from path - path = path.Substring(0, path.IndexOf("?")); - } - // remove admin route elements from path - string[] segments = path.Split('/'); - int result; - // admin routes are in the form of path/moduleid/control or path/moduleid - if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result)) - { - control = segments[segments.Length - 1]; - moduleid = result; - path = path.Replace("/" + moduleid.ToString() + "/" + control, ""); - } - else - { - if (segments.Length >= 1 && int.TryParse(segments[segments.Length - 1], out result)) - { - moduleid = result; - path = path.Replace("/" + moduleid.ToString(), ""); - } - } - if (PageState == null || reload == true) { page = pages.Where(item => item.Path == path).FirstOrDefault(); diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs index 3ec81ddd..6c32a49f 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextContext.cs @@ -2,14 +2,15 @@ using Oqtane.Shared.Modules.HtmlText.Models; using Oqtane.Repository; using Oqtane.Modules; +using Microsoft.AspNetCore.Http; namespace Oqtane.Server.Modules.HtmlText.Repository { - public class HtmlTextContext : ContextBase, IService + public class HtmlTextContext : DBContextBase, IService { public virtual DbSet HtmlText { get; set; } - public HtmlTextContext(ITenantResolver TenantResolver):base(TenantResolver) + public HtmlTextContext(ITenantResolver TenantResolver, IHttpContextAccessor accessor) : base(TenantResolver, accessor) { // ContextBase handles multi-tenant database connections } diff --git a/Oqtane.Server/Repository/AliasRepository.cs b/Oqtane.Server/Repository/AliasRepository.cs index ca9f3059..8d512a59 100644 --- a/Oqtane.Server/Repository/AliasRepository.cs +++ b/Oqtane.Server/Repository/AliasRepository.cs @@ -9,10 +9,10 @@ namespace Oqtane.Repository { public class AliasRepository : IAliasRepository { - private MasterContext db; + private MasterDBContext db; private readonly IMemoryCache _cache; - public AliasRepository(MasterContext context, IMemoryCache cache) + public AliasRepository(MasterDBContext context, IMemoryCache cache) { db = context; _cache = cache; diff --git a/Oqtane.Server/Repository/ContextBase.cs b/Oqtane.Server/Repository/ContextBase.cs deleted file mode 100644 index bc1f475f..00000000 --- a/Oqtane.Server/Repository/ContextBase.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Oqtane.Models; -using System; - -namespace Oqtane.Repository -{ - public class ContextBase : DbContext - { - private Tenant tenant; - - public ContextBase(ITenantResolver TenantResolver) - { - tenant = TenantResolver.GetTenant(); - } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseSqlServer(tenant.DBConnectionString - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString()) - ); - base.OnConfiguring(optionsBuilder); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - if (tenant.DBSchema != "") - { - modelBuilder.HasDefaultSchema(tenant.DBSchema); - } - base.OnModelCreating(modelBuilder); - } - } -} diff --git a/Oqtane.Server/Repository/DBContextBase.cs b/Oqtane.Server/Repository/DBContextBase.cs new file mode 100644 index 00000000..bb2c6d8a --- /dev/null +++ b/Oqtane.Server/Repository/DBContextBase.cs @@ -0,0 +1,74 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Oqtane.Models; +using System; +using System.Linq; + +namespace Oqtane.Repository +{ + public class DBContextBase : IdentityDbContext + { + private Tenant tenant; + private IHttpContextAccessor accessor; + + public DBContextBase(ITenantResolver TenantResolver, IHttpContextAccessor accessor) + { + tenant = TenantResolver.GetTenant(); + this.accessor = accessor; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(tenant.DBConnectionString + .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString()) + ); + base.OnConfiguring(optionsBuilder); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + if (tenant.DBSchema != "") + { + modelBuilder.HasDefaultSchema(tenant.DBSchema); + } + } + + public override int SaveChanges() + { + ChangeTracker.DetectChanges(); + + string username = accessor.HttpContext.User.Identity.Name; + DateTime date = DateTime.Now; + + var created = ChangeTracker.Entries() + .Where(x => x.State == EntityState.Added); + + foreach(var item in created) + { + if (item.Entity is IAuditable entity) + { + item.CurrentValues[nameof(IAuditable.CreatedBy)] = username; + item.CurrentValues[nameof(IAuditable.CreatedOn)] = date; + } + } + + var modified = ChangeTracker.Entries() + .Where(x => x.State == EntityState.Modified || x.State == EntityState.Added); + + foreach (var item in modified) + { + if (item.Entity is IAuditable entity) + { + item.CurrentValues[nameof(IAuditable.ModifiedBy)] = username; + item.CurrentValues[nameof(IAuditable.ModifiedOn)] = date; + } + } + + return base.SaveChanges(); + } + } +} diff --git a/Oqtane.Server/Repository/MasterContext.cs b/Oqtane.Server/Repository/MasterDBContext.cs similarity index 61% rename from Oqtane.Server/Repository/MasterContext.cs rename to Oqtane.Server/Repository/MasterDBContext.cs index 21dca1dd..5e749fa8 100644 --- a/Oqtane.Server/Repository/MasterContext.cs +++ b/Oqtane.Server/Repository/MasterDBContext.cs @@ -3,9 +3,9 @@ using Oqtane.Models; namespace Oqtane.Repository { - public class MasterContext : DbContext + public class MasterDBContext : DbContext { - public MasterContext(DbContextOptions options) : base(options) { } + public MasterDBContext(DbContextOptions options) : base(options) { } public virtual DbSet Alias { get; set; } public virtual DbSet Tenant { get; set; } diff --git a/Oqtane.Server/Repository/ModuleRepository.cs b/Oqtane.Server/Repository/ModuleRepository.cs index fbec388e..aef77fbb 100644 --- a/Oqtane.Server/Repository/ModuleRepository.cs +++ b/Oqtane.Server/Repository/ModuleRepository.cs @@ -7,9 +7,9 @@ namespace Oqtane.Repository { public class ModuleRepository : IModuleRepository { - private TenantContext db; + private TenantDBContext db; - public ModuleRepository(TenantContext context) + public ModuleRepository(TenantDBContext context) { db = context; } diff --git a/Oqtane.Server/Repository/PageModuleRepository.cs b/Oqtane.Server/Repository/PageModuleRepository.cs index 791dea65..130d56e9 100644 --- a/Oqtane.Server/Repository/PageModuleRepository.cs +++ b/Oqtane.Server/Repository/PageModuleRepository.cs @@ -7,9 +7,9 @@ namespace Oqtane.Repository { public class PageModuleRepository : IPageModuleRepository { - private TenantContext db; + private TenantDBContext db; - public PageModuleRepository(TenantContext context) + public PageModuleRepository(TenantDBContext context) { db = context; } diff --git a/Oqtane.Server/Repository/PageRepository.cs b/Oqtane.Server/Repository/PageRepository.cs index 8045e038..45a09d7c 100644 --- a/Oqtane.Server/Repository/PageRepository.cs +++ b/Oqtane.Server/Repository/PageRepository.cs @@ -7,9 +7,9 @@ namespace Oqtane.Repository { public class PageRepository : IPageRepository { - private TenantContext db; + private TenantDBContext db; - public PageRepository(TenantContext context) + public PageRepository(TenantDBContext context) { db = context; } diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 7310266f..b382a214 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -7,9 +7,9 @@ namespace Oqtane.Repository { public class SiteRepository : ISiteRepository { - private TenantContext db; + private TenantDBContext db; - public SiteRepository(TenantContext context) + public SiteRepository(TenantDBContext context) { db = context; } diff --git a/Oqtane.Server/Repository/TenantContext.cs b/Oqtane.Server/Repository/TenantContext.cs deleted file mode 100644 index b74ce34d..00000000 --- a/Oqtane.Server/Repository/TenantContext.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Oqtane.Models; -using System; - -namespace Oqtane.Repository -{ - public class TenantContext : IdentityDbContext - { - public virtual DbSet Site { get; set; } - public virtual DbSet Page { get; set; } - public virtual DbSet PageModule { get; set; } - public virtual DbSet Module { get; set; } - public virtual DbSet User { get; set; } - - private readonly Tenant tenant; - - public TenantContext(ITenantResolver TenantResolver) - { - tenant = TenantResolver.GetTenant(); - } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseSqlServer(tenant.DBConnectionString - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString()) - ); - base.OnConfiguring(optionsBuilder); - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - if (tenant.DBSchema != "") - { - modelBuilder.HasDefaultSchema(tenant.DBSchema); - } - base.OnModelCreating(modelBuilder); - } - } -} diff --git a/Oqtane.Server/Repository/TenantDBContext.cs b/Oqtane.Server/Repository/TenantDBContext.cs new file mode 100644 index 00000000..190fe9e0 --- /dev/null +++ b/Oqtane.Server/Repository/TenantDBContext.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public class TenantDBContext : DBContextBase + { + public virtual DbSet Site { get; set; } + public virtual DbSet Page { get; set; } + public virtual DbSet PageModule { get; set; } + public virtual DbSet Module { get; set; } + public virtual DbSet User { get; set; } + + public TenantDBContext(ITenantResolver TenantResolver, IHttpContextAccessor accessor) : base(TenantResolver, accessor) + { + // ContextBase handles multi-tenant database connections + } + + } +} diff --git a/Oqtane.Server/Repository/TenantRepository.cs b/Oqtane.Server/Repository/TenantRepository.cs index da7c6be9..42d2c00a 100644 --- a/Oqtane.Server/Repository/TenantRepository.cs +++ b/Oqtane.Server/Repository/TenantRepository.cs @@ -10,10 +10,10 @@ namespace Oqtane.Repository { public class TenantRepository : ITenantRepository { - private MasterContext db; + private MasterDBContext db; private readonly IMemoryCache _cache; - public TenantRepository(MasterContext context, IMemoryCache cache) + public TenantRepository(MasterDBContext context, IMemoryCache cache) { db = context; _cache = cache; diff --git a/Oqtane.Server/Repository/TenantResolver.cs b/Oqtane.Server/Repository/TenantResolver.cs index bd78f450..08c553c2 100644 --- a/Oqtane.Server/Repository/TenantResolver.cs +++ b/Oqtane.Server/Repository/TenantResolver.cs @@ -7,12 +7,12 @@ namespace Oqtane.Repository { public class TenantResolver : ITenantResolver { - private MasterContext db; + private MasterDBContext db; private readonly string aliasname; private readonly IAliasRepository _aliasrepository; private readonly ITenantRepository _tenantrepository; - public TenantResolver(MasterContext context, IHttpContextAccessor accessor, IAliasRepository aliasrepository, ITenantRepository tenantrepository) + public TenantResolver(MasterDBContext context, IHttpContextAccessor accessor, IAliasRepository aliasrepository, ITenantRepository tenantrepository) { db = context; _aliasrepository = aliasrepository; diff --git a/Oqtane.Server/Repository/UserRepository.cs b/Oqtane.Server/Repository/UserRepository.cs index a750a405..b296110e 100644 --- a/Oqtane.Server/Repository/UserRepository.cs +++ b/Oqtane.Server/Repository/UserRepository.cs @@ -7,9 +7,9 @@ namespace Oqtane.Repository { public class UserRepository : IUserRepository { - private TenantContext db; + private TenantDBContext db; - public UserRepository(TenantContext context) + public UserRepository(TenantDBContext context) { db = context; } diff --git a/Oqtane.Server/Scripts/Tenant.sql b/Oqtane.Server/Scripts/Tenant.sql index 5719f48f..38c866de 100644 --- a/Oqtane.Server/Scripts/Tenant.sql +++ b/Oqtane.Server/Scripts/Tenant.sql @@ -8,6 +8,10 @@ CREATE TABLE [dbo].[Site]( [SiteId] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](200) NOT NULL, [Logo] [nvarchar](50) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_Site] PRIMARY KEY CLUSTERED ( [SiteId] ASC @@ -68,6 +72,10 @@ CREATE TABLE [dbo].[HtmlText]( [HtmlTextId] [int] IDENTITY(1,1) NOT NULL, [ModuleId] [int] NOT NULL, [Content] [nvarchar](max) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_HtmlText] PRIMARY KEY CLUSTERED ( [HtmlTextId] ASC @@ -77,7 +85,7 @@ GO CREATE TABLE [dbo].[User]( [UserId] [int] IDENTITY(1,1) NOT NULL, - [Username] [nvarchar](50) NOT NULL, + [Username] [nvarchar](256) NOT NULL, [DisplayName] [nvarchar](50) NOT NULL, [Roles] [nvarchar](50) NOT NULL, [IsSuperUser] [bit] NOT NULL, @@ -125,11 +133,11 @@ Create seed data SET IDENTITY_INSERT [dbo].[Site] ON GO -INSERT [dbo].[Site] ([SiteId], [Name], [Logo]) -VALUES (1, N'Site1', N'oqtane.png') +INSERT [dbo].[Site] ([SiteId], [Name], [Logo], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, N'Site1', N'oqtane.png', '', getdate(), '', getdate()) GO -INSERT [dbo].[Site] ([SiteId], [Name], [Logo]) -VALUES (2, N'Site2', N'oqtane.png') +INSERT [dbo].[Site] ([SiteId], [Name], [Logo], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, N'Site2', N'oqtane.png', '', getdate(), '', getdate()) GO SET IDENTITY_INSERT [dbo].[Site] OFF GO @@ -292,23 +300,23 @@ GO SET IDENTITY_INSERT [dbo].[HtmlText] ON GO -INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content]) -VALUES (1, 3, N'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Go To Site2') +INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, 3, N'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Go To Site2', '', getdate(), '', getdate()) GO -INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content]) -VALUES (2, 5, N'Enim sed faucibus turpis in eu mi bibendum neque egestas. Quis hendrerit dolor magna eget est lorem. Dui faucibus in ornare quam viverra orci sagittis. Integer eget aliquet nibh praesent tristique magna sit. Nunc aliquet bibendum enim facilisis gravida neque convallis a cras. Tortor id aliquet lectus proin. Diam volutpat commodo sed egestas egestas fringilla. Posuere sollicitudin aliquam ultrices sagittis orci. Viverra mauris in aliquam sem fringilla ut morbi tincidunt. Eget gravida cum sociis natoque penatibus et. Sagittis orci a scelerisque purus semper. Eget velit aliquet sagittis id consectetur purus. Volutpat blandit aliquam etiam erat. Et tortor consequat id porta nibh venenatis cras. Volutpat odio facilisis mauris sit amet. Varius duis at consectetur lorem.') +INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, 5, N'Enim sed faucibus turpis in eu mi bibendum neque egestas. Quis hendrerit dolor magna eget est lorem. Dui faucibus in ornare quam viverra orci sagittis. Integer eget aliquet nibh praesent tristique magna sit. Nunc aliquet bibendum enim facilisis gravida neque convallis a cras. Tortor id aliquet lectus proin. Diam volutpat commodo sed egestas egestas fringilla. Posuere sollicitudin aliquam ultrices sagittis orci. Viverra mauris in aliquam sem fringilla ut morbi tincidunt. Eget gravida cum sociis natoque penatibus et. Sagittis orci a scelerisque purus semper. Eget velit aliquet sagittis id consectetur purus. Volutpat blandit aliquam etiam erat. Et tortor consequat id porta nibh venenatis cras. Volutpat odio facilisis mauris sit amet. Varius duis at consectetur lorem.', '', getdate(), '', getdate()) GO -INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content]) -VALUES (3, 6, N'Id consectetur purus ut faucibus pulvinar elementum integer. Bibendum neque egestas congue quisque egestas diam in arcu. Eget nullam non nisi est sit amet facilisis. Sit amet consectetur adipiscing elit pellentesque. Id aliquet risus feugiat in. Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat. Commodo odio aenean sed adipiscing. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Aliquet enim tortor at auctor urna nunc. Nulla pellentesque dignissim enim sit amet. Suscipit adipiscing bibendum est ultricies integer quis auctor. Lacinia quis vel eros donec ac odio tempor. Aliquam vestibulum morbi blandit cursus risus at.') +INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (3, 6, N'Id consectetur purus ut faucibus pulvinar elementum integer. Bibendum neque egestas congue quisque egestas diam in arcu. Eget nullam non nisi est sit amet facilisis. Sit amet consectetur adipiscing elit pellentesque. Id aliquet risus feugiat in. Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat. Commodo odio aenean sed adipiscing. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Aliquet enim tortor at auctor urna nunc. Nulla pellentesque dignissim enim sit amet. Suscipit adipiscing bibendum est ultricies integer quis auctor. Lacinia quis vel eros donec ac odio tempor. Aliquam vestibulum morbi blandit cursus risus at.', '', getdate(), '', getdate()) GO -INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content]) -VALUES (4, 7, N'Ornare arcu dui vivamus arcu felis bibendum ut. Tortor vitae purus faucibus ornare. Lectus sit amet est placerat in egestas erat imperdiet sed. Aliquam sem et tortor consequat id. Fermentum iaculis eu non diam phasellus vestibulum. Ultricies integer quis auctor elit sed. Fermentum odio eu feugiat pretium nibh ipsum. Ut consequat semper viverra nam libero. Blandit aliquam etiam erat velit scelerisque in dictum non consectetur. At risus viverra adipiscing at in tellus. Facilisi nullam vehicula ipsum a arcu cursus vitae congue. At varius vel pharetra vel turpis nunc eget lorem dolor. Morbi non arcu risus quis varius. Turpis massa sed elementum tempus egestas.') +INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (4, 7, N'Ornare arcu dui vivamus arcu felis bibendum ut. Tortor vitae purus faucibus ornare. Lectus sit amet est placerat in egestas erat imperdiet sed. Aliquam sem et tortor consequat id. Fermentum iaculis eu non diam phasellus vestibulum. Ultricies integer quis auctor elit sed. Fermentum odio eu feugiat pretium nibh ipsum. Ut consequat semper viverra nam libero. Blandit aliquam etiam erat velit scelerisque in dictum non consectetur. At risus viverra adipiscing at in tellus. Facilisi nullam vehicula ipsum a arcu cursus vitae congue. At varius vel pharetra vel turpis nunc eget lorem dolor. Morbi non arcu risus quis varius. Turpis massa sed elementum tempus egestas.', '', getdate(), '', getdate()) GO -INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content]) -VALUES (5, 16, N'Id consectetur purus ut faucibus pulvinar elementum integer. Bibendum neque egestas congue quisque egestas diam in arcu. Eget nullam non nisi est sit amet facilisis. Sit amet consectetur adipiscing elit pellentesque. Id aliquet risus feugiat in. Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat. Commodo odio aenean sed adipiscing. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Aliquet enim tortor at auctor urna nunc. Nulla pellentesque dignissim enim sit amet. Suscipit adipiscing bibendum est ultricies integer quis auctor. Lacinia quis vel eros donec ac odio tempor. Aliquam vestibulum morbi blandit cursus risus at.

Go To Site1') +INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (5, 16, N'Id consectetur purus ut faucibus pulvinar elementum integer. Bibendum neque egestas congue quisque egestas diam in arcu. Eget nullam non nisi est sit amet facilisis. Sit amet consectetur adipiscing elit pellentesque. Id aliquet risus feugiat in. Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat. Commodo odio aenean sed adipiscing. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Aliquet enim tortor at auctor urna nunc. Nulla pellentesque dignissim enim sit amet. Suscipit adipiscing bibendum est ultricies integer quis auctor. Lacinia quis vel eros donec ac odio tempor. Aliquam vestibulum morbi blandit cursus risus at.

Go To Site1', '', getdate(), '', getdate()) GO -INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content]) -VALUES (6, 17, N'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.') +INSERT [dbo].[HtmlText] ([HtmlTextId], [ModuleId], [Content], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (6, 17, N'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', '', getdate(), '', getdate()) GO SET IDENTITY_INSERT [dbo].[HtmlText] OFF GO diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index d071f537..10c2a516 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -101,14 +101,14 @@ namespace Oqtane.Server services.AddSingleton(); - services.AddDbContext(options => + services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection") .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString()) )); - services.AddDbContext(options => { }); + services.AddDbContext(options => { }); services.AddIdentity() - .AddEntityFrameworkStores() + .AddEntityFrameworkStores() .AddDefaultTokenProviders(); services.Configure(options => @@ -235,14 +235,14 @@ namespace Oqtane.Server { services.AddSingleton(); - services.AddDbContext(options => + services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection") .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString()) )); - services.AddDbContext(options => { }); + services.AddDbContext(options => { }); services.AddIdentity() - .AddEntityFrameworkStores() + .AddEntityFrameworkStores() .AddDefaultTokenProviders(); services.Configure(options => diff --git a/Oqtane.Shared/Models/HtmlTextInfo.cs b/Oqtane.Shared/Models/HtmlTextInfo.cs index 31364b59..c26fa269 100644 --- a/Oqtane.Shared/Models/HtmlTextInfo.cs +++ b/Oqtane.Shared/Models/HtmlTextInfo.cs @@ -1,14 +1,21 @@ +using System; +using Oqtane.Models; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Oqtane.Shared.Modules.HtmlText.Models { [Table("HtmlText")] - public class HtmlTextInfo + public class HtmlTextInfo : IAuditable { [Key] public int HtmlTextId { get; set; } public int ModuleId { get; set; } public string Content { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } } } diff --git a/Oqtane.Shared/Models/IAuditable.cs b/Oqtane.Shared/Models/IAuditable.cs new file mode 100644 index 00000000..83cd1c1f --- /dev/null +++ b/Oqtane.Shared/Models/IAuditable.cs @@ -0,0 +1,12 @@ +using System; + +namespace Oqtane.Models +{ + public interface IAuditable + { + string CreatedBy { get; set; } + DateTime CreatedOn { get; set; } + string ModifiedBy { get; set; } + DateTime ModifiedOn { get; set; } + } +} diff --git a/Oqtane.Shared/Models/Site.cs b/Oqtane.Shared/Models/Site.cs index c3f214f8..14c5c34a 100644 --- a/Oqtane.Shared/Models/Site.cs +++ b/Oqtane.Shared/Models/Site.cs @@ -1,9 +1,16 @@ -namespace Oqtane.Models +using System; + +namespace Oqtane.Models { - public class Site + public class Site : IAuditable { public int SiteId { get; set; } public string Name { get; set; } public string Logo { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } } } From 9fbc71b53100f7caeaf924b4d968ee68d8d5517b Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Thu, 1 Aug 2019 12:53:02 -0400 Subject: [PATCH 03/44] Add type="button" to all buttons and prevent display of Installer if already installed --- .../Modules/Admin/ModuleSettings/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Add.razor | 2 +- .../Modules/Admin/Pages/Delete.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Edit.razor | 2 +- Oqtane.Client/Modules/Admin/Sites/Add.razor | 2 +- Oqtane.Client/Modules/Counter/Index.razor | 2 +- Oqtane.Client/Modules/HtmlText/Edit.razor | 2 +- Oqtane.Client/Shared/Installer.razor | 219 +++++++++--------- Oqtane.Client/Shared/SiteRouter.razor | 2 - .../Themes/Controls/ModuleActions.razor | 2 +- 10 files changed, 123 insertions(+), 114 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor index 68d4d13c..6c0f1b0f 100644 --- a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor @@ -63,7 +63,7 @@ - + Cancel @code { diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index 1e5868bf..0a719364 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -111,7 +111,7 @@ - + Cancel @code { diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index 0a3cf339..05f8360f 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -111,7 +111,7 @@ - + Cancel @code { diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 5eadcd24..269695b9 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -112,7 +112,7 @@ - + Cancel @code { diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index ff04b471..9db5663c 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -55,7 +55,7 @@ else - + Cancel } diff --git a/Oqtane.Client/Modules/Counter/Index.razor b/Oqtane.Client/Modules/Counter/Index.razor index 77dd787d..175aeb38 100644 --- a/Oqtane.Client/Modules/Counter/Index.razor +++ b/Oqtane.Client/Modules/Counter/Index.razor @@ -2,7 +2,7 @@ @inherits ModuleBase Current count: @currentCount
- +

@code { diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor index 099a9c21..0214db4c 100644 --- a/Oqtane.Client/Modules/HtmlText/Edit.razor +++ b/Oqtane.Client/Modules/HtmlText/Edit.razor @@ -20,7 +20,7 @@ - + Cancel diff --git a/Oqtane.Client/Shared/Installer.razor b/Oqtane.Client/Shared/Installer.razor index 321f8d3d..98aebf80 100644 --- a/Oqtane.Client/Shared/Installer.razor +++ b/Oqtane.Client/Shared/Installer.razor @@ -1,113 +1,116 @@ @using Oqtane.Services @using Oqtane.Models @inject IUriHelper UriHelper -@inject IInstallationService InstallationService +@inject IInstallationService InstallationService @inject IUserService UserService - -
-
-
- + +@if (!Installed) +{ +
+
+
+ +
+
+
+

Database Configuration

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+
+
+
+

Application Administrator

+
+
+ + + + + + + + + + + +
+ + + +
+ + + +
+
+
+
+
+

+ @((MarkupString)@Message) +
+
-
-

Database Configuration

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
- - - -
- - - -
- - - -
- - - -
-
-
-
-

Application Administrator

-
-
- - - - - - - - - - - -
- - - -
- - - -
-
-
-
-
-

- @((MarkupString)@Message) -
-
-
-
+} @code { @@ -124,6 +127,14 @@ private string Message = ""; private string IntegratedSecurityDisplay = "display:none;"; private string LoadingDisplay = "display:none;"; +private bool Installed = true; + +protected override async Task OnInitAsync() +{ + var response = await InstallationService.IsInstalled(); + Installed = response.Success; +} + private void SetIntegratedSecurity(UIChangeEventArgs e) { if (Convert.ToBoolean(e.Value)) diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index cde8bd28..31259eae 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -4,14 +4,12 @@ @using System.Linq @using System.Collections.Generic @using Oqtane.Shared -@using Microsoft.JSInterop @using Microsoft.AspNetCore.Components.Routing @inject AuthenticationStateProvider AuthenticationStateProvider @inject SiteState SiteState @inject IUriHelper UriHelper @inject INavigationInterception NavigationInterception @inject IComponentContext ComponentContext -@inject IJSRuntime jsRuntime @inject IAliasService AliasService @inject ITenantService TenantService @inject ISiteService SiteService diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor index 3f814787..bb60fe73 100644 --- a/Oqtane.Client/Themes/Controls/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor @@ -7,7 +7,7 @@ @inject IPageModuleService PageModuleService @code { -public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Anonymous; } } + public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Anonymous; } } -public string Username { get; set; } = ""; -public string Password { get; set; } = ""; + public string Username { get; set; } = ""; + public string Password { get; set; } = ""; -private async Task RegisterUser() -{ - User user = new User(); - user.Username = Username; - user.DisplayName = Username; - user.Roles = "Administrators;"; - user.IsSuperUser = false; - user.Password = Password; - await UserService.AddUserAsync(user); - UriHelper.NavigateTo(""); -} + private async Task RegisterUser() + { + User user = new User(); + user.Username = Username; + user.DisplayName = Username; + user.Roles = "Administrators;"; + user.IsSuperUser = false; + user.Password = Password; + await UserService.AddUserAsync(user); + UriHelper.NavigateTo(""); + } + + private void Cancel() + { + UriHelper.NavigateTo(NavigateUrl("")); // navigate to home + } } diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor index 0214db4c..2668df87 100644 --- a/Oqtane.Client/Modules/HtmlText/Edit.razor +++ b/Oqtane.Client/Modules/HtmlText/Edit.razor @@ -57,6 +57,7 @@ htmltext.Content = content; await htmltextservice.AddHtmlTextAsync(htmltext); } - UriHelper.NavigateTo(NavigateUrl(true)); + PageState.Reload = Constants.ReloadPage; + UriHelper.NavigateTo(NavigateUrl()); } } diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index 80fc318b..d654eabd 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -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); } } } diff --git a/Oqtane.Client/Services/PageModuleService.cs b/Oqtane.Client/Services/PageModuleService.cs index 8a65de2d..65ea4b9f 100644 --- a/Oqtane.Client/Services/PageModuleService.cs +++ b/Oqtane.Client/Services/PageModuleService.cs @@ -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> GetPageModulesAsync() diff --git a/Oqtane.Client/Shared/Constants.cs b/Oqtane.Client/Shared/Constants.cs index 54d2d35f..80d3070a 100644 --- a/Oqtane.Client/Shared/Constants.cs +++ b/Oqtane.Client/Shared/Constants.cs @@ -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; } } diff --git a/Oqtane.Client/Shared/Container.razor b/Oqtane.Client/Shared/Container.razor index 9d309925..0efcdcc3 100644 --- a/Oqtane.Client/Shared/Container.razor +++ b/Oqtane.Client/Shared/Container.razor @@ -21,26 +21,32 @@ { DynamicComponent = builder => { - Type containerType = Type.GetType(container); - if (containerType != null) + if (ModuleState != null) { - builder.OpenComponent(0, containerType); - builder.CloseComponent(); - } - else - { - // container does not exist with type specified + Type containerType = Type.GetType(container); + if (containerType != null) + { + 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() { - ModuleState = Module; // passed in from Pane component - container = ModuleState.ContainerType; - if (PageState.ModuleId != -1 && PageState.Control != "") + if (PageState.Page.PageId == Module.PageId) { - container = Constants.DefaultAdminContainer; + ModuleState = Module; // passed in from Pane component + container = ModuleState.ContainerType; + if (PageState.ModuleId != -1 && PageState.Control != "") + { + container = Constants.DefaultAdminContainer; + } } return Task.CompletedTask; } diff --git a/Oqtane.Client/Shared/ModuleInstance.razor b/Oqtane.Client/Shared/ModuleInstance.razor index 8a2513a1..a1fb24ab 100644 --- a/Oqtane.Client/Shared/ModuleInstance.razor +++ b/Oqtane.Client/Shared/ModuleInstance.razor @@ -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 diff --git a/Oqtane.Client/Shared/PageState.cs b/Oqtane.Client/Shared/PageState.cs index 419b92ad..1de78738 100644 --- a/Oqtane.Client/Shared/PageState.cs +++ b/Oqtane.Client/Shared/PageState.cs @@ -19,5 +19,6 @@ namespace Oqtane.Shared public Dictionary QueryString { get; set; } public int ModuleId { get; set; } public string Control { get; set; } + public int Reload { get; set; } } } diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index 31259eae..edd0ff7e 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -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 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); } diff --git a/Oqtane.Client/Shared/Utilities.cs b/Oqtane.Client/Shared/Utilities.cs index b038c322..f9282acc 100644 --- a/Oqtane.Client/Shared/Utilities.cs +++ b/Oqtane.Client/Shared/Utilities.cs @@ -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); - } - - public static string NavigateUrl(PageState pagestate, string path) - { - return NavigateUrl(pagestate, path, false); - } - - public static string NavigateUrl(PageState pagestate, string path, bool reload) - { - string url = pagestate.Alias.Path + "/" + path; - if (reload) + string url = ""; + if (alias != "") { - if (url.Contains("?")) - { - url += "&reload=true"; - } - else - { - url += "?reload=true"; - } + url += alias + "/"; + } + if (path != "") + { + url += path + "/"; + } + if (!url.StartsWith("/")) + { + 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, ""); - } - - public static string EditUrl(PageState pagestate, Module modulestate, string action, string parameters) - { - string url = pagestate.Alias.Path; - if (pagestate.Page.Path != "") + string url = NavigateUrl(alias, path); + if ( url == "/" ) { - url += "/" + pagestate.Page.Path; + url = ""; } - url += "/" + modulestate.ModuleId.ToString(); - if (action != "") + if (moduleid != -1) + { + url += "/" + moduleid.ToString(); + } + if (moduleid != -1 && action != "") { url += "/" + action; } @@ -58,6 +43,10 @@ namespace Oqtane.Shared { url += "?" + parameters; } + if (!url.StartsWith("/")) + { + url = "/" + url; + } return url; } diff --git a/Oqtane.Client/Themes/ContainerBase.cs b/Oqtane.Client/Themes/ContainerBase.cs index d476b7b7..7eb915da 100644 --- a/Oqtane.Client/Themes/ContainerBase.cs +++ b/Oqtane.Client/Themes/ContainerBase.cs @@ -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); + } + } } diff --git a/Oqtane.Client/Themes/Controls/ControlPanel.razor b/Oqtane.Client/Themes/Controls/ControlPanel.razor index 45dc4d4a..b0e675f8 100644 --- a/Oqtane.Client/Themes/Controls/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/ControlPanel.razor @@ -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; } } diff --git a/Oqtane.Client/Themes/Controls/Login.razor b/Oqtane.Client/Themes/Controls/Login.razor index cae8a035..34492a17 100644 --- a/Oqtane.Client/Themes/Controls/Login.razor +++ b/Oqtane.Client/Themes/Controls/Login.razor @@ -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()); } } } diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor index bb60fe73..4d3e5ef3 100644 --- a/Oqtane.Client/Themes/Controls/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor @@ -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 diff --git a/Oqtane.Client/Themes/ThemeBase.cs b/Oqtane.Client/Themes/ThemeBase.cs index d9190f0e..e922247e 100644 --- a/Oqtane.Client/Themes/ThemeBase.cs +++ b/Oqtane.Client/Themes/ThemeBase.cs @@ -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); } } diff --git a/Oqtane.Client/Themes/ThemeObjectBase.cs b/Oqtane.Client/Themes/ThemeObjectBase.cs index 61402bc6..332f1889 100644 --- a/Oqtane.Client/Themes/ThemeObjectBase.cs +++ b/Oqtane.Client/Themes/ThemeObjectBase.cs @@ -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); } } } diff --git a/Oqtane.Server/Pages/Login.cshtml.cs b/Oqtane.Server/Pages/Login.cshtml.cs index ed88df50..eb8399e5 100644 --- a/Oqtane.Server/Pages/Login.cshtml.cs +++ b/Oqtane.Server/Pages/Login.cshtml.cs @@ -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); } } } \ No newline at end of file diff --git a/Oqtane.Server/Pages/Logout.cshtml.cs b/Oqtane.Server/Pages/Logout.cshtml.cs index f66575c4..95ec1a71 100644 --- a/Oqtane.Server/Pages/Logout.cshtml.cs +++ b/Oqtane.Server/Pages/Logout.cshtml.cs @@ -12,15 +12,19 @@ using Oqtane.Models; namespace Oqtane.Pages { - [IgnoreAntiforgeryToken(Order = 1001)] [AllowAnonymous] public class LogoutModel : PageModel { - public async Task OnPostAsync() + public async Task OnPostAsync(string returnurl) { await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); - return LocalRedirect(Url.Content("~/")); + string url = "~/"; + if (returnurl != "/") + { + url = Url.Content("~/" + returnurl); + } + return LocalRedirect(url); } } } \ No newline at end of file diff --git a/Oqtane.Server/Scripts/Tenant.sql b/Oqtane.Server/Scripts/Tenant.sql index 38c866de..9b3a1a7d 100644 --- a/Oqtane.Server/Scripts/Tenant.sql +++ b/Oqtane.Server/Scripts/Tenant.sql @@ -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 From abd2f6e6b45a86792a178075166dae12e708d867 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 2 Aug 2019 15:58:20 -0400 Subject: [PATCH 05/44] Update README.md --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/README.md b/README.md index f17fa9b2..cdf0a384 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,42 @@ Oqtane uses Blazor, a new web framework for .NET Core that lets you build intera 5. Download or Clone the Oqtane source code to your local system. Open the **Oqtane.sln** solution file. If you want to develop using **server-side** Blazor ( which includes a full debugging experience in Visual Studio ) you should choose to Build the solution using the default Debug configuration. If you want to develop using **client-side** Blazor ( WebAssembly ) you should first choose the "Wasm" configuration option in the Visual Studio toolbar and then Build. +# Roadmap +This project is a work in progress and the schedule for implementing the items identified below is dependent upon the availability of community members who are able to assist. + +Security +- Need ability to associate a User to a Site and restrict access +- Need ability to manage Roles and association to Users +- Need ability to manage Permissions + - a permission UI component for pages/modules + - may also need to include Permission table schema similar to DNN +- Need ability to manage Authorization ( will need to be custom so that permissions set by user are observed at API level ) +- Need audit fields ( ie. CreatedBy, CreateOn, etc… ) on all core tables +- Logging + +Design +- Need modern Admin UI theme +- Need to cleanly separate site.css +- CSS registration for modules and skins + +Packaging +- Need ability to package/install Modules +- Need ability to package/install Themes + +Admin +- Need fully functional administrative modules for all core entities ( user, role, site, etc… ) +- Need ability to create a new Site and auto provision Admin pages/modules +- Need ability to soft delete core entities +- Drag and Drop modules + +Upgrade +- Need ability to upgrade application seamlessly +- integrated store/catalog of extensions +- auto update - provide url to check for updates, perhaps even download in background - core and extensions + +Multi-Tenant +- Need ability to provision a new tenant DB + # Background Oqtane was created by [Shaun Walker](https://www.linkedin.com/in/shaunbrucewalker/) and is inspired by the DotNetNuke web application framework. Initially created as a proof of concept, Oqtane is a native Blazor application written from the ground up using modern .NET Core technology. It is a modular framework offering a fully dynamic page compositing model, multi-site support, designer friendly templates ( skins ), and extensibility via third party modules. From e8b5e2f0b2acede38b73fea59394c87c45bdcef5 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 2 Aug 2019 16:08:05 -0400 Subject: [PATCH 06/44] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index cdf0a384..ba345b83 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,9 @@ Upgrade Multi-Tenant - Need ability to provision a new tenant DB +Database +- Need ability to run on SQLite + # Background Oqtane was created by [Shaun Walker](https://www.linkedin.com/in/shaunbrucewalker/) and is inspired by the DotNetNuke web application framework. Initially created as a proof of concept, Oqtane is a native Blazor application written from the ground up using modern .NET Core technology. It is a modular framework offering a fully dynamic page compositing model, multi-site support, designer friendly templates ( skins ), and extensibility via third party modules. From 7ff1eb9081cb8290cce70ee5e4181a03d30706d3 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 2 Aug 2019 16:12:22 -0400 Subject: [PATCH 07/44] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ba345b83..3b748921 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Security - Need ability to manage Authorization ( will need to be custom so that permissions set by user are observed at API level ) - Need audit fields ( ie. CreatedBy, CreateOn, etc… ) on all core tables - Logging +- Support for friendly Page Not Found handling Design - Need modern Admin UI theme From e00ce5cd905dfd7b4d11026a9474a4424c24768f Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Sat, 3 Aug 2019 15:09:49 -0400 Subject: [PATCH 08/44] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b748921..eea4fd37 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ At this point Oqtane offers a minimum of desired functionality and is not recomm # Example Screenshots -A simplistic login flow ( note that a full authentication story has not been implemented at this point ): +A seamless login flow utilizing .NET Core Identity services: ![Login](https://github.com/oqtane/framework/blob/master/screenshot1.png?raw=true "Login") From 4fda7b17d0e76404d554ef0f85e744e8412a8d61 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 5 Aug 2019 09:31:04 -0400 Subject: [PATCH 09/44] Refactored repository pattern for Add and Update methods so that they return their respective entity objects --- Oqtane.Client/Services/AliasService.cs | 8 +- Oqtane.Client/Services/IAliasService.cs | 4 +- Oqtane.Client/Services/IModuleService.cs | 4 +- Oqtane.Client/Services/IPageModuleService.cs | 4 +- Oqtane.Client/Services/IPageService.cs | 4 +- Oqtane.Client/Services/ISiteService.cs | 4 +- Oqtane.Client/Services/IUserService.cs | 8 +- Oqtane.Client/Services/ModuleService.cs | 8 +- Oqtane.Client/Services/PageModuleService.cs | 8 +- Oqtane.Client/Services/PageService.cs | 8 +- Oqtane.Client/Services/SiteService.cs | 8 +- Oqtane.Client/Services/UserService.cs | 24 ++--- Oqtane.Client/Shared/Installer.razor | 1 - Oqtane.Server/Controllers/AliasController.cs | 14 ++- Oqtane.Server/Controllers/ModuleController.cs | 14 ++- Oqtane.Server/Controllers/PageController.cs | 14 ++- .../Controllers/PageModuleController.cs | 14 ++- Oqtane.Server/Controllers/SiteController.cs | 14 ++- Oqtane.Server/Controllers/TenantController.cs | 14 ++- Oqtane.Server/Controllers/UserController.cs | 20 ++-- .../Controllers/HtmlTextController.cs | 14 ++- .../HtmlText/Repository/HtmlTextRepository.cs | 6 +- .../Repository/IHtmlTextRepository.cs | 4 +- Oqtane.Server/Repository/AliasRepository.cs | 18 ++-- Oqtane.Server/Repository/IAliasRepository.cs | 8 +- Oqtane.Server/Repository/IModuleRepository.cs | 4 +- .../Repository/IPageModuleRepository.cs | 4 +- Oqtane.Server/Repository/IPageRepository.cs | 4 +- Oqtane.Server/Repository/ISiteRepository.cs | 8 +- .../Repository/ISiteUserRepository.cs | 15 +++ Oqtane.Server/Repository/ITenantRepository.cs | 8 +- Oqtane.Server/Repository/IUserRepository.cs | 4 +- Oqtane.Server/Repository/ModuleRepository.cs | 6 +- .../Repository/PageModuleRepository.cs | 6 +- Oqtane.Server/Repository/PageRepository.cs | 6 +- Oqtane.Server/Repository/SiteRepository.cs | 10 +- .../Repository/SiteUserRepository.cs | 100 ++++++++++++++++++ Oqtane.Server/Repository/TenantDBContext.cs | 1 + Oqtane.Server/Repository/TenantRepository.cs | 18 ++-- Oqtane.Server/Repository/UserRepository.cs | 6 +- Oqtane.Server/Scripts/Tenant.sql | 24 +++++ Oqtane.Shared/Models/SiteUser.cs | 17 +++ Oqtane.Shared/Models/User.cs | 2 + 43 files changed, 353 insertions(+), 137 deletions(-) create mode 100644 Oqtane.Server/Repository/ISiteUserRepository.cs create mode 100644 Oqtane.Server/Repository/SiteUserRepository.cs create mode 100644 Oqtane.Shared/Models/SiteUser.cs diff --git a/Oqtane.Client/Services/AliasService.cs b/Oqtane.Client/Services/AliasService.cs index 1d29f68a..f1b22cb3 100644 --- a/Oqtane.Client/Services/AliasService.cs +++ b/Oqtane.Client/Services/AliasService.cs @@ -37,14 +37,14 @@ namespace Oqtane.Services return await http.GetJsonAsync(apiurl + "/" + AliasId.ToString()); } - public async Task AddAliasAsync(Alias alias) + public async Task AddAliasAsync(Alias alias) { - await http.PostJsonAsync(apiurl, alias); + return await http.PostJsonAsync(apiurl, alias); } - public async Task UpdateAliasAsync(Alias alias) + public async Task UpdateAliasAsync(Alias alias) { - await http.PutJsonAsync(apiurl + "/" + alias.AliasId.ToString(), alias); + return await http.PutJsonAsync(apiurl + "/" + alias.AliasId.ToString(), alias); } public async Task DeleteAliasAsync(int AliasId) { diff --git a/Oqtane.Client/Services/IAliasService.cs b/Oqtane.Client/Services/IAliasService.cs index c4fe200b..b9b515ac 100644 --- a/Oqtane.Client/Services/IAliasService.cs +++ b/Oqtane.Client/Services/IAliasService.cs @@ -10,9 +10,9 @@ namespace Oqtane.Services Task GetAliasAsync(int AliasId); - Task AddAliasAsync(Alias alias); + Task AddAliasAsync(Alias Alias); - Task UpdateAliasAsync(Alias alias); + Task UpdateAliasAsync(Alias Alias); Task DeleteAliasAsync(int AliasId); } diff --git a/Oqtane.Client/Services/IModuleService.cs b/Oqtane.Client/Services/IModuleService.cs index 4f800cf7..2252e7b6 100644 --- a/Oqtane.Client/Services/IModuleService.cs +++ b/Oqtane.Client/Services/IModuleService.cs @@ -9,8 +9,8 @@ namespace Oqtane.Services Task> GetModulesAsync(int PageId); Task> GetModulesAsync(int SiteId, string ModuleDefinitionName); Task GetModuleAsync(int ModuleId); - Task AddModuleAsync(Module module); - Task UpdateModuleAsync(Module module); + Task AddModuleAsync(Module Module); + Task UpdateModuleAsync(Module Module); Task DeleteModuleAsync(int ModuleId); } } diff --git a/Oqtane.Client/Services/IPageModuleService.cs b/Oqtane.Client/Services/IPageModuleService.cs index 2f3d037c..e574ad34 100644 --- a/Oqtane.Client/Services/IPageModuleService.cs +++ b/Oqtane.Client/Services/IPageModuleService.cs @@ -7,8 +7,8 @@ namespace Oqtane.Services public interface IPageModuleService { Task> GetPageModulesAsync(); - Task AddPageModuleAsync(PageModule pagemodule); - Task UpdatePageModuleAsync(PageModule pagemodule); + Task AddPageModuleAsync(PageModule PageModule); + Task UpdatePageModuleAsync(PageModule PageModule); Task DeletePageModuleAsync(int PageModuleId); } } diff --git a/Oqtane.Client/Services/IPageService.cs b/Oqtane.Client/Services/IPageService.cs index 5388af7b..846c7b9a 100644 --- a/Oqtane.Client/Services/IPageService.cs +++ b/Oqtane.Client/Services/IPageService.cs @@ -8,8 +8,8 @@ namespace Oqtane.Services { Task> GetPagesAsync(int SiteId); Task GetPageAsync(int PageId); - Task AddPageAsync(Page page); - Task UpdatePageAsync(Page page); + Task AddPageAsync(Page Page); + Task UpdatePageAsync(Page Page); Task DeletePageAsync(int PageId); } } diff --git a/Oqtane.Client/Services/ISiteService.cs b/Oqtane.Client/Services/ISiteService.cs index 4fb0ab98..fc81edcf 100644 --- a/Oqtane.Client/Services/ISiteService.cs +++ b/Oqtane.Client/Services/ISiteService.cs @@ -10,9 +10,9 @@ namespace Oqtane.Services Task GetSiteAsync(int SiteId); - Task AddSiteAsync(Site site); + Task AddSiteAsync(Site Site); - Task UpdateSiteAsync(Site site); + Task UpdateSiteAsync(Site Site); Task DeleteSiteAsync(int SiteId); } diff --git a/Oqtane.Client/Services/IUserService.cs b/Oqtane.Client/Services/IUserService.cs index e1b42bdd..e263d92c 100644 --- a/Oqtane.Client/Services/IUserService.cs +++ b/Oqtane.Client/Services/IUserService.cs @@ -12,18 +12,18 @@ namespace Oqtane.Services Task GetUserAsync(string Username); - Task AddUserAsync(User user); + Task AddUserAsync(User User); - Task UpdateUserAsync(User user); + Task UpdateUserAsync(User User); Task DeleteUserAsync(int UserId); Task GetCurrentUserAsync(); - Task LoginUserAsync(User user); + Task LoginUserAsync(User User); Task LogoutUserAsync(); - bool IsAuthorized(User user, string accesscontrollist); + bool IsAuthorized(User User, string AccessControlList); } } diff --git a/Oqtane.Client/Services/ModuleService.cs b/Oqtane.Client/Services/ModuleService.cs index 60f22eeb..8fa12e89 100644 --- a/Oqtane.Client/Services/ModuleService.cs +++ b/Oqtane.Client/Services/ModuleService.cs @@ -46,14 +46,14 @@ namespace Oqtane.Services return await http.GetJsonAsync(apiurl + "/" + ModuleId.ToString()); } - public async Task AddModuleAsync(Module module) + public async Task AddModuleAsync(Module Module) { - await http.PostJsonAsync(apiurl, module); + return await http.PostJsonAsync(apiurl, Module); } - public async Task UpdateModuleAsync(Module module) + public async Task UpdateModuleAsync(Module Module) { - await http.PutJsonAsync(apiurl + "/" + module.ModuleId.ToString(), module); + return await http.PutJsonAsync(apiurl + "/" + Module.ModuleId.ToString(), Module); } public async Task DeleteModuleAsync(int ModuleId) diff --git a/Oqtane.Client/Services/PageModuleService.cs b/Oqtane.Client/Services/PageModuleService.cs index 65ea4b9f..3c7dbf66 100644 --- a/Oqtane.Client/Services/PageModuleService.cs +++ b/Oqtane.Client/Services/PageModuleService.cs @@ -31,14 +31,14 @@ namespace Oqtane.Services return await http.GetJsonAsync>(apiurl); } - public async Task AddPageModuleAsync(PageModule pagemodule) + public async Task AddPageModuleAsync(PageModule PageModule) { - await http.PostJsonAsync(apiurl, pagemodule); + return await http.PostJsonAsync(apiurl, PageModule); } - public async Task UpdatePageModuleAsync(PageModule pagemodule) + public async Task UpdatePageModuleAsync(PageModule PageModule) { - await http.PutJsonAsync(apiurl + "/" + pagemodule.PageModuleId.ToString(), pagemodule); + return await http.PutJsonAsync(apiurl + "/" + PageModule.PageModuleId.ToString(), PageModule); } public async Task DeletePageModuleAsync(int PageModuleId) diff --git a/Oqtane.Client/Services/PageService.cs b/Oqtane.Client/Services/PageService.cs index d0124c79..74f75e15 100644 --- a/Oqtane.Client/Services/PageService.cs +++ b/Oqtane.Client/Services/PageService.cs @@ -37,14 +37,14 @@ namespace Oqtane.Services return await http.GetJsonAsync(apiurl + "/" + PageId.ToString()); } - public async Task AddPageAsync(Page page) + public async Task AddPageAsync(Page Page) { - await http.PostJsonAsync(apiurl, page); + return await http.PostJsonAsync(apiurl, Page); } - public async Task UpdatePageAsync(Page page) + public async Task UpdatePageAsync(Page Page) { - await http.PutJsonAsync(apiurl + "/" + page.PageId.ToString(), page); + return await http.PutJsonAsync(apiurl + "/" + Page.PageId.ToString(), Page); } public async Task DeletePageAsync(int PageId) { diff --git a/Oqtane.Client/Services/SiteService.cs b/Oqtane.Client/Services/SiteService.cs index 83cfad34..2ca7139b 100644 --- a/Oqtane.Client/Services/SiteService.cs +++ b/Oqtane.Client/Services/SiteService.cs @@ -37,14 +37,14 @@ namespace Oqtane.Services return await http.GetJsonAsync(apiurl + "/" + SiteId.ToString()); } - public async Task AddSiteAsync(Site site) + public async Task AddSiteAsync(Site Site) { - await http.PostJsonAsync(apiurl, site); + return await http.PostJsonAsync(apiurl, Site); } - public async Task UpdateSiteAsync(Site site) + public async Task UpdateSiteAsync(Site Site) { - await http.PutJsonAsync(apiurl + "/" + site.SiteId.ToString(), site); + return await http.PutJsonAsync(apiurl + "/" + Site.SiteId.ToString(), Site); } public async Task DeleteSiteAsync(int SiteId) { diff --git a/Oqtane.Client/Services/UserService.cs b/Oqtane.Client/Services/UserService.cs index eeb19433..d9dd281d 100644 --- a/Oqtane.Client/Services/UserService.cs +++ b/Oqtane.Client/Services/UserService.cs @@ -43,14 +43,14 @@ namespace Oqtane.Services return await http.GetJsonAsync(apiurl + "/name/" + Username); } - public async Task AddUserAsync(User user) + public async Task AddUserAsync(User User) { - await http.PostJsonAsync(apiurl, user); + return await http.PostJsonAsync(apiurl, User); } - public async Task UpdateUserAsync(User user) + public async Task UpdateUserAsync(User User) { - await http.PutJsonAsync(apiurl + "/" + user.UserId.ToString(), user); + return await http.PutJsonAsync(apiurl + "/" + User.UserId.ToString(), User); } public async Task DeleteUserAsync(int UserId) { @@ -62,9 +62,9 @@ namespace Oqtane.Services return await http.GetJsonAsync(apiurl + "/current"); } - public async Task LoginUserAsync(User user) + public async Task LoginUserAsync(User User) { - return await http.PostJsonAsync(apiurl + "/login", user); + return await http.PostJsonAsync(apiurl + "/login", User); } public async Task LogoutUserAsync() @@ -74,23 +74,23 @@ namespace Oqtane.Services } // ACLs are stored in the format "!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]" where "!" designates Deny permissions - public bool IsAuthorized(User user, string accesscontrollist) + public bool IsAuthorized(User User, string AccessControlList) { bool isAllowed = false; - if (user != null) + if (User != null) { //super user always has full access - isAllowed = user.IsSuperUser; + isAllowed = User.IsSuperUser; } if (!isAllowed) { - if (accesscontrollist != null) + if (AccessControlList != null) { - foreach (string permission in accesscontrollist.Split(new[] { ';' })) + foreach (string permission in AccessControlList.Split(new[] { ';' })) { - bool? allowed = VerifyPermission(user, permission); + bool? allowed = VerifyPermission(User, permission); if (allowed.HasValue) { isAllowed = allowed.Value; diff --git a/Oqtane.Client/Shared/Installer.razor b/Oqtane.Client/Shared/Installer.razor index 98aebf80..1c0f497a 100644 --- a/Oqtane.Client/Shared/Installer.razor +++ b/Oqtane.Client/Shared/Installer.razor @@ -117,7 +117,6 @@ private string DatabaseType = "LocalDB"; private string ServerName = "(LocalDb)\\MSSQLLocalDB"; private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm"); -private bool IntegratedSecurity = true; private string Username = ""; private string Password = ""; private string HostUsername = "host"; diff --git a/Oqtane.Server/Controllers/AliasController.cs b/Oqtane.Server/Controllers/AliasController.cs index 772bb974..facd0453 100644 --- a/Oqtane.Server/Controllers/AliasController.cs +++ b/Oqtane.Server/Controllers/AliasController.cs @@ -31,18 +31,24 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - public void Post([FromBody] Alias alias) + public Alias Post([FromBody] Alias Alias) { if (ModelState.IsValid) - aliases.AddAlias(alias); + { + Alias = aliases.AddAlias(Alias); + } + return Alias; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] Alias alias) + public Alias Put(int id, [FromBody] Alias Alias) { if (ModelState.IsValid) - aliases.UpdateAlias(alias); + { + Alias = aliases.UpdateAlias(Alias); + } + return Alias; } // DELETE api//5 diff --git a/Oqtane.Server/Controllers/ModuleController.cs b/Oqtane.Server/Controllers/ModuleController.cs index 12e4c739..994afbae 100644 --- a/Oqtane.Server/Controllers/ModuleController.cs +++ b/Oqtane.Server/Controllers/ModuleController.cs @@ -53,18 +53,24 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - public void Post([FromBody] Module Module) + public Module Post([FromBody] Module Module) { if (ModelState.IsValid) - modules.AddModule(Module); + { + Module = modules.AddModule(Module); + } + return Module; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] Module Module) + public Module Put(int id, [FromBody] Module Module) { if (ModelState.IsValid) - modules.UpdateModule(Module); + { + Module = modules.UpdateModule(Module); + } + return Module; } // DELETE api//5 diff --git a/Oqtane.Server/Controllers/PageController.cs b/Oqtane.Server/Controllers/PageController.cs index a2addeb4..59ac9bdd 100644 --- a/Oqtane.Server/Controllers/PageController.cs +++ b/Oqtane.Server/Controllers/PageController.cs @@ -38,18 +38,24 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - public void Post([FromBody] Page Page) + public Page Post([FromBody] Page Page) { if (ModelState.IsValid) - pages.AddPage(Page); + { + Page = pages.AddPage(Page); + } + return Page; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] Page Page) + public Page Put(int id, [FromBody] Page Page) { if (ModelState.IsValid) - pages.UpdatePage(Page); + { + Page = pages.UpdatePage(Page); + } + return Page; } // DELETE api//5 diff --git a/Oqtane.Server/Controllers/PageModuleController.cs b/Oqtane.Server/Controllers/PageModuleController.cs index 25d225da..500825d0 100644 --- a/Oqtane.Server/Controllers/PageModuleController.cs +++ b/Oqtane.Server/Controllers/PageModuleController.cs @@ -31,18 +31,24 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - public void Post([FromBody] PageModule PageModule) + public PageModule Post([FromBody] PageModule PageModule) { if (ModelState.IsValid) - pagemodules.AddPageModule(PageModule); + { + PageModule = pagemodules.AddPageModule(PageModule); + } + return PageModule; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] PageModule PageModule) + public PageModule Put(int id, [FromBody] PageModule PageModule) { if (ModelState.IsValid) - pagemodules.UpdatePageModule(PageModule); + { + PageModule = pagemodules.UpdatePageModule(PageModule); + } + return PageModule; } // DELETE api//5 diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs index c6493504..3d2528f9 100644 --- a/Oqtane.Server/Controllers/SiteController.cs +++ b/Oqtane.Server/Controllers/SiteController.cs @@ -31,18 +31,24 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - public void Post([FromBody] Site site) + public Site Post([FromBody] Site Site) { if (ModelState.IsValid) - sites.AddSite(site); + { + Site = sites.AddSite(Site); + } + return Site; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] Site site) + public Site Put(int id, [FromBody] Site Site) { if (ModelState.IsValid) - sites.UpdateSite(site); + { + Site = sites.UpdateSite(Site); + } + return Site; } // DELETE api//5 diff --git a/Oqtane.Server/Controllers/TenantController.cs b/Oqtane.Server/Controllers/TenantController.cs index af19f7af..a5c38ebe 100644 --- a/Oqtane.Server/Controllers/TenantController.cs +++ b/Oqtane.Server/Controllers/TenantController.cs @@ -31,18 +31,24 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - public void Post([FromBody] Tenant site) + public Tenant Post([FromBody] Tenant Tenant) { if (ModelState.IsValid) - tenants.AddTenant(site); + { + Tenant = tenants.AddTenant(Tenant); + } + return Tenant; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] Tenant site) + public Tenant Put(int id, [FromBody] Tenant Tenant) { if (ModelState.IsValid) - tenants.UpdateTenant(site); + { + Tenant = tenants.UpdateTenant(Tenant); + } + return Tenant; } // DELETE api//5 diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs index 86f1fa8a..00f4fb9b 100644 --- a/Oqtane.Server/Controllers/UserController.cs +++ b/Oqtane.Server/Controllers/UserController.cs @@ -4,8 +4,6 @@ using Oqtane.Repository; using Oqtane.Models; using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; -using Microsoft.Extensions.Primitives; -using System.Security.Claims; namespace Oqtane.Controllers { @@ -39,33 +37,35 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - public async Task Post([FromBody] User user) + public async Task Post([FromBody] User User) { if (ModelState.IsValid) { - IdentityUser identityuser = await identityUserManager.FindByNameAsync(user.Username); + IdentityUser identityuser = await identityUserManager.FindByNameAsync(User.Username); if (identityuser == null) { identityuser = new IdentityUser(); - identityuser.UserName = user.Username; - identityuser.Email = user.Username; - var result = await identityUserManager.CreateAsync(identityuser, user.Password); + identityuser.UserName = User.Username; + identityuser.Email = User.Username; + var result = await identityUserManager.CreateAsync(identityuser, User.Password); if (result.Succeeded) { - users.AddUser(user); + User = users.AddUser(User); } } } + return User; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] User user) + public User Put(int id, [FromBody] User User) { if (ModelState.IsValid) { - users.UpdateUser(user); + User = users.UpdateUser(User); } + return User; } // DELETE api//5 diff --git a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs index 36eda275..f3dc2d9b 100644 --- a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs +++ b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs @@ -31,18 +31,24 @@ namespace Oqtane.Server.Modules.HtmlText.Controllers // POST api/ [HttpPost] - public void Post([FromBody] HtmlTextInfo HtmlText) + public HtmlTextInfo Post([FromBody] HtmlTextInfo HtmlText) { if (ModelState.IsValid) - htmltext.AddHtmlText(HtmlText); + { + HtmlText = htmltext.AddHtmlText(HtmlText); + } + return HtmlText; } // PUT api//5 [HttpPut("{id}")] - public void Put(int id, [FromBody] HtmlTextInfo HtmlText) + public HtmlTextInfo Put(int id, [FromBody] HtmlTextInfo HtmlText) { if (ModelState.IsValid) - htmltext.UpdateHtmlText(HtmlText); + { + HtmlText = htmltext.UpdateHtmlText(HtmlText); + } + return HtmlText; } // DELETE api//5 diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs index ff5a8534..2347e601 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs @@ -27,12 +27,13 @@ namespace Oqtane.Server.Modules.HtmlText.Repository } } - public void AddHtmlText(HtmlTextInfo HtmlText) + public HtmlTextInfo AddHtmlText(HtmlTextInfo HtmlText) { try { db.HtmlText.Add(HtmlText); db.SaveChanges(); + return HtmlText; } catch { @@ -40,12 +41,13 @@ namespace Oqtane.Server.Modules.HtmlText.Repository } } - public void UpdateHtmlText(HtmlTextInfo HtmlText) + public HtmlTextInfo UpdateHtmlText(HtmlTextInfo HtmlText) { try { db.Entry(HtmlText).State = EntityState.Modified; db.SaveChanges(); + return HtmlText; } catch { diff --git a/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs b/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs index 6afc00c2..463d5e50 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs @@ -6,8 +6,8 @@ namespace Oqtane.Server.Modules.HtmlText.Repository public interface IHtmlTextRepository { IEnumerable GetHtmlText(); - void AddHtmlText(HtmlTextInfo HtmlText); - void UpdateHtmlText(HtmlTextInfo HtmlText); + HtmlTextInfo AddHtmlText(HtmlTextInfo HtmlText); + HtmlTextInfo UpdateHtmlText(HtmlTextInfo HtmlText); HtmlTextInfo GetHtmlText(int HtmlTextIdId); void DeleteHtmlText(int HtmlTextId); } diff --git a/Oqtane.Server/Repository/AliasRepository.cs b/Oqtane.Server/Repository/AliasRepository.cs index 8d512a59..8595557c 100644 --- a/Oqtane.Server/Repository/AliasRepository.cs +++ b/Oqtane.Server/Repository/AliasRepository.cs @@ -35,12 +35,13 @@ namespace Oqtane.Repository } } - public void AddAlias(Alias alias) + public Alias AddAlias(Alias Alias) { try { - db.Alias.Add(alias); + db.Alias.Add(Alias); db.SaveChanges(); + return Alias; } catch { @@ -48,12 +49,13 @@ namespace Oqtane.Repository } } - public void UpdateAlias(Alias alias) + public Alias UpdateAlias(Alias Alias) { try { - db.Entry(alias).State = EntityState.Modified; + db.Entry(Alias).State = EntityState.Modified; db.SaveChanges(); + return Alias; } catch { @@ -61,11 +63,11 @@ namespace Oqtane.Repository } } - public Alias GetAlias(int aliasId) + public Alias GetAlias(int AliasId) { try { - Alias alias = db.Alias.Find(aliasId); + Alias alias = db.Alias.Find(AliasId); return alias; } catch @@ -74,11 +76,11 @@ namespace Oqtane.Repository } } - public void DeleteAlias(int aliasId) + public void DeleteAlias(int AliasId) { try { - Alias alias = db.Alias.Find(aliasId); + Alias alias = db.Alias.Find(AliasId); db.Alias.Remove(alias); db.SaveChanges(); } diff --git a/Oqtane.Server/Repository/IAliasRepository.cs b/Oqtane.Server/Repository/IAliasRepository.cs index 4bc56f7b..3ab61f13 100644 --- a/Oqtane.Server/Repository/IAliasRepository.cs +++ b/Oqtane.Server/Repository/IAliasRepository.cs @@ -6,9 +6,9 @@ namespace Oqtane.Repository public interface IAliasRepository { IEnumerable GetAliases(); - void AddAlias(Alias alias); - void UpdateAlias(Alias alias); - Alias GetAlias(int aliasId); - void DeleteAlias(int aliasId); + Alias AddAlias(Alias Alias); + Alias UpdateAlias(Alias Alias); + Alias GetAlias(int AliasId); + void DeleteAlias(int AliasId); } } diff --git a/Oqtane.Server/Repository/IModuleRepository.cs b/Oqtane.Server/Repository/IModuleRepository.cs index 5fd6e321..9e9cde33 100644 --- a/Oqtane.Server/Repository/IModuleRepository.cs +++ b/Oqtane.Server/Repository/IModuleRepository.cs @@ -7,8 +7,8 @@ namespace Oqtane.Repository { IEnumerable GetModules(); IEnumerable GetModules(int SiteId, string ModuleDefinitionName); - void AddModule(Module Module); - void UpdateModule(Module Module); + Module AddModule(Module Module); + Module UpdateModule(Module Module); Module GetModule(int ModuleId); void DeleteModule(int ModuleId); } diff --git a/Oqtane.Server/Repository/IPageModuleRepository.cs b/Oqtane.Server/Repository/IPageModuleRepository.cs index 4b00f98f..a1fccef8 100644 --- a/Oqtane.Server/Repository/IPageModuleRepository.cs +++ b/Oqtane.Server/Repository/IPageModuleRepository.cs @@ -7,8 +7,8 @@ namespace Oqtane.Repository { IEnumerable GetPageModules(); IEnumerable GetPageModules(int PageId); - void AddPageModule(PageModule PageModule); - void UpdatePageModule(PageModule PageModule); + PageModule AddPageModule(PageModule PageModule); + PageModule UpdatePageModule(PageModule PageModule); PageModule GetPageModule(int PageModuleId); void DeletePageModule(int PageModuleId); } diff --git a/Oqtane.Server/Repository/IPageRepository.cs b/Oqtane.Server/Repository/IPageRepository.cs index 128810c8..cb479e98 100644 --- a/Oqtane.Server/Repository/IPageRepository.cs +++ b/Oqtane.Server/Repository/IPageRepository.cs @@ -7,8 +7,8 @@ namespace Oqtane.Repository { IEnumerable GetPages(); IEnumerable GetPages(int SiteId); - void AddPage(Page Page); - void UpdatePage(Page Page); + Page AddPage(Page Page); + Page UpdatePage(Page Page); Page GetPage(int PageId); void DeletePage(int PageId); } diff --git a/Oqtane.Server/Repository/ISiteRepository.cs b/Oqtane.Server/Repository/ISiteRepository.cs index a032c580..65cf9aff 100644 --- a/Oqtane.Server/Repository/ISiteRepository.cs +++ b/Oqtane.Server/Repository/ISiteRepository.cs @@ -6,9 +6,9 @@ namespace Oqtane.Repository public interface ISiteRepository { IEnumerable GetSites(); - void AddSite(Site site); - void UpdateSite(Site site); - Site GetSite(int siteId); - void DeleteSite(int siteId); + Site AddSite(Site Site); + Site UpdateSite(Site Site); + Site GetSite(int SiteId); + void DeleteSite(int SiteId); } } diff --git a/Oqtane.Server/Repository/ISiteUserRepository.cs b/Oqtane.Server/Repository/ISiteUserRepository.cs new file mode 100644 index 00000000..747f95e6 --- /dev/null +++ b/Oqtane.Server/Repository/ISiteUserRepository.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public interface ISiteUserRepository + { + IEnumerable GetSiteUsers(); + IEnumerable GetSiteUsers(int SiteId, int UserId); + SiteUser AddSiteUser(SiteUser SiteUser); + SiteUser UpdateSiteUser(SiteUser SiteUser); + SiteUser GetSiteUser(int SiteUserId); + void DeleteSiteUser(int SiteUserId); + } +} diff --git a/Oqtane.Server/Repository/ITenantRepository.cs b/Oqtane.Server/Repository/ITenantRepository.cs index df9181f6..17a8b1d0 100644 --- a/Oqtane.Server/Repository/ITenantRepository.cs +++ b/Oqtane.Server/Repository/ITenantRepository.cs @@ -6,9 +6,9 @@ namespace Oqtane.Repository public interface ITenantRepository { IEnumerable GetTenants(); - void AddTenant(Tenant tenant); - void UpdateTenant(Tenant tenant); - Tenant GetTenant(int tenantId); - void DeleteTenant(int tenantId); + Tenant AddTenant(Tenant Tenant); + Tenant UpdateTenant(Tenant Tenant); + Tenant GetTenant(int TenantId); + void DeleteTenant(int TenantId); } } diff --git a/Oqtane.Server/Repository/IUserRepository.cs b/Oqtane.Server/Repository/IUserRepository.cs index 05ede0ad..63757b49 100644 --- a/Oqtane.Server/Repository/IUserRepository.cs +++ b/Oqtane.Server/Repository/IUserRepository.cs @@ -6,8 +6,8 @@ namespace Oqtane.Repository public interface IUserRepository { IEnumerable GetUsers(); - void AddUser(User User); - void UpdateUser(User User); + User AddUser(User User); + User UpdateUser(User User); User GetUser(int UserId); User GetUser(string Username); void DeleteUser(int UserId); diff --git a/Oqtane.Server/Repository/ModuleRepository.cs b/Oqtane.Server/Repository/ModuleRepository.cs index aef77fbb..76c07605 100644 --- a/Oqtane.Server/Repository/ModuleRepository.cs +++ b/Oqtane.Server/Repository/ModuleRepository.cs @@ -41,12 +41,13 @@ namespace Oqtane.Repository } } - public void AddModule(Module Module) + public Module AddModule(Module Module) { try { db.Module.Add(Module); db.SaveChanges(); + return Module; } catch { @@ -54,12 +55,13 @@ namespace Oqtane.Repository } } - public void UpdateModule(Module Module) + public Module UpdateModule(Module Module) { try { db.Entry(Module).State = EntityState.Modified; db.SaveChanges(); + return Module; } catch { diff --git a/Oqtane.Server/Repository/PageModuleRepository.cs b/Oqtane.Server/Repository/PageModuleRepository.cs index 130d56e9..00c0fd0b 100644 --- a/Oqtane.Server/Repository/PageModuleRepository.cs +++ b/Oqtane.Server/Repository/PageModuleRepository.cs @@ -40,12 +40,13 @@ namespace Oqtane.Repository } } - public void AddPageModule(PageModule PageModule) + public PageModule AddPageModule(PageModule PageModule) { try { db.PageModule.Add(PageModule); db.SaveChanges(); + return PageModule; } catch { @@ -53,12 +54,13 @@ namespace Oqtane.Repository } } - public void UpdatePageModule(PageModule PageModule) + public PageModule UpdatePageModule(PageModule PageModule) { try { db.Entry(PageModule).State = EntityState.Modified; db.SaveChanges(); + return PageModule; } catch { diff --git a/Oqtane.Server/Repository/PageRepository.cs b/Oqtane.Server/Repository/PageRepository.cs index 45a09d7c..33612112 100644 --- a/Oqtane.Server/Repository/PageRepository.cs +++ b/Oqtane.Server/Repository/PageRepository.cs @@ -38,12 +38,13 @@ namespace Oqtane.Repository } } - public void AddPage(Page Page) + public Page AddPage(Page Page) { try { db.Page.Add(Page); db.SaveChanges(); + return Page; } catch { @@ -51,12 +52,13 @@ namespace Oqtane.Repository } } - public void UpdatePage(Page Page) + public Page UpdatePage(Page Page) { try { db.Entry(Page).State = EntityState.Modified; db.SaveChanges(); + return Page; } catch { diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index b382a214..bba65d22 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -26,12 +26,13 @@ namespace Oqtane.Repository } } - public void AddSite(Site site) + public Site AddSite(Site Site) { try { - db.Site.Add(site); + db.Site.Add(Site); db.SaveChanges(); + return Site; } catch { @@ -39,12 +40,13 @@ namespace Oqtane.Repository } } - public void UpdateSite(Site site) + public Site UpdateSite(Site Site) { try { - db.Entry(site).State = EntityState.Modified; + db.Entry(Site).State = EntityState.Modified; db.SaveChanges(); + return Site; } catch { diff --git a/Oqtane.Server/Repository/SiteUserRepository.cs b/Oqtane.Server/Repository/SiteUserRepository.cs new file mode 100644 index 00000000..81fa29f5 --- /dev/null +++ b/Oqtane.Server/Repository/SiteUserRepository.cs @@ -0,0 +1,100 @@ +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public class SiteUserRepository : ISiteUserRepository + { + private TenantDBContext db; + + public SiteUserRepository(TenantDBContext context) + { + db = context; + } + + public IEnumerable GetSiteUsers() + { + try + { + return db.SiteUser.ToList(); + } + catch + { + throw; + } + } + public IEnumerable GetSiteUsers(int SiteId, int UserId) + { + try + { + List siteusers = db.SiteUser.Where(item => item.SiteId == SiteId).ToList(); + if (UserId != -1) + { + siteusers = siteusers.Where(item => item.UserId == UserId).ToList(); + } + return siteusers; + } + catch + { + throw; + } + } + + public SiteUser AddSiteUser(SiteUser SiteUser) + { + try + { + db.SiteUser.Add(SiteUser); + db.SaveChanges(); + return SiteUser; + } + catch + { + throw; + } + } + + public SiteUser UpdateSiteUser(SiteUser SiteUser) + { + try + { + db.Entry(SiteUser).State = EntityState.Modified; + db.SaveChanges(); + return SiteUser; + } + catch + { + throw; + } + } + + public SiteUser GetSiteUser(int SiteUserId) + { + try + { + SiteUser SiteUser = db.SiteUser.Find(SiteUserId); + return SiteUser; + } + catch + { + throw; + } + } + + public void DeleteSiteUser(int SiteUserId) + { + try + { + SiteUser SiteUser = db.SiteUser.Find(SiteUserId); + db.SiteUser.Remove(SiteUser); + db.SaveChanges(); + } + catch + { + throw; + } + } + } +} diff --git a/Oqtane.Server/Repository/TenantDBContext.cs b/Oqtane.Server/Repository/TenantDBContext.cs index 190fe9e0..a6f83e57 100644 --- a/Oqtane.Server/Repository/TenantDBContext.cs +++ b/Oqtane.Server/Repository/TenantDBContext.cs @@ -11,6 +11,7 @@ namespace Oqtane.Repository public virtual DbSet PageModule { get; set; } public virtual DbSet Module { get; set; } public virtual DbSet User { get; set; } + public virtual DbSet SiteUser { get; set; } public TenantDBContext(ITenantResolver TenantResolver, IHttpContextAccessor accessor) : base(TenantResolver, accessor) { diff --git a/Oqtane.Server/Repository/TenantRepository.cs b/Oqtane.Server/Repository/TenantRepository.cs index 42d2c00a..d21d8f2e 100644 --- a/Oqtane.Server/Repository/TenantRepository.cs +++ b/Oqtane.Server/Repository/TenantRepository.cs @@ -36,12 +36,13 @@ namespace Oqtane.Repository } } - public void AddTenant(Tenant tenant) + public Tenant AddTenant(Tenant Tenant) { try { - db.Tenant.Add(tenant); + db.Tenant.Add(Tenant); db.SaveChanges(); + return Tenant; } catch { @@ -49,12 +50,13 @@ namespace Oqtane.Repository } } - public void UpdateTenant(Tenant tenant) + public Tenant UpdateTenant(Tenant Tenant) { try { - db.Entry(tenant).State = EntityState.Modified; + db.Entry(Tenant).State = EntityState.Modified; db.SaveChanges(); + return Tenant; } catch { @@ -62,11 +64,11 @@ namespace Oqtane.Repository } } - public Tenant GetTenant(int tenantId) + public Tenant GetTenant(int TenantId) { try { - Tenant tenant = db.Tenant.Find(tenantId); + Tenant tenant = db.Tenant.Find(TenantId); return tenant; } catch @@ -75,11 +77,11 @@ namespace Oqtane.Repository } } - public void DeleteTenant(int tenantId) + public void DeleteTenant(int TenantId) { try { - Tenant tenant = db.Tenant.Find(tenantId); + Tenant tenant = db.Tenant.Find(TenantId); db.Tenant.Remove(tenant); db.SaveChanges(); } diff --git a/Oqtane.Server/Repository/UserRepository.cs b/Oqtane.Server/Repository/UserRepository.cs index b296110e..6b863e37 100644 --- a/Oqtane.Server/Repository/UserRepository.cs +++ b/Oqtane.Server/Repository/UserRepository.cs @@ -26,12 +26,13 @@ namespace Oqtane.Repository } } - public void AddUser(User user) + public User AddUser(User user) { try { db.User.Add(user); db.SaveChanges(); + return user; } catch { @@ -39,12 +40,13 @@ namespace Oqtane.Repository } } - public void UpdateUser(User user) + public User UpdateUser(User user) { try { db.Entry(user).State = EntityState.Modified; db.SaveChanges(); + return user; } catch { diff --git a/Oqtane.Server/Scripts/Tenant.sql b/Oqtane.Server/Scripts/Tenant.sql index 9b3a1a7d..d81f34f7 100644 --- a/Oqtane.Server/Scripts/Tenant.sql +++ b/Oqtane.Server/Scripts/Tenant.sql @@ -96,6 +96,21 @@ CREATE TABLE [dbo].[User]( ) GO +CREATE TABLE [dbo].[SiteUser]( + [SiteUserId] [int] IDENTITY(1,1) NOT NULL, + [SiteId] [int] NOT NULL, + [UserId] [int] NOT NULL, + [IsAuthorized] [bit] NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_SiteUser] PRIMARY KEY CLUSTERED + ( + [SiteUserId] ASC + ) +) +GO /* Create foreign key relationships @@ -125,6 +140,15 @@ REFERENCES [dbo].[Page] ([PageId]) ON DELETE CASCADE GO +ALTER TABLE [dbo].[SiteUser] WITH CHECK ADD CONSTRAINT [FK_SiteUser_Site] FOREIGN KEY([SiteId]) +REFERENCES [dbo].[Site] ([SiteId]) +ON DELETE CASCADE +GO + +ALTER TABLE [dbo].[SiteUser] WITH CHECK ADD CONSTRAINT [FK_SiteUser_User] FOREIGN KEY([UserId]) +REFERENCES [dbo].[User] ([UserId]) +GO + /* Create seed data diff --git a/Oqtane.Shared/Models/SiteUser.cs b/Oqtane.Shared/Models/SiteUser.cs new file mode 100644 index 00000000..cfae5d2f --- /dev/null +++ b/Oqtane.Shared/Models/SiteUser.cs @@ -0,0 +1,17 @@ +using System; + +namespace Oqtane.Models +{ + public class SiteUser : IAuditable + { + public int SiteUserId { get; set; } + public int SiteId { get; set; } + public int UserId { get; set; } + public bool IsAuthorized { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + } +} diff --git a/Oqtane.Shared/Models/User.cs b/Oqtane.Shared/Models/User.cs index 34b27776..96e7d786 100644 --- a/Oqtane.Shared/Models/User.cs +++ b/Oqtane.Shared/Models/User.cs @@ -10,6 +10,8 @@ namespace Oqtane.Models public string Roles { get; set; } public bool IsSuperUser { get; set; } + [NotMapped] + public int SiteId { get; set; } [NotMapped] public string Password { get; set; } [NotMapped] From 916109015f5afac64d0fd60b7b7a988432da47aa Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 5 Aug 2019 11:28:59 -0400 Subject: [PATCH 10/44] Add standard audit fields to all entities --- Oqtane.Server/Repository/DBContextBase.cs | 6 +- Oqtane.Server/Repository/MasterDBContext.cs | 50 ++++- Oqtane.Server/Scripts/Master.sql | 22 +- Oqtane.Server/Scripts/Tenant.sql | 228 +++++++++++--------- Oqtane.Shared/Models/Alias.cs | 11 +- Oqtane.Shared/Models/Module.cs | 11 +- Oqtane.Shared/Models/Page.cs | 11 +- Oqtane.Shared/Models/PageModule.cs | 12 +- Oqtane.Shared/Models/Tenant.cs | 7 +- Oqtane.Shared/Models/User.cs | 10 +- 10 files changed, 241 insertions(+), 127 deletions(-) diff --git a/Oqtane.Server/Repository/DBContextBase.cs b/Oqtane.Server/Repository/DBContextBase.cs index bb2c6d8a..a6b07ac4 100644 --- a/Oqtane.Server/Repository/DBContextBase.cs +++ b/Oqtane.Server/Repository/DBContextBase.cs @@ -41,7 +41,11 @@ namespace Oqtane.Repository { ChangeTracker.DetectChanges(); - string username = accessor.HttpContext.User.Identity.Name; + string username = ""; + if (accessor.HttpContext.User.Identity.Name != null) + { + username = accessor.HttpContext.User.Identity.Name; + } DateTime date = DateTime.Now; var created = ChangeTracker.Entries() diff --git a/Oqtane.Server/Repository/MasterDBContext.cs b/Oqtane.Server/Repository/MasterDBContext.cs index 5e749fa8..0cc802a6 100644 --- a/Oqtane.Server/Repository/MasterDBContext.cs +++ b/Oqtane.Server/Repository/MasterDBContext.cs @@ -1,13 +1,59 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; using Oqtane.Models; +using System; +using System.Linq; namespace Oqtane.Repository { public class MasterDBContext : DbContext { - public MasterDBContext(DbContextOptions options) : base(options) { } + private IHttpContextAccessor accessor; + + public MasterDBContext(DbContextOptions options, IHttpContextAccessor accessor) : base(options) + { + this.accessor = accessor; + } public virtual DbSet Alias { get; set; } public virtual DbSet Tenant { get; set; } + + public override int SaveChanges() + { + ChangeTracker.DetectChanges(); + + string username = ""; + if (accessor.HttpContext.User.Identity.Name != null) + { + username = accessor.HttpContext.User.Identity.Name; + } + DateTime date = DateTime.Now; + + var created = ChangeTracker.Entries() + .Where(x => x.State == EntityState.Added); + + foreach (var item in created) + { + if (item.Entity is IAuditable entity) + { + item.CurrentValues[nameof(IAuditable.CreatedBy)] = username; + item.CurrentValues[nameof(IAuditable.CreatedOn)] = date; + } + } + + var modified = ChangeTracker.Entries() + .Where(x => x.State == EntityState.Modified || x.State == EntityState.Added); + + foreach (var item in modified) + { + if (item.Entity is IAuditable entity) + { + item.CurrentValues[nameof(IAuditable.ModifiedBy)] = username; + item.CurrentValues[nameof(IAuditable.ModifiedOn)] = date; + } + } + + return base.SaveChanges(); + } } } diff --git a/Oqtane.Server/Scripts/Master.sql b/Oqtane.Server/Scripts/Master.sql index 9c2cb0b4..cbe422d1 100644 --- a/Oqtane.Server/Scripts/Master.sql +++ b/Oqtane.Server/Scripts/Master.sql @@ -8,6 +8,10 @@ CREATE TABLE [dbo].[Alias]( [Name] [nvarchar](200) NOT NULL, [TenantId] [int] NOT NULL, [SiteId] [int] NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_Alias] PRIMARY KEY CLUSTERED ( [AliasId] ASC @@ -19,7 +23,11 @@ CREATE TABLE [dbo].[Tenant]( [TenantId] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](100) NOT NULL, [DBConnectionString] [nvarchar](1024) NOT NULL, - [DBSchema] [nvarchar](50) NOT NULL + [DBSchema] [nvarchar](50) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_Tenant] PRIMARY KEY CLUSTERED ( [TenantId] ASC @@ -45,19 +53,19 @@ Create seed data */ SET IDENTITY_INSERT [dbo].[Tenant] ON GO -INSERT [dbo].[Tenant] ([TenantId], [Name], [DBConnectionString], [DBSchema]) -VALUES (1, N'Tenant1', N'{ConnectionString}', N'') +INSERT [dbo].[Tenant] ([TenantId], [Name], [DBConnectionString], [DBSchema], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, N'Tenant1', N'{ConnectionString}', N'', '', getdate(), '', getdate()) GO SET IDENTITY_INSERT [dbo].[Tenant] OFF GO SET IDENTITY_INSERT [dbo].[Alias] ON GO -INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId]) -VALUES (1, N'{Alias}', 1, 1) +INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, N'{Alias}', 1, 1, '', getdate(), '', getdate()) GO -INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId]) -VALUES (2, N'{Alias}/site2', 1, 2) +INSERT [dbo].[Alias] ([AliasId], [Name], [TenantId], [SiteId], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, N'{Alias}/site2', 1, 2, '', getdate(), '', getdate()) GO SET IDENTITY_INSERT [dbo].[Alias] OFF GO diff --git a/Oqtane.Server/Scripts/Tenant.sql b/Oqtane.Server/Scripts/Tenant.sql index d81f34f7..ed1626be 100644 --- a/Oqtane.Server/Scripts/Tenant.sql +++ b/Oqtane.Server/Scripts/Tenant.sql @@ -33,6 +33,10 @@ CREATE TABLE [dbo].[Page]( [Order] [int] NOT NULL, [IsNavigation] [bit] NOT NULL, [LayoutType] [nvarchar](200) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_Page] PRIMARY KEY CLUSTERED ( [PageId] ASC @@ -46,6 +50,10 @@ CREATE TABLE [dbo].[Module]( [ModuleDefinitionName] [nvarchar](200) NOT NULL, [ViewPermissions] [nvarchar](500) NOT NULL, [EditPermissions] [nvarchar](500) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_Module] PRIMARY KEY CLUSTERED ( [ModuleId] ASC @@ -61,6 +69,10 @@ CREATE TABLE [dbo].[PageModule]( [Pane] [nvarchar](50) NOT NULL, [Order] [int] NOT NULL, [ContainerType] [nvarchar](200) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_PageModule] PRIMARY KEY CLUSTERED ( [PageModuleId] ASC @@ -89,6 +101,10 @@ CREATE TABLE [dbo].[User]( [DisplayName] [nvarchar](50) NOT NULL, [Roles] [nvarchar](50) NOT NULL, [IsSuperUser] [bit] NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ( [UserId] ASC @@ -168,174 +184,174 @@ GO SET IDENTITY_INSERT [dbo].[Page] ON GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (1, 1, N'Page1', N'', N'Oqtane.Client.Themes.Theme1.Theme1, Oqtane.Client', N'oi-home', N'Left;Right', N'All Users', N'Administrators', NULL, 1, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, 1, N'Page1', N'', N'Oqtane.Client.Themes.Theme1.Theme1, Oqtane.Client', N'oi-home', N'Left;Right', N'All Users', N'Administrators', NULL, 1, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (2, 1, N'Page2', N'page2', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-plus', N'Top;Bottom', N'Administrators;Editors;', N'Administrators', NULL, 3, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, 1, N'Page2', N'page2', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-plus', N'Top;Bottom', N'Administrators;Editors;', N'Administrators', NULL, 3, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (3, 1, N'Page3', N'page3', N'Oqtane.Client.Themes.Theme3.Theme3, Oqtane.Client', N'oi-list-rich', N'Left;Right', N'All Users', N'Administrators', NULL, 3, 1, N'Oqtane.Client.Themes.Theme3.HorizontalLayout, Oqtane.Client') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (3, 1, N'Page3', N'page3', N'Oqtane.Client.Themes.Theme3.Theme3, Oqtane.Client', N'oi-list-rich', N'Left;Right', N'All Users', N'Administrators', NULL, 3, 1, N'Oqtane.Client.Themes.Theme3.HorizontalLayout, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (4, 1, N'Admin', N'admin', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-home', N'Top;Bottom', N'Administrators', N'Administrators', NULL, 7, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (4, 1, N'Admin', N'admin', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-home', N'Top;Bottom', N'Administrators', N'Administrators', NULL, 7, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (5, 1, N'Page Management', N'admin/pages', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 1, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (5, 1, N'Page Management', N'admin/pages', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 1, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (6, 1, 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'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (6, 1, 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'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (7, 1, 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'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (7, 1, 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'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (8, 1, N'Site Management', N'admin/sites', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 0, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (8, 1, N'Site Management', N'admin/sites', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 0, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (9, 1, N'User Management', N'admin/users', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 2, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (9, 1, N'User Management', N'admin/users', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 2, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (10, 1, N'Module Management', N'admin/modules', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 3, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (10, 1, N'Module Management', N'admin/modules', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 3, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (11, 1, N'Theme Management', N'admin/themes', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 4, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (11, 1, N'Theme Management', N'admin/themes', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 4, 1, N'', '', getdate(), '', getdate()) GO -INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType]) -VALUES (12, 2, N'Page1', N'', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-home', N'Top;Bottom', N'All Users', N'Administrators', NULL, 1, 1, N'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (12, 2, N'Page1', N'', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-home', N'Top;Bottom', N'All Users', N'Administrators', NULL, 1, 1, N'', '', getdate(), '', getdate()) 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'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +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'', '', getdate(), '', getdate()) 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'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +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'', '', getdate(), '', getdate()) 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'') +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +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'', '', getdate(), '', getdate()) GO SET IDENTITY_INSERT [dbo].[Page] OFF GO SET IDENTITY_INSERT [dbo].[Module] ON GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (1, 1, N'Oqtane.Client.Modules.Weather, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, 1, N'Oqtane.Client.Modules.Weather, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (2, 1, N'Oqtane.Client.Modules.Counter, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, 1, N'Oqtane.Client.Modules.Counter, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (3, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (3, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (4, 1, N'Oqtane.Client.Modules.Weather, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (4, 1, N'Oqtane.Client.Modules.Weather, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (5, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (5, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (6, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (6, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (7, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'Administrators;Editors;Members;', N'Administrators;Editors;') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (7, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'Administrators;Editors;Members;', N'Administrators;Editors;', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (8, 1, N'Oqtane.Client.Modules.Admin.Pages, Oqtane.Client', N'Administrators', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (8, 1, N'Oqtane.Client.Modules.Admin.Pages, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (9, 1, N'Oqtane.Client.Modules.Admin.Login, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (9, 1, N'Oqtane.Client.Modules.Admin.Login, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (10, 1, N'Oqtane.Client.Modules.Admin.Register, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (10, 1, N'Oqtane.Client.Modules.Admin.Register, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (11, 1, N'Oqtane.Client.Modules.Admin.Admin, Oqtane.Client', N'Administrators', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (11, 1, N'Oqtane.Client.Modules.Admin.Admin, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (12, 1, N'Oqtane.Client.Modules.Admin.Sites, Oqtane.Client', N'Administrators', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (12, 1, N'Oqtane.Client.Modules.Admin.Sites, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (13, 1, N'Oqtane.Client.Modules.Admin.Users, Oqtane.Client', N'Administrators', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (13, 1, N'Oqtane.Client.Modules.Admin.Users, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (14, 1, N'Oqtane.Client.Modules.Admin.ModuleDefinitions, Oqtane.Client', N'Administrators', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (14, 1, N'Oqtane.Client.Modules.Admin.ModuleDefinitions, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (15, 1, N'Oqtane.Client.Modules.Admin.Themes, Oqtane.Client', N'Administrators', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (15, 1, N'Oqtane.Client.Modules.Admin.Themes, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (16, 2, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (16, 2, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO -INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions]) -VALUES (17, 2, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (17, 2, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) 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') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (18, 2, N'Oqtane.Client.Modules.Admin.Login, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) 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') +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (19, 2, N'Oqtane.Client.Modules.Admin.Register, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO SET IDENTITY_INSERT [dbo].[Module] OFF GO SET IDENTITY_INSERT [dbo].[PageModule] ON GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (1, 1, 1, N'Weather', N'Right', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, 1, 1, N'Weather', N'Right', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (2, 1, 2, N'Counter', N'Left', 1, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, 1, 2, N'Counter', N'Left', 1, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (3, 1, 3, N'Text', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (3, 1, 3, N'Text', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (4, 2, 4, N'Weather', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (4, 2, 4, N'Weather', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (5, 2, 5, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (5, 2, 5, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (6, 3, 6, N'Text', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (6, 3, 6, N'Text', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (7, 3, 7, N'Text', N'Right', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (7, 3, 7, N'Text', N'Right', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (8, 5, 8, N'Page Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (8, 5, 8, N'Page Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (9, 6, 9, N'Login', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (9, 6, 9, N'Login', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (10, 7, 10, N'Register', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (10, 7, 10, N'Register', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (11, 4, 11, N'Administration', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (11, 4, 11, N'Administration', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (12, 8, 12, N'Site Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (12, 8, 12, N'Site Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (13, 9, 13, N'User Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (13, 9, 13, N'User Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (14, 10, 14, N'Module Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (14, 10, 14, N'Module Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (15, 11, 15, N'Theme Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (15, 11, 15, N'Theme Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO -INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType]) -VALUES (16, 12, 16, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (16, 12, 16, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) 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') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (17, 13, 17, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) 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') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (18, 14, 18, N'Login', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) 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') +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (19, 15, 19, N'Register', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO SET IDENTITY_INSERT [dbo].[PageModule] OFF GO diff --git a/Oqtane.Shared/Models/Alias.cs b/Oqtane.Shared/Models/Alias.cs index 704acf43..a2caa95f 100644 --- a/Oqtane.Shared/Models/Alias.cs +++ b/Oqtane.Shared/Models/Alias.cs @@ -1,14 +1,21 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System; +using System.ComponentModel.DataAnnotations.Schema; namespace Oqtane.Models { - public class Alias + public class Alias : IAuditable { public int AliasId { get; set; } public string Name { get; set; } public int TenantId { get; set; } public int SiteId { get; set; } + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + + [NotMapped] public string Scheme { get; set; } diff --git a/Oqtane.Shared/Models/Module.cs b/Oqtane.Shared/Models/Module.cs index e7522b99..04e359cf 100644 --- a/Oqtane.Shared/Models/Module.cs +++ b/Oqtane.Shared/Models/Module.cs @@ -1,15 +1,22 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; namespace Oqtane.Models { - public class Module + public class Module : IAuditable { public int ModuleId { get; set; } public int SiteId { get; set; } public string ModuleDefinitionName { get; set; } public string ViewPermissions { get; set; } public string EditPermissions { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + [NotMapped] public int PageModuleId { get; set; } [NotMapped] diff --git a/Oqtane.Shared/Models/Page.cs b/Oqtane.Shared/Models/Page.cs index 1e04f4c3..e01aa0cd 100644 --- a/Oqtane.Shared/Models/Page.cs +++ b/Oqtane.Shared/Models/Page.cs @@ -1,6 +1,8 @@ -namespace Oqtane.Models +using System; + +namespace Oqtane.Models { - public class Page + public class Page : IAuditable { public int PageId { get; set; } public int SiteId { get; set; } @@ -15,5 +17,10 @@ public string ViewPermissions { get; set; } public string EditPermissions { get; set; } public bool IsNavigation { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } } } diff --git a/Oqtane.Shared/Models/PageModule.cs b/Oqtane.Shared/Models/PageModule.cs index af8b330b..ffeb1872 100644 --- a/Oqtane.Shared/Models/PageModule.cs +++ b/Oqtane.Shared/Models/PageModule.cs @@ -1,6 +1,8 @@ -namespace Oqtane.Models +using System; + +namespace Oqtane.Models { - public class PageModule + public class PageModule : IAuditable { public int PageModuleId { get; set; } public int PageId { get; set; } @@ -10,6 +12,12 @@ public int Order { get; set; } public string ContainerType { get; set; } + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + + public Module Module { get; set; } } } diff --git a/Oqtane.Shared/Models/Tenant.cs b/Oqtane.Shared/Models/Tenant.cs index 9a4fd66a..f7eb85a4 100644 --- a/Oqtane.Shared/Models/Tenant.cs +++ b/Oqtane.Shared/Models/Tenant.cs @@ -2,11 +2,16 @@ namespace Oqtane.Models { - public class Tenant + public class Tenant : IAuditable { public int TenantId { get; set; } public string Name { get; set; } public string DBConnectionString { get; set; } public string DBSchema { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } } } diff --git a/Oqtane.Shared/Models/User.cs b/Oqtane.Shared/Models/User.cs index 96e7d786..6c759a74 100644 --- a/Oqtane.Shared/Models/User.cs +++ b/Oqtane.Shared/Models/User.cs @@ -1,8 +1,9 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System; +using System.ComponentModel.DataAnnotations.Schema; namespace Oqtane.Models { - public class User + public class User : IAuditable { public int UserId { get; set; } public string Username { get; set; } @@ -10,6 +11,11 @@ namespace Oqtane.Models public string Roles { get; set; } public bool IsSuperUser { get; set; } + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + [NotMapped] public int SiteId { get; set; } [NotMapped] From 62b5ea77b34d060b8c7aaf0ac1e64e41c9f4834f Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 5 Aug 2019 11:31:17 -0400 Subject: [PATCH 11/44] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index eea4fd37..581df7e2 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,7 @@ Security - Need ability to manage Permissions - a permission UI component for pages/modules - may also need to include Permission table schema similar to DNN -- Need ability to manage Authorization ( will need to be custom so that permissions set by user are observed at API level ) -- Need audit fields ( ie. CreatedBy, CreateOn, etc… ) on all core tables +- Need ability to manage Authorization ( will need to be custom so that permissions set by user are observed at API level ) - Logging - Support for friendly Page Not Found handling From b71f0079813934a1fa7555aad642329236059833 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 14 Aug 2019 09:34:35 -0400 Subject: [PATCH 12/44] Support for third party modules, improved error handling, standardardized enum naming, reorganized interface definitions, support for DB script upgrades, added Settings entity --- Oqtane.Client/App.razor | 2 +- Oqtane.Client/Modules/Admin/Login/Index.razor | 71 +++++----- .../Admin/ModuleDefinitions/Index.razor | 2 +- .../Modules/Admin/ModuleSettings/Index.razor | 34 ++++- Oqtane.Client/Modules/Admin/Pages/Add.razor | 2 +- .../Modules/Admin/Pages/Delete.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Edit.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Index.razor | 2 +- .../Modules/Admin/Register/Index.razor | 3 +- Oqtane.Client/Modules/Admin/Sites/Add.razor | 2 +- Oqtane.Client/Modules/Admin/Sites/Index.razor | 2 +- .../Modules/Admin/Themes/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Users/Index.razor | 2 +- .../Modules/Controls/ActionLink.razor | 17 ++- .../Modules/Controls/ModuleMessage.razor | 44 +++++++ Oqtane.Client/Modules/HtmlText/Edit.razor | 2 +- Oqtane.Client/Modules/HtmlText/Index.razor | 2 +- Oqtane.Client/Modules/IModuleControl.cs | 2 +- Oqtane.Client/Modules/MessageType.cs | 10 ++ Oqtane.Client/Modules/ModuleBase.cs | 9 +- Oqtane.Client/Modules/SecurityAccessLevel.cs | 2 +- Oqtane.Client/Properties/launchSettings.json | 2 +- .../{ => Interfaces}/IAliasService.cs | 0 .../{ => Interfaces}/IInstallationService.cs | 0 .../IModuleDefinitionService.cs | 0 .../{ => Interfaces}/IModuleService.cs | 0 .../{ => Interfaces}/IPageModuleService.cs | 1 + .../Services/{ => Interfaces}/IPageService.cs | 0 .../Services/Interfaces/ISettingService.cs | 27 ++++ .../Services/{ => Interfaces}/ISiteService.cs | 0 .../{ => Interfaces}/ITenantService.cs | 0 .../IThemeService.cs} | 0 .../Services/{ => Interfaces}/IUserService.cs | 0 .../{ => Interfaces}/InstallationService.cs | 0 Oqtane.Client/Services/PageModuleService.cs | 5 + Oqtane.Client/Services/SettingService.cs | 92 +++++++++++++ Oqtane.Client/Shared/Constants.cs | 1 + Oqtane.Client/Shared/Container.razor | 7 +- Oqtane.Client/Shared/Installer.razor | 119 +++++++++-------- Oqtane.Client/Shared/ModuleInstance.razor | 17 ++- Oqtane.Client/Shared/Pane.razor | 12 +- Oqtane.Client/Shared/SiteRouter.razor | 12 +- Oqtane.Client/Shared/Theme.razor | 7 +- Oqtane.Client/Shared/Utilities.cs | 8 +- Oqtane.Client/Startup.cs | 4 +- Oqtane.Client/Themes/ContainerBase.cs | 7 +- Oqtane.Client/Themes/Controls/Logo.razor | 3 +- Oqtane.Client/Themes/Controls/Menu.razor | 3 +- .../Themes/Controls/ModuleTitle.razor | 3 +- Oqtane.Client/Themes/ThemeBase.cs | 7 +- Oqtane.Client/Themes/ThemeObjectBase.cs | 7 +- .../Controllers/InstallationController.cs | 66 +++++++++- .../Controllers/SettingController.cs | 61 +++++++++ Oqtane.Server/Controllers/UserController.cs | 47 ++++--- Oqtane.Server/Modules/MVCModuleExtension.cs | 30 +++++ Oqtane.Server/Oqtane.Server.csproj | 6 +- .../Repository/{ => Context}/DBContextBase.cs | 0 .../{ => Context}/MasterDBContext.cs | 0 .../{ => Context}/TenantDBContext.cs | 1 + .../{ => Interfaces}/IAliasRepository.cs | 0 .../IModuleDefinitionRepository.cs | 0 .../{ => Interfaces}/IModuleRepository.cs | 0 .../{ => Interfaces}/IPageModuleRepository.cs | 0 .../{ => Interfaces}/IPageRepository.cs | 0 .../Interfaces/ISettingRepository.cs | 14 ++ .../{ => Interfaces}/ISiteRepository.cs | 0 .../{ => Interfaces}/ISiteUserRepository.cs | 0 .../{ => Interfaces}/ITenantRepository.cs | 0 .../{ => Interfaces}/ITenantResolver.cs | 0 .../{ => Interfaces}/IThemeRepository.cs | 0 .../{ => Interfaces}/IUserRepository.cs | 0 .../Repository/ModuleDefinitionRepository.cs | 10 +- Oqtane.Server/Repository/SettingRepository.cs | 85 ++++++++++++ Oqtane.Server/Repository/ThemeRepository.cs | 8 +- .../Scripts/{Tenant.sql => 00.00.00.sql} | 43 ++++++- .../Scripts/{Identity.sql => 00.00.01.sql} | 0 Oqtane.Server/Startup.cs | 121 ++++++++---------- Oqtane.Shared/Models/Setting.cs | 18 +++ 78 files changed, 809 insertions(+), 261 deletions(-) create mode 100644 Oqtane.Client/Modules/Controls/ModuleMessage.razor create mode 100644 Oqtane.Client/Modules/MessageType.cs rename Oqtane.Client/Services/{ => Interfaces}/IAliasService.cs (100%) rename Oqtane.Client/Services/{ => Interfaces}/IInstallationService.cs (100%) rename Oqtane.Client/Services/{ => Interfaces}/IModuleDefinitionService.cs (100%) rename Oqtane.Client/Services/{ => Interfaces}/IModuleService.cs (100%) rename Oqtane.Client/Services/{ => Interfaces}/IPageModuleService.cs (86%) rename Oqtane.Client/Services/{ => Interfaces}/IPageService.cs (100%) create mode 100644 Oqtane.Client/Services/Interfaces/ISettingService.cs rename Oqtane.Client/Services/{ => Interfaces}/ISiteService.cs (100%) rename Oqtane.Client/Services/{ => Interfaces}/ITenantService.cs (100%) rename Oqtane.Client/Services/{IthemeService.cs => Interfaces/IThemeService.cs} (100%) rename Oqtane.Client/Services/{ => Interfaces}/IUserService.cs (100%) rename Oqtane.Client/Services/{ => Interfaces}/InstallationService.cs (100%) create mode 100644 Oqtane.Client/Services/SettingService.cs create mode 100644 Oqtane.Server/Controllers/SettingController.cs create mode 100644 Oqtane.Server/Modules/MVCModuleExtension.cs rename Oqtane.Server/Repository/{ => Context}/DBContextBase.cs (100%) rename Oqtane.Server/Repository/{ => Context}/MasterDBContext.cs (100%) rename Oqtane.Server/Repository/{ => Context}/TenantDBContext.cs (92%) rename Oqtane.Server/Repository/{ => Interfaces}/IAliasRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/IModuleDefinitionRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/IModuleRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/IPageModuleRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/IPageRepository.cs (100%) create mode 100644 Oqtane.Server/Repository/Interfaces/ISettingRepository.cs rename Oqtane.Server/Repository/{ => Interfaces}/ISiteRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/ISiteUserRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/ITenantRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/ITenantResolver.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/IThemeRepository.cs (100%) rename Oqtane.Server/Repository/{ => Interfaces}/IUserRepository.cs (100%) create mode 100644 Oqtane.Server/Repository/SettingRepository.cs rename Oqtane.Server/Scripts/{Tenant.sql => 00.00.00.sql} (95%) rename Oqtane.Server/Scripts/{Identity.sql => 00.00.01.sql} (100%) create mode 100644 Oqtane.Shared/Models/Setting.cs diff --git a/Oqtane.Client/App.razor b/Oqtane.Client/App.razor index 6ad2be28..8deaf8a0 100644 --- a/Oqtane.Client/App.razor +++ b/Oqtane.Client/App.razor @@ -5,7 +5,7 @@ @if (!Installed) { - + } else { diff --git a/Oqtane.Client/Modules/Admin/Login/Index.razor b/Oqtane.Client/Modules/Admin/Login/Index.razor index b419ab98..1e0dde3e 100644 --- a/Oqtane.Client/Modules/Admin/Login/Index.razor +++ b/Oqtane.Client/Modules/Admin/Login/Index.razor @@ -42,50 +42,51 @@ @code { -public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Anonymous; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Anonymous; } } -public string Message { get; set; } = ""; -public string Username { get; set; } = ""; -public string Password { get; set; } = ""; -public bool Remember { get; set; } = false; + public string Message { get; set; } = ""; + public string Username { get; set; } = ""; + public string Password { get; set; } = ""; + public bool Remember { get; set; } = false; -private async Task Login() -{ - User user = new User(); - user.Username = Username; - user.Password = Password; - user.IsPersistent = Remember; - user = await UserService.LoginUserAsync(user); - if (user.IsAuthenticated) + private async Task Login() { - string ReturnUrl = PageState.QueryString["returnurl"]; - - var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider)); - if (authstateprovider == null) + User user = new User(); + user.SiteId = PageState.Site.SiteId; + user.Username = Username; + user.Password = Password; + user.IsPersistent = Remember; + user = await UserService.LoginUserAsync(user); + if (user.IsAuthenticated) { - // server-side Blazor - var interop = new Interop(jsRuntime); - string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken"); - var fields = new { __RequestVerificationToken = antiforgerytoken, username = Username, password = Password, remember = Remember, returnurl = ReturnUrl }; - await interop.SubmitForm("/login/", fields); + string ReturnUrl = PageState.QueryString["returnurl"]; + + var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider)); + if (authstateprovider == null) + { + // server-side Blazor + var interop = new Interop(jsRuntime); + string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken"); + var fields = new { __RequestVerificationToken = antiforgerytoken, username = Username, password = Password, remember = Remember, returnurl = ReturnUrl }; + await interop.SubmitForm("/login/", fields); + } + else + { + // client-side Blazor + authstateprovider.NotifyAuthenticationChanged(); + PageState.Reload = Constants.ReloadPage; + UriHelper.NavigateTo(NavigateUrl(ReturnUrl)); + } } else { - // client-side Blazor - authstateprovider.NotifyAuthenticationChanged(); - PageState.Reload = Constants.ReloadPage; - UriHelper.NavigateTo(NavigateUrl(ReturnUrl)); + Message = "
Login Failed. Please Remember That Passwords Are Case Sensitive.
"; } } - else + + private void Cancel() { - Message = "
Login Failed. Please Remember That Passwords Are Case Sensitive.
"; + string ReturnUrl = PageState.QueryString["returnurl"]; + UriHelper.NavigateTo(ReturnUrl); } } - -private void Cancel() -{ - string ReturnUrl = PageState.QueryString["returnurl"]; - UriHelper.NavigateTo(ReturnUrl); -} -} diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor index 55b017d4..475c5e2a 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor @@ -30,7 +30,7 @@ else } @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Host; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } } List moduledefinitions; diff --git a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor index a6e472d4..c0c9925f 100644 --- a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor @@ -63,11 +63,15 @@ + +@DynamicComponent + Cancel + @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Edit; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } } public override string Title { get { return "Module Settings"; } } Dictionary containers = new Dictionary(); @@ -77,6 +81,9 @@ string editpermissions; string pageid; + RenderFragment DynamicComponent { get; set; } + object settings; + protected override async Task OnInitAsync() { title = ModuleState.Title; @@ -85,6 +92,17 @@ viewpermissions = ModuleState.ViewPermissions; editpermissions = ModuleState.EditPermissions; pageid = ModuleState.PageId.ToString(); + + DynamicComponent = builder => + { + Type moduleType = Type.GetType(ModuleState.ModuleType); + if (moduleType != null) + { + builder.OpenComponent(0, moduleType); + builder.AddComponentReferenceCapture(1, inst => { settings = Convert.ChangeType(inst, moduleType); }); + builder.CloseComponent(); + } + }; } private async Task SaveModule() @@ -94,17 +112,19 @@ module.EditPermissions = editpermissions; await ModuleService.UpdateModuleAsync(module); - PageModule pagemodule = new PageModule(); - pagemodule.PageModuleId = ModuleState.PageModuleId; - pagemodule.PageId = Int32.Parse(pageid); - pagemodule.ModuleId = ModuleState.ModuleId; + PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); pagemodule.Title = title; - pagemodule.Pane = ModuleState.Pane; - pagemodule.Order = ModuleState.Order; pagemodule.ContainerType = containertype; await PageModuleService.UpdatePageModuleAsync(pagemodule); + Type moduleType = Type.GetType(ModuleState.ModuleType); + if (moduleType != null) + { + moduleType.GetMethod("UpdateSettings").Invoke(settings, null); // method must be public in settings component + } + PageState.Reload = Constants.ReloadPage; UriHelper.NavigateTo(NavigateUrl()); } + } diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index 2337a59e..d808e08b 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -115,7 +115,7 @@ Cancel @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Admin; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } Dictionary themes = new Dictionary(); Dictionary panelayouts = new Dictionary(); diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index 964b1f32..e3ef602a 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -115,7 +115,7 @@ Cancel @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Admin; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } Dictionary themes = new Dictionary(); Dictionary panelayouts = new Dictionary(); diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 269695b9..c5734f56 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -116,7 +116,7 @@ Cancel @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Admin; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } Dictionary themes = new Dictionary(); Dictionary panelayouts = new Dictionary(); diff --git a/Oqtane.Client/Modules/Admin/Pages/Index.razor b/Oqtane.Client/Modules/Admin/Pages/Index.razor index 73c6856f..e1c55bf9 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Index.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Index.razor @@ -36,5 +36,5 @@ else } @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Admin; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } } \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/Register/Index.razor b/Oqtane.Client/Modules/Admin/Register/Index.razor index 4a5a680f..a3ed92a7 100644 --- a/Oqtane.Client/Modules/Admin/Register/Index.razor +++ b/Oqtane.Client/Modules/Admin/Register/Index.razor @@ -20,7 +20,7 @@
@code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Anonymous; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Anonymous; } } public string Username { get; set; } = ""; public string Password { get; set; } = ""; @@ -28,6 +28,7 @@ private async Task RegisterUser() { User user = new User(); + user.SiteId = PageState.Site.SiteId; user.Username = Username; user.DisplayName = Username; user.Roles = "Administrators;"; diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index 9db5663c..e67505c0 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -60,7 +60,7 @@ else } @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Host; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } } List tenants; string tenantid; diff --git a/Oqtane.Client/Modules/Admin/Sites/Index.razor b/Oqtane.Client/Modules/Admin/Sites/Index.razor index bc54b094..264f3987 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Index.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Index.razor @@ -31,7 +31,7 @@ else } @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Host; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } } List sites; diff --git a/Oqtane.Client/Modules/Admin/Themes/Index.razor b/Oqtane.Client/Modules/Admin/Themes/Index.razor index 4c606d1a..c06f1ba4 100644 --- a/Oqtane.Client/Modules/Admin/Themes/Index.razor +++ b/Oqtane.Client/Modules/Admin/Themes/Index.razor @@ -29,7 +29,7 @@ else } @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Host; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } } List Themes; diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index 5445251b..cb0ca1a6 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -30,7 +30,7 @@ else } @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Host; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } } List Users; diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index bccc2d14..0954b864 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -54,23 +54,26 @@ if (moduleType != null) { var moduleobject = Activator.CreateInstance(moduleType); - SecurityAccessLevelEnum SecurityAccessLevel = (SecurityAccessLevelEnum)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); + SecurityAccessLevel SecurityAccessLevel = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); switch (SecurityAccessLevel) { - case SecurityAccessLevelEnum.Anonymous: + case SecurityAccessLevel.Anonymous: authorized = true; break; - case SecurityAccessLevelEnum.View: + case SecurityAccessLevel.View: authorized = UserService.IsAuthorized(PageState.User, ModuleState.ViewPermissions); break; - case SecurityAccessLevelEnum.Edit: + case SecurityAccessLevel.Edit: authorized = UserService.IsAuthorized(PageState.User, ModuleState.EditPermissions); break; - case SecurityAccessLevelEnum.Admin: + case SecurityAccessLevel.Admin: authorized = UserService.IsAuthorized(PageState.User, Constants.AdminRole); break; - case SecurityAccessLevelEnum.Host: - authorized = PageState.User.IsSuperUser; + case SecurityAccessLevel.Host: + if (PageState.User != null) + { + authorized = PageState.User.IsSuperUser; + } break; } } diff --git a/Oqtane.Client/Modules/Controls/ModuleMessage.razor b/Oqtane.Client/Modules/Controls/ModuleMessage.razor new file mode 100644 index 00000000..3aec02f3 --- /dev/null +++ b/Oqtane.Client/Modules/Controls/ModuleMessage.razor @@ -0,0 +1,44 @@ +@using Oqtane.Modules +@inherits ModuleBase + +@if (authorized) +{ +
+ @Message +
+} + +@code { + [Parameter] + private MessageType Type { get; set; } + + [Parameter] + private string Message { get; set; } + + string type = "alert alert-success"; // optional + bool authorized = false; + + protected override void OnInit() + { + if (PageState.User != null) + { + authorized = PageState.User.IsSuperUser; + } + + switch (Type) + { + case MessageType.Success: + type = "alert alert-success"; + break; + case MessageType.Info: + type = "alert alert-info"; + break; + case MessageType.Warning: + type = "alert alert-warning"; + break; + case MessageType.Error: + type = "alert alert-danger"; + break; + } + } +} diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor index 2668df87..5f34a2a6 100644 --- a/Oqtane.Client/Modules/HtmlText/Edit.razor +++ b/Oqtane.Client/Modules/HtmlText/Edit.razor @@ -25,7 +25,7 @@ @code { - public override SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.Edit; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } } public override string Title { get { return "Edit Html/Text"; } } HtmlTextInfo htmltext; diff --git a/Oqtane.Client/Modules/HtmlText/Index.razor b/Oqtane.Client/Modules/HtmlText/Index.razor index 90d86153..e39d1148 100644 --- a/Oqtane.Client/Modules/HtmlText/Index.razor +++ b/Oqtane.Client/Modules/HtmlText/Index.razor @@ -16,7 +16,7 @@ @code { string content; - protected override async Task OnInitAsync() + protected override async Task OnParametersSetAsync() { HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper); List htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); diff --git a/Oqtane.Client/Modules/IModuleControl.cs b/Oqtane.Client/Modules/IModuleControl.cs index 7f1eb4b6..ebb8dcd4 100644 --- a/Oqtane.Client/Modules/IModuleControl.cs +++ b/Oqtane.Client/Modules/IModuleControl.cs @@ -3,7 +3,7 @@ public interface IModuleControl { string Title { get; } - SecurityAccessLevelEnum SecurityAccessLevel { get; } + SecurityAccessLevel SecurityAccessLevel { get; } string Actions { get; } // can be specified as a comma delimited set of values } } diff --git a/Oqtane.Client/Modules/MessageType.cs b/Oqtane.Client/Modules/MessageType.cs new file mode 100644 index 00000000..a78f95f9 --- /dev/null +++ b/Oqtane.Client/Modules/MessageType.cs @@ -0,0 +1,10 @@ +namespace Oqtane.Modules +{ + public enum MessageType + { + Success, + Info, + Warning, + Error + } +} diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index d654eabd..06948293 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -14,7 +14,7 @@ namespace Oqtane.Modules public virtual string Title { get { return ""; } } - public virtual SecurityAccessLevelEnum SecurityAccessLevel { get { return SecurityAccessLevelEnum.View; } set { } } // default security + public virtual SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } set { } } // default security public virtual string Actions { get { return ""; } } @@ -25,7 +25,12 @@ namespace Oqtane.Modules public string NavigateUrl(string path) { - return Utilities.NavigateUrl(PageState.Alias.Path, path); + return NavigateUrl(path, ""); + } + + public string NavigateUrl(string path, string parameters) + { + return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters); } public string EditUrl(string action) diff --git a/Oqtane.Client/Modules/SecurityAccessLevel.cs b/Oqtane.Client/Modules/SecurityAccessLevel.cs index 241507f8..abaf4f6e 100644 --- a/Oqtane.Client/Modules/SecurityAccessLevel.cs +++ b/Oqtane.Client/Modules/SecurityAccessLevel.cs @@ -1,6 +1,6 @@ namespace Oqtane.Modules { - public enum SecurityAccessLevelEnum + public enum SecurityAccessLevel { Anonymous, View, diff --git a/Oqtane.Client/Properties/launchSettings.json b/Oqtane.Client/Properties/launchSettings.json index 2b36d1d7..4899842e 100644 --- a/Oqtane.Client/Properties/launchSettings.json +++ b/Oqtane.Client/Properties/launchSettings.json @@ -21,7 +21,7 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "http://localhost:14246/" + "applicationUrl": "http://localhost:44358/" } } } \ No newline at end of file diff --git a/Oqtane.Client/Services/IAliasService.cs b/Oqtane.Client/Services/Interfaces/IAliasService.cs similarity index 100% rename from Oqtane.Client/Services/IAliasService.cs rename to Oqtane.Client/Services/Interfaces/IAliasService.cs diff --git a/Oqtane.Client/Services/IInstallationService.cs b/Oqtane.Client/Services/Interfaces/IInstallationService.cs similarity index 100% rename from Oqtane.Client/Services/IInstallationService.cs rename to Oqtane.Client/Services/Interfaces/IInstallationService.cs diff --git a/Oqtane.Client/Services/IModuleDefinitionService.cs b/Oqtane.Client/Services/Interfaces/IModuleDefinitionService.cs similarity index 100% rename from Oqtane.Client/Services/IModuleDefinitionService.cs rename to Oqtane.Client/Services/Interfaces/IModuleDefinitionService.cs diff --git a/Oqtane.Client/Services/IModuleService.cs b/Oqtane.Client/Services/Interfaces/IModuleService.cs similarity index 100% rename from Oqtane.Client/Services/IModuleService.cs rename to Oqtane.Client/Services/Interfaces/IModuleService.cs diff --git a/Oqtane.Client/Services/IPageModuleService.cs b/Oqtane.Client/Services/Interfaces/IPageModuleService.cs similarity index 86% rename from Oqtane.Client/Services/IPageModuleService.cs rename to Oqtane.Client/Services/Interfaces/IPageModuleService.cs index e574ad34..9efd8183 100644 --- a/Oqtane.Client/Services/IPageModuleService.cs +++ b/Oqtane.Client/Services/Interfaces/IPageModuleService.cs @@ -7,6 +7,7 @@ namespace Oqtane.Services public interface IPageModuleService { Task> GetPageModulesAsync(); + Task GetPageModuleAsync(int PageModuleId); Task AddPageModuleAsync(PageModule PageModule); Task UpdatePageModuleAsync(PageModule PageModule); Task DeletePageModuleAsync(int PageModuleId); diff --git a/Oqtane.Client/Services/IPageService.cs b/Oqtane.Client/Services/Interfaces/IPageService.cs similarity index 100% rename from Oqtane.Client/Services/IPageService.cs rename to Oqtane.Client/Services/Interfaces/IPageService.cs diff --git a/Oqtane.Client/Services/Interfaces/ISettingService.cs b/Oqtane.Client/Services/Interfaces/ISettingService.cs new file mode 100644 index 00000000..aa9834fd --- /dev/null +++ b/Oqtane.Client/Services/Interfaces/ISettingService.cs @@ -0,0 +1,27 @@ +using Oqtane.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Oqtane.Services +{ + public interface ISettingService + { + Task> GetModuleSettingsAsync(int ModuleId); + + Task UpdateModuleSettingsAsync(List ModuleSettings, int ModuleId, string SettingName, string SettingValue); + + + Task> GetSettingsAsync(string EntityName, int EntityId); + + Task GetSettingAsync(int SettingId); + + Task AddSettingAsync(Setting Setting); + + Task UpdateSettingAsync(Setting Setting); + + Task DeleteSettingAsync(int SettingId); + + + string GetSetting(List Settings, string SettingName, string DefaultValue); + } +} diff --git a/Oqtane.Client/Services/ISiteService.cs b/Oqtane.Client/Services/Interfaces/ISiteService.cs similarity index 100% rename from Oqtane.Client/Services/ISiteService.cs rename to Oqtane.Client/Services/Interfaces/ISiteService.cs diff --git a/Oqtane.Client/Services/ITenantService.cs b/Oqtane.Client/Services/Interfaces/ITenantService.cs similarity index 100% rename from Oqtane.Client/Services/ITenantService.cs rename to Oqtane.Client/Services/Interfaces/ITenantService.cs diff --git a/Oqtane.Client/Services/IthemeService.cs b/Oqtane.Client/Services/Interfaces/IThemeService.cs similarity index 100% rename from Oqtane.Client/Services/IthemeService.cs rename to Oqtane.Client/Services/Interfaces/IThemeService.cs diff --git a/Oqtane.Client/Services/IUserService.cs b/Oqtane.Client/Services/Interfaces/IUserService.cs similarity index 100% rename from Oqtane.Client/Services/IUserService.cs rename to Oqtane.Client/Services/Interfaces/IUserService.cs diff --git a/Oqtane.Client/Services/InstallationService.cs b/Oqtane.Client/Services/Interfaces/InstallationService.cs similarity index 100% rename from Oqtane.Client/Services/InstallationService.cs rename to Oqtane.Client/Services/Interfaces/InstallationService.cs diff --git a/Oqtane.Client/Services/PageModuleService.cs b/Oqtane.Client/Services/PageModuleService.cs index 3c7dbf66..fb6390e1 100644 --- a/Oqtane.Client/Services/PageModuleService.cs +++ b/Oqtane.Client/Services/PageModuleService.cs @@ -31,6 +31,11 @@ namespace Oqtane.Services return await http.GetJsonAsync>(apiurl); } + public async Task GetPageModuleAsync(int PageModuleId) + { + return await http.GetJsonAsync(apiurl + "/" + PageModuleId.ToString()); + } + public async Task AddPageModuleAsync(PageModule PageModule) { return await http.PostJsonAsync(apiurl, PageModule); diff --git a/Oqtane.Client/Services/SettingService.cs b/Oqtane.Client/Services/SettingService.cs new file mode 100644 index 00000000..cea5f994 --- /dev/null +++ b/Oqtane.Client/Services/SettingService.cs @@ -0,0 +1,92 @@ +using Oqtane.Models; +using System.Threading.Tasks; +using System.Net.Http; +using System.Linq; +using Microsoft.AspNetCore.Components; +using System.Collections.Generic; +using Oqtane.Shared; +using System; + +namespace Oqtane.Services +{ + public class SettingService : ServiceBase, ISettingService + { + private readonly HttpClient http; + private readonly SiteState sitestate; + private readonly IUriHelper urihelper; + + public SettingService(HttpClient http, SiteState sitestate, IUriHelper urihelper) + { + this.http = http; + this.sitestate = sitestate; + this.urihelper = urihelper; + } + + private string apiurl + { + get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Setting"); } + } + + public async Task> GetModuleSettingsAsync(int ModuleId) + { + return await GetSettingsAsync("Module", ModuleId); + } + + public async Task UpdateModuleSettingsAsync(List ModuleSettings, int ModuleId, string SettingName, string SettingValue) + { + Setting setting = ModuleSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); + if (setting == null) + { + setting = new Setting(); + setting.EntityName = "Module"; + setting.EntityId = ModuleId; + setting.SettingName = SettingName; + setting.SettingValue = SettingValue; + setting = await AddSettingAsync(setting); + } + else + { + setting.SettingValue = SettingValue; + setting = await UpdateSettingAsync(setting); + } + return setting; + } + + public async Task> GetSettingsAsync(string EntityName, int EntityId) + { + List Settings = await http.GetJsonAsync>(apiurl + "?entityname=" + EntityName + "&entityid=" + EntityId.ToString()); + return Settings.OrderBy(item => item.SettingName).ToList(); + } + + public async Task GetSettingAsync(int SettingId) + { + return await http.GetJsonAsync(apiurl + "/" + SettingId.ToString()); + } + + public async Task AddSettingAsync(Setting Setting) + { + return await http.PostJsonAsync(apiurl, Setting); + } + + public async Task UpdateSettingAsync(Setting Setting) + { + return await http.PutJsonAsync(apiurl + "/" + Setting.SettingId.ToString(), Setting); + } + public async Task DeleteSettingAsync(int SettingId) + { + await http.DeleteAsync(apiurl + "/" + SettingId.ToString()); + } + + + public string GetSetting(List Settings, string SettingName, string DefaultValue) + { + string value = DefaultValue; + Setting setting = Settings.Where(item => item.SettingName == SettingName).FirstOrDefault(); + if (setting != null) + { + value = setting.SettingValue; + } + return value; + } + } +} diff --git a/Oqtane.Client/Shared/Constants.cs b/Oqtane.Client/Shared/Constants.cs index 80d3070a..4c63ff43 100644 --- a/Oqtane.Client/Shared/Constants.cs +++ b/Oqtane.Client/Shared/Constants.cs @@ -7,6 +7,7 @@ public const string DefaultAdminContainer = "Oqtane.Client.Themes.AdminContainer, Oqtane.Client"; public const string DefaultSettingsControl = "Oqtane.Client.Modules.Admin.ModuleSettings.Index, Oqtane.Client"; public const string PageManagementModule = "Oqtane.Client.Modules.Admin.Pages, Oqtane.Client"; + public const string ModuleMessageControl = "Oqtane.Client.Modules.Controls.ModuleMessage, Oqtane.Client"; public const string DefaultControl = "Index"; public const string AdminPane = "Admin"; diff --git a/Oqtane.Client/Shared/Container.razor b/Oqtane.Client/Shared/Container.razor index 0efcdcc3..a1b17bb5 100644 --- a/Oqtane.Client/Shared/Container.razor +++ b/Oqtane.Client/Shared/Container.razor @@ -1,5 +1,6 @@ @using Oqtane.Models @using Oqtane.Shared +@using Oqtane.Modules @DynamicComponent @@ -26,12 +27,16 @@ Type containerType = Type.GetType(container); if (containerType != null) { - builder.OpenComponent(ModuleState.ModuleId, containerType); // set sequence to moduleid so that component tree is able to differentiate + builder.OpenComponent(0, containerType); builder.CloseComponent(); } else { // container does not exist with type specified + builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); + builder.AddAttribute(1, "Type", MessageType.Error); + builder.AddAttribute(2, "Message", "Error Loading Module Container " + container); + builder.CloseComponent(); } } }; diff --git a/Oqtane.Client/Shared/Installer.razor b/Oqtane.Client/Shared/Installer.razor index 1c0f497a..7950974a 100644 --- a/Oqtane.Client/Shared/Installer.razor +++ b/Oqtane.Client/Shared/Installer.razor @@ -113,85 +113,80 @@ } @code { + [Parameter] + private bool Installed { get; set; } -private string DatabaseType = "LocalDB"; -private string ServerName = "(LocalDb)\\MSSQLLocalDB"; -private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm"); -private string Username = ""; -private string Password = ""; -private string HostUsername = "host"; -private string HostPassword = ""; -private string Message = ""; + private string DatabaseType = "LocalDB"; + private string ServerName = "(LocalDb)\\MSSQLLocalDB"; + private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm"); + private string Username = ""; + private string Password = ""; + private string HostUsername = "host"; + private string HostPassword = ""; + private string Message = ""; -private string IntegratedSecurityDisplay = "display:none;"; -private string LoadingDisplay = "display:none;"; + private string IntegratedSecurityDisplay = "display:none;"; + private string LoadingDisplay = "display:none;"; -private bool Installed = true; - -protected override async Task OnInitAsync() -{ - var response = await InstallationService.IsInstalled(); - Installed = response.Success; -} - -private void SetIntegratedSecurity(UIChangeEventArgs e) -{ - if (Convert.ToBoolean(e.Value)) + private void SetIntegratedSecurity(UIChangeEventArgs e) { - IntegratedSecurityDisplay = "display:none;"; - } - else - { - IntegratedSecurityDisplay = ""; - } -} - -private async Task Install() -{ - if (HostPassword.Length >= 6) - { - LoadingDisplay = ""; - StateHasChanged(); - - string connectionstring = ""; - if (DatabaseType == "LocalDB") + if (Convert.ToBoolean(e.Value)) { - connectionstring = "Data Source=" + ServerName + ";AttachDbFilename=|DataDirectory|\\" + DatabaseName + ".mdf;Initial Catalog=" + DatabaseName + ";Integrated Security=SSPI;"; + IntegratedSecurityDisplay = "display:none;"; } else { - connectionstring = "Data Source=" + ServerName + ";Initial Catalog=" + DatabaseName + ";"; - if (IntegratedSecurityDisplay == "display:none;") + IntegratedSecurityDisplay = ""; + } + } + + private async Task Install() + { + if (HostPassword.Length >= 6) + { + LoadingDisplay = ""; + StateHasChanged(); + + string connectionstring = ""; + if (DatabaseType == "LocalDB") { - connectionstring += "Integrated Security=SSPI;"; + connectionstring = "Data Source=" + ServerName + ";AttachDbFilename=|DataDirectory|\\" + DatabaseName + ".mdf;Initial Catalog=" + DatabaseName + ";Integrated Security=SSPI;"; } else { - connectionstring += "User ID=" + Username + ";Password=" + Password; + connectionstring = "Data Source=" + ServerName + ";Initial Catalog=" + DatabaseName + ";"; + if (IntegratedSecurityDisplay == "display:none;") + { + connectionstring += "Integrated Security=SSPI;"; + } + else + { + connectionstring += "User ID=" + Username + ";Password=" + Password; + } + } + GenericResponse response = await InstallationService.Install(connectionstring); + if (response.Success) + { + User user = new User(); + user.SiteId = 1; + user.Username = HostUsername; + user.DisplayName = HostUsername; + user.Password = HostPassword; + user.IsSuperUser = true; + user.Roles = ""; + await UserService.AddUserAsync(user); + UriHelper.NavigateTo("", true); + } + else + { + Message = "
" + response.Message + "
"; + LoadingDisplay = "display:none;"; } - } - GenericResponse response = await InstallationService.Install(connectionstring); - if (response.Success) - { - User user = new User(); - user.Username = HostUsername; - user.DisplayName = HostUsername; - user.Password = HostPassword; - user.IsSuperUser = true; - user.Roles = ""; - await UserService.AddUserAsync(user); - UriHelper.NavigateTo("", true); } else { - Message = "
" + response.Message + "
"; - LoadingDisplay = "display:none;"; + Message = "
Password Must Be 6 Characters Or Greater
"; } } - else - { - Message = "
Password Must Be 6 Characters Or Greater
"; - } -} } diff --git a/Oqtane.Client/Shared/ModuleInstance.razor b/Oqtane.Client/Shared/ModuleInstance.razor index a1fb24ab..5f75ac6c 100644 --- a/Oqtane.Client/Shared/ModuleInstance.razor +++ b/Oqtane.Client/Shared/ModuleInstance.razor @@ -1,5 +1,6 @@ @using Oqtane.Models @using Oqtane.Shared +@using Oqtane.Modules @DynamicComponent @@ -18,18 +19,26 @@ { string typename = ModuleState.ModuleType; if (PageState.Control == "Settings") // module settings are a core component - { + { typename = Constants.DefaultSettingsControl; } - Type moduleType = Type.GetType(typename); + Type moduleType = null; + if (typename != null) + { + moduleType = Type.GetType(typename); + } if (moduleType != null) { - builder.OpenComponent(ModuleState.ModuleId, moduleType); // set sequence to moduleid so that component tree is able to differentiate + builder.OpenComponent(0, moduleType); builder.CloseComponent(); } else { - // module control does not exist with typename specified + // module does not exist with typename specified + builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); + builder.AddAttribute(1, "Type", MessageType.Error); + builder.AddAttribute(2, "Message", "Error Loading Component For Module " + ModuleState.ModuleDefinitionName); + builder.CloseComponent(); } }; } diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor index 89776819..42d41431 100644 --- a/Oqtane.Client/Shared/Pane.razor +++ b/Oqtane.Client/Shared/Pane.razor @@ -52,23 +52,23 @@ { var moduleobject = Activator.CreateInstance(moduleType); // verify security access level for this module control - SecurityAccessLevelEnum SecurityAccessLevel = (SecurityAccessLevelEnum)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); + SecurityAccessLevel SecurityAccessLevel = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); bool authorized = false; switch (SecurityAccessLevel) { - case SecurityAccessLevelEnum.Anonymous: + case SecurityAccessLevel.Anonymous: authorized = true; break; - case SecurityAccessLevelEnum.View: + case SecurityAccessLevel.View: authorized = UserService.IsAuthorized(PageState.User, module.ViewPermissions); break; - case SecurityAccessLevelEnum.Edit: + case SecurityAccessLevel.Edit: authorized = UserService.IsAuthorized(PageState.User, module.EditPermissions); break; - case SecurityAccessLevelEnum.Admin: + case SecurityAccessLevel.Admin: authorized = UserService.IsAuthorized(PageState.User, Constants.AdminRole); break; - case SecurityAccessLevelEnum.Host: + case SecurityAccessLevel.Host: authorized = PageState.User.IsSuperUser; break; } diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index edd0ff7e..8bc36116 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -55,10 +55,18 @@ } protected override async Task OnParametersSetAsync() - { + { if (PageState == null) { - await Refresh(); + // misconfigured api calls should not be processed through the router + if (!_absoluteUri.Contains("~/api/")) + { + await Refresh(); + } + else + { + System.Diagnostics.Debug.WriteLine(this.GetType().FullName + ": Error: " + _absoluteUri + " is not mapped to a Controller"); + } } } diff --git a/Oqtane.Client/Shared/Theme.razor b/Oqtane.Client/Shared/Theme.razor index b059255c..0d41a0b9 100644 --- a/Oqtane.Client/Shared/Theme.razor +++ b/Oqtane.Client/Shared/Theme.razor @@ -1,4 +1,5 @@ @using Oqtane.Shared +@using Oqtane.Modules @DynamicComponent @@ -19,7 +20,11 @@ } else { - // theme does not exist with type specified + // theme does not exist with type specified + builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); + builder.AddAttribute(1, "Type", MessageType.Error); + builder.AddAttribute(2, "Message", "Error Loading Page Theme " + PageState.Page.ThemeType); + builder.CloseComponent(); } }; } diff --git a/Oqtane.Client/Shared/Utilities.cs b/Oqtane.Client/Shared/Utilities.cs index f9282acc..72518271 100644 --- a/Oqtane.Client/Shared/Utilities.cs +++ b/Oqtane.Client/Shared/Utilities.cs @@ -6,7 +6,7 @@ namespace Oqtane.Shared public class Utilities { - public static string NavigateUrl(string alias, string path) + public static string NavigateUrl(string alias, string path, string parameters) { string url = ""; if (alias != "") @@ -17,6 +17,10 @@ namespace Oqtane.Shared { url += path + "/"; } + if (!string.IsNullOrEmpty(parameters)) + { + url += "?" + parameters; + } if (!url.StartsWith("/")) { url = "/" + url; @@ -26,7 +30,7 @@ namespace Oqtane.Shared public static string EditUrl(string alias, string path, int moduleid, string action, string parameters) { - string url = NavigateUrl(alias, path); + string url = NavigateUrl(alias, path, ""); if ( url == "/" ) { url = ""; diff --git a/Oqtane.Client/Startup.cs b/Oqtane.Client/Startup.cs index 1c64ca52..07c3b631 100644 --- a/Oqtane.Client/Startup.cs +++ b/Oqtane.Client/Startup.cs @@ -46,7 +46,7 @@ namespace Oqtane.Client services.AddScoped(); services.AddScoped(); services.AddScoped(); - + services.AddScoped(); // dynamically register module contexts and repository services Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); @@ -57,7 +57,7 @@ namespace Oqtane.Client .ToArray(); foreach (Type implementationtype in implementationtypes) { - Type servicetype = Type.GetType(implementationtype.FullName.Replace(implementationtype.Name, "I" + implementationtype.Name)); + Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name)); if (servicetype != null) { services.AddScoped(servicetype, implementationtype); // traditional service interface diff --git a/Oqtane.Client/Themes/ContainerBase.cs b/Oqtane.Client/Themes/ContainerBase.cs index 7eb915da..6a939f5b 100644 --- a/Oqtane.Client/Themes/ContainerBase.cs +++ b/Oqtane.Client/Themes/ContainerBase.cs @@ -21,14 +21,13 @@ namespace Oqtane.Themes public string NavigateUrl(string path) { - return Utilities.NavigateUrl(PageState.Alias.Path, path); + return NavigateUrl(path, ""); } - public string EditUrl(string action) + public string NavigateUrl(string path, string parameters) { - return EditUrl(ModuleState.ModuleId, action); + return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters); } - public string EditUrl(string action, string parameters) { return EditUrl(ModuleState.ModuleId, action, parameters); diff --git a/Oqtane.Client/Themes/Controls/Logo.razor b/Oqtane.Client/Themes/Controls/Logo.razor index 3f77d859..5970ce31 100644 --- a/Oqtane.Client/Themes/Controls/Logo.razor +++ b/Oqtane.Client/Themes/Controls/Logo.razor @@ -6,11 +6,12 @@ @code { string logo = ""; - protected override void OnInit() + protected override Task OnParametersSetAsync() { if (PageState.Site.Logo != "") { logo = "\"""; } + return Task.CompletedTask; } } \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Menu.razor b/Oqtane.Client/Themes/Controls/Menu.razor index 4a5536dd..1d841837 100644 --- a/Oqtane.Client/Themes/Controls/Menu.razor +++ b/Oqtane.Client/Themes/Controls/Menu.razor @@ -34,7 +34,7 @@ List pages; Page parent = null; - protected override void OnInit() + protected override Task OnParametersSetAsync() { // if current page has no children if (PageState.Pages.Where(item => item.ParentId == PageState.Page.PageId).FirstOrDefault() == null) @@ -54,5 +54,6 @@ // current page is parent parent = PageState.Pages.Where(item => item.ParentId == PageState.Page.ParentId).FirstOrDefault(); } + return Task.CompletedTask; } } diff --git a/Oqtane.Client/Themes/Controls/ModuleTitle.razor b/Oqtane.Client/Themes/Controls/ModuleTitle.razor index 886ae21b..fa7e92a9 100644 --- a/Oqtane.Client/Themes/Controls/ModuleTitle.razor +++ b/Oqtane.Client/Themes/Controls/ModuleTitle.razor @@ -6,12 +6,13 @@ @code { string title = ""; - protected override void OnInit() + protected override Task OnParametersSetAsync() { title = ModuleState.Title; if (PageState.Control == "Settings") { title = PageState.Control; } + return Task.CompletedTask; } } diff --git a/Oqtane.Client/Themes/ThemeBase.cs b/Oqtane.Client/Themes/ThemeBase.cs index e922247e..2ad2956c 100644 --- a/Oqtane.Client/Themes/ThemeBase.cs +++ b/Oqtane.Client/Themes/ThemeBase.cs @@ -17,7 +17,12 @@ namespace Oqtane.Themes public string NavigateUrl(string path) { - return Utilities.NavigateUrl(PageState.Alias.Path, path); + return NavigateUrl(path, ""); + } + + public string NavigateUrl(string path, string parameters) + { + return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters); } } diff --git a/Oqtane.Client/Themes/ThemeObjectBase.cs b/Oqtane.Client/Themes/ThemeObjectBase.cs index 332f1889..efa59f63 100644 --- a/Oqtane.Client/Themes/ThemeObjectBase.cs +++ b/Oqtane.Client/Themes/ThemeObjectBase.cs @@ -15,7 +15,12 @@ namespace Oqtane.Themes public string NavigateUrl(string path) { - return Utilities.NavigateUrl(PageState.Alias.Path, path); + return NavigateUrl(path, ""); + } + + public string NavigateUrl(string path, string parameters) + { + return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters); } public string EditUrl(int moduleid, string action) diff --git a/Oqtane.Server/Controllers/InstallationController.cs b/Oqtane.Server/Controllers/InstallationController.cs index 3297c572..06defd92 100644 --- a/Oqtane.Server/Controllers/InstallationController.cs +++ b/Oqtane.Server/Controllers/InstallationController.cs @@ -1,11 +1,15 @@ using DbUp; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Oqtane.Models; +using Oqtane.Repository; using System; +using System.Collections.Generic; using System.Data.SqlClient; using System.IO; +using System.Linq; using System.Reflection; using System.Threading; @@ -182,11 +186,71 @@ namespace Oqtane.Controllers response.Success = !dbUpgrade.IsUpgradeRequired(); if (!response.Success) { - response.Message = "Scripts Have Not Been Run"; + response.Message = "Master Installation Scripts Have Not Been Executed"; + } + else + { + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() + .Where(item => item.FullName.Contains(".Module.")).ToArray(); + + // get tenants + using (var db = new InstallationContext(connectionString)) + { + foreach (Tenant tenant in db.Tenant.ToList()) + { + // upgrade framework + dbUpgradeConfig = DeployChanges.To.SqlDatabase(tenant.DBConnectionString) + .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()); + dbUpgrade = dbUpgradeConfig.Build(); + if (dbUpgrade.IsUpgradeRequired()) + { + var result = dbUpgrade.PerformUpgrade(); + if (!result.Successful) + { + // TODO: log result.Error.Message; + } + } + // iterate through Oqtane module assemblies and execute any database scripts + foreach (Assembly assembly in assemblies) + { + InstallModule(assembly, tenant.DBConnectionString); + } + } + } } } return response; } + + private void InstallModule(Assembly assembly, string connectionstring) + { + var dbUpgradeConfig = DeployChanges.To.SqlDatabase(connectionstring) + .WithScriptsEmbeddedInAssembly(assembly); // scripts must be included as Embedded Resources + var dbUpgrade = dbUpgradeConfig.Build(); + if (dbUpgrade.IsUpgradeRequired()) + { + var result = dbUpgrade.PerformUpgrade(); + if (!result.Successful) + { + // TODO: log result.Error.Message; + } + } + } + } + + public class InstallationContext : DbContext + { + private readonly string _connectionString; + + public InstallationContext(string connectionString) + { + _connectionString = connectionString; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseSqlServer(_connectionString); + + public virtual DbSet Tenant { get; set; } } } diff --git a/Oqtane.Server/Controllers/SettingController.cs b/Oqtane.Server/Controllers/SettingController.cs new file mode 100644 index 00000000..2f90efd9 --- /dev/null +++ b/Oqtane.Server/Controllers/SettingController.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Oqtane.Repository; +using Oqtane.Models; + +namespace Oqtane.Controllers +{ + [Route("{site}/api/[controller]")] + public class SettingController : Controller + { + private readonly ISettingRepository Settings; + + public SettingController(ISettingRepository Settings) + { + this.Settings = Settings; + } + + // GET: api/ + [HttpGet] + public IEnumerable Get(string entityname, int entityid) + { + return Settings.GetSettings(entityname, entityid); + } + + // GET api//5 + [HttpGet("{id}")] + public Setting Get(int id) + { + return Settings.GetSetting(id); + } + + // POST api/ + [HttpPost] + public Setting Post([FromBody] Setting Setting) + { + if (ModelState.IsValid) + { + Setting = Settings.AddSetting(Setting); + } + return Setting; + } + + // PUT api//5 + [HttpPut("{id}")] + public Setting Put(int id, [FromBody] Setting Setting) + { + if (ModelState.IsValid) + { + Setting = Settings.UpdateSetting(Setting); + } + return Setting; + } + + // DELETE api//5 + [HttpDelete("{id}")] + public void Delete(int id) + { + Settings.DeleteSetting(id); + } + } +} diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs index 00f4fb9b..209a90cc 100644 --- a/Oqtane.Server/Controllers/UserController.cs +++ b/Oqtane.Server/Controllers/UserController.cs @@ -4,6 +4,7 @@ using Oqtane.Repository; using Oqtane.Models; using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; +using System.Linq; namespace Oqtane.Controllers { @@ -11,12 +12,14 @@ namespace Oqtane.Controllers public class UserController : Controller { private readonly IUserRepository users; + private readonly ISiteUserRepository siteusers; private readonly UserManager identityUserManager; private readonly SignInManager identitySignInManager; - public UserController(IUserRepository Users, UserManager IdentityUserManager, SignInManager IdentitySignInManager) + public UserController(IUserRepository Users, ISiteUserRepository SiteUsers, UserManager IdentityUserManager, SignInManager IdentitySignInManager) { users = Users; + siteusers = SiteUsers; identityUserManager = IdentityUserManager; identitySignInManager = IdentitySignInManager; } @@ -39,6 +42,8 @@ namespace Oqtane.Controllers [HttpPost] public async Task Post([FromBody] User User) { + User user = null; + if (ModelState.IsValid) { IdentityUser identityuser = await identityUserManager.FindByNameAsync(User.Username); @@ -50,11 +55,17 @@ namespace Oqtane.Controllers var result = await identityUserManager.CreateAsync(identityuser, User.Password); if (result.Succeeded) { - User = users.AddUser(User); + user = users.AddUser(User); + SiteUser SiteUser = new SiteUser(); + SiteUser.SiteId = User.SiteId; + SiteUser.UserId = user.UserId; + SiteUser.IsAuthorized = true; + siteusers.AddSiteUser(SiteUser); } } } - return User; + + return user; } // PUT api//5 @@ -84,36 +95,38 @@ namespace Oqtane.Controllers // POST api//login [HttpPost("login")] - public async Task Login([FromBody] User user) + public async Task Login([FromBody] User User) { + User user = new Models.User { Username = User.Username, IsAuthenticated = false }; + if (ModelState.IsValid) { - IdentityUser identityuser = await identityUserManager.FindByNameAsync(user.Username); + IdentityUser identityuser = await identityUserManager.FindByNameAsync(User.Username); if (identityuser != null) { - var result = await identitySignInManager.CheckPasswordSignInAsync(identityuser, user.Password, false); + var result = await identitySignInManager.CheckPasswordSignInAsync(identityuser, User.Password, false); if (result.Succeeded) { - await identitySignInManager.SignInAsync(identityuser, user.IsPersistent); user = users.GetUser(identityuser.UserName); - user.IsAuthenticated = true; + if (user != null) + { + SiteUser siteuser = siteusers.GetSiteUsers(User.SiteId, user.UserId).FirstOrDefault(); + if (siteuser.IsAuthorized) + { + await identitySignInManager.SignInAsync(identityuser, User.IsPersistent); + user.IsAuthenticated = true; + } + } } - else - { - user = new Models.User { Username = user.Username, IsAuthenticated = false }; - } - } - else - { - user = new Models.User { Username = user.Username, IsAuthenticated = false }; } } + return user; } // POST api//logout [HttpPost("logout")] - public async Task Logout([FromBody] User user) + public async Task Logout([FromBody] User User) { await identitySignInManager.SignOutAsync(); } diff --git a/Oqtane.Server/Modules/MVCModuleExtension.cs b/Oqtane.Server/Modules/MVCModuleExtension.cs new file mode 100644 index 00000000..fdbaec4a --- /dev/null +++ b/Oqtane.Server/Modules/MVCModuleExtension.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ApplicationParts; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class MvcModuleExtensions + { + public static IMvcBuilder AddModuleAssemblies(this IMvcBuilder mvcBuilder, List assemblies) + { + // load MVC application parts from module assemblies + foreach (Assembly assembly in assemblies) + { + // check if assembly contains MVC Controllers + if (assembly.GetTypes().Where(item => item.IsSubclassOf(typeof(Controller))).ToArray().Length > 0) + { + var partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly); + foreach (var part in partFactory.GetApplicationParts(assembly)) + { + mvcBuilder.PartManager.ApplicationParts.Add(part); + } + } + } + return mvcBuilder; + } + } +} \ No newline at end of file diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index efb5ecaf..05779e3f 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -26,14 +26,14 @@ - + - - + + diff --git a/Oqtane.Server/Repository/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs similarity index 100% rename from Oqtane.Server/Repository/DBContextBase.cs rename to Oqtane.Server/Repository/Context/DBContextBase.cs diff --git a/Oqtane.Server/Repository/MasterDBContext.cs b/Oqtane.Server/Repository/Context/MasterDBContext.cs similarity index 100% rename from Oqtane.Server/Repository/MasterDBContext.cs rename to Oqtane.Server/Repository/Context/MasterDBContext.cs diff --git a/Oqtane.Server/Repository/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs similarity index 92% rename from Oqtane.Server/Repository/TenantDBContext.cs rename to Oqtane.Server/Repository/Context/TenantDBContext.cs index a6f83e57..3e0c1ca7 100644 --- a/Oqtane.Server/Repository/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -12,6 +12,7 @@ namespace Oqtane.Repository public virtual DbSet Module { get; set; } public virtual DbSet User { get; set; } public virtual DbSet SiteUser { get; set; } + public virtual DbSet Setting { get; set; } public TenantDBContext(ITenantResolver TenantResolver, IHttpContextAccessor accessor) : base(TenantResolver, accessor) { diff --git a/Oqtane.Server/Repository/IAliasRepository.cs b/Oqtane.Server/Repository/Interfaces/IAliasRepository.cs similarity index 100% rename from Oqtane.Server/Repository/IAliasRepository.cs rename to Oqtane.Server/Repository/Interfaces/IAliasRepository.cs diff --git a/Oqtane.Server/Repository/IModuleDefinitionRepository.cs b/Oqtane.Server/Repository/Interfaces/IModuleDefinitionRepository.cs similarity index 100% rename from Oqtane.Server/Repository/IModuleDefinitionRepository.cs rename to Oqtane.Server/Repository/Interfaces/IModuleDefinitionRepository.cs diff --git a/Oqtane.Server/Repository/IModuleRepository.cs b/Oqtane.Server/Repository/Interfaces/IModuleRepository.cs similarity index 100% rename from Oqtane.Server/Repository/IModuleRepository.cs rename to Oqtane.Server/Repository/Interfaces/IModuleRepository.cs diff --git a/Oqtane.Server/Repository/IPageModuleRepository.cs b/Oqtane.Server/Repository/Interfaces/IPageModuleRepository.cs similarity index 100% rename from Oqtane.Server/Repository/IPageModuleRepository.cs rename to Oqtane.Server/Repository/Interfaces/IPageModuleRepository.cs diff --git a/Oqtane.Server/Repository/IPageRepository.cs b/Oqtane.Server/Repository/Interfaces/IPageRepository.cs similarity index 100% rename from Oqtane.Server/Repository/IPageRepository.cs rename to Oqtane.Server/Repository/Interfaces/IPageRepository.cs diff --git a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs new file mode 100644 index 00000000..0ffad860 --- /dev/null +++ b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public interface ISettingRepository + { + IEnumerable GetSettings(string EntityName, int EntityId); + Setting AddSetting(Setting Setting); + Setting UpdateSetting(Setting Setting); + Setting GetSetting(int SettingId); + void DeleteSetting(int SettingId); + } +} diff --git a/Oqtane.Server/Repository/ISiteRepository.cs b/Oqtane.Server/Repository/Interfaces/ISiteRepository.cs similarity index 100% rename from Oqtane.Server/Repository/ISiteRepository.cs rename to Oqtane.Server/Repository/Interfaces/ISiteRepository.cs diff --git a/Oqtane.Server/Repository/ISiteUserRepository.cs b/Oqtane.Server/Repository/Interfaces/ISiteUserRepository.cs similarity index 100% rename from Oqtane.Server/Repository/ISiteUserRepository.cs rename to Oqtane.Server/Repository/Interfaces/ISiteUserRepository.cs diff --git a/Oqtane.Server/Repository/ITenantRepository.cs b/Oqtane.Server/Repository/Interfaces/ITenantRepository.cs similarity index 100% rename from Oqtane.Server/Repository/ITenantRepository.cs rename to Oqtane.Server/Repository/Interfaces/ITenantRepository.cs diff --git a/Oqtane.Server/Repository/ITenantResolver.cs b/Oqtane.Server/Repository/Interfaces/ITenantResolver.cs similarity index 100% rename from Oqtane.Server/Repository/ITenantResolver.cs rename to Oqtane.Server/Repository/Interfaces/ITenantResolver.cs diff --git a/Oqtane.Server/Repository/IThemeRepository.cs b/Oqtane.Server/Repository/Interfaces/IThemeRepository.cs similarity index 100% rename from Oqtane.Server/Repository/IThemeRepository.cs rename to Oqtane.Server/Repository/Interfaces/IThemeRepository.cs diff --git a/Oqtane.Server/Repository/IUserRepository.cs b/Oqtane.Server/Repository/Interfaces/IUserRepository.cs similarity index 100% rename from Oqtane.Server/Repository/IUserRepository.cs rename to Oqtane.Server/Repository/Interfaces/IUserRepository.cs diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index a16572fe..ca612fae 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -22,12 +22,11 @@ namespace Oqtane.Repository List moduledefinitions = new List(); // iterate through Oqtane module assemblies - foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() + .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module.")).ToArray(); + foreach (Assembly assembly in assemblies) { - if (assembly.FullName.StartsWith("Oqtane.Client") || assembly.FullName.StartsWith("Oqtane.Module.")) - { - moduledefinitions = LoadModuleDefinitionsFromAssembly(moduledefinitions, assembly); - } + moduledefinitions = LoadModuleDefinitionsFromAssembly(moduledefinitions, assembly); } return moduledefinitions; @@ -119,6 +118,5 @@ namespace Oqtane.Repository return moduledefinitions; } - } } diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs new file mode 100644 index 00000000..b5a17bd5 --- /dev/null +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -0,0 +1,85 @@ +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public class SettingRepository : ISettingRepository + { + private TenantDBContext db; + + public SettingRepository(TenantDBContext context) + { + db = context; + } + + public IEnumerable GetSettings(string EntityName, int EntityId) + { + try + { + return db.Setting.Where(item => item.EntityName == EntityName) + .Where(item => item.EntityId == EntityId).ToList(); + } + catch + { + throw; + } + } + + public Setting AddSetting(Setting Setting) + { + try + { + db.Setting.Add(Setting); + db.SaveChanges(); + return Setting; + } + catch + { + throw; + } + } + + public Setting UpdateSetting(Setting Setting) + { + try + { + db.Entry(Setting).State = EntityState.Modified; + db.SaveChanges(); + return Setting; + } + catch + { + throw; + } + } + + public Setting GetSetting(int SettingId) + { + try + { + Setting Setting = db.Setting.Find(SettingId); + return Setting; + } + catch + { + throw; + } + } + + public void DeleteSetting(int SettingId) + { + try + { + Setting Setting = db.Setting.Find(SettingId); + db.Setting.Remove(Setting); + db.SaveChanges(); + } + catch + { + throw; + } + } + } +} diff --git a/Oqtane.Server/Repository/ThemeRepository.cs b/Oqtane.Server/Repository/ThemeRepository.cs index aec59868..9eb25aa6 100644 --- a/Oqtane.Server/Repository/ThemeRepository.cs +++ b/Oqtane.Server/Repository/ThemeRepository.cs @@ -22,13 +22,11 @@ namespace Oqtane.Repository List themes = new List(); // iterate through Oqtane theme assemblies - // TODO: Remove restriction on assembly + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() + .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Theme.")).ToArray(); foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { - if (assembly.FullName.StartsWith("Oqtane.Client") || assembly.FullName.StartsWith("Oqtane.Theme.")) - { - themes = LoadThemesFromAssembly(themes, assembly); - } + themes = LoadThemesFromAssembly(themes, assembly); } return themes; diff --git a/Oqtane.Server/Scripts/Tenant.sql b/Oqtane.Server/Scripts/00.00.00.sql similarity index 95% rename from Oqtane.Server/Scripts/Tenant.sql rename to Oqtane.Server/Scripts/00.00.00.sql index ed1626be..c5d950d8 100644 --- a/Oqtane.Server/Scripts/Tenant.sql +++ b/Oqtane.Server/Scripts/00.00.00.sql @@ -127,6 +127,23 @@ CREATE TABLE [dbo].[SiteUser]( ) ) GO + +CREATE TABLE [dbo].[Setting]( + [SettingId] [int] IDENTITY(1,1) NOT NULL, + [EntityName] [nvarchar](50) NOT NULL, + [EntityId] [int] NOT NULL, + [SettingName] [nvarchar](50) NOT NULL, + [SettingValue] [nvarchar](max) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_Setting] PRIMARY KEY CLUSTERED + ( + [SettingId] ASC + ) +) +GO /* Create foreign key relationships @@ -167,6 +184,20 @@ GO /* +Create indexes + +*/ + +CREATE UNIQUE NONCLUSTERED INDEX IX_Setting ON dbo.Setting + ( + EntityName, + EntityId, + SettingName + ) ON [PRIMARY] +GO + +/* + Create seed data */ @@ -303,19 +334,19 @@ INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane] VALUES (2, 1, 2, N'Counter', N'Left', 1, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (3, 1, 3, N'Text', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) +VALUES (3, 1, 3, N'Lorem ipsum', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (4, 2, 4, N'Weather', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (5, 2, 5, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) +VALUES (5, 2, 5, N'Enim sed', N'Top', 1, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (6, 3, 6, N'Text', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) +VALUES (6, 3, 6, N'Id consectetur', N'Left', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (7, 3, 7, N'Text', N'Right', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) +VALUES (7, 3, 7, N'Ornare arcu', N'Right', 0, N'Oqtane.Client.Themes.Theme1.Container1, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (8, 5, 8, N'Page Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) @@ -342,10 +373,10 @@ INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane] VALUES (15, 11, 15, N'Theme Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (16, 12, 16, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) +VALUES (16, 12, 16, N'Id consectetur', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (17, 13, 17, N'Text', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) +VALUES (17, 13, 17, N'Lorem ipsum', N'Top', 1, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (18, 14, 18, N'Login', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) diff --git a/Oqtane.Server/Scripts/Identity.sql b/Oqtane.Server/Scripts/00.00.01.sql similarity index 100% rename from Oqtane.Server/Scripts/Identity.sql rename to Oqtane.Server/Scripts/00.00.01.sql diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 10c2a516..3ca8f994 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.ResponseCompression; +using Microsoft.AspNetCore.ResponseCompression; // needed for WASM using Microsoft.Extensions.DependencyInjection; using System.Linq; using Microsoft.Extensions.Configuration; @@ -19,6 +19,7 @@ using Microsoft.AspNetCore.Components; using Oqtane.Shared; using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; +using System.Collections.Generic; namespace Oqtane.Server { @@ -77,27 +78,7 @@ namespace Oqtane.Server services.AddScoped(); services.AddScoped(); services.AddScoped(); - - // dynamically register module contexts and repository services - Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (Assembly assembly in assemblies) - { - Type[] implementationtypes = assembly.GetTypes() - .Where(item => item.GetInterfaces().Contains(typeof(IService))) - .ToArray(); - foreach (Type implementationtype in implementationtypes) - { - Type servicetype = Type.GetType(implementationtype.FullName.Replace(implementationtype.Name, "I" + implementationtype.Name)); - if (servicetype != null) - { - services.AddScoped(servicetype, implementationtype); // traditional service interface - } - else - { - services.AddScoped(implementationtype, implementationtype); // no interface defined for service - } - } - } + services.AddScoped(); services.AddSingleton(); @@ -139,9 +120,26 @@ namespace Oqtane.Server }; }); - services.AddMemoryCache(); + // get list of loaded assemblies + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - services.AddMvc().AddNewtonsoftJson(); + // iterate through Oqtane module assemblies in /bin ( filter is narrow to optimize loading process ) + string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + DirectoryInfo folder = new DirectoryInfo(path); + List moduleassemblies = new List(); + foreach (FileInfo file in folder.EnumerateFiles("*.Module.*.dll")) + { + // check if assembly is already loaded + Assembly assembly = assemblies.Where(item => item.Location == file.FullName).FirstOrDefault(); + if (assembly == null) + { + // load assembly ( as long as dependencies are in /bin they will load as well ) + assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName); + moduleassemblies.Add(assembly); + } + } + + services.AddMvc().AddModuleAssemblies(moduleassemblies).AddNewtonsoftJson(); // register singleton scoped core services services.AddSingleton(Configuration); @@ -157,26 +155,12 @@ namespace Oqtane.Server services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - // get list of loaded assemblies - assemblies = AppDomain.CurrentDomain.GetAssemblies(); - // get path to /bin - string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - DirectoryInfo folder = new DirectoryInfo(path); - // iterate through Oqtane assemblies in /bin ( filter is narrow to optimize loading process ) - foreach (FileInfo file in folder.EnumerateFiles("Oqtane.*.dll")) - { - // check if assembly is already loaded - Assembly assembly = assemblies.Where(item => item.Location == file.FullName).FirstOrDefault(); - if (assembly == null) - { - // load assembly ( as long as dependencies are in /bin they will load as well ) - assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName); - } - } - - // dynamically register module contexts and repository services - assemblies = AppDomain.CurrentDomain.GetAssemblies(); + // dynamically register module services, contexts, and repository classes + assemblies = AppDomain.CurrentDomain.GetAssemblies() + .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module.")).ToArray(); foreach (Assembly assembly in assemblies) { Type[] implementationtypes = assembly.GetTypes() @@ -184,7 +168,7 @@ namespace Oqtane.Server .ToArray(); foreach (Type implementationtype in implementationtypes) { - Type servicetype = Type.GetType(implementationtype.FullName.Replace(implementationtype.Name, "I" + implementationtype.Name)); + Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name)); if (servicetype != null) { services.AddScoped(servicetype, implementationtype); // traditional service interface @@ -273,9 +257,26 @@ namespace Oqtane.Server }; }); - services.AddMemoryCache(); + // get list of loaded assemblies + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - services.AddMvc().AddNewtonsoftJson(); + // iterate through Oqtane module assemblies in /bin ( filter is narrow to optimize loading process ) + string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + DirectoryInfo folder = new DirectoryInfo(path); + List moduleassemblies = new List(); + foreach (FileInfo file in folder.EnumerateFiles("*.Module.*.dll")) + { + // check if assembly is already loaded + Assembly assembly = assemblies.Where(item => item.Location == file.FullName).FirstOrDefault(); + if (assembly == null) + { + // load assembly ( as long as dependencies are in /bin they will load as well ) + assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName); + moduleassemblies.Add(assembly); + } + } + + services.AddMvc().AddModuleAssemblies(moduleassemblies).AddNewtonsoftJson(); // register singleton scoped core services services.AddSingleton(Configuration); @@ -291,26 +292,12 @@ namespace Oqtane.Server services.AddTransient(); services.AddTransient(); services.AddTransient(); - - // get list of loaded assemblies - Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - // get path to /bin - string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - DirectoryInfo folder = new DirectoryInfo(path); - // iterate through Oqtane assemblies in /bin ( filter is narrow to optimize loading process ) - foreach (FileInfo file in folder.EnumerateFiles("Oqtane.*.dll")) - { - // check if assembly is already loaded - Assembly assembly = assemblies.Where(item => item.Location == file.FullName).FirstOrDefault(); - if (assembly == null) - { - // load assembly ( as long as dependencies are in /bin they will load as well ) - assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName); - } - } - - // dynamically register module contexts and repository services - assemblies = AppDomain.CurrentDomain.GetAssemblies(); + services.AddTransient(); + services.AddTransient(); + + // dynamically register module services, contexts, and repository classes + assemblies = AppDomain.CurrentDomain.GetAssemblies() + .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module.")).ToArray(); foreach (Assembly assembly in assemblies) { Type[] implementationtypes = assembly.GetTypes() @@ -318,7 +305,7 @@ namespace Oqtane.Server .ToArray(); foreach (Type implementationtype in implementationtypes) { - Type servicetype = Type.GetType(implementationtype.FullName.Replace(implementationtype.Name, "I" + implementationtype.Name)); + Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name)); if (servicetype != null) { services.AddScoped(servicetype, implementationtype); // traditional service interface diff --git a/Oqtane.Shared/Models/Setting.cs b/Oqtane.Shared/Models/Setting.cs new file mode 100644 index 00000000..d7742c84 --- /dev/null +++ b/Oqtane.Shared/Models/Setting.cs @@ -0,0 +1,18 @@ +using System; + +namespace Oqtane.Models +{ + public class Setting : IAuditable + { + public int SettingId { get; set; } + public string EntityName { get; set; } + public int EntityId { get; set; } + public string SettingName { get; set; } + public string SettingValue { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + } +} From 77d131637cb312d4e4b1be472d75c488a86b3dcd Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 14 Aug 2019 11:16:39 -0400 Subject: [PATCH 13/44] Fix bug related to managing modules on page --- Oqtane.Client/Themes/Controls/ModuleActions.razor | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor index 4d3e5ef3..0c9d9aad 100644 --- a/Oqtane.Client/Themes/Controls/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor @@ -50,14 +50,7 @@ protected async Task ModuleAction(string action) { - PageModule pagemodule = new PageModule(); - pagemodule.PageModuleId = ModuleState.PageModuleId; - pagemodule.PageId = ModuleState.PageId; - pagemodule.ModuleId = ModuleState.ModuleId; - pagemodule.Title = ModuleState.Title; - pagemodule.Pane = ModuleState.Pane; - pagemodule.Order = ModuleState.Order; - pagemodule.ContainerType = ModuleState.ContainerType; + PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); string url = NavigateUrl(); switch (action) From 03c7a99906e84473fb3b9c2c034620029c7b1ef9 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 14 Aug 2019 13:28:49 -0400 Subject: [PATCH 14/44] Upgrade to Preview8 --- Oqtane.Client/App.razor | 2 +- Oqtane.Client/Modules/Admin/Admin/Index.razor | 2 +- .../Modules/Admin/ModuleDefinitions/Index.razor | 2 +- Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Add.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Delete.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Edit.razor | 2 +- Oqtane.Client/Modules/Admin/Sites/Add.razor | 2 +- Oqtane.Client/Modules/Admin/Sites/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Themes/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Users/Index.razor | 2 +- Oqtane.Client/Modules/Controls/ActionLink.razor | 2 +- Oqtane.Client/Modules/Controls/ModuleMessage.razor | 2 +- Oqtane.Client/Modules/HtmlText/Edit.razor | 2 +- Oqtane.Client/Modules/Weather/Index.razor | 2 +- Oqtane.Client/Oqtane.Client.csproj | 5 +++-- Oqtane.Client/Shared/Container.razor | 2 +- Oqtane.Client/Shared/ModuleInstance.razor | 2 +- Oqtane.Client/Shared/Pane.razor | 2 +- Oqtane.Client/Shared/PaneLayout.razor | 2 +- Oqtane.Client/Shared/SiteRouter.razor | 2 +- Oqtane.Client/Shared/Theme.razor | 2 +- Oqtane.Client/Themes/AdminContainer.razor | 2 +- Oqtane.Client/Themes/Controls/ControlPanel.razor | 2 +- Oqtane.Client/Themes/Controls/ModuleActions.razor | 2 +- Oqtane.Server/Oqtane.Server.csproj | 10 +++++----- 26 files changed, 32 insertions(+), 31 deletions(-) diff --git a/Oqtane.Client/App.razor b/Oqtane.Client/App.razor index 8deaf8a0..ac3d1e75 100644 --- a/Oqtane.Client/App.razor +++ b/Oqtane.Client/App.razor @@ -20,7 +20,7 @@ else private bool Installed = false; private PageState PageState { get; set; } - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { var response = await InstallationService.IsInstalled(); Installed = response.Success; diff --git a/Oqtane.Client/Modules/Admin/Admin/Index.razor b/Oqtane.Client/Modules/Admin/Admin/Index.razor index 3c38f89a..9065812c 100644 --- a/Oqtane.Client/Modules/Admin/Admin/Index.razor +++ b/Oqtane.Client/Modules/Admin/Admin/Index.razor @@ -26,7 +26,7 @@ @code { List pages; - protected override void OnInit() + protected override void OnInitialized() { // display list of pages which are children of current page pages = PageState.Pages.Where(item => item.ParentId == PageState.Page.PageId).ToList(); diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor index 475c5e2a..4d3f8de3 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor @@ -34,7 +34,7 @@ else List moduledefinitions; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(); } diff --git a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor index c0c9925f..ca8cef80 100644 --- a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor @@ -84,7 +84,7 @@ RenderFragment DynamicComponent { get; set; } object settings; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { title = ModuleState.Title; containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync()); diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index d808e08b..7ceb31cc 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -131,7 +131,7 @@ string viewpermissions = "All Users"; string editpermissions = "Administrators"; - protected override void OnInit() + protected override void OnInitialized() { themes = ThemeService.GetThemeTypes(PageState.Themes); panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index e3ef602a..ad6efa47 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -132,7 +132,7 @@ string viewpermissions; string editpermissions; - protected override void OnInit() + protected override void OnInitialized() { themes = ThemeService.GetThemeTypes(PageState.Themes); panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index c5734f56..568cfad0 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -133,7 +133,7 @@ string viewpermissions; string editpermissions; - protected override void OnInit() + protected override void OnInitialized() { themes = ThemeService.GetThemeTypes(PageState.Themes); panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index e67505c0..32612845 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -68,7 +68,7 @@ else string url; string logo; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { tenants = await TenantService.GetTenantsAsync(); } diff --git a/Oqtane.Client/Modules/Admin/Sites/Index.razor b/Oqtane.Client/Modules/Admin/Sites/Index.razor index 264f3987..8c57d292 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Index.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Index.razor @@ -35,7 +35,7 @@ else List sites; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { sites = await SiteService.GetSitesAsync(); } diff --git a/Oqtane.Client/Modules/Admin/Themes/Index.razor b/Oqtane.Client/Modules/Admin/Themes/Index.razor index c06f1ba4..743215ee 100644 --- a/Oqtane.Client/Modules/Admin/Themes/Index.razor +++ b/Oqtane.Client/Modules/Admin/Themes/Index.razor @@ -33,7 +33,7 @@ else List Themes; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { Themes = await ThemeService.GetThemesAsync(); } diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index cb0ca1a6..ea748d40 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -34,7 +34,7 @@ else List Users; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { Users = await UserService.GetUsersAsync(); } diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index 0954b864..459b6f7b 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -29,7 +29,7 @@ string buttonClass = "btn btn-primary"; bool authorized = false; - protected override void OnInit() + protected override void OnInitialized() { text = Action; if (!String.IsNullOrEmpty(Text)) diff --git a/Oqtane.Client/Modules/Controls/ModuleMessage.razor b/Oqtane.Client/Modules/Controls/ModuleMessage.razor index 3aec02f3..78b6205f 100644 --- a/Oqtane.Client/Modules/Controls/ModuleMessage.razor +++ b/Oqtane.Client/Modules/Controls/ModuleMessage.razor @@ -18,7 +18,7 @@ string type = "alert alert-success"; // optional bool authorized = false; - protected override void OnInit() + protected override void OnInitialized() { if (PageState.User != null) { diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor index 5f34a2a6..591c436d 100644 --- a/Oqtane.Client/Modules/HtmlText/Edit.razor +++ b/Oqtane.Client/Modules/HtmlText/Edit.razor @@ -31,7 +31,7 @@ HtmlTextInfo htmltext; string content; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper); List htmltextlist = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); diff --git a/Oqtane.Client/Modules/Weather/Index.razor b/Oqtane.Client/Modules/Weather/Index.razor index 5ca38bc8..200b279e 100644 --- a/Oqtane.Client/Modules/Weather/Index.razor +++ b/Oqtane.Client/Modules/Weather/Index.razor @@ -34,7 +34,7 @@ else @code { WeatherForecast[] forecasts; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { WeatherForecastService forecastservice = new WeatherForecastService(); forecasts = await forecastservice.GetForecastAsync(DateTime.Now); diff --git a/Oqtane.Client/Oqtane.Client.csproj b/Oqtane.Client/Oqtane.Client.csproj index 12c8fdef..63384937 100644 --- a/Oqtane.Client/Oqtane.Client.csproj +++ b/Oqtane.Client/Oqtane.Client.csproj @@ -27,8 +27,9 @@ - - + + + diff --git a/Oqtane.Client/Shared/Container.razor b/Oqtane.Client/Shared/Container.razor index a1b17bb5..b3b4a633 100644 --- a/Oqtane.Client/Shared/Container.razor +++ b/Oqtane.Client/Shared/Container.razor @@ -18,7 +18,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInit() + protected override void OnInitialized() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Shared/ModuleInstance.razor b/Oqtane.Client/Shared/ModuleInstance.razor index 5f75ac6c..3c8e3e37 100644 --- a/Oqtane.Client/Shared/ModuleInstance.razor +++ b/Oqtane.Client/Shared/ModuleInstance.razor @@ -13,7 +13,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInit() + protected override void OnInitialized() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor index 42d41431..4c26d40a 100644 --- a/Oqtane.Client/Shared/Pane.razor +++ b/Oqtane.Client/Shared/Pane.razor @@ -25,7 +25,7 @@ string paneadminborder = ""; string panetitle = ""; - protected override void OnInit() + protected override void OnInitialized() { if (UserService.IsAuthorized(PageState.User, PageState.Page.EditPermissions) && Name != Constants.AdminPane) { diff --git a/Oqtane.Client/Shared/PaneLayout.razor b/Oqtane.Client/Shared/PaneLayout.razor index d07d5920..74310b60 100644 --- a/Oqtane.Client/Shared/PaneLayout.razor +++ b/Oqtane.Client/Shared/PaneLayout.razor @@ -9,7 +9,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInit() + protected override void OnInitialized() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index 8bc36116..c0f99db1 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -34,7 +34,7 @@ string _absoluteUri; bool _navigationInterceptionEnabled; - protected override void OnInit() + protected override void OnInitialized() { _absoluteUri = UriHelper.GetAbsoluteUri(); UriHelper.OnLocationChanged += OnLocationChanged; diff --git a/Oqtane.Client/Shared/Theme.razor b/Oqtane.Client/Shared/Theme.razor index 0d41a0b9..3f83b411 100644 --- a/Oqtane.Client/Shared/Theme.razor +++ b/Oqtane.Client/Shared/Theme.razor @@ -8,7 +8,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInit() + protected override void OnInitialized() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Themes/AdminContainer.razor b/Oqtane.Client/Themes/AdminContainer.razor index 57f1f1a0..ff2f67f1 100644 --- a/Oqtane.Client/Themes/AdminContainer.razor +++ b/Oqtane.Client/Themes/AdminContainer.razor @@ -23,7 +23,7 @@ @code { string closeurl; - protected override void OnInit() + protected override void OnInitialized() { closeurl = NavigateUrl(); } diff --git a/Oqtane.Client/Themes/Controls/ControlPanel.razor b/Oqtane.Client/Themes/Controls/ControlPanel.razor index b0e675f8..7a51c3db 100644 --- a/Oqtane.Client/Themes/Controls/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/ControlPanel.razor @@ -80,7 +80,7 @@ string title = ""; string containertype; - protected override async Task OnInitAsync() + protected override async Task OnInitializedAsync() { moduledefinitions = PageState.ModuleDefinitions; containers = ThemeService.GetContainerTypes(PageState.Themes); diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor index 0c9d9aad..66c4c451 100644 --- a/Oqtane.Client/Themes/Controls/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor @@ -21,7 +21,7 @@ string display = "display: none"; List actions; - protected override void OnInit() + protected override void OnInitialized() { actions = new List(); if (ModuleState.PaneModuleIndex > 0) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 05779e3f..c3a1dce1 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -38,11 +38,11 @@ - - - - - + + + + + From ea70c047739831f752c2184aab6234a2c3d34c19 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 14 Aug 2019 13:35:05 -0400 Subject: [PATCH 15/44] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 581df7e2..937e4c1e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Oqtane uses Blazor, a new web framework for .NET Core that lets you build intera **To get started with Oqtane:** - 1. Oqtane is currently compatible with **[.NET Core 3.0 Preview 6 SDK (3.0.0-preview6.19307.2)](https://dotnet.microsoft.com/download/dotnet-core/3.0)**. Microsoft continues to release new versions of .NET Core 3.0 on a regular basis and we do our best to keep up; however, for the best results you should use the most compatible .NET Core 3.0 version. + 1. Oqtane is currently compatible with **[.NET Core 3.0 Preview 8 SDK (3.0.0-preview8.19405.7)](https://dotnet.microsoft.com/download/dotnet-core/3.0)**. Microsoft continues to release new versions of .NET Core 3.0 on a regular basis and we do our best to keep up; however, for the best results you should use the most compatible .NET Core 3.0 version. 2. Install the latest **Preview** edition of [Visual Studio 2019](https://visualstudio.com/preview) with the **ASP.NET and web development** workload. @@ -21,7 +21,6 @@ Oqtane uses Blazor, a new web framework for .NET Core that lets you build intera This project is a work in progress and the schedule for implementing the items identified below is dependent upon the availability of community members who are able to assist. Security -- Need ability to associate a User to a Site and restrict access - Need ability to manage Roles and association to Users - Need ability to manage Permissions - a permission UI component for pages/modules From 49625bd5943392a4cc03ecf6e1968de29c4cb70f Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 14 Aug 2019 13:37:59 -0400 Subject: [PATCH 16/44] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 937e4c1e..b52d1fc4 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Admin - Need fully functional administrative modules for all core entities ( user, role, site, etc… ) - Need ability to create a new Site and auto provision Admin pages/modules - Need ability to soft delete core entities +- Re-ordering of modules in panes - Drag and Drop modules Upgrade From 9dbd44b112d6192de67298a9d3058892cf8211f8 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Thu, 15 Aug 2019 08:25:02 -0400 Subject: [PATCH 17/44] Correct EF Core references --- Oqtane.Client/Services/ModuleDefinitionService.cs | 5 ++++- Oqtane.Client/Shared/ModuleInstance.razor | 4 ++-- Oqtane.Server/Oqtane.Server.csproj | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Oqtane.Client/Services/ModuleDefinitionService.cs b/Oqtane.Client/Services/ModuleDefinitionService.cs index 31fff1ba..ffd28632 100644 --- a/Oqtane.Client/Services/ModuleDefinitionService.cs +++ b/Oqtane.Client/Services/ModuleDefinitionService.cs @@ -30,13 +30,15 @@ namespace Oqtane.Services public async Task> GetModuleDefinitionsAsync() { + // get list of modules from the server List moduledefinitions = await http.GetJsonAsync>(apiurl); - // get list of loaded assemblies + // get list of loaded assemblies on the client ( in the client-side hosting module the browser client has its own app domain ) Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (ModuleDefinition moduledefinition in moduledefinitions) { + // if a module has dependencies, check if they are loaded if (moduledefinition.Dependencies != "") { foreach (string dependency in moduledefinition.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) @@ -50,6 +52,7 @@ namespace Oqtane.Services } } } + // check if the module assembly is loaded if (assemblies.Where(item => item.FullName.StartsWith(moduledefinition.AssemblyName + ",")).FirstOrDefault() == null) { // download assembly from server and load diff --git a/Oqtane.Client/Shared/ModuleInstance.razor b/Oqtane.Client/Shared/ModuleInstance.razor index 3c8e3e37..a1d3548e 100644 --- a/Oqtane.Client/Shared/ModuleInstance.razor +++ b/Oqtane.Client/Shared/ModuleInstance.razor @@ -34,8 +34,8 @@ } else { - // module does not exist with typename specified - builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); + // module does not exist with typename specified + builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); builder.AddAttribute(1, "Type", MessageType.Error); builder.AddAttribute(2, "Message", "Error Loading Component For Module " + ModuleState.ModuleDefinitionName); builder.CloseComponent(); diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index c3a1dce1..0bb6003b 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -41,8 +41,8 @@ - - + + From 58b27d172d09f6aae33a91b5aa3a9aba749311a0 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Thu, 15 Aug 2019 12:18:09 -0400 Subject: [PATCH 18/44] Made parameters public for Preview8 --- Oqtane.Client/App.razor | 30 ++++++++++++------- .../Modules/Controls/ActionLink.razor | 8 ++--- .../Modules/Controls/ModuleMessage.razor | 4 +-- Oqtane.Client/Shared/Container.razor | 2 +- Oqtane.Client/Shared/Installer.razor | 2 +- Oqtane.Client/Shared/Pane.razor | 2 +- Oqtane.Client/Shared/SiteRouter.razor | 6 ++-- 7 files changed, 32 insertions(+), 22 deletions(-) diff --git a/Oqtane.Client/App.razor b/Oqtane.Client/App.razor index ac3d1e75..a95d3885 100644 --- a/Oqtane.Client/App.razor +++ b/Oqtane.Client/App.razor @@ -3,20 +3,23 @@ @using Oqtane.Services @inject IInstallationService InstallationService -@if (!Installed) -{ - -} -else -{ - - - - - +@if (Initialized) + @if (!Installed) + { + + } + else + { + + + + + + } } @code { + private bool Initialized = false; private bool Installed = false; private PageState PageState { get; set; } @@ -26,6 +29,11 @@ else Installed = response.Success; } + protected override void OnAfterRender() + { + Initialized = true; + } + private void ChangeState(PageState pagestate) { PageState = pagestate; diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index 459b6f7b..72bd6f26 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -12,16 +12,16 @@ @code { [Parameter] - private string Action { get; set; } + public string Action { get; set; } [Parameter] - private string Text { get; set; } // optional + public string Text { get; set; } // optional [Parameter] - private string Parameters { get; set; } // optional + public string Parameters { get; set; } // optional [Parameter] - private string ButtonClass { get; set; } // optional + public string ButtonClass { get; set; } // optional string text = ""; string url = ""; diff --git a/Oqtane.Client/Modules/Controls/ModuleMessage.razor b/Oqtane.Client/Modules/Controls/ModuleMessage.razor index 78b6205f..69d1c84d 100644 --- a/Oqtane.Client/Modules/Controls/ModuleMessage.razor +++ b/Oqtane.Client/Modules/Controls/ModuleMessage.razor @@ -10,10 +10,10 @@ @code { [Parameter] - private MessageType Type { get; set; } + public MessageType Type { get; set; } [Parameter] - private string Message { get; set; } + public string Message { get; set; } string type = "alert alert-success"; // optional bool authorized = false; diff --git a/Oqtane.Client/Shared/Container.razor b/Oqtane.Client/Shared/Container.razor index b3b4a633..907df9c8 100644 --- a/Oqtane.Client/Shared/Container.razor +++ b/Oqtane.Client/Shared/Container.razor @@ -11,7 +11,7 @@ protected PageState PageState { get; set; } [Parameter] - private Module Module { get; set; } + public Module Module { get; set; } Module ModuleState; string container; diff --git a/Oqtane.Client/Shared/Installer.razor b/Oqtane.Client/Shared/Installer.razor index 7950974a..9b862ff7 100644 --- a/Oqtane.Client/Shared/Installer.razor +++ b/Oqtane.Client/Shared/Installer.razor @@ -114,7 +114,7 @@ @code { [Parameter] - private bool Installed { get; set; } + public bool Installed { get; set; } private string DatabaseType = "LocalDB"; private string ServerName = "(LocalDb)\\MSSQLLocalDB"; diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor index 4c26d40a..b2f803aa 100644 --- a/Oqtane.Client/Shared/Pane.razor +++ b/Oqtane.Client/Shared/Pane.razor @@ -18,7 +18,7 @@ protected PageState PageState { get; set; } [Parameter] - private string Name { get; set; } + public string Name { get; set; } RenderFragment DynamicComponent { get; set; } diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index c0f99db1..8a44e141 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -24,9 +24,11 @@ @code { - [CascadingParameter] PageState PageState { get; set; } + [CascadingParameter] + PageState PageState { get; set; } - [Parameter] Action OnStateChange { get; set; } + [Parameter] + public Action OnStateChange { get; set; } PageState pagestate; RenderFragment DynamicComponent { get; set; } From 9cda80f7e947b214d595eb31af2b4402ec881cc4 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Thu, 15 Aug 2019 12:33:19 -0400 Subject: [PATCH 19/44] Installer improvements for client-side Blazor --- Oqtane.Client/App.razor | 9 +- Oqtane.Client/Shared/Installer.razor | 210 +++++++++++++-------------- 2 files changed, 105 insertions(+), 114 deletions(-) diff --git a/Oqtane.Client/App.razor b/Oqtane.Client/App.razor index a95d3885..bb666be4 100644 --- a/Oqtane.Client/App.razor +++ b/Oqtane.Client/App.razor @@ -4,9 +4,10 @@ @inject IInstallationService InstallationService @if (Initialized) +{ @if (!Installed) { - + } else { @@ -23,14 +24,10 @@ private bool Installed = false; private PageState PageState { get; set; } - protected override async Task OnInitializedAsync() + protected override async Task OnParametersSetAsync() { var response = await InstallationService.IsInstalled(); Installed = response.Success; - } - - protected override void OnAfterRender() - { Initialized = true; } diff --git a/Oqtane.Client/Shared/Installer.razor b/Oqtane.Client/Shared/Installer.razor index 9b862ff7..f624b89a 100644 --- a/Oqtane.Client/Shared/Installer.razor +++ b/Oqtane.Client/Shared/Installer.razor @@ -4,118 +4,112 @@ @inject IInstallationService InstallationService @inject IUserService UserService -@if (!Installed) -{ -
-
-
- -
-
-
-

Database Configuration

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
- - - -
- - - -
- - - -
- - - -
-
-
-
-

Application Administrator

-
-
- - - - - - - - - - - -
- - - -
- - - -
-
-
-
-
-

- @((MarkupString)@Message) -
-
+
+
+
+
-} +
+

Database Configuration

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+
+
+
+

Application Administrator

+
+
+ + + + + + + + + + + +
+ + + +
+ + + +
+
+
+
+
+

+ @((MarkupString)@Message) +
+
+
+
@code { - [Parameter] - public bool Installed { get; set; } - private string DatabaseType = "LocalDB"; private string ServerName = "(LocalDb)\\MSSQLLocalDB"; private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm"); From 0c57813bf889cd15744cb79b393bb5a7ae2f54f8 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 16 Aug 2019 09:49:26 -0400 Subject: [PATCH 20/44] Improve HtmlText module performance --- Oqtane.Client/Modules/HtmlText/Edit.razor | 7 +- Oqtane.Client/Modules/HtmlText/Index.razor | 4 +- .../HtmlText/Services/HtmlTextService.cs | 8 +- .../HtmlText/Services/IHtmlTextService.cs | 2 +- .../Services/Interfaces/ISettingService.cs | 16 +++ Oqtane.Client/Services/SettingService.cs | 101 +++++++++++++++++- .../Controllers/HtmlTextController.cs | 7 -- .../HtmlText/Repository/HtmlTextRepository.cs | 18 +--- .../Repository/IHtmlTextRepository.cs | 3 +- 9 files changed, 128 insertions(+), 38 deletions(-) diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor index 591c436d..3bc2812a 100644 --- a/Oqtane.Client/Modules/HtmlText/Edit.razor +++ b/Oqtane.Client/Modules/HtmlText/Edit.razor @@ -28,16 +28,14 @@ public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } } public override string Title { get { return "Edit Html/Text"; } } - HtmlTextInfo htmltext; string content; protected override async Task OnInitializedAsync() { HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper); - List htmltextlist = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); - if (htmltextlist != null) + HtmlTextInfo htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); + if (htmltext != null) { - htmltext = htmltextlist.FirstOrDefault(); content = htmltext.Content; } } @@ -45,6 +43,7 @@ private async Task SaveContent() { HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper); + HtmlTextInfo htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); if (htmltext != null) { htmltext.Content = content; diff --git a/Oqtane.Client/Modules/HtmlText/Index.razor b/Oqtane.Client/Modules/HtmlText/Index.razor index e39d1148..d172eacd 100644 --- a/Oqtane.Client/Modules/HtmlText/Index.razor +++ b/Oqtane.Client/Modules/HtmlText/Index.razor @@ -19,10 +19,10 @@ protected override async Task OnParametersSetAsync() { HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, UriHelper); - List htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); + HtmlTextInfo htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); if (htmltext != null) { - content = htmltext.FirstOrDefault().Content; + content = htmltext.Content; } } } \ No newline at end of file diff --git a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs index e8257b00..aca530af 100644 --- a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs +++ b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs @@ -27,13 +27,9 @@ namespace Oqtane.Client.Modules.HtmlText.Services get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "HtmlText"); } } - public async Task> GetHtmlTextAsync(int ModuleId) + public async Task GetHtmlTextAsync(int ModuleId) { - List htmltext = await http.GetJsonAsync>(apiurl); - htmltext = htmltext - .Where(item => item.ModuleId == ModuleId) - .ToList(); - return htmltext; + return await http.GetJsonAsync(apiurl + "/" + ModuleId.ToString()); } public async Task AddHtmlTextAsync(HtmlTextInfo htmltext) diff --git a/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs b/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs index c0dcc46c..9d3bfa98 100644 --- a/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs +++ b/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs @@ -6,7 +6,7 @@ namespace Oqtane.Client.Modules.HtmlText.Services { public interface IHtmlTextService { - Task> GetHtmlTextAsync(int ModuleId); + Task GetHtmlTextAsync(int ModuleId); Task AddHtmlTextAsync(HtmlTextInfo htmltext); diff --git a/Oqtane.Client/Services/Interfaces/ISettingService.cs b/Oqtane.Client/Services/Interfaces/ISettingService.cs index aa9834fd..c6b617c5 100644 --- a/Oqtane.Client/Services/Interfaces/ISettingService.cs +++ b/Oqtane.Client/Services/Interfaces/ISettingService.cs @@ -6,6 +6,22 @@ namespace Oqtane.Services { public interface ISettingService { + Task> GetHostSettingsAsync(); + + Task UpdateHostSettingsAsync(List HostSettings, string SettingName, string SettingValue); + + Task> GetSiteSettingsAsync(int SiteId); + + Task UpdateSiteSettingsAsync(List SiteSettings, int SiteId, string SettingName, string SettingValue); + + Task> GetPageSettingsAsync(int PageId); + + Task UpdatePageSettingsAsync(List PageSettings, int PageId, string SettingName, string SettingValue); + + Task> GetPageModuleSettingsAsync(int PageModuleId); + + Task UpdatePageModuleSettingsAsync(List PageModuleSettings, int PageModuleId, string SettingName, string SettingValue); + Task> GetModuleSettingsAsync(int ModuleId); Task UpdateModuleSettingsAsync(List ModuleSettings, int ModuleId, string SettingName, string SettingValue); diff --git a/Oqtane.Client/Services/SettingService.cs b/Oqtane.Client/Services/SettingService.cs index cea5f994..f6bfaac2 100644 --- a/Oqtane.Client/Services/SettingService.cs +++ b/Oqtane.Client/Services/SettingService.cs @@ -5,7 +5,6 @@ using System.Linq; using Microsoft.AspNetCore.Components; using System.Collections.Generic; using Oqtane.Shared; -using System; namespace Oqtane.Services { @@ -27,6 +26,106 @@ namespace Oqtane.Services get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Setting"); } } + public async Task> GetHostSettingsAsync() + { + return await GetSettingsAsync("Host", -1); + } + + public async Task UpdateHostSettingsAsync(List HostSettings, string SettingName, string SettingValue) + { + Setting setting = HostSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); + if (setting == null) + { + setting = new Setting(); + setting.EntityName = "Host"; + setting.EntityId = -1; + setting.SettingName = SettingName; + setting.SettingValue = SettingValue; + setting = await AddSettingAsync(setting); + } + else + { + setting.SettingValue = SettingValue; + setting = await UpdateSettingAsync(setting); + } + return setting; + } + + public async Task> GetSiteSettingsAsync(int SiteId) + { + return await GetSettingsAsync("Site", SiteId); + } + + public async Task UpdateSiteSettingsAsync(List SiteSettings, int SiteId, string SettingName, string SettingValue) + { + Setting setting = SiteSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); + if (setting == null) + { + setting = new Setting(); + setting.EntityName = "Site"; + setting.EntityId = SiteId; + setting.SettingName = SettingName; + setting.SettingValue = SettingValue; + setting = await AddSettingAsync(setting); + } + else + { + setting.SettingValue = SettingValue; + setting = await UpdateSettingAsync(setting); + } + return setting; + } + + public async Task> GetPageSettingsAsync(int PageId) + { + return await GetSettingsAsync("Page", PageId); + } + + public async Task UpdatePageSettingsAsync(List PageSettings, int PageId, string SettingName, string SettingValue) + { + Setting setting = PageSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); + if (setting == null) + { + setting = new Setting(); + setting.EntityName = "Page"; + setting.EntityId = PageId; + setting.SettingName = SettingName; + setting.SettingValue = SettingValue; + setting = await AddSettingAsync(setting); + } + else + { + setting.SettingValue = SettingValue; + setting = await UpdateSettingAsync(setting); + } + return setting; + } + + public async Task> GetPageModuleSettingsAsync(int PageModuleId) + { + return await GetSettingsAsync("PageModule", PageModuleId); + } + + public async Task UpdatePageModuleSettingsAsync(List PageModuleSettings, int PageModuleId, string SettingName, string SettingValue) + { + Setting setting = PageModuleSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); + if (setting == null) + { + setting = new Setting(); + setting.EntityName = "PageModule"; + setting.EntityId = PageModuleId; + setting.SettingName = SettingName; + setting.SettingValue = SettingValue; + setting = await AddSettingAsync(setting); + } + else + { + setting.SettingValue = SettingValue; + setting = await UpdateSettingAsync(setting); + } + return setting; + } + public async Task> GetModuleSettingsAsync(int ModuleId) { return await GetSettingsAsync("Module", ModuleId); diff --git a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs index f3dc2d9b..695e460b 100644 --- a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs +++ b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs @@ -15,13 +15,6 @@ namespace Oqtane.Server.Modules.HtmlText.Controllers htmltext = HtmlText; } - // GET: api/ - [HttpGet] - public IEnumerable Get() - { - return htmltext.GetHtmlText(); - } - // GET api//5 [HttpGet("{id}")] public HtmlTextInfo Get(int id) diff --git a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs index 2347e601..fc80ddfc 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs @@ -15,11 +15,11 @@ namespace Oqtane.Server.Modules.HtmlText.Repository db = context; } - public IEnumerable GetHtmlText() + public HtmlTextInfo GetHtmlText(int ModuleId) { try { - return db.HtmlText.ToList(); + return db.HtmlText.Where(item => item.ModuleId == ModuleId).FirstOrDefault(); } catch { @@ -27,6 +27,7 @@ namespace Oqtane.Server.Modules.HtmlText.Repository } } + public HtmlTextInfo AddHtmlText(HtmlTextInfo HtmlText) { try @@ -55,19 +56,6 @@ namespace Oqtane.Server.Modules.HtmlText.Repository } } - public HtmlTextInfo GetHtmlText(int HtmlTextId) - { - try - { - HtmlTextInfo HtmlText = db.HtmlText.Find(HtmlTextId); - return HtmlText; - } - catch - { - throw; - } - } - public void DeleteHtmlText(int HtmlTextId) { try diff --git a/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs b/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs index 463d5e50..cd7ea0e8 100644 --- a/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs +++ b/Oqtane.Server/Modules/HtmlText/Repository/IHtmlTextRepository.cs @@ -5,10 +5,9 @@ namespace Oqtane.Server.Modules.HtmlText.Repository { public interface IHtmlTextRepository { - IEnumerable GetHtmlText(); + HtmlTextInfo GetHtmlText(int ModuleId); HtmlTextInfo AddHtmlText(HtmlTextInfo HtmlText); HtmlTextInfo UpdateHtmlText(HtmlTextInfo HtmlText); - HtmlTextInfo GetHtmlText(int HtmlTextIdId); void DeleteHtmlText(int HtmlTextId); } } From de4fa48a29a8c571adcea6c4c3cba09ccfc0904a Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 16 Aug 2019 11:35:00 -0400 Subject: [PATCH 21/44] Added Swagger support for API --- Oqtane.Server/Oqtane.Server.csproj | 1 + Oqtane.Server/Startup.cs | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 0bb6003b..540d0f80 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -43,6 +43,7 @@ + diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 3ca8f994..434ec1da 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -20,6 +20,7 @@ using Oqtane.Shared; using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; using System.Collections.Generic; +using Microsoft.OpenApi.Models; namespace Oqtane.Server { @@ -179,6 +180,11 @@ namespace Oqtane.Server } } } + + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo { Title = "Oqtane", Version = "v1" }); + }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -202,6 +208,12 @@ namespace Oqtane.Server app.UseAuthentication(); app.UseAuthorization(); + app.UseSwagger(); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "Oqtane V1"); + }); + app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); @@ -317,6 +329,11 @@ namespace Oqtane.Server } } + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo { Title = "Oqtane", Version = "v1" }); + }); + services.AddResponseCompression(opts => { opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat( @@ -341,6 +358,12 @@ namespace Oqtane.Server app.UseAuthentication(); app.UseAuthorization(); + app.UseSwagger(); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "Oqtane V1"); + }); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); From b95db2248b422e51e2c0886286036640be68f393 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 19 Aug 2019 14:28:44 -0400 Subject: [PATCH 22/44] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b52d1fc4..6ade6af8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ Oqtane uses Blazor, a new web framework for .NET Core that lets you build intera 4. Enable Visual Studio to use preview SDKs: Open **Tools** > **Options** in the menu bar. Open the **Environment** node. Open the **Preview Features** tab. Check the box for **Use previews of the .NET Core SDK**. Select **OK**. 5. Download or Clone the Oqtane source code to your local system. Open the **Oqtane.sln** solution file. If you want to develop using **server-side** Blazor ( which includes a full debugging experience in Visual Studio ) you should choose to Build the solution using the default Debug configuration. If you want to develop using **client-side** Blazor ( WebAssembly ) you should first choose the "Wasm" configuration option in the Visual Studio toolbar and then Build. + + NOTE: If you have already installed a previous version of Oqtane and you wish to install a newer version, there is currently no upgrade path from one version to the next. The recommended upgrade approach is to get the latest code and build it, and then reset the DefaultConnection value to "" in the appsettings.json file in the Oqtane.server project. # Roadmap This project is a work in progress and the schedule for implementing the items identified below is dependent upon the availability of community members who are able to assist. From c93b34ea823ffb6dfeec6638f85b484ff46abc70 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 19 Aug 2019 14:29:48 -0400 Subject: [PATCH 23/44] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ade6af8..dbe47669 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Oqtane uses Blazor, a new web framework for .NET Core that lets you build intera 5. Download or Clone the Oqtane source code to your local system. Open the **Oqtane.sln** solution file. If you want to develop using **server-side** Blazor ( which includes a full debugging experience in Visual Studio ) you should choose to Build the solution using the default Debug configuration. If you want to develop using **client-side** Blazor ( WebAssembly ) you should first choose the "Wasm" configuration option in the Visual Studio toolbar and then Build. - NOTE: If you have already installed a previous version of Oqtane and you wish to install a newer version, there is currently no upgrade path from one version to the next. The recommended upgrade approach is to get the latest code and build it, and then reset the DefaultConnection value to "" in the appsettings.json file in the Oqtane.server project. + NOTE: If you have already installed a previous version of Oqtane and you wish to install a newer version, there is currently no upgrade path from one version to the next. The recommended upgrade approach is to get the latest code and build it, and then reset the DefaultConnection value to "" in the appsettings.json file in the Oqtane.server project. This will trigger a re-install when you run the application which will execute the latest database scripts. # Roadmap This project is a work in progress and the schedule for implementing the items identified below is dependent upon the availability of community members who are able to assist. From 42c6efbfdbd88818616fc8bf180eae2534d3d8a8 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Tue, 20 Aug 2019 16:43:35 -0400 Subject: [PATCH 24/44] Dynamic User Roles --- Oqtane.Client/Modules/Admin/Roles/Index.razor | 40 ++++ Oqtane.Client/Modules/Admin/Users/Index.razor | 4 +- .../Services/Interfaces/IRoleService.cs | 21 ++ .../Services/Interfaces/IUserRoleService.cs | 16 ++ .../Services/Interfaces/IUserService.cs | 8 +- Oqtane.Client/Services/RoleService.cs | 60 ++++++ Oqtane.Client/Services/UserRoleService.cs | 59 ++++++ Oqtane.Client/Services/UserService.cs | 19 +- Oqtane.Client/Shared/Installer.razor | 3 +- Oqtane.Client/Shared/PaneLayout.razor | 4 +- Oqtane.Client/Shared/SiteRouter.razor | 2 +- Oqtane.Client/Shared/Theme.razor | 4 +- Oqtane.Client/Startup.cs | 2 + Oqtane.Client/Themes/Controls/Login.razor | 7 +- Oqtane.Server/Controllers/AliasController.cs | 14 +- .../Controllers/InstallationController.cs | 10 +- Oqtane.Server/Controllers/ModuleController.cs | 20 +- .../Controllers/ModuleDefinitionController.cs | 6 +- Oqtane.Server/Controllers/PageController.cs | 16 +- .../Controllers/PageModuleController.cs | 14 +- Oqtane.Server/Controllers/RoleController.cs | 68 +++++++ Oqtane.Server/Controllers/SiteController.cs | 14 +- Oqtane.Server/Controllers/TenantController.cs | 14 +- Oqtane.Server/Controllers/ThemeController.cs | 6 +- Oqtane.Server/Controllers/UserController.cs | 189 ++++++++++++++---- .../Controllers/UserRoleController.cs | 68 +++++++ Oqtane.Server/Pages/Login.cshtml.cs | 7 +- Oqtane.Server/Pages/Logout.cshtml.cs | 7 +- Oqtane.Server/Repository/AliasRepository.cs | 6 +- .../Repository/Context/TenantDBContext.cs | 2 + .../Repository/Interfaces/IRoleRepository.cs | 15 ++ .../Interfaces/ISiteUserRepository.cs | 3 +- .../Interfaces/IUserRoleRepository.cs | 15 ++ .../Repository/ModuleDefinitionRepository.cs | 12 +- Oqtane.Server/Repository/ModuleRepository.cs | 3 +- .../Repository/PageModuleRepository.cs | 9 +- Oqtane.Server/Repository/PageRepository.cs | 3 +- Oqtane.Server/Repository/RoleRepository.cs | 95 +++++++++ Oqtane.Server/Repository/SettingRepository.cs | 3 +- Oqtane.Server/Repository/SiteRepository.cs | 3 +- .../Repository/SiteUserRepository.cs | 27 ++- Oqtane.Server/Repository/TenantRepository.cs | 6 +- Oqtane.Server/Repository/ThemeRepository.cs | 12 +- Oqtane.Server/Repository/UserRepository.cs | 6 +- .../Repository/UserRoleRepository.cs | 97 +++++++++ Oqtane.Server/Scripts/00.00.00.sql | 61 +++++- Oqtane.Server/Startup.cs | 6 + Oqtane.Shared/Models/Role.cs | 18 ++ Oqtane.Shared/Models/SiteUser.cs | 3 +- Oqtane.Shared/Models/User.cs | 8 +- Oqtane.Shared/Models/UserRole.cs | 20 ++ 51 files changed, 942 insertions(+), 193 deletions(-) create mode 100644 Oqtane.Client/Modules/Admin/Roles/Index.razor create mode 100644 Oqtane.Client/Services/Interfaces/IRoleService.cs create mode 100644 Oqtane.Client/Services/Interfaces/IUserRoleService.cs create mode 100644 Oqtane.Client/Services/RoleService.cs create mode 100644 Oqtane.Client/Services/UserRoleService.cs create mode 100644 Oqtane.Server/Controllers/RoleController.cs create mode 100644 Oqtane.Server/Controllers/UserRoleController.cs create mode 100644 Oqtane.Server/Repository/Interfaces/IRoleRepository.cs create mode 100644 Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs create mode 100644 Oqtane.Server/Repository/RoleRepository.cs create mode 100644 Oqtane.Server/Repository/UserRoleRepository.cs create mode 100644 Oqtane.Shared/Models/Role.cs create mode 100644 Oqtane.Shared/Models/UserRole.cs diff --git a/Oqtane.Client/Modules/Admin/Roles/Index.razor b/Oqtane.Client/Modules/Admin/Roles/Index.razor new file mode 100644 index 00000000..c21f185d --- /dev/null +++ b/Oqtane.Client/Modules/Admin/Roles/Index.razor @@ -0,0 +1,40 @@ +@using Oqtane.Services +@using Oqtane.Models +@using Oqtane.Modules +@using Oqtane.Client.Modules.Controls +@inherits ModuleBase +@inject IRoleService RoleService + +@if (Roles == null) +{ +

Loading...

+} +else +{ + + + + + + + + @foreach (var Role in Roles) + { + + + + } + +
Name
@Role.Name
+} + +@code { + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } + + List Roles; + + protected override async Task OnInitializedAsync() + { + Roles = await RoleService.GetRolesAsync(PageState.Site.SiteId); + } +} \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index ea748d40..481e0ae4 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -30,12 +30,12 @@ else } @code { - public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } } + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } List Users; protected override async Task OnInitializedAsync() { - Users = await UserService.GetUsersAsync(); + Users = await UserService.GetUsersAsync(PageState.Site.SiteId); } } \ No newline at end of file diff --git a/Oqtane.Client/Services/Interfaces/IRoleService.cs b/Oqtane.Client/Services/Interfaces/IRoleService.cs new file mode 100644 index 00000000..d7f26332 --- /dev/null +++ b/Oqtane.Client/Services/Interfaces/IRoleService.cs @@ -0,0 +1,21 @@ +using Oqtane.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Oqtane.Services +{ + public interface IRoleService + { + Task> GetRolesAsync(); + + Task> GetRolesAsync(int SiteId); + + Task GetRoleAsync(int RoleId); + + Task AddRoleAsync(Role Role); + + Task UpdateRoleAsync(Role Role); + + Task DeleteRoleAsync(int RoleId); + } +} diff --git a/Oqtane.Client/Services/Interfaces/IUserRoleService.cs b/Oqtane.Client/Services/Interfaces/IUserRoleService.cs new file mode 100644 index 00000000..9030e2c1 --- /dev/null +++ b/Oqtane.Client/Services/Interfaces/IUserRoleService.cs @@ -0,0 +1,16 @@ +using Oqtane.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Oqtane.Services +{ + public interface IUserRoleService + { + Task> GetUserRolesAsync(); + Task> GetUserRolesAsync(int UserId); + Task GetUserRoleAsync(int UserRoleId); + Task AddUserRoleAsync(UserRole UserRole); + Task UpdateUserRoleAsync(UserRole UserRole); + Task DeleteUserRoleAsync(int UserRoleId); + } +} diff --git a/Oqtane.Client/Services/Interfaces/IUserService.cs b/Oqtane.Client/Services/Interfaces/IUserService.cs index e263d92c..6ffc4991 100644 --- a/Oqtane.Client/Services/Interfaces/IUserService.cs +++ b/Oqtane.Client/Services/Interfaces/IUserService.cs @@ -6,11 +6,11 @@ namespace Oqtane.Services { public interface IUserService { - Task> GetUsersAsync(); + Task> GetUsersAsync(int SiteId); - Task GetUserAsync(int UserId); + Task GetUserAsync(int UserId, int SiteId); - Task GetUserAsync(string Username); + Task GetUserAsync(string Username, int SiteId); Task AddUserAsync(User User); @@ -18,8 +18,6 @@ namespace Oqtane.Services Task DeleteUserAsync(int UserId); - Task GetCurrentUserAsync(); - Task LoginUserAsync(User User); Task LogoutUserAsync(); diff --git a/Oqtane.Client/Services/RoleService.cs b/Oqtane.Client/Services/RoleService.cs new file mode 100644 index 00000000..8f770e78 --- /dev/null +++ b/Oqtane.Client/Services/RoleService.cs @@ -0,0 +1,60 @@ +using Oqtane.Models; +using System.Threading.Tasks; +using System.Net.Http; +using System.Linq; +using Microsoft.AspNetCore.Components; +using System.Collections.Generic; +using Oqtane.Shared; + +namespace Oqtane.Services +{ + public class RoleService : ServiceBase, IRoleService + { + private readonly HttpClient http; + private readonly SiteState sitestate; + private readonly IUriHelper urihelper; + + public RoleService(HttpClient http, SiteState sitestate, IUriHelper urihelper) + { + this.http = http; + this.sitestate = sitestate; + this.urihelper = urihelper; + } + + private string apiurl + { + get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Role"); } + } + + public async Task> GetRolesAsync() + { + List Roles = await http.GetJsonAsync>(apiurl); + return Roles.OrderBy(item => item.Name).ToList(); + } + + public async Task> GetRolesAsync(int SiteId) + { + List Roles = await http.GetJsonAsync>(apiurl + "?siteid=" + SiteId.ToString()); + return Roles.OrderBy(item => item.Name).ToList(); + } + + public async Task GetRoleAsync(int RoleId) + { + return await http.GetJsonAsync(apiurl + "/" + RoleId.ToString()); + } + + public async Task AddRoleAsync(Role Role) + { + return await http.PostJsonAsync(apiurl, Role); + } + + public async Task UpdateRoleAsync(Role Role) + { + return await http.PutJsonAsync(apiurl + "/" + Role.SiteId.ToString(), Role); + } + public async Task DeleteRoleAsync(int RoleId) + { + await http.DeleteAsync(apiurl + "/" + RoleId.ToString()); + } + } +} diff --git a/Oqtane.Client/Services/UserRoleService.cs b/Oqtane.Client/Services/UserRoleService.cs new file mode 100644 index 00000000..b84a8450 --- /dev/null +++ b/Oqtane.Client/Services/UserRoleService.cs @@ -0,0 +1,59 @@ +using Oqtane.Models; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Oqtane.Shared; + +namespace Oqtane.Services +{ + public class UserRoleService : ServiceBase, IUserRoleService + { + private readonly HttpClient http; + private readonly SiteState sitestate; + private readonly IUriHelper urihelper; + + public UserRoleService(HttpClient http, SiteState sitestate, IUriHelper urihelper) + { + this.http = http; + this.sitestate = sitestate; + this.urihelper = urihelper; + } + + private string apiurl + { + get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "UserRole"); } + } + + public async Task> GetUserRolesAsync() + { + return await http.GetJsonAsync>(apiurl); + } + + public async Task> GetUserRolesAsync(int UserId) + { + return await http.GetJsonAsync>(apiurl + "?userid=" + UserId.ToString()); + } + + public async Task GetUserRoleAsync(int UserRoleId) + { + return await http.GetJsonAsync(apiurl + "/" + UserRoleId.ToString()); + } + + public async Task AddUserRoleAsync(UserRole UserRole) + { + return await http.PostJsonAsync(apiurl, UserRole); + } + + public async Task UpdateUserRoleAsync(UserRole UserRole) + { + return await http.PutJsonAsync(apiurl + "/" + UserRole.UserRoleId.ToString(), UserRole); + } + + public async Task DeleteUserRoleAsync(int UserRoleId) + { + await http.DeleteAsync(apiurl + "/" + UserRoleId.ToString()); + } + } +} diff --git a/Oqtane.Client/Services/UserService.cs b/Oqtane.Client/Services/UserService.cs index d9dd281d..333f1cdf 100644 --- a/Oqtane.Client/Services/UserService.cs +++ b/Oqtane.Client/Services/UserService.cs @@ -27,20 +27,20 @@ namespace Oqtane.Services get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "User"); } } - public async Task> GetUsersAsync() + public async Task> GetUsersAsync(int SiteId) { - List users = await http.GetJsonAsync>(apiurl); + List users = await http.GetJsonAsync>(apiurl + "?siteid=" + SiteId.ToString()); return users.OrderBy(item => item.DisplayName).ToList(); } - public async Task GetUserAsync(int UserId) + public async Task GetUserAsync(int UserId, int SiteId) { - return await http.GetJsonAsync(apiurl + "/" + UserId.ToString()); + return await http.GetJsonAsync(apiurl + "/" + UserId.ToString() + "?siteid=" + SiteId.ToString()); } - public async Task GetUserAsync(string Username) + public async Task GetUserAsync(string Username, int SiteId) { - return await http.GetJsonAsync(apiurl + "/name/" + Username); + return await http.GetJsonAsync(apiurl + "/name/" + Username + "?siteid=" + SiteId.ToString()); } public async Task AddUserAsync(User User) @@ -57,11 +57,6 @@ namespace Oqtane.Services await http.DeleteAsync(apiurl + "/" + UserId.ToString()); } - public async Task GetCurrentUserAsync() - { - return await http.GetJsonAsync(apiurl + "/current"); - } - public async Task LoginUserAsync(User User) { return await http.PostJsonAsync(apiurl + "/login", User); @@ -80,7 +75,7 @@ namespace Oqtane.Services if (User != null) { - //super user always has full access + // super user always has full access isAllowed = User.IsSuperUser; } diff --git a/Oqtane.Client/Shared/Installer.razor b/Oqtane.Client/Shared/Installer.razor index f624b89a..72e662e7 100644 --- a/Oqtane.Client/Shared/Installer.razor +++ b/Oqtane.Client/Shared/Installer.razor @@ -169,7 +169,8 @@ user.Password = HostPassword; user.IsSuperUser = true; user.Roles = ""; - await UserService.AddUserAsync(user); + user = await UserService.AddUserAsync(user); + UriHelper.NavigateTo("", true); } else diff --git a/Oqtane.Client/Shared/PaneLayout.razor b/Oqtane.Client/Shared/PaneLayout.razor index 74310b60..9fe4f572 100644 --- a/Oqtane.Client/Shared/PaneLayout.razor +++ b/Oqtane.Client/Shared/PaneLayout.razor @@ -21,8 +21,8 @@ } else { - // layout does not exist with type specified - } + // layout does not exist with type specified + } }; } } \ No newline at end of file diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index 8a44e141..995e5b55 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -195,7 +195,7 @@ var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); if (authState.User.Identity.IsAuthenticated) { - user = await UserService.GetUserAsync(authState.User.Identity.Name); + user = await UserService.GetUserAsync(authState.User.Identity.Name, site.SiteId); } } else diff --git a/Oqtane.Client/Shared/Theme.razor b/Oqtane.Client/Shared/Theme.razor index 3f83b411..b9431f4d 100644 --- a/Oqtane.Client/Shared/Theme.razor +++ b/Oqtane.Client/Shared/Theme.razor @@ -20,8 +20,8 @@ } else { - // theme does not exist with type specified - builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); + // theme does not exist with type specified + builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); builder.AddAttribute(1, "Type", MessageType.Error); builder.AddAttribute(2, "Message", "Error Loading Page Theme " + PageState.Page.ThemeType); builder.CloseComponent(); diff --git a/Oqtane.Client/Startup.cs b/Oqtane.Client/Startup.cs index 07c3b631..754ca6ad 100644 --- a/Oqtane.Client/Startup.cs +++ b/Oqtane.Client/Startup.cs @@ -46,6 +46,8 @@ namespace Oqtane.Client services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddScoped(); // dynamically register module contexts and repository services diff --git a/Oqtane.Client/Themes/Controls/Login.razor b/Oqtane.Client/Themes/Controls/Login.razor index 34492a17..811febd9 100644 --- a/Oqtane.Client/Themes/Controls/Login.razor +++ b/Oqtane.Client/Themes/Controls/Login.razor @@ -1,8 +1,7 @@ @using Oqtane.Themes -@using Oqtane.Services +@using Oqtane.Services @using Oqtane.Providers @using Oqtane.Shared -@using Oqtane.Models @using Microsoft.JSInterop @inherits ThemeObjectBase @inject IUriHelper UriHelper @@ -51,8 +50,8 @@ { // client-side Blazor authstateprovider.NotifyAuthenticationChanged(); - PageState.Reload = Constants.ReloadPage; - UriHelper.NavigateTo(NavigateUrl()); + PageState.Reload = Constants.ReloadSite; + UriHelper.NavigateTo(NavigateUrl(PageState.Page.Path)); } } } diff --git a/Oqtane.Server/Controllers/AliasController.cs b/Oqtane.Server/Controllers/AliasController.cs index facd0453..86ff6a04 100644 --- a/Oqtane.Server/Controllers/AliasController.cs +++ b/Oqtane.Server/Controllers/AliasController.cs @@ -8,25 +8,25 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class AliasController : Controller { - private readonly IAliasRepository aliases; + private readonly IAliasRepository Aliases; public AliasController(IAliasRepository Aliases) { - aliases = Aliases; + this.Aliases = Aliases; } // GET: api/ [HttpGet] public IEnumerable Get() { - return aliases.GetAliases(); + return Aliases.GetAliases(); } // GET api//5 [HttpGet("{id}")] public Alias Get(int id) { - return aliases.GetAlias(id); + return Aliases.GetAlias(id); } // POST api/ @@ -35,7 +35,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Alias = aliases.AddAlias(Alias); + Alias = Aliases.AddAlias(Alias); } return Alias; } @@ -46,7 +46,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Alias = aliases.UpdateAlias(Alias); + Alias = Aliases.UpdateAlias(Alias); } return Alias; } @@ -55,7 +55,7 @@ namespace Oqtane.Controllers [HttpDelete("{id}")] public void Delete(int id) { - aliases.DeleteAlias(id); + Aliases.DeleteAlias(id); } } } diff --git a/Oqtane.Server/Controllers/InstallationController.cs b/Oqtane.Server/Controllers/InstallationController.cs index 06defd92..7390dfd7 100644 --- a/Oqtane.Server/Controllers/InstallationController.cs +++ b/Oqtane.Server/Controllers/InstallationController.cs @@ -18,11 +18,11 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class InstallationController : Controller { - private readonly IConfigurationRoot _config; + private readonly IConfigurationRoot Config; - public InstallationController(IConfigurationRoot config) + public InstallationController(IConfigurationRoot Config) { - _config = config; + this.Config = Config; } // POST api/ @@ -139,7 +139,7 @@ namespace Oqtane.Controllers { writer.WriteLine(config); } - _config.Reload(); + Config.Reload(); response.Success = true; } } @@ -160,7 +160,7 @@ namespace Oqtane.Controllers var response = new GenericResponse { Success = false, Message = "" }; string datadirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString(); - string connectionString = _config.GetConnectionString("DefaultConnection"); + string connectionString = Config.GetConnectionString("DefaultConnection"); connectionString = connectionString.Replace("|DataDirectory|", datadirectory); SqlConnection connection = new SqlConnection(connectionString); diff --git a/Oqtane.Server/Controllers/ModuleController.cs b/Oqtane.Server/Controllers/ModuleController.cs index 994afbae..ef819edc 100644 --- a/Oqtane.Server/Controllers/ModuleController.cs +++ b/Oqtane.Server/Controllers/ModuleController.cs @@ -8,13 +8,13 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class ModuleController : Controller { - private readonly IModuleRepository modules; - private readonly IPageModuleRepository pagemodules; + private readonly IModuleRepository Modules; + private readonly IPageModuleRepository PageModules; public ModuleController(IModuleRepository Modules, IPageModuleRepository PageModules) { - modules = Modules; - pagemodules = PageModules; + this.Modules = Modules; + this.PageModules = PageModules; } // GET: api/?pageid=x @@ -25,7 +25,7 @@ namespace Oqtane.Controllers if (!string.IsNullOrEmpty(pageid)) { List modulelist = new List(); - foreach (PageModule pagemodule in pagemodules.GetPageModules(int.Parse(pageid))) + foreach (PageModule pagemodule in PageModules.GetPageModules(int.Parse(pageid))) { Module module = pagemodule.Module; module.PageModuleId = pagemodule.PageModuleId; @@ -40,7 +40,7 @@ namespace Oqtane.Controllers } else { - return modules.GetModules(int.Parse(siteid), moduledefinitionname); + return Modules.GetModules(int.Parse(siteid), moduledefinitionname); } } @@ -48,7 +48,7 @@ namespace Oqtane.Controllers [HttpGet("{id}")] public Module Get(int id) { - return modules.GetModule(id); + return Modules.GetModule(id); } // POST api/ @@ -57,7 +57,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Module = modules.AddModule(Module); + Module = Modules.AddModule(Module); } return Module; } @@ -68,7 +68,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Module = modules.UpdateModule(Module); + Module = Modules.UpdateModule(Module); } return Module; } @@ -77,7 +77,7 @@ namespace Oqtane.Controllers [HttpDelete("{id}")] public void Delete(int id) { - modules.DeleteModule(id); + Modules.DeleteModule(id); } } } diff --git a/Oqtane.Server/Controllers/ModuleDefinitionController.cs b/Oqtane.Server/Controllers/ModuleDefinitionController.cs index b523111b..d69275db 100644 --- a/Oqtane.Server/Controllers/ModuleDefinitionController.cs +++ b/Oqtane.Server/Controllers/ModuleDefinitionController.cs @@ -8,18 +8,18 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class ModuleDefinitionController : Controller { - private readonly IModuleDefinitionRepository moduledefinitions; + private readonly IModuleDefinitionRepository ModuleDefinitions; public ModuleDefinitionController(IModuleDefinitionRepository ModuleDefinitions) { - moduledefinitions = ModuleDefinitions; + this.ModuleDefinitions = ModuleDefinitions; } // GET: api/ [HttpGet] public IEnumerable Get() { - return moduledefinitions.GetModuleDefinitions(); + return ModuleDefinitions.GetModuleDefinitions(); } } } diff --git a/Oqtane.Server/Controllers/PageController.cs b/Oqtane.Server/Controllers/PageController.cs index 59ac9bdd..96ef61af 100644 --- a/Oqtane.Server/Controllers/PageController.cs +++ b/Oqtane.Server/Controllers/PageController.cs @@ -8,11 +8,11 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class PageController : Controller { - private readonly IPageRepository pages; + private readonly IPageRepository Pages; public PageController(IPageRepository Pages) { - pages = Pages; + this.Pages = Pages; } // GET: api/?siteid=x @@ -21,11 +21,11 @@ namespace Oqtane.Controllers { if (siteid == "") { - return pages.GetPages(); + return Pages.GetPages(); } else { - return pages.GetPages(int.Parse(siteid)); + return Pages.GetPages(int.Parse(siteid)); } } @@ -33,7 +33,7 @@ namespace Oqtane.Controllers [HttpGet("{id}")] public Page Get(int id) { - return pages.GetPage(id); + return Pages.GetPage(id); } // POST api/ @@ -42,7 +42,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Page = pages.AddPage(Page); + Page = Pages.AddPage(Page); } return Page; } @@ -53,7 +53,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Page = pages.UpdatePage(Page); + Page = Pages.UpdatePage(Page); } return Page; } @@ -62,7 +62,7 @@ namespace Oqtane.Controllers [HttpDelete("{id}")] public void Delete(int id) { - pages.DeletePage(id); + Pages.DeletePage(id); } } } diff --git a/Oqtane.Server/Controllers/PageModuleController.cs b/Oqtane.Server/Controllers/PageModuleController.cs index 500825d0..fa99465e 100644 --- a/Oqtane.Server/Controllers/PageModuleController.cs +++ b/Oqtane.Server/Controllers/PageModuleController.cs @@ -8,25 +8,25 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class PageModuleController : Controller { - private readonly IPageModuleRepository pagemodules; + private readonly IPageModuleRepository PageModules; public PageModuleController(IPageModuleRepository PageModules) { - pagemodules = PageModules; + this.PageModules = PageModules; } // GET: api/ [HttpGet] public IEnumerable Get() { - return pagemodules.GetPageModules(); + return PageModules.GetPageModules(); } // GET api//5 [HttpGet("{id}")] public PageModule Get(int id) { - return pagemodules.GetPageModule(id); + return PageModules.GetPageModule(id); } // POST api/ @@ -35,7 +35,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - PageModule = pagemodules.AddPageModule(PageModule); + PageModule = PageModules.AddPageModule(PageModule); } return PageModule; } @@ -46,7 +46,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - PageModule = pagemodules.UpdatePageModule(PageModule); + PageModule = PageModules.UpdatePageModule(PageModule); } return PageModule; } @@ -55,7 +55,7 @@ namespace Oqtane.Controllers [HttpDelete("{id}")] public void Delete(int id) { - pagemodules.DeletePageModule(id); + PageModules.DeletePageModule(id); } } } diff --git a/Oqtane.Server/Controllers/RoleController.cs b/Oqtane.Server/Controllers/RoleController.cs new file mode 100644 index 00000000..85f32f55 --- /dev/null +++ b/Oqtane.Server/Controllers/RoleController.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Oqtane.Repository; +using Oqtane.Models; + +namespace Oqtane.Controllers +{ + [Route("{site}/api/[controller]")] + public class RoleController : Controller + { + private readonly IRoleRepository Roles; + + public RoleController(IRoleRepository Roles) + { + this.Roles = Roles; + } + + // GET: api/?siteid=x + [HttpGet] + public IEnumerable Get(string siteid) + { + if (siteid == "") + { + return Roles.GetRoles(); + } + else + { + return Roles.GetRoles(int.Parse(siteid)); + } + } + + // GET api//5 + [HttpGet("{id}")] + public Role Get(int id) + { + return Roles.GetRole(id); + } + + // POST api/ + [HttpPost] + public Role Post([FromBody] Role Role) + { + if (ModelState.IsValid) + { + Role = Roles.AddRole(Role); + } + return Role; + } + + // PUT api//5 + [HttpPut("{id}")] + public Role Put(int id, [FromBody] Role Role) + { + if (ModelState.IsValid) + { + Role = Roles.UpdateRole(Role); + } + return Role; + } + + // DELETE api//5 + [HttpDelete("{id}")] + public void Delete(int id) + { + Roles.DeleteRole(id); + } + } +} diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs index 3d2528f9..b5892ec6 100644 --- a/Oqtane.Server/Controllers/SiteController.cs +++ b/Oqtane.Server/Controllers/SiteController.cs @@ -8,25 +8,25 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class SiteController : Controller { - private readonly ISiteRepository sites; + private readonly ISiteRepository Sites; public SiteController(ISiteRepository Sites) { - sites = Sites; + this.Sites = Sites; } // GET: api/ [HttpGet] public IEnumerable Get() { - return sites.GetSites(); + return Sites.GetSites(); } // GET api//5 [HttpGet("{id}")] public Site Get(int id) { - return sites.GetSite(id); + return Sites.GetSite(id); } // POST api/ @@ -35,7 +35,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Site = sites.AddSite(Site); + Site = Sites.AddSite(Site); } return Site; } @@ -46,7 +46,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Site = sites.UpdateSite(Site); + Site = Sites.UpdateSite(Site); } return Site; } @@ -55,7 +55,7 @@ namespace Oqtane.Controllers [HttpDelete("{id}")] public void Delete(int id) { - sites.DeleteSite(id); + Sites.DeleteSite(id); } } } diff --git a/Oqtane.Server/Controllers/TenantController.cs b/Oqtane.Server/Controllers/TenantController.cs index a5c38ebe..e56d86ee 100644 --- a/Oqtane.Server/Controllers/TenantController.cs +++ b/Oqtane.Server/Controllers/TenantController.cs @@ -8,25 +8,25 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class TenantController : Controller { - private readonly ITenantRepository tenants; + private readonly ITenantRepository Tenants; public TenantController(ITenantRepository Tenants) { - tenants = Tenants; + this.Tenants = Tenants; } // GET: api/ [HttpGet] public IEnumerable Get() { - return tenants.GetTenants(); + return Tenants.GetTenants(); } // GET api//5 [HttpGet("{id}")] public Tenant Get(int id) { - return tenants.GetTenant(id); + return Tenants.GetTenant(id); } // POST api/ @@ -35,7 +35,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Tenant = tenants.AddTenant(Tenant); + Tenant = Tenants.AddTenant(Tenant); } return Tenant; } @@ -46,7 +46,7 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - Tenant = tenants.UpdateTenant(Tenant); + Tenant = Tenants.UpdateTenant(Tenant); } return Tenant; } @@ -55,7 +55,7 @@ namespace Oqtane.Controllers [HttpDelete("{id}")] public void Delete(int id) { - tenants.DeleteTenant(id); + Tenants.DeleteTenant(id); } } } diff --git a/Oqtane.Server/Controllers/ThemeController.cs b/Oqtane.Server/Controllers/ThemeController.cs index 0b22b963..8cb7afe9 100644 --- a/Oqtane.Server/Controllers/ThemeController.cs +++ b/Oqtane.Server/Controllers/ThemeController.cs @@ -8,18 +8,18 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class ThemeController : Controller { - private readonly IThemeRepository themes; + private readonly IThemeRepository Themes; public ThemeController(IThemeRepository Themes) { - themes = Themes; + this.Themes = Themes; } // GET: api/ [HttpGet] public IEnumerable Get() { - return themes.GetThemes(); + return Themes.GetThemes(); } } } diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs index 209a90cc..914e23e7 100644 --- a/Oqtane.Server/Controllers/UserController.cs +++ b/Oqtane.Server/Controllers/UserController.cs @@ -11,33 +11,82 @@ namespace Oqtane.Controllers [Route("{site}/api/[controller]")] public class UserController : Controller { - private readonly IUserRepository users; - private readonly ISiteUserRepository siteusers; - private readonly UserManager identityUserManager; - private readonly SignInManager identitySignInManager; + private readonly IUserRepository Users; + private readonly ISiteUserRepository SiteUsers; + private readonly IRoleRepository Roles; + private readonly IUserRoleRepository UserRoles; + private readonly UserManager IdentityUserManager; + private readonly SignInManager IdentitySignInManager; - public UserController(IUserRepository Users, ISiteUserRepository SiteUsers, UserManager IdentityUserManager, SignInManager IdentitySignInManager) + public UserController(IUserRepository Users, ISiteUserRepository SiteUsers, IRoleRepository Roles, IUserRoleRepository UserRoles, UserManager IdentityUserManager, SignInManager IdentitySignInManager) { - users = Users; - siteusers = SiteUsers; - identityUserManager = IdentityUserManager; - identitySignInManager = IdentitySignInManager; + this.Users = Users; + this.SiteUsers = SiteUsers; + this.Roles = Roles; + this.UserRoles = UserRoles; + this.IdentityUserManager = IdentityUserManager; + this.IdentitySignInManager = IdentitySignInManager; } - // GET: api/ + // GET: api/?siteid=x [HttpGet] - public IEnumerable Get() + public IEnumerable Get(string siteid) { - return users.GetUsers(); + List users = new List(); + IEnumerable siteusers = SiteUsers.GetSiteUsers(int.Parse(siteid)); + foreach (SiteUser siteuser in siteusers) + { + User user = siteuser.User; + user.SiteId = siteuser.SiteId; + users.Add(user); + } + return users; } - // GET api//5 + // GET api//5?siteid=x [HttpGet("{id}")] - public User Get(int id) + public User Get(int id, string siteid) { - return users.GetUser(id); + User user = Users.GetUser(id); + if (user != null) + { + user.SiteId = int.Parse(siteid); + if (!user.IsSuperUser) // super users are part of every site by default + { + SiteUser siteuser = SiteUsers.GetSiteUser(user.SiteId, id); + if (siteuser != null) + { + user.Roles = GetUserRoles(user.UserId, user.SiteId); + } + } + } + return user; } - + + // GET api//name/x?siteid=x + [HttpGet("name/{name}")] + public User Get(string name, string siteid) + { + User user = Users.GetUser(name); + if (user != null) + { + user.SiteId = int.Parse(siteid); + if (!user.IsSuperUser) // super users are part of every site by default + { + SiteUser siteuser = SiteUsers.GetSiteUser(user.SiteId, user.UserId); + if (siteuser != null) + { + user.Roles = GetUserRoles(user.UserId, user.SiteId); + } + else + { + user = null; + } + } + } + return user; + } + // POST api/ [HttpPost] public async Task Post([FromBody] User User) @@ -46,21 +95,55 @@ namespace Oqtane.Controllers if (ModelState.IsValid) { - IdentityUser identityuser = await identityUserManager.FindByNameAsync(User.Username); + IdentityUser identityuser = await IdentityUserManager.FindByNameAsync(User.Username); if (identityuser == null) { identityuser = new IdentityUser(); identityuser.UserName = User.Username; identityuser.Email = User.Username; - var result = await identityUserManager.CreateAsync(identityuser, User.Password); + var result = await IdentityUserManager.CreateAsync(identityuser, User.Password); if (result.Succeeded) { - user = users.AddUser(User); - SiteUser SiteUser = new SiteUser(); - SiteUser.SiteId = User.SiteId; - SiteUser.UserId = user.UserId; - SiteUser.IsAuthorized = true; - siteusers.AddSiteUser(SiteUser); + user = Users.AddUser(User); + + SiteUser siteuser = new SiteUser(); + siteuser.SiteId = User.SiteId; + siteuser.UserId = user.UserId; + SiteUsers.AddSiteUser(siteuser); + + List roles = Roles.GetRoles(user.SiteId).Where(item => item.IsAutoAssigned == true).ToList(); + foreach (Role role in roles) + { + UserRole userrole = new UserRole(); + userrole.UserId = user.UserId; + userrole.RoleId = role.RoleId; + userrole.EffectiveDate = null; + userrole.ExpiryDate = null; + UserRoles.AddUserRole(userrole); + } + } + } + else + { + user = Users.GetUser(User.Username); + SiteUser siteuser = SiteUsers.GetSiteUser(User.SiteId, user.UserId); + if (siteuser == null) + { + siteuser = new SiteUser(); + siteuser.SiteId = User.SiteId; + siteuser.UserId = user.UserId; + SiteUsers.AddSiteUser(siteuser); + + List roles = Roles.GetRoles(User.SiteId).Where(item => item.IsAutoAssigned == true).ToList(); + foreach (Role role in roles) + { + UserRole userrole = new UserRole(); + userrole.UserId = user.UserId; + userrole.RoleId = role.RoleId; + userrole.EffectiveDate = null; + userrole.ExpiryDate = null; + UserRoles.AddUserRole(userrole); + } } } } @@ -74,23 +157,20 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - User = users.UpdateUser(User); + User = Users.UpdateUser(User); } return User; } - // DELETE api//5 + // DELETE api//5?siteid=x [HttpDelete("{id}")] - public void Delete(int id) + public void Delete(int id, string siteid) { - users.DeleteUser(id); - } - - // GET api//name/x - [HttpGet("name/{name}")] - public User GetByName(string name) - { - return users.GetUser(name); + SiteUser siteuser = SiteUsers.GetSiteUser(id, int.Parse(siteid)); + if (siteuser != null) + { + SiteUsers.DeleteSiteUser(siteuser.SiteUserId); + } } // POST api//login @@ -101,21 +181,31 @@ namespace Oqtane.Controllers if (ModelState.IsValid) { - IdentityUser identityuser = await identityUserManager.FindByNameAsync(User.Username); + IdentityUser identityuser = await IdentityUserManager.FindByNameAsync(User.Username); if (identityuser != null) { - var result = await identitySignInManager.CheckPasswordSignInAsync(identityuser, User.Password, false); + var result = await IdentitySignInManager.CheckPasswordSignInAsync(identityuser, User.Password, false); if (result.Succeeded) { - user = users.GetUser(identityuser.UserName); + user = Users.GetUser(identityuser.UserName); if (user != null) { - SiteUser siteuser = siteusers.GetSiteUsers(User.SiteId, user.UserId).FirstOrDefault(); - if (siteuser.IsAuthorized) + if (!user.IsSuperUser) // super users are part of every site by default + { + SiteUser siteuser = SiteUsers.GetSiteUser(User.SiteId, user.UserId); + if (siteuser != null) + { + user.IsAuthenticated = true; + } + } + else { - await identitySignInManager.SignInAsync(identityuser, User.IsPersistent); user.IsAuthenticated = true; } + if (user.IsAuthenticated) + { + await IdentitySignInManager.SignInAsync(identityuser, User.IsPersistent); + } } } } @@ -128,7 +218,7 @@ namespace Oqtane.Controllers [HttpPost("logout")] public async Task Logout([FromBody] User User) { - await identitySignInManager.SignOutAsync(); + await IdentitySignInManager.SignOutAsync(); } // GET api//current @@ -137,5 +227,20 @@ namespace Oqtane.Controllers { return new User { Username = User.Identity.Name, IsAuthenticated = User.Identity.IsAuthenticated }; } + + private string GetUserRoles(int UserId, int SiteId) + { + string roles = ""; + IEnumerable userroles = UserRoles.GetUserRoles(UserId); + foreach (UserRole userrole in userroles) + { + if (userrole.Role.SiteId == SiteId) + { + roles += userrole.Role.Name + ";"; + } + } + if (roles != "") roles = ";" + roles; + return roles; + } } } diff --git a/Oqtane.Server/Controllers/UserRoleController.cs b/Oqtane.Server/Controllers/UserRoleController.cs new file mode 100644 index 00000000..8865e763 --- /dev/null +++ b/Oqtane.Server/Controllers/UserRoleController.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Oqtane.Repository; +using Oqtane.Models; + +namespace Oqtane.Controllers +{ + [Route("{site}/api/[controller]")] + public class UserRoleController : Controller + { + private readonly IUserRoleRepository UserRoles; + + public UserRoleController(IUserRoleRepository UserRoles) + { + this.UserRoles = UserRoles; + } + + // GET: api/?userid=x + [HttpGet] + public IEnumerable Get(string userid) + { + if (userid == "") + { + return UserRoles.GetUserRoles(); + } + else + { + return UserRoles.GetUserRoles(int.Parse(userid)); + } + } + + // GET api//5 + [HttpGet("{id}")] + public UserRole Get(int id) + { + return UserRoles.GetUserRole(id); + } + + // POST api/ + [HttpPost] + public UserRole Post([FromBody] UserRole UserRole) + { + if (ModelState.IsValid) + { + UserRole = UserRoles.AddUserRole(UserRole); + } + return UserRole; + } + + // PUT api//5 + [HttpPut("{id}")] + public UserRole Put(int id, [FromBody] UserRole UserRole) + { + if (ModelState.IsValid) + { + UserRole = UserRoles.UpdateUserRole(UserRole); + } + return UserRole; + } + + // DELETE api//5 + [HttpDelete("{id}")] + public void Delete(int id) + { + UserRoles.DeleteUserRole(id); + } + } +} diff --git a/Oqtane.Server/Pages/Login.cshtml.cs b/Oqtane.Server/Pages/Login.cshtml.cs index eb8399e5..cc1877cc 100644 --- a/Oqtane.Server/Pages/Login.cshtml.cs +++ b/Oqtane.Server/Pages/Login.cshtml.cs @@ -46,12 +46,7 @@ namespace Oqtane.Pages await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); } - string url = "~/"; - if (returnurl != "/") - { - url = Url.Content("~/" + returnurl); - } - return LocalRedirect(url); + return LocalRedirect(Url.Content("~" + returnurl)); } } } \ No newline at end of file diff --git a/Oqtane.Server/Pages/Logout.cshtml.cs b/Oqtane.Server/Pages/Logout.cshtml.cs index 95ec1a71..d976f39d 100644 --- a/Oqtane.Server/Pages/Logout.cshtml.cs +++ b/Oqtane.Server/Pages/Logout.cshtml.cs @@ -19,12 +19,7 @@ namespace Oqtane.Pages { await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); - string url = "~/"; - if (returnurl != "/") - { - url = Url.Content("~/" + returnurl); - } - return LocalRedirect(url); + return LocalRedirect(Url.Content("~" + returnurl)); } } } \ No newline at end of file diff --git a/Oqtane.Server/Repository/AliasRepository.cs b/Oqtane.Server/Repository/AliasRepository.cs index 8595557c..1ebda180 100644 --- a/Oqtane.Server/Repository/AliasRepository.cs +++ b/Oqtane.Server/Repository/AliasRepository.cs @@ -22,12 +22,11 @@ namespace Oqtane.Repository { try { - IEnumerable aliases = _cache.GetOrCreate("aliases", entry => + return _cache.GetOrCreate("aliases", entry => { entry.SlidingExpiration = TimeSpan.FromMinutes(30); return db.Alias.ToList(); }); - return aliases; } catch { @@ -67,8 +66,7 @@ namespace Oqtane.Repository { try { - Alias alias = db.Alias.Find(AliasId); - return alias; + return db.Alias.Find(AliasId); } catch { diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index 3e0c1ca7..62c54b0d 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -12,6 +12,8 @@ namespace Oqtane.Repository public virtual DbSet Module { get; set; } public virtual DbSet User { get; set; } public virtual DbSet SiteUser { get; set; } + public virtual DbSet Role { get; set; } + public virtual DbSet UserRole { get; set; } public virtual DbSet Setting { get; set; } public TenantDBContext(ITenantResolver TenantResolver, IHttpContextAccessor accessor) : base(TenantResolver, accessor) diff --git a/Oqtane.Server/Repository/Interfaces/IRoleRepository.cs b/Oqtane.Server/Repository/Interfaces/IRoleRepository.cs new file mode 100644 index 00000000..61541336 --- /dev/null +++ b/Oqtane.Server/Repository/Interfaces/IRoleRepository.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public interface IRoleRepository + { + IEnumerable GetRoles(); + IEnumerable GetRoles(int SiteId); + Role AddRole(Role Role); + Role UpdateRole(Role Role); + Role GetRole(int RoleId); + void DeleteRole(int RoleId); + } +} diff --git a/Oqtane.Server/Repository/Interfaces/ISiteUserRepository.cs b/Oqtane.Server/Repository/Interfaces/ISiteUserRepository.cs index 747f95e6..67beb7d2 100644 --- a/Oqtane.Server/Repository/Interfaces/ISiteUserRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISiteUserRepository.cs @@ -6,10 +6,11 @@ namespace Oqtane.Repository public interface ISiteUserRepository { IEnumerable GetSiteUsers(); - IEnumerable GetSiteUsers(int SiteId, int UserId); + IEnumerable GetSiteUsers(int SiteId); SiteUser AddSiteUser(SiteUser SiteUser); SiteUser UpdateSiteUser(SiteUser SiteUser); SiteUser GetSiteUser(int SiteUserId); + SiteUser GetSiteUser(int SiteId, int UserId); void DeleteSiteUser(int SiteUserId); } } diff --git a/Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs b/Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs new file mode 100644 index 00000000..fad2f850 --- /dev/null +++ b/Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public interface IUserRoleRepository + { + IEnumerable GetUserRoles(); + IEnumerable GetUserRoles(int UserId); + UserRole AddUserRole(UserRole UserRole); + UserRole UpdateUserRole(UserRole UserRole); + UserRole GetUserRole(int UserRoleId); + void DeleteUserRole(int UserRoleId); + } +} diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index ca612fae..d626ead3 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -10,26 +10,26 @@ namespace Oqtane.Repository { public class ModuleDefinitionRepository : IModuleDefinitionRepository { - private readonly List moduledefinitions; + private readonly List ModuleDefinitions; public ModuleDefinitionRepository() { - moduledefinitions = LoadModuleDefinitions(); + ModuleDefinitions = LoadModuleDefinitions(); } private List LoadModuleDefinitions() { - List moduledefinitions = new List(); + List ModuleDefinitions = new List(); // iterate through Oqtane module assemblies Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Module.")).ToArray(); foreach (Assembly assembly in assemblies) { - moduledefinitions = LoadModuleDefinitionsFromAssembly(moduledefinitions, assembly); + ModuleDefinitions = LoadModuleDefinitionsFromAssembly(ModuleDefinitions, assembly); } - return moduledefinitions; + return ModuleDefinitions; } private List LoadModuleDefinitionsFromAssembly(List moduledefinitions, Assembly assembly) @@ -115,7 +115,7 @@ namespace Oqtane.Repository public IEnumerable GetModuleDefinitions() { - return moduledefinitions; + return ModuleDefinitions; } } diff --git a/Oqtane.Server/Repository/ModuleRepository.cs b/Oqtane.Server/Repository/ModuleRepository.cs index 76c07605..b8248f40 100644 --- a/Oqtane.Server/Repository/ModuleRepository.cs +++ b/Oqtane.Server/Repository/ModuleRepository.cs @@ -73,8 +73,7 @@ namespace Oqtane.Repository { try { - Module Module = db.Module.Find(ModuleId); - return Module; + return db.Module.Find(ModuleId); } catch { diff --git a/Oqtane.Server/Repository/PageModuleRepository.cs b/Oqtane.Server/Repository/PageModuleRepository.cs index 00c0fd0b..f626c472 100644 --- a/Oqtane.Server/Repository/PageModuleRepository.cs +++ b/Oqtane.Server/Repository/PageModuleRepository.cs @@ -29,10 +29,9 @@ namespace Oqtane.Repository { try { - List pagemodules = db.PageModule.Where(item => item.PageId == PageId) - .Include(item => item.Module) + return db.PageModule.Where(item => item.PageId == PageId) + .Include(item => item.Module) // eager load modules .ToList(); - return pagemodules; } catch { @@ -72,8 +71,8 @@ namespace Oqtane.Repository { try { - PageModule PageModule = db.PageModule.Find(PageModuleId); - return PageModule; + return db.PageModule.Include(item => item.Module) // eager load modules + .SingleOrDefault(item => item.PageModuleId == PageModuleId); } catch { diff --git a/Oqtane.Server/Repository/PageRepository.cs b/Oqtane.Server/Repository/PageRepository.cs index 33612112..fcf11a98 100644 --- a/Oqtane.Server/Repository/PageRepository.cs +++ b/Oqtane.Server/Repository/PageRepository.cs @@ -70,8 +70,7 @@ namespace Oqtane.Repository { try { - Page Page = db.Page.Find(PageId); - return Page; + return db.Page.Find(PageId); } catch { diff --git a/Oqtane.Server/Repository/RoleRepository.cs b/Oqtane.Server/Repository/RoleRepository.cs new file mode 100644 index 00000000..afb1fc09 --- /dev/null +++ b/Oqtane.Server/Repository/RoleRepository.cs @@ -0,0 +1,95 @@ +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public class RoleRepository : IRoleRepository + { + private TenantDBContext db; + + public RoleRepository(TenantDBContext context) + { + db = context; + } + + public IEnumerable GetRoles() + { + try + { + return db.Role.ToList(); + } + catch + { + throw; + } + } + + public IEnumerable GetRoles(int SiteId) + { + try + { + return db.Role.Where(item => item.SiteId == SiteId).ToList(); + } + catch + { + throw; + } + } + + public Role AddRole(Role Role) + { + try + { + db.Role.Add(Role); + db.SaveChanges(); + return Role; + } + catch + { + throw; + } + } + + public Role UpdateRole(Role Role) + { + try + { + db.Entry(Role).State = EntityState.Modified; + db.SaveChanges(); + return Role; + } + catch + { + throw; + } + } + + public Role GetRole(int RoleId) + { + try + { + return db.Role.Find(RoleId); + } + catch + { + throw; + } + } + + public void DeleteRole(int RoleId) + { + try + { + Role Role = db.Role.Find(RoleId); + db.Role.Remove(Role); + db.SaveChanges(); + } + catch + { + throw; + } + } + } +} diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index b5a17bd5..a12040ec 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -59,8 +59,7 @@ namespace Oqtane.Repository { try { - Setting Setting = db.Setting.Find(SettingId); - return Setting; + return db.Setting.Find(SettingId); } catch { diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index bba65d22..88ec72df 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -58,8 +58,7 @@ namespace Oqtane.Repository { try { - Site site = db.Site.Find(siteId); - return site; + return db.Site.Find(siteId); } catch { diff --git a/Oqtane.Server/Repository/SiteUserRepository.cs b/Oqtane.Server/Repository/SiteUserRepository.cs index 81fa29f5..f0209b48 100644 --- a/Oqtane.Server/Repository/SiteUserRepository.cs +++ b/Oqtane.Server/Repository/SiteUserRepository.cs @@ -25,16 +25,13 @@ namespace Oqtane.Repository throw; } } - public IEnumerable GetSiteUsers(int SiteId, int UserId) + public IEnumerable GetSiteUsers(int SiteId) { try { - List siteusers = db.SiteUser.Where(item => item.SiteId == SiteId).ToList(); - if (UserId != -1) - { - siteusers = siteusers.Where(item => item.UserId == UserId).ToList(); - } - return siteusers; + return db.SiteUser.Where(item => item.SiteId == SiteId) + .Include(item => item.User) // eager load users + .ToList(); } catch { @@ -74,8 +71,20 @@ namespace Oqtane.Repository { try { - SiteUser SiteUser = db.SiteUser.Find(SiteUserId); - return SiteUser; + return db.SiteUser.Include(item => item.User) // eager load users + .SingleOrDefault(item => item.SiteUserId == SiteUserId); + } + catch + { + throw; + } + } + + public SiteUser GetSiteUser(int SiteId, int UserId) + { + try + { + return db.SiteUser.Where(item => item.SiteId == SiteId).Where(item => item.UserId == UserId).FirstOrDefault(); } catch { diff --git a/Oqtane.Server/Repository/TenantRepository.cs b/Oqtane.Server/Repository/TenantRepository.cs index d21d8f2e..58d7df30 100644 --- a/Oqtane.Server/Repository/TenantRepository.cs +++ b/Oqtane.Server/Repository/TenantRepository.cs @@ -23,12 +23,11 @@ namespace Oqtane.Repository { try { - IEnumerable tenants = _cache.GetOrCreate("tenants", entry => + return _cache.GetOrCreate("tenants", entry => { entry.SlidingExpiration = TimeSpan.FromMinutes(30); return db.Tenant.ToList(); }); - return tenants; } catch { @@ -68,8 +67,7 @@ namespace Oqtane.Repository { try { - Tenant tenant = db.Tenant.Find(TenantId); - return tenant; + return db.Tenant.Find(TenantId); } catch { diff --git a/Oqtane.Server/Repository/ThemeRepository.cs b/Oqtane.Server/Repository/ThemeRepository.cs index 9eb25aa6..1b7ead1e 100644 --- a/Oqtane.Server/Repository/ThemeRepository.cs +++ b/Oqtane.Server/Repository/ThemeRepository.cs @@ -10,26 +10,26 @@ namespace Oqtane.Repository { public class ThemeRepository : IThemeRepository { - private readonly List themes; + private readonly List Themes; public ThemeRepository() { - themes = LoadThemes(); + Themes = LoadThemes(); } private List LoadThemes() { - List themes = new List(); + List Themes = new List(); // iterate through Oqtane theme assemblies Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies() .Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Theme.")).ToArray(); foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { - themes = LoadThemesFromAssembly(themes, assembly); + Themes = LoadThemesFromAssembly(Themes, assembly); } - return themes; + return Themes; } private List LoadThemesFromAssembly(List themes, Assembly assembly) @@ -120,7 +120,7 @@ namespace Oqtane.Repository public IEnumerable GetThemes() { - return themes; + return Themes; } } } diff --git a/Oqtane.Server/Repository/UserRepository.cs b/Oqtane.Server/Repository/UserRepository.cs index 6b863e37..c31b73d4 100644 --- a/Oqtane.Server/Repository/UserRepository.cs +++ b/Oqtane.Server/Repository/UserRepository.cs @@ -58,8 +58,7 @@ namespace Oqtane.Repository { try { - User user = db.User.Find(userId); - return user; + return db.User.Find(userId); } catch { @@ -71,8 +70,7 @@ namespace Oqtane.Repository { try { - User user = db.User.Where(item => item.Username == Username).FirstOrDefault(); - return user; + return db.User.Where(item => item.Username == Username).FirstOrDefault(); } catch { diff --git a/Oqtane.Server/Repository/UserRoleRepository.cs b/Oqtane.Server/Repository/UserRoleRepository.cs new file mode 100644 index 00000000..8e095ffb --- /dev/null +++ b/Oqtane.Server/Repository/UserRoleRepository.cs @@ -0,0 +1,97 @@ +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public class UserRoleRepository : IUserRoleRepository + { + private TenantDBContext db; + + public UserRoleRepository(TenantDBContext context) + { + db = context; + } + + public IEnumerable GetUserRoles() + { + try + { + return db.UserRole.ToList(); + } + catch + { + throw; + } + } + public IEnumerable GetUserRoles(int UserId) + { + try + { + return db.UserRole.Where(item => item.UserId == UserId) + .Include(item => item.Role) // eager load roles + .ToList(); + } + catch + { + throw; + } + } + + public UserRole AddUserRole(UserRole UserRole) + { + try + { + db.UserRole.Add(UserRole); + db.SaveChanges(); + return UserRole; + } + catch + { + throw; + } + } + + public UserRole UpdateUserRole(UserRole UserRole) + { + try + { + db.Entry(UserRole).State = EntityState.Modified; + db.SaveChanges(); + return UserRole; + } + catch + { + throw; + } + } + + public UserRole GetUserRole(int UserRoleId) + { + try + { + return db.UserRole.Include(item => item.Role) // eager load roles + .SingleOrDefault(item => item.UserRoleId == UserRoleId); + } + catch + { + throw; + } + } + + public void DeleteUserRole(int UserRoleId) + { + try + { + UserRole UserRole = db.UserRole.Find(UserRoleId); + db.UserRole.Remove(UserRole); + db.SaveChanges(); + } + catch + { + throw; + } + } + } +} diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql index c5d950d8..d047d5f8 100644 --- a/Oqtane.Server/Scripts/00.00.00.sql +++ b/Oqtane.Server/Scripts/00.00.00.sql @@ -99,7 +99,6 @@ CREATE TABLE [dbo].[User]( [UserId] [int] IDENTITY(1,1) NOT NULL, [Username] [nvarchar](256) NOT NULL, [DisplayName] [nvarchar](50) NOT NULL, - [Roles] [nvarchar](50) NOT NULL, [IsSuperUser] [bit] NOT NULL, [CreatedBy] [nvarchar](256) NOT NULL, [CreatedOn] [datetime] NOT NULL, @@ -116,7 +115,6 @@ CREATE TABLE [dbo].[SiteUser]( [SiteUserId] [int] IDENTITY(1,1) NOT NULL, [SiteId] [int] NOT NULL, [UserId] [int] NOT NULL, - [IsAuthorized] [bit] NOT NULL, [CreatedBy] [nvarchar](256) NOT NULL, [CreatedOn] [datetime] NOT NULL, [ModifiedBy] [nvarchar](256) NOT NULL, @@ -128,6 +126,40 @@ CREATE TABLE [dbo].[SiteUser]( ) GO +CREATE TABLE [dbo].[Role]( + [RoleId] [int] IDENTITY(1,1) NOT NULL, + [SiteId] [int] NOT NULL, + [Name] [nvarchar](256) NOT NULL, + [Description] [nvarchar](50) NOT NULL, + [IsAutoAssigned] [bit] NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED + ( + [RoleId] ASC + ) +) +GO + +CREATE TABLE [dbo].[UserRole]( + [UserRoleId] [int] IDENTITY(1,1) NOT NULL, + [UserId] [int] NOT NULL, + [RoleId] [int] NOT NULL, + [EffectiveDate] [datetime] NULL, + [ExpiryDate] [datetime] NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED + ( + [UserRoleId] ASC + ) +) +GO + CREATE TABLE [dbo].[Setting]( [SettingId] [int] IDENTITY(1,1) NOT NULL, [EntityName] [nvarchar](50) NOT NULL, @@ -260,6 +292,9 @@ GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) 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'', '', getdate(), '', getdate()) GO +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (16, 1, N'Role Management', N'admin/roles', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', N'Administrators', N'Administrators', 4, 5, 1, N'', '', getdate(), '', getdate()) +GO SET IDENTITY_INSERT [dbo].[Page] OFF GO @@ -322,6 +357,9 @@ GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (19, 2, N'Oqtane.Client.Modules.Admin.Register, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (20, 1, N'Oqtane.Client.Modules.Admin.Roles, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) +GO SET IDENTITY_INSERT [dbo].[Module] OFF GO @@ -384,6 +422,9 @@ GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (19, 15, 19, N'Register', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (20, 16, 20, N'Role Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) +GO SET IDENTITY_INSERT [dbo].[PageModule] OFF GO @@ -410,4 +451,20 @@ GO SET IDENTITY_INSERT [dbo].[HtmlText] OFF GO +SET IDENTITY_INSERT [dbo].[Role] ON +GO +INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, 1, N'Administrators', N'Site Administrators', 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, 1, N'Registered Users', N'Registered Users', 1, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (3, 2, N'Administrators', N'Site Administrators', 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (4, 2, N'Registered Users', N'Registered Users', 1, '', getdate(), '', getdate()) +GO +SET IDENTITY_INSERT [dbo].[Role] OFF +GO diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 434ec1da..ebf18df8 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -79,6 +79,8 @@ namespace Oqtane.Server services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddSingleton(); @@ -157,6 +159,8 @@ namespace Oqtane.Server services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); // dynamically register module services, contexts, and repository classes @@ -305,6 +309,8 @@ namespace Oqtane.Server services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); // dynamically register module services, contexts, and repository classes diff --git a/Oqtane.Shared/Models/Role.cs b/Oqtane.Shared/Models/Role.cs new file mode 100644 index 00000000..f892cabc --- /dev/null +++ b/Oqtane.Shared/Models/Role.cs @@ -0,0 +1,18 @@ +using System; + +namespace Oqtane.Models +{ + public class Role : IAuditable + { + public int RoleId { get; set; } + public int SiteId { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public bool IsAutoAssigned { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + } +} diff --git a/Oqtane.Shared/Models/SiteUser.cs b/Oqtane.Shared/Models/SiteUser.cs index cfae5d2f..15e23c41 100644 --- a/Oqtane.Shared/Models/SiteUser.cs +++ b/Oqtane.Shared/Models/SiteUser.cs @@ -7,11 +7,12 @@ namespace Oqtane.Models public int SiteUserId { get; set; } public int SiteId { get; set; } public int UserId { get; set; } - public bool IsAuthorized { get; set; } public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; } public string ModifiedBy { get; set; } public DateTime ModifiedOn { get; set; } + + public User User { get; set; } } } diff --git a/Oqtane.Shared/Models/User.cs b/Oqtane.Shared/Models/User.cs index 6c759a74..e57f765f 100644 --- a/Oqtane.Shared/Models/User.cs +++ b/Oqtane.Shared/Models/User.cs @@ -8,21 +8,23 @@ namespace Oqtane.Models public int UserId { get; set; } public string Username { get; set; } public string DisplayName { get; set; } - public string Roles { get; set; } public bool IsSuperUser { get; set; } + [NotMapped] + public int SiteId { get; set; } + [NotMapped] + public string Roles { get; set; } public string CreatedBy { get; set; } public DateTime CreatedOn { get; set; } public string ModifiedBy { get; set; } public DateTime ModifiedOn { get; set; } - [NotMapped] - public int SiteId { get; set; } [NotMapped] public string Password { get; set; } [NotMapped] public bool IsAuthenticated { get; set; } [NotMapped] public bool IsPersistent { get; set; } + } } diff --git a/Oqtane.Shared/Models/UserRole.cs b/Oqtane.Shared/Models/UserRole.cs new file mode 100644 index 00000000..3ed423bb --- /dev/null +++ b/Oqtane.Shared/Models/UserRole.cs @@ -0,0 +1,20 @@ +using System; + +namespace Oqtane.Models +{ + public class UserRole : IAuditable + { + public int UserRoleId { get; set; } + public int UserId { get; set; } + public int RoleId { get; set; } + public DateTime? EffectiveDate { get; set; } + public DateTime? ExpiryDate { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + + public Role Role { get; set; } + } +} From ad2d865d7ce43fa599ccdb39b4ff3b121c87e37c Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 21 Aug 2019 10:37:02 -0400 Subject: [PATCH 25/44] Page management cleanup --- Oqtane.Client/Modules/Admin/Pages/Add.razor | 89 +++++++----- .../Modules/Admin/Pages/Delete.razor | 73 +++++++--- Oqtane.Client/Modules/Admin/Pages/Edit.razor | 136 +++++++++++------- Oqtane.Client/Modules/Admin/Pages/Index.razor | 18 +-- .../Modules/Controls/ActionLink.razor | 19 ++- .../Modules/Controls/AuditInfo.razor | 55 +++++++ 6 files changed, 266 insertions(+), 124 deletions(-) create mode 100644 Oqtane.Client/Modules/Controls/AuditInfo.razor diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index 7ceb31cc..8c07b2bc 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -8,6 +8,8 @@ @inject IPageService PageService @inject IThemeService ThemeService +@message + @@ -53,8 +55,8 @@ @@ -117,6 +119,8 @@ @code { public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } + string message = ""; + Dictionary themes = new Dictionary(); Dictionary panelayouts = new Dictionary(); @@ -133,44 +137,59 @@ protected override void OnInitialized() { - themes = ThemeService.GetThemeTypes(PageState.Themes); - panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); + try + { + themes = ThemeService.GetThemeTypes(PageState.Themes); + panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); + } + catch (Exception ex) + { + message = ex.Message; + } } private async Task SavePage() { - Page p = new Page(); - p.SiteId = PageState.Page.SiteId; - if (string.IsNullOrEmpty(parentid)) + try { - p.ParentId = null; + Page page = new Page(); + page.SiteId = PageState.Page.SiteId; + if (string.IsNullOrEmpty(parentid)) + { + page.ParentId = null; + } + else + { + page.ParentId = Int32.Parse(parentid); + } + page.Name = name; + page.Path = path; + page.Order = (order == null ? 1 : Int32.Parse(order)); + page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation)); + page.ThemeType = themetype; + page.LayoutType = (layouttype == null ? "" : layouttype); + page.Icon = (icon == null ? "" : icon); + Type type; + if (!string.IsNullOrEmpty(layouttype)) + { + type = Type.GetType(layouttype); + } + else + { + type = Type.GetType(themetype); + } + System.Reflection.PropertyInfo property = type.GetProperty("Panes"); + page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); + page.ViewPermissions = viewpermissions; + page.EditPermissions = editpermissions; + await PageService.AddPageAsync(page); + + PageState.Reload = Constants.ReloadSite; + UriHelper.NavigateTo(NavigateUrl(path)); } - else + catch (Exception ex) { - p.ParentId = Int32.Parse(parentid); + message = ex.Message; } - p.Name = name; - p.Path = path; - p.Order = (order == null ? 1 : Int32.Parse(order)); - p.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation)); - p.ThemeType = themetype; - p.LayoutType = (layouttype == null ? "" : layouttype); - p.Icon = (icon == null ? "" : icon); - Type type; - if (!string.IsNullOrEmpty(layouttype)) - { - type = Type.GetType(layouttype); - } - else - { - type = Type.GetType(themetype); - } - System.Reflection.PropertyInfo property = type.GetProperty("Panes"); - p.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - p.ViewPermissions = viewpermissions; - p.EditPermissions = editpermissions; - await PageService.AddPageAsync(p); - PageState.Reload = Constants.ReloadSite; - UriHelper.NavigateTo(NavigateUrl(path)); } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index ad6efa47..85703eb7 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -3,11 +3,14 @@ @using Oqtane.Services @using Oqtane.Modules @using Oqtane.Shared +@using Oqtane.Client.Modules.Controls @inherits ModuleBase @inject IUriHelper UriHelper @inject IPageService PageService @inject IThemeService ThemeService +@message +
@@ -32,9 +34,9 @@
@@ -63,7 +66,7 @@
@@ -53,8 +56,8 @@
- @foreach (KeyValuePair item in themes) { @@ -77,7 +80,7 @@ - @foreach (KeyValuePair panelayout in panelayouts) { @@ -113,10 +116,14 @@
Cancel +

+ @code { public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } + string message = ""; + Dictionary themes = new Dictionary(); Dictionary panelayouts = new Dictionary(); @@ -131,33 +138,55 @@ string icon; string viewpermissions; string editpermissions; + string createdby; + DateTime createdon; + string modifiedby; + DateTime modifiedon; protected override void OnInitialized() { - themes = ThemeService.GetThemeTypes(PageState.Themes); - panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); - - PageId = Int32.Parse(PageState.QueryString["id"]); - Page p = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault(); - if (p != null) + try { - name = p.Name; - path = p.Path; + themes = ThemeService.GetThemeTypes(PageState.Themes); + panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); - order = p.Order.ToString(); - isnavigation = p.IsNavigation.ToString(); - themetype = p.ThemeType; - layouttype = p.LayoutType; - icon = p.Icon; - viewpermissions = p.ViewPermissions; - editpermissions = p.EditPermissions; + PageId = Int32.Parse(PageState.QueryString["id"]); + Page page = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault(); + if (page != null) + { + name = page.Name; + path = page.Path; + + order = page.Order.ToString(); + isnavigation = page.IsNavigation.ToString(); + themetype = page.ThemeType; + layouttype = page.LayoutType; + icon = page.Icon; + viewpermissions = page.ViewPermissions; + editpermissions = page.EditPermissions; + createdby = page.CreatedBy; + createdon = page.CreatedOn; + modifiedby = page.ModifiedBy; + modifiedon = page.ModifiedOn; + } + } + catch (Exception ex) + { + message = ex.Message; } } private async Task DeletePage() { - await PageService.DeletePageAsync(Int32.Parse(PageState.QueryString["id"])); - PageState.Reload = Constants.ReloadSite; - UriHelper.NavigateTo(NavigateUrl()); + try + { + await PageService.DeletePageAsync(Int32.Parse(PageState.QueryString["id"])); + PageState.Reload = Constants.ReloadSite; + UriHelper.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + message = ex.Message; + } } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 568cfad0..88163633 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -9,6 +9,8 @@ @inject IPageService PageService @inject IThemeService ThemeService +@message + @@ -54,8 +56,8 @@ @@ -114,10 +116,14 @@
@@ -33,9 +35,9 @@
Cancel +

+ @code { public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } } + string message = ""; + Dictionary themes = new Dictionary(); Dictionary panelayouts = new Dictionary(); @@ -132,69 +138,93 @@ string icon; string viewpermissions; string editpermissions; + string createdby; + DateTime createdon; + string modifiedby; + DateTime modifiedon; protected override void OnInitialized() { - themes = ThemeService.GetThemeTypes(PageState.Themes); - panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); - - PageId = Int32.Parse(PageState.QueryString["id"]); - Page p = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault(); - if (p != null) + try { - name = p.Name; - path = p.Path; - if (p.ParentId == null) + themes = ThemeService.GetThemeTypes(PageState.Themes); + panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); + + PageId = Int32.Parse(PageState.QueryString["id"]); + Page page = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault(); + if (page != null) { - parentid = ""; + name = page.Name; + path = page.Path; + if (page.ParentId == null) + { + parentid = ""; + } + else + { + parentid = page.ParentId.ToString(); + } + order = page.Order.ToString(); + isnavigation = page.IsNavigation.ToString(); + themetype = page.ThemeType; + layouttype = page.LayoutType; + icon = page.Icon; + viewpermissions = page.ViewPermissions; + editpermissions = page.EditPermissions; + createdby = page.CreatedBy; + createdon = page.CreatedOn; + modifiedby = page.ModifiedBy; + modifiedon = page.ModifiedOn; } - else - { - parentid = p.ParentId.ToString(); - } - order = p.Order.ToString(); - isnavigation = p.IsNavigation.ToString(); - themetype = p.ThemeType; - layouttype = p.LayoutType; - icon = p.Icon; - viewpermissions = p.ViewPermissions; - editpermissions = p.EditPermissions; + } + catch (Exception ex) + { + message = ex.Message; } } private async Task SavePage() { - Page p = PageState.Page; - p.PageId = Int32.Parse(PageState.QueryString["id"]); - if (string.IsNullOrEmpty(parentid)) + try { - p.ParentId = null; + Page page = PageState.Page; + page.PageId = Int32.Parse(PageState.QueryString["id"]); + if (string.IsNullOrEmpty(parentid)) + { + page.ParentId = null; + } + else + { + page.ParentId = Int32.Parse(parentid); + } + page.Name = name; + page.Path = path; + page.Order = (order == null ? 1 : Int32.Parse(order)); + page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation)); + page.ThemeType = themetype; + page.LayoutType = (layouttype == null ? "" : layouttype); + page.Icon = (icon == null ? "" : icon); + Type type; + if (!string.IsNullOrEmpty(layouttype)) + { + type = Type.GetType(layouttype); + } + else + { + type = Type.GetType(themetype); + } + System.Reflection.PropertyInfo property = type.GetProperty("Panes"); + page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); + page.ViewPermissions = viewpermissions; + page.EditPermissions = editpermissions; + await PageService.UpdatePageAsync(page); + + PageState.Reload = Constants.ReloadSite; + UriHelper.NavigateTo(NavigateUrl(path)); } - else + catch (Exception ex) { - p.ParentId = Int32.Parse(parentid); + message = ex.Message; } - p.Name = name; - p.Path = path; - p.Order = (order == null ? 1 : Int32.Parse(order)); - p.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation)); - p.ThemeType = themetype; - p.LayoutType = (layouttype == null ? "" : layouttype); - p.Icon = (icon == null ? "" : icon); - Type type; - if (!string.IsNullOrEmpty(layouttype)) - { - type = Type.GetType(layouttype); - } - else - { - type = Type.GetType(themetype); - } - System.Reflection.PropertyInfo property = type.GetProperty("Panes"); - p.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - p.ViewPermissions = viewpermissions; - p.EditPermissions = editpermissions; - await PageService.UpdatePageAsync(p); - UriHelper.NavigateTo(NavigateUrl(path)); } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Index.razor b/Oqtane.Client/Modules/Admin/Pages/Index.razor index e1c55bf9..f150ab34 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Index.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Index.razor @@ -3,7 +3,6 @@ @using Oqtane.Modules @using Oqtane.Client.Modules.Controls @inherits ModuleBase - @inject IPageService PageService @if (PageState.Pages == null) @@ -12,27 +11,28 @@ } else { + - + + - @foreach (var p in PageState.Pages) + @foreach (Page page in PageState.Pages) { - - - - + + + + } -
   Path Name
@p.Path@p.Name@(page.Path)@(page.Name)
- + } @code { diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index 72bd6f26..3dc6ae12 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -7,7 +7,7 @@ @if (authorized) { - @text + @text } @code { @@ -21,12 +21,16 @@ public string Parameters { get; set; } // optional [Parameter] - public string ButtonClass { get; set; } // optional + public string Class { get; set; } // optional + + [Parameter] + public string Style { get; set; } // optional string text = ""; string url = ""; string parameters = ""; - string buttonClass = "btn btn-primary"; + string classname = "btn btn-primary"; + string style = ""; bool authorized = false; protected override void OnInitialized() @@ -42,9 +46,14 @@ parameters = Parameters; } - if (!string.IsNullOrEmpty(ButtonClass)) + if (!string.IsNullOrEmpty(Class)) { - buttonClass = "btn " + ButtonClass; + classname = Class; + } + + if (!string.IsNullOrEmpty(Style)) + { + style = Style; } url = EditUrl(Action, parameters); diff --git a/Oqtane.Client/Modules/Controls/AuditInfo.razor b/Oqtane.Client/Modules/Controls/AuditInfo.razor new file mode 100644 index 00000000..d4358070 --- /dev/null +++ b/Oqtane.Client/Modules/Controls/AuditInfo.razor @@ -0,0 +1,55 @@ +@using Oqtane.Modules +@inherits ModuleBase + +@((MarkupString)@text) + +@code { + [Parameter] + public string CreatedBy { get; set; } + + [Parameter] + public DateTime CreatedOn { get; set; } + + [Parameter] + public string ModifiedBy { get; set; } + + [Parameter] + public DateTime ModifiedOn { get; set; } + + [Parameter] + public string Style { get; set; } + + string text = ""; + string style = ""; + + protected override void OnInitialized() + { + if (!String.IsNullOrEmpty(CreatedBy) || CreatedOn != null) + { + text += "

Created "; + if (!String.IsNullOrEmpty(CreatedBy)) + { + text += " by " + CreatedBy + ""; + } + if (CreatedOn != null) + { + text += " on " + CreatedOn.ToString("MMM dd yyyy HH:mm:ss") + ""; + } + text += "

"; + } + + if (!String.IsNullOrEmpty(ModifiedBy) || ModifiedOn != null) + { + text += "

Last modified "; + if (!String.IsNullOrEmpty(ModifiedBy)) + { + text += " by " + ModifiedBy + ""; + } + if (ModifiedOn != null) + { + text += " on " + ModifiedOn.ToString("MMM dd yyyy HH:mm:ss") + ""; + } + text += "

"; + } + } +} From f037898c6e7776497eecd03da3836869ddd14610 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Sun, 25 Aug 2019 14:52:25 -0400 Subject: [PATCH 26/44] Multi-tenant role authorization --- Oqtane.Client/Modules/Admin/Login/Index.razor | 46 +++--- Oqtane.Client/Modules/Admin/Pages/Add.razor | 15 +- .../Modules/Admin/Pages/Delete.razor | 18 ++- Oqtane.Client/Modules/Admin/Pages/Edit.razor | 18 ++- .../Modules/Controls/AuditInfo.razor | 1 - .../IdentityAuthenticationStateProvider.cs | 22 ++- .../Services/Interfaces/IUserService.cs | 2 +- Oqtane.Client/Services/ServiceBase.cs | 2 +- Oqtane.Client/Services/UserService.cs | 4 +- Oqtane.Client/Shared/Utilities.cs | 10 +- Oqtane.Client/Themes/Controls/Login.razor | 2 +- Oqtane.Server/Controllers/AliasController.cs | 4 + Oqtane.Server/Controllers/ModuleController.cs | 4 + Oqtane.Server/Controllers/PageController.cs | 4 + .../Controllers/PageModuleController.cs | 4 + Oqtane.Server/Controllers/RoleController.cs | 4 + .../Controllers/SettingController.cs | 4 + Oqtane.Server/Controllers/SiteController.cs | 4 + Oqtane.Server/Controllers/TenantController.cs | 4 + Oqtane.Server/Controllers/UserController.cs | 92 +++++++----- .../Controllers/UserRoleController.cs | 4 + .../Controllers/HtmlTextController.cs | 4 + Oqtane.Server/Pages/Login.cshtml.cs | 25 +--- Oqtane.Server/Pages/Logout.cshtml.cs | 7 +- .../Repository/Context/DBContextBase.cs | 2 +- .../Repository/Interfaces/ITenantResolver.cs | 1 + .../Interfaces/IUserRoleRepository.cs | 1 + Oqtane.Server/Repository/TenantResolver.cs | 17 ++- .../Repository/UserRoleRepository.cs | 15 ++ Oqtane.Server/Scripts/00.00.00.sql | 4 +- Oqtane.Server/Scripts/00.00.01.sql | 140 ++---------------- .../Security/ClaimsPrincipalFactory.cs | 50 +++++++ Oqtane.Server/Startup.cs | 27 +++- Oqtane.Shared/Models/User.cs | 3 - 34 files changed, 312 insertions(+), 252 deletions(-) create mode 100644 Oqtane.Server/Security/ClaimsPrincipalFactory.cs diff --git a/Oqtane.Client/Modules/Admin/Login/Index.razor b/Oqtane.Client/Modules/Admin/Login/Index.razor index 1e0dde3e..5f852efa 100644 --- a/Oqtane.Client/Modules/Admin/Login/Index.razor +++ b/Oqtane.Client/Modules/Admin/Login/Index.razor @@ -51,20 +51,20 @@ private async Task Login() { - User user = new User(); - user.SiteId = PageState.Site.SiteId; - user.Username = Username; - user.Password = Password; - user.IsPersistent = Remember; - user = await UserService.LoginUserAsync(user); - if (user.IsAuthenticated) - { - string ReturnUrl = PageState.QueryString["returnurl"]; + string ReturnUrl = PageState.QueryString["returnurl"]; - var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider)); - if (authstateprovider == null) + var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider)); + if (authstateprovider == null) + { + // server-side Blazor + User user = new User(); + user.SiteId = PageState.Site.SiteId; + user.Username = Username; + user.Password = Password; + user = await UserService.LoginUserAsync(user, false, false); + if (user.IsAuthenticated) { - // server-side Blazor + // complete the login on the server so that the cookies are set correctly on SignalR var interop = new Interop(jsRuntime); string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken"); var fields = new { __RequestVerificationToken = antiforgerytoken, username = Username, password = Password, remember = Remember, returnurl = ReturnUrl }; @@ -72,15 +72,27 @@ } else { - // client-side Blazor - authstateprovider.NotifyAuthenticationChanged(); - PageState.Reload = Constants.ReloadPage; - UriHelper.NavigateTo(NavigateUrl(ReturnUrl)); + Message = "
Login Failed. Please Remember That Passwords Are Case Sensitive.
"; } } else { - Message = "
Login Failed. Please Remember That Passwords Are Case Sensitive.
"; + // client-side Blazor + User user = new User(); + user.SiteId = PageState.Site.SiteId; + user.Username = Username; + user.Password = Password; + user = await UserService.LoginUserAsync(user, true, Remember); + if (user.IsAuthenticated) + { + authstateprovider.NotifyAuthenticationChanged(); + PageState.Reload = Constants.ReloadSite; + UriHelper.NavigateTo(NavigateUrl(ReturnUrl)); + } + else + { + Message = "
Login Failed. Please Remember That Passwords Are Case Sensitive.
"; + } } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index 8c07b2bc..ab6fbca1 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -8,7 +8,7 @@ @inject IPageService PageService @inject IThemeService ThemeService -@message +@((MarkupString)message) @@ -144,7 +144,7 @@ } catch (Exception ex) { - message = ex.Message; + message = "
" + ex.Message + "


"; } } @@ -185,11 +185,18 @@ await PageService.AddPageAsync(page); PageState.Reload = Constants.ReloadSite; - UriHelper.NavigateTo(NavigateUrl(path)); + if (PageState.Page.Name == "Page Management") + { + UriHelper.NavigateTo(NavigateUrl()); + } + else + { + UriHelper.NavigateTo(NavigateUrl(path)); + } } catch (Exception ex) { - message = ex.Message; + message = "
" + ex.Message + "


"; } } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index 85703eb7..97d56b58 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -9,7 +9,7 @@ @inject IPageService PageService @inject IThemeService ThemeService -@message +@((MarkupString)message)
@@ -116,7 +116,8 @@
Cancel -

+
+
@code { @@ -172,7 +173,7 @@ } catch (Exception ex) { - message = ex.Message; + message = "
" + ex.Message + "


"; } } @@ -182,11 +183,18 @@ { await PageService.DeletePageAsync(Int32.Parse(PageState.QueryString["id"])); PageState.Reload = Constants.ReloadSite; - UriHelper.NavigateTo(NavigateUrl()); + if (PageState.Page.Name == "Page Management") + { + UriHelper.NavigateTo(NavigateUrl()); + } + else + { + UriHelper.NavigateTo(NavigateUrl("")); + } } catch (Exception ex) { - message = ex.Message; + message = "
" + ex.Message + "


"; } } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 88163633..5661b344 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -9,7 +9,7 @@ @inject IPageService PageService @inject IThemeService ThemeService -@message +@((MarkupString)message) @@ -116,7 +116,8 @@
Cancel -

+
+
@code { @@ -179,7 +180,7 @@ } catch (Exception ex) { - message = ex.Message; + message = "
" + ex.Message + "


"; } } @@ -220,11 +221,18 @@ await PageService.UpdatePageAsync(page); PageState.Reload = Constants.ReloadSite; - UriHelper.NavigateTo(NavigateUrl(path)); + if (PageState.Page.Name == "Page Management") + { + UriHelper.NavigateTo(NavigateUrl()); + } + else + { + UriHelper.NavigateTo(NavigateUrl(path)); + } } catch (Exception ex) { - message = ex.Message; + message = "
" + ex.Message + "


"; } } } diff --git a/Oqtane.Client/Modules/Controls/AuditInfo.razor b/Oqtane.Client/Modules/Controls/AuditInfo.razor index d4358070..f03a832b 100644 --- a/Oqtane.Client/Modules/Controls/AuditInfo.razor +++ b/Oqtane.Client/Modules/Controls/AuditInfo.razor @@ -20,7 +20,6 @@ public string Style { get; set; } string text = ""; - string style = ""; protected override void OnInitialized() { diff --git a/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs b/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs index 9ad5b1c7..083aa7c5 100644 --- a/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs +++ b/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs @@ -4,29 +4,39 @@ using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using Oqtane.Models; +using Oqtane.Services; +using Oqtane.Shared; namespace Oqtane.Providers { public class IdentityAuthenticationStateProvider : AuthenticationStateProvider { private readonly IUriHelper urihelper; + private readonly SiteState sitestate; - public IdentityAuthenticationStateProvider(IUriHelper urihelper) + public IdentityAuthenticationStateProvider(IUriHelper urihelper, SiteState sitestate) { this.urihelper = urihelper; + this.sitestate = sitestate; } public override async Task GetAuthenticationStateAsync() { // hack: create a new HttpClient rather than relying on the registered service as the AuthenticationStateProvider is initialized prior to IUriHelper ( https://github.com/aspnet/AspNetCore/issues/11867 ) HttpClient http = new HttpClient(); - Uri uri = new Uri(urihelper.GetAbsoluteUri()); - string apiurl = uri.Scheme + "://" + uri.Authority + "/~/api/User/authenticate"; + string apiurl = ServiceBase.CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "User") + "/authenticate"; User user = await http.GetJsonAsync(apiurl); - var identity = user.IsAuthenticated - ? new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, user.Username) }, "Identity.Application") - : new ClaimsIdentity(); + ClaimsIdentity identity = new ClaimsIdentity(); + if (user.IsAuthenticated) + { + identity = new ClaimsIdentity("Identity.Application"); + identity.AddClaim(new Claim(ClaimTypes.Name, user.Username)); + foreach(string role in user.Roles.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) + { + identity.AddClaim(new Claim(ClaimTypes.Role, role)); + } + } return new AuthenticationState(new ClaimsPrincipal(identity)); } diff --git a/Oqtane.Client/Services/Interfaces/IUserService.cs b/Oqtane.Client/Services/Interfaces/IUserService.cs index 6ffc4991..e1626201 100644 --- a/Oqtane.Client/Services/Interfaces/IUserService.cs +++ b/Oqtane.Client/Services/Interfaces/IUserService.cs @@ -18,7 +18,7 @@ namespace Oqtane.Services Task DeleteUserAsync(int UserId); - Task LoginUserAsync(User User); + Task LoginUserAsync(User User, bool SetCookie, bool IsPersistent); Task LogoutUserAsync(); diff --git a/Oqtane.Client/Services/ServiceBase.cs b/Oqtane.Client/Services/ServiceBase.cs index b970c373..b7cf911b 100644 --- a/Oqtane.Client/Services/ServiceBase.cs +++ b/Oqtane.Client/Services/ServiceBase.cs @@ -8,7 +8,7 @@ namespace Oqtane.Services public class ServiceBase { - public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName) + public static string CreateApiUrl(Alias alias, string absoluteUri, string serviceName) { string apiurl = ""; if (alias != null) diff --git a/Oqtane.Client/Services/UserService.cs b/Oqtane.Client/Services/UserService.cs index 333f1cdf..ec35fc39 100644 --- a/Oqtane.Client/Services/UserService.cs +++ b/Oqtane.Client/Services/UserService.cs @@ -57,9 +57,9 @@ namespace Oqtane.Services await http.DeleteAsync(apiurl + "/" + UserId.ToString()); } - public async Task LoginUserAsync(User User) + public async Task LoginUserAsync(User User, bool SetCookie, bool IsPersistent) { - return await http.PostJsonAsync(apiurl + "/login", User); + return await http.PostJsonAsync(apiurl + "/login?setcookie=" + SetCookie.ToString() + "&persistent =" + IsPersistent.ToString(), User); } public async Task LogoutUserAsync() diff --git a/Oqtane.Client/Shared/Utilities.cs b/Oqtane.Client/Shared/Utilities.cs index 72518271..fc4524f7 100644 --- a/Oqtane.Client/Shared/Utilities.cs +++ b/Oqtane.Client/Shared/Utilities.cs @@ -13,10 +13,14 @@ namespace Oqtane.Shared { url += alias + "/"; } - if (path != "") + if (path != "" && path != "/") { url += path + "/"; } + if (url.EndsWith("/")) + { + url = url.Substring(0, url.Length - 1); + } if (!string.IsNullOrEmpty(parameters)) { url += "?" + parameters; @@ -31,10 +35,6 @@ namespace Oqtane.Shared public static string EditUrl(string alias, string path, int moduleid, string action, string parameters) { string url = NavigateUrl(alias, path, ""); - if ( url == "/" ) - { - url = ""; - } if (moduleid != -1) { url += "/" + moduleid.ToString(); diff --git a/Oqtane.Client/Themes/Controls/Login.razor b/Oqtane.Client/Themes/Controls/Login.razor index 811febd9..faba904d 100644 --- a/Oqtane.Client/Themes/Controls/Login.razor +++ b/Oqtane.Client/Themes/Controls/Login.razor @@ -51,7 +51,7 @@ // client-side Blazor authstateprovider.NotifyAuthenticationChanged(); PageState.Reload = Constants.ReloadSite; - UriHelper.NavigateTo(NavigateUrl(PageState.Page.Path)); + UriHelper.NavigateTo(NavigateUrl(PageState.Page.Path, "logout")); } } } diff --git a/Oqtane.Server/Controllers/AliasController.cs b/Oqtane.Server/Controllers/AliasController.cs index 86ff6a04..f09fa92d 100644 --- a/Oqtane.Server/Controllers/AliasController.cs +++ b/Oqtane.Server/Controllers/AliasController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -31,6 +32,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public Alias Post([FromBody] Alias Alias) { if (ModelState.IsValid) @@ -42,6 +44,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public Alias Put(int id, [FromBody] Alias Alias) { if (ModelState.IsValid) @@ -52,6 +55,7 @@ namespace Oqtane.Controllers } // DELETE api//5 + [Authorize] [HttpDelete("{id}")] public void Delete(int id) { diff --git a/Oqtane.Server/Controllers/ModuleController.cs b/Oqtane.Server/Controllers/ModuleController.cs index ef819edc..2a9045db 100644 --- a/Oqtane.Server/Controllers/ModuleController.cs +++ b/Oqtane.Server/Controllers/ModuleController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -53,6 +54,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public Module Post([FromBody] Module Module) { if (ModelState.IsValid) @@ -64,6 +66,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public Module Put(int id, [FromBody] Module Module) { if (ModelState.IsValid) @@ -75,6 +78,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { Modules.DeleteModule(id); diff --git a/Oqtane.Server/Controllers/PageController.cs b/Oqtane.Server/Controllers/PageController.cs index 96ef61af..03c140e6 100644 --- a/Oqtane.Server/Controllers/PageController.cs +++ b/Oqtane.Server/Controllers/PageController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -38,6 +39,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize(Roles = "Administrators")] public Page Post([FromBody] Page Page) { if (ModelState.IsValid) @@ -49,6 +51,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize(Roles = "Administrators")] public Page Put(int id, [FromBody] Page Page) { if (ModelState.IsValid) @@ -60,6 +63,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize(Roles = "Administrators")] public void Delete(int id) { Pages.DeletePage(id); diff --git a/Oqtane.Server/Controllers/PageModuleController.cs b/Oqtane.Server/Controllers/PageModuleController.cs index fa99465e..ae4f41e8 100644 --- a/Oqtane.Server/Controllers/PageModuleController.cs +++ b/Oqtane.Server/Controllers/PageModuleController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -31,6 +32,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public PageModule Post([FromBody] PageModule PageModule) { if (ModelState.IsValid) @@ -42,6 +44,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public PageModule Put(int id, [FromBody] PageModule PageModule) { if (ModelState.IsValid) @@ -53,6 +56,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { PageModules.DeletePageModule(id); diff --git a/Oqtane.Server/Controllers/RoleController.cs b/Oqtane.Server/Controllers/RoleController.cs index 85f32f55..f94dbcb9 100644 --- a/Oqtane.Server/Controllers/RoleController.cs +++ b/Oqtane.Server/Controllers/RoleController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -38,6 +39,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public Role Post([FromBody] Role Role) { if (ModelState.IsValid) @@ -49,6 +51,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public Role Put(int id, [FromBody] Role Role) { if (ModelState.IsValid) @@ -60,6 +63,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { Roles.DeleteRole(id); diff --git a/Oqtane.Server/Controllers/SettingController.cs b/Oqtane.Server/Controllers/SettingController.cs index 2f90efd9..4c674138 100644 --- a/Oqtane.Server/Controllers/SettingController.cs +++ b/Oqtane.Server/Controllers/SettingController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -31,6 +32,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public Setting Post([FromBody] Setting Setting) { if (ModelState.IsValid) @@ -42,6 +44,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public Setting Put(int id, [FromBody] Setting Setting) { if (ModelState.IsValid) @@ -53,6 +56,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { Settings.DeleteSetting(id); diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs index b5892ec6..4377b67a 100644 --- a/Oqtane.Server/Controllers/SiteController.cs +++ b/Oqtane.Server/Controllers/SiteController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -31,6 +32,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public Site Post([FromBody] Site Site) { if (ModelState.IsValid) @@ -42,6 +44,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public Site Put(int id, [FromBody] Site Site) { if (ModelState.IsValid) @@ -53,6 +56,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { Sites.DeleteSite(id); diff --git a/Oqtane.Server/Controllers/TenantController.cs b/Oqtane.Server/Controllers/TenantController.cs index e56d86ee..c3f41289 100644 --- a/Oqtane.Server/Controllers/TenantController.cs +++ b/Oqtane.Server/Controllers/TenantController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; using System.Collections.Generic; @@ -31,6 +32,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public Tenant Post([FromBody] Tenant Tenant) { if (ModelState.IsValid) @@ -42,6 +44,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public Tenant Put(int id, [FromBody] Tenant Tenant) { if (ModelState.IsValid) @@ -53,6 +56,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { Tenants.DeleteTenant(id); diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs index 914e23e7..c64fd905 100644 --- a/Oqtane.Server/Controllers/UserController.cs +++ b/Oqtane.Server/Controllers/UserController.cs @@ -1,10 +1,13 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; using System.Linq; +using System.Security.Claims; namespace Oqtane.Controllers { @@ -105,21 +108,23 @@ namespace Oqtane.Controllers if (result.Succeeded) { user = Users.AddUser(User); - - SiteUser siteuser = new SiteUser(); - siteuser.SiteId = User.SiteId; - siteuser.UserId = user.UserId; - SiteUsers.AddSiteUser(siteuser); - - List roles = Roles.GetRoles(user.SiteId).Where(item => item.IsAutoAssigned == true).ToList(); - foreach (Role role in roles) + if (!user.IsSuperUser) { - UserRole userrole = new UserRole(); - userrole.UserId = user.UserId; - userrole.RoleId = role.RoleId; - userrole.EffectiveDate = null; - userrole.ExpiryDate = null; - UserRoles.AddUserRole(userrole); + SiteUser siteuser = new SiteUser(); + siteuser.SiteId = User.SiteId; + siteuser.UserId = user.UserId; + SiteUsers.AddSiteUser(siteuser); + + List roles = Roles.GetRoles(user.SiteId).Where(item => item.IsAutoAssigned == true).ToList(); + foreach (Role role in roles) + { + UserRole userrole = new UserRole(); + userrole.UserId = user.UserId; + userrole.RoleId = role.RoleId; + userrole.EffectiveDate = null; + userrole.ExpiryDate = null; + UserRoles.AddUserRole(userrole); + } } } } @@ -129,20 +134,23 @@ namespace Oqtane.Controllers SiteUser siteuser = SiteUsers.GetSiteUser(User.SiteId, user.UserId); if (siteuser == null) { - siteuser = new SiteUser(); - siteuser.SiteId = User.SiteId; - siteuser.UserId = user.UserId; - SiteUsers.AddSiteUser(siteuser); - - List roles = Roles.GetRoles(User.SiteId).Where(item => item.IsAutoAssigned == true).ToList(); - foreach (Role role in roles) + if (!user.IsSuperUser) { - UserRole userrole = new UserRole(); - userrole.UserId = user.UserId; - userrole.RoleId = role.RoleId; - userrole.EffectiveDate = null; - userrole.ExpiryDate = null; - UserRoles.AddUserRole(userrole); + siteuser = new SiteUser(); + siteuser.SiteId = User.SiteId; + siteuser.UserId = user.UserId; + SiteUsers.AddSiteUser(siteuser); + + List roles = Roles.GetRoles(User.SiteId).Where(item => item.IsAutoAssigned == true).ToList(); + foreach (Role role in roles) + { + UserRole userrole = new UserRole(); + userrole.UserId = user.UserId; + userrole.RoleId = role.RoleId; + userrole.EffectiveDate = null; + userrole.ExpiryDate = null; + UserRoles.AddUserRole(userrole); + } } } } @@ -153,6 +161,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public User Put(int id, [FromBody] User User) { if (ModelState.IsValid) @@ -164,6 +173,7 @@ namespace Oqtane.Controllers // DELETE api//5?siteid=x [HttpDelete("{id}")] + [Authorize] public void Delete(int id, string siteid) { SiteUser siteuser = SiteUsers.GetSiteUser(id, int.Parse(siteid)); @@ -175,7 +185,7 @@ namespace Oqtane.Controllers // POST api//login [HttpPost("login")] - public async Task Login([FromBody] User User) + public async Task Login([FromBody] User User, bool SetCookie, bool IsPersistent) { User user = new Models.User { Username = User.Username, IsAuthenticated = false }; @@ -202,9 +212,9 @@ namespace Oqtane.Controllers { user.IsAuthenticated = true; } - if (user.IsAuthenticated) + if (user.IsAuthenticated && SetCookie) { - await IdentitySignInManager.SignInAsync(identityuser, User.IsPersistent); + await IdentitySignInManager.SignInAsync(identityuser, IsPersistent); } } } @@ -216,28 +226,36 @@ namespace Oqtane.Controllers // POST api//logout [HttpPost("logout")] + [Authorize] public async Task Logout([FromBody] User User) { - await IdentitySignInManager.SignOutAsync(); + await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); } // GET api//current [HttpGet("authenticate")] public User Authenticate() { - return new User { Username = User.Identity.Name, IsAuthenticated = User.Identity.IsAuthenticated }; + User user = new User(); + user.Username = User.Identity.Name; + user.IsAuthenticated = User.Identity.IsAuthenticated; + string roles = ""; + foreach (var claim in User.Claims.Where(item => item.Type == ClaimTypes.Role)) + { + roles += claim.Value + ";"; + } + if (roles != "") roles = ";" + roles; + user.Roles = roles; + return user; } private string GetUserRoles(int UserId, int SiteId) { string roles = ""; - IEnumerable userroles = UserRoles.GetUserRoles(UserId); + IEnumerable userroles = UserRoles.GetUserRoles(UserId, SiteId); foreach (UserRole userrole in userroles) { - if (userrole.Role.SiteId == SiteId) - { - roles += userrole.Role.Name + ";"; - } + roles += userrole.Role.Name + ";"; } if (roles != "") roles = ";" + roles; return roles; diff --git a/Oqtane.Server/Controllers/UserRoleController.cs b/Oqtane.Server/Controllers/UserRoleController.cs index 8865e763..36f6879d 100644 --- a/Oqtane.Server/Controllers/UserRoleController.cs +++ b/Oqtane.Server/Controllers/UserRoleController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; @@ -38,6 +39,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] + [Authorize] public UserRole Post([FromBody] UserRole UserRole) { if (ModelState.IsValid) @@ -49,6 +51,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public UserRole Put(int id, [FromBody] UserRole UserRole) { if (ModelState.IsValid) @@ -60,6 +63,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { UserRoles.DeleteUserRole(id); diff --git a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs index 695e460b..6a0119d1 100644 --- a/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs +++ b/Oqtane.Server/Modules/HtmlText/Controllers/HtmlTextController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; using Oqtane.Shared.Modules.HtmlText.Models; using Oqtane.Server.Modules.HtmlText.Repository; @@ -24,6 +25,7 @@ namespace Oqtane.Server.Modules.HtmlText.Controllers // POST api/ [HttpPost] + [Authorize] public HtmlTextInfo Post([FromBody] HtmlTextInfo HtmlText) { if (ModelState.IsValid) @@ -35,6 +37,7 @@ namespace Oqtane.Server.Modules.HtmlText.Controllers // PUT api//5 [HttpPut("{id}")] + [Authorize] public HtmlTextInfo Put(int id, [FromBody] HtmlTextInfo HtmlText) { if (ModelState.IsValid) @@ -46,6 +49,7 @@ namespace Oqtane.Server.Modules.HtmlText.Controllers // DELETE api//5 [HttpDelete("{id}")] + [Authorize] public void Delete(int id) { htmltext.DeleteHtmlText(id); diff --git a/Oqtane.Server/Pages/Login.cshtml.cs b/Oqtane.Server/Pages/Login.cshtml.cs index cc1877cc..4c08b1d5 100644 --- a/Oqtane.Server/Pages/Login.cshtml.cs +++ b/Oqtane.Server/Pages/Login.cshtml.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; @@ -14,24 +10,22 @@ namespace Oqtane.Pages public class LoginModel : PageModel { - private readonly UserManager identityUserManager; - private readonly SignInManager identitySignInManager; + private readonly UserManager IdentityUserManager; + private readonly SignInManager IdentitySignInManager; public LoginModel(UserManager IdentityUserManager, SignInManager IdentitySignInManager) { - identityUserManager = IdentityUserManager; - identitySignInManager = IdentitySignInManager; + this.IdentityUserManager = IdentityUserManager; + this.IdentitySignInManager = IdentitySignInManager; } public async Task OnPostAsync(string username, string password, bool remember, string returnurl) { - await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); - bool validuser = false; - IdentityUser identityuser = await identityUserManager.FindByNameAsync(username); + IdentityUser identityuser = await IdentityUserManager.FindByNameAsync(username); if (identityuser != null) { - var result = await identitySignInManager.CheckPasswordSignInAsync(identityuser, password, false); + var result = await IdentitySignInManager.CheckPasswordSignInAsync(identityuser, password, false); if (result.Succeeded) { validuser = true; @@ -40,10 +34,7 @@ namespace Oqtane.Pages if (validuser) { - var claims = new List{ new Claim(ClaimTypes.Name, username) }; - var claimsIdentity = new ClaimsIdentity(claims, IdentityConstants.ApplicationScheme); - var authProperties = new AuthenticationProperties{IsPersistent = remember}; - await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); + await IdentitySignInManager.SignInAsync(identityuser, remember); } return LocalRedirect(Url.Content("~" + returnurl)); diff --git a/Oqtane.Server/Pages/Logout.cshtml.cs b/Oqtane.Server/Pages/Logout.cshtml.cs index d976f39d..e4629619 100644 --- a/Oqtane.Server/Pages/Logout.cshtml.cs +++ b/Oqtane.Server/Pages/Logout.cshtml.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Oqtane.Models; namespace Oqtane.Pages { diff --git a/Oqtane.Server/Repository/Context/DBContextBase.cs b/Oqtane.Server/Repository/Context/DBContextBase.cs index a6b07ac4..0b12b6d7 100644 --- a/Oqtane.Server/Repository/Context/DBContextBase.cs +++ b/Oqtane.Server/Repository/Context/DBContextBase.cs @@ -8,7 +8,7 @@ using System.Linq; namespace Oqtane.Repository { - public class DBContextBase : IdentityDbContext + public class DBContextBase : IdentityUserContext { private Tenant tenant; private IHttpContextAccessor accessor; diff --git a/Oqtane.Server/Repository/Interfaces/ITenantResolver.cs b/Oqtane.Server/Repository/Interfaces/ITenantResolver.cs index e665d76c..95e916f7 100644 --- a/Oqtane.Server/Repository/Interfaces/ITenantResolver.cs +++ b/Oqtane.Server/Repository/Interfaces/ITenantResolver.cs @@ -4,6 +4,7 @@ namespace Oqtane.Repository { public interface ITenantResolver { + Alias GetAlias(); Tenant GetTenant(); } } diff --git a/Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs b/Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs index fad2f850..d2141a13 100644 --- a/Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/IUserRoleRepository.cs @@ -7,6 +7,7 @@ namespace Oqtane.Repository { IEnumerable GetUserRoles(); IEnumerable GetUserRoles(int UserId); + IEnumerable GetUserRoles(int UserId, int SiteId); UserRole AddUserRole(UserRole UserRole); UserRole UpdateUserRole(UserRole UserRole); UserRole GetUserRole(int UserRoleId); diff --git a/Oqtane.Server/Repository/TenantResolver.cs b/Oqtane.Server/Repository/TenantResolver.cs index 08c553c2..35d4b0ab 100644 --- a/Oqtane.Server/Repository/TenantResolver.cs +++ b/Oqtane.Server/Repository/TenantResolver.cs @@ -32,14 +32,25 @@ namespace Oqtane.Repository } } - public Tenant GetTenant() + public Alias GetAlias() { try { IEnumerable aliases = _aliasrepository.GetAliases(); // cached - Alias alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault(); + return aliases.Where(item => item.Name == aliasname).FirstOrDefault(); + } + catch + { + throw; + } + } + + public Tenant GetTenant() + { + try + { IEnumerable tenants = _tenantrepository.GetTenants(); // cached - return tenants.Where(item => item.TenantId == alias.TenantId).FirstOrDefault(); + return tenants.Where(item => item.TenantId == GetAlias().TenantId).FirstOrDefault(); } catch { diff --git a/Oqtane.Server/Repository/UserRoleRepository.cs b/Oqtane.Server/Repository/UserRoleRepository.cs index 8e095ffb..82911356 100644 --- a/Oqtane.Server/Repository/UserRoleRepository.cs +++ b/Oqtane.Server/Repository/UserRoleRepository.cs @@ -39,6 +39,21 @@ namespace Oqtane.Repository } } + public IEnumerable GetUserRoles(int UserId, int SiteId) + { + try + { + return db.UserRole.Where(item => item.UserId == UserId) + .Include(item => item.Role) // eager load roles + .Where(item => item.Role.SiteId == SiteId) + .ToList(); + } + catch + { + throw; + } + } + public UserRole AddUserRole(UserRole UserRole) { try diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql index d047d5f8..fe02870e 100644 --- a/Oqtane.Server/Scripts/00.00.00.sql +++ b/Oqtane.Server/Scripts/00.00.00.sql @@ -251,7 +251,7 @@ INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [P VALUES (1, 1, N'Page1', N'', N'Oqtane.Client.Themes.Theme1.Theme1, Oqtane.Client', N'oi-home', N'Left;Right', N'All Users', N'Administrators', NULL, 1, 1, N'', '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (2, 1, N'Page2', N'page2', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-plus', N'Top;Bottom', N'Administrators;Editors;', N'Administrators', NULL, 3, 1, N'', '', getdate(), '', getdate()) +VALUES (2, 1, N'Page2', N'page2', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'oi-plus', N'Top;Bottom', N'Administrators', N'Administrators', NULL, 3, 1, N'', '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ViewPermissions], [EditPermissions], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (3, 1, N'Page3', N'page3', N'Oqtane.Client.Themes.Theme3.Theme3, Oqtane.Client', N'oi-list-rich', N'Left;Right', N'All Users', N'Administrators', NULL, 3, 1, N'Oqtane.Client.Themes.Theme3.HorizontalLayout, Oqtane.Client', '', getdate(), '', getdate()) @@ -319,7 +319,7 @@ INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermis VALUES (6, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'All Users', N'Administrators', '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) -VALUES (7, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'Administrators;Editors;Members;', N'Administrators;Editors;', '', getdate(), '', getdate()) +VALUES (7, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [ViewPermissions], [EditPermissions], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (8, 1, N'Oqtane.Client.Modules.Admin.Pages, Oqtane.Client', N'Administrators', N'Administrators', '', getdate(), '', getdate()) diff --git a/Oqtane.Server/Scripts/00.00.01.sql b/Oqtane.Server/Scripts/00.00.01.sql index 45f9cd66..90118490 100644 --- a/Oqtane.Server/Scripts/00.00.01.sql +++ b/Oqtane.Server/Scripts/00.00.01.sql @@ -1,62 +1,8 @@ -CREATE TABLE [dbo].[AspNetRoleClaims]( - [Id] [int] IDENTITY(1,1) NOT NULL, - [RoleId] [nvarchar](450) NOT NULL, - [ClaimType] [nvarchar](max) NULL, - [ClaimValue] [nvarchar](max) NULL, - CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY CLUSTERED -( - [Id] ASC -) ON [PRIMARY] -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] -GO +/* -CREATE TABLE [dbo].[AspNetRoles]( - [Id] [nvarchar](450) NOT NULL, - [Name] [nvarchar](256) NULL, - [NormalizedName] [nvarchar](256) NULL, - [ConcurrencyStamp] [nvarchar](max) NULL, - CONSTRAINT [PK_AspNetRoles] PRIMARY KEY CLUSTERED -( - [Id] ASC -) ON [PRIMARY] -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] -GO +ASP.NET Identity Minimal Schema -CREATE TABLE [dbo].[AspNetUserClaims]( - [Id] [int] IDENTITY(1,1) NOT NULL, - [UserId] [nvarchar](450) NOT NULL, - [ClaimType] [nvarchar](max) NULL, - [ClaimValue] [nvarchar](max) NULL, - CONSTRAINT [PK_AspNetUserClaims] PRIMARY KEY CLUSTERED -( - [Id] ASC -) ON [PRIMARY] -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] -GO - -CREATE TABLE [dbo].[AspNetUserLogins]( - [LoginProvider] [nvarchar](128) NOT NULL, - [ProviderKey] [nvarchar](128) NOT NULL, - [ProviderDisplayName] [nvarchar](max) NULL, - [UserId] [nvarchar](450) NOT NULL, - CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY CLUSTERED -( - [LoginProvider] ASC, - [ProviderKey] ASC -) ON [PRIMARY] -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] -GO - -CREATE TABLE [dbo].[AspNetUserRoles]( - [UserId] [nvarchar](450) NOT NULL, - [RoleId] [nvarchar](450) NOT NULL, - CONSTRAINT [PK_AspNetUserRoles] PRIMARY KEY CLUSTERED -( - [UserId] ASC, - [RoleId] ASC -) ON [PRIMARY] -) ON [PRIMARY] -GO +*/ CREATE TABLE [dbo].[AspNetUsers]( [Id] [nvarchar](450) NOT NULL, @@ -81,52 +27,24 @@ CREATE TABLE [dbo].[AspNetUsers]( ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -CREATE TABLE [dbo].[AspNetUserTokens]( +CREATE TABLE [dbo].[AspNetUserClaims]( + [Id] [int] IDENTITY(1,1) NOT NULL, [UserId] [nvarchar](450) NOT NULL, - [LoginProvider] [nvarchar](128) NOT NULL, - [Name] [nvarchar](128) NOT NULL, - [Value] [nvarchar](max) NULL, - CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY CLUSTERED + [ClaimType] [nvarchar](max) NULL, + [ClaimValue] [nvarchar](max) NULL, + CONSTRAINT [PK_AspNetUserClaims] PRIMARY KEY CLUSTERED ( - [UserId] ASC, - [LoginProvider] ASC, - [Name] ASC + [Id] ASC ) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO -CREATE NONCLUSTERED INDEX [IX_AspNetRoleClaims_RoleId] ON [dbo].[AspNetRoleClaims] -( - [RoleId] ASC -) ON [PRIMARY] -GO - -CREATE UNIQUE NONCLUSTERED INDEX [RoleNameIndex] ON [dbo].[AspNetRoles] -( - [NormalizedName] ASC -) -WHERE ([NormalizedName] IS NOT NULL) - ON [PRIMARY] -GO - CREATE NONCLUSTERED INDEX [IX_AspNetUserClaims_UserId] ON [dbo].[AspNetUserClaims] ( [UserId] ASC ) ON [PRIMARY] GO -CREATE NONCLUSTERED INDEX [IX_AspNetUserLogins_UserId] ON [dbo].[AspNetUserLogins] -( - [UserId] ASC -) ON [PRIMARY] -GO - -CREATE NONCLUSTERED INDEX [IX_AspNetUserRoles_RoleId] ON [dbo].[AspNetUserRoles] -( - [RoleId] ASC -) ON [PRIMARY] -GO - CREATE NONCLUSTERED INDEX [EmailIndex] ON [dbo].[AspNetUsers] ( [NormalizedEmail] ASC @@ -141,14 +59,6 @@ WHERE ([NormalizedUserName] IS NOT NULL) ON [PRIMARY] GO -ALTER TABLE [dbo].[AspNetRoleClaims] WITH CHECK ADD CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY([RoleId]) -REFERENCES [dbo].[AspNetRoles] ([Id]) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[AspNetRoleClaims] CHECK CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] -GO - ALTER TABLE [dbo].[AspNetUserClaims] WITH CHECK ADD CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE @@ -156,35 +66,3 @@ GO ALTER TABLE [dbo].[AspNetUserClaims] CHECK CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] GO - -ALTER TABLE [dbo].[AspNetUserLogins] WITH CHECK ADD CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY([UserId]) -REFERENCES [dbo].[AspNetUsers] ([Id]) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[AspNetUserLogins] CHECK CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] -GO - -ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK ADD CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY([RoleId]) -REFERENCES [dbo].[AspNetRoles] ([Id]) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] -GO - -ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK ADD CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY([UserId]) -REFERENCES [dbo].[AspNetUsers] ([Id]) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] -GO - -ALTER TABLE [dbo].[AspNetUserTokens] WITH CHECK ADD CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY([UserId]) -REFERENCES [dbo].[AspNetUsers] ([Id]) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[AspNetUserTokens] CHECK CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] -GO diff --git a/Oqtane.Server/Security/ClaimsPrincipalFactory.cs b/Oqtane.Server/Security/ClaimsPrincipalFactory.cs new file mode 100644 index 00000000..d62ba167 --- /dev/null +++ b/Oqtane.Server/Security/ClaimsPrincipalFactory.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using System.Security.Claims; +using System.Threading.Tasks; +using Oqtane.Repository; +using Oqtane.Models; + +namespace Oqtane.Security +{ + public class ClaimsPrincipalFactory : UserClaimsPrincipalFactory where TUser : IdentityUser + { + private readonly IdentityOptions options; + private readonly ITenantResolver Tenants; + private readonly IUserRepository Users; + private readonly IUserRoleRepository UserRoles; + + public ClaimsPrincipalFactory(UserManager userManager, IOptions optionsAccessor, ITenantResolver tenants, IUserRepository users, IUserRoleRepository userroles) : base(userManager, optionsAccessor) + { + options = optionsAccessor.Value; + Tenants = tenants; + Users = users; + UserRoles = userroles; + } + + protected override async Task GenerateClaimsAsync(TUser identityuser) + { + var id = await base.GenerateClaimsAsync(identityuser); + + User user = Users.GetUser(identityuser.UserName); + if (user != null) + { + if (user.IsSuperUser) + { + id.AddClaim(new Claim(options.ClaimsIdentity.RoleClaimType, "Administrators")); + } + else + { + Alias alias = Tenants.GetAlias(); + foreach (UserRole userrole in UserRoles.GetUserRoles(user.UserId, alias.SiteId)) + { + id.AddClaim(new Claim(options.ClaimsIdentity.RoleClaimType, userrole.Role.Name)); + } + } + } + + return id; + } + } + +} diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index ebf18df8..a084f410 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -21,6 +21,10 @@ using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Oqtane.Security; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication; +using System.Net; namespace Oqtane.Server { @@ -91,10 +95,11 @@ namespace Oqtane.Server )); services.AddDbContext(options => { }); - services.AddIdentity() + services.AddIdentityCore(options => { }) .AddEntityFrameworkStores() + .AddSignInManager() .AddDefaultTokenProviders(); - + services.Configure(options => { // Password settings @@ -113,6 +118,9 @@ namespace Oqtane.Server options.User.RequireUniqueEmail = false; }); + services.AddAuthentication(IdentityConstants.ApplicationScheme) + .AddCookie(IdentityConstants.ApplicationScheme); + services.ConfigureApplicationCookie(options => { options.Cookie.HttpOnly = false; @@ -123,6 +131,9 @@ namespace Oqtane.Server }; }); + // register custom claims principal factory for role claims + services.AddTransient, ClaimsPrincipalFactory>(); + // get list of loaded assemblies Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); @@ -241,8 +252,9 @@ namespace Oqtane.Server )); services.AddDbContext(options => { }); - services.AddIdentity() + services.AddIdentityCore(options => { }) .AddEntityFrameworkStores() + .AddSignInManager() .AddDefaultTokenProviders(); services.Configure(options => @@ -263,6 +275,9 @@ namespace Oqtane.Server options.User.RequireUniqueEmail = false; }); + services.AddAuthentication(IdentityConstants.ApplicationScheme) + .AddCookie(IdentityConstants.ApplicationScheme); + services.ConfigureApplicationCookie(options => { options.Cookie.HttpOnly = false; @@ -273,7 +288,10 @@ namespace Oqtane.Server }; }); - // get list of loaded assemblies + // register custom claims principal factory for role claims + services.AddTransient, ClaimsPrincipalFactory>(); + + // get list of loaded assemblies Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); // iterate through Oqtane module assemblies in /bin ( filter is narrow to optimize loading process ) @@ -377,5 +395,6 @@ namespace Oqtane.Server }); } #endif + } } diff --git a/Oqtane.Shared/Models/User.cs b/Oqtane.Shared/Models/User.cs index e57f765f..0cd2bcc2 100644 --- a/Oqtane.Shared/Models/User.cs +++ b/Oqtane.Shared/Models/User.cs @@ -23,8 +23,5 @@ namespace Oqtane.Models public string Password { get; set; } [NotMapped] public bool IsAuthenticated { get; set; } - [NotMapped] - public bool IsPersistent { get; set; } - } } From 3ce7f1a227df68d2e64937a5ce7eec148e1b0a03 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Tue, 27 Aug 2019 17:14:41 -0400 Subject: [PATCH 27/44] Permission-based authorization utilizing Policies --- Oqtane.Client/Modules/Admin/Admin/Index.razor | 3 +- .../Modules/Admin/ModuleSettings/Index.razor | 8 +- Oqtane.Client/Modules/Admin/Pages/Add.razor | 12 +- .../Modules/Admin/Pages/Delete.razor | 13 +- Oqtane.Client/Modules/Admin/Pages/Edit.razor | 16 +- Oqtane.Client/Modules/Admin/Pages/Index.razor | 4 +- .../Modules/Admin/Register/Index.razor | 12 +- Oqtane.Client/Modules/Admin/Sites/Add.razor | 5 +- .../Modules/Controls/ActionLink.razor | 12 +- .../Modules/Controls/ModuleMessage.razor | 20 +- .../HtmlText/Services/HtmlTextService.cs | 10 +- .../HtmlText/Services/IHtmlTextService.cs | 2 +- .../IdentityAuthenticationStateProvider.cs | 3 +- .../Services/Interfaces/IUserService.cs | 2 - Oqtane.Client/Services/UserService.cs | 73 ---- Oqtane.Client/Shared/Container.razor | 3 +- Oqtane.Client/Shared/Installer.razor | 14 +- Oqtane.Client/Shared/ModuleInstance.razor | 3 +- Oqtane.Client/Shared/Pane.razor | 15 +- Oqtane.Client/Shared/SiteRouter.razor | 13 +- Oqtane.Client/Shared/Theme.razor | 3 +- Oqtane.Client/Shared/Utilities.cs | 1 + .../Themes/Controls/ControlPanel.razor | 8 +- Oqtane.Client/Themes/Controls/Menu.razor | 3 +- .../Themes/Controls/ModuleActions.razor | 5 +- Oqtane.Server/Controllers/AliasController.cs | 6 +- .../Controllers/InstallationController.cs | 2 - Oqtane.Server/Controllers/ModuleController.cs | 6 +- .../Controllers/PageModuleController.cs | 6 +- .../Controllers/PermissionController.cs | 65 +++ Oqtane.Server/Controllers/RoleController.cs | 6 +- Oqtane.Server/Controllers/UserController.cs | 111 +++-- .../Controllers/UserRoleController.cs | 6 +- .../Controllers/HtmlTextController.cs | 34 +- .../HtmlText/Repository/HtmlTextRepository.cs | 4 +- .../Repository/IHtmlTextRepository.cs | 2 +- .../Repository/Context/TenantDBContext.cs | 1 + .../Interfaces/IPermissionRepository.cs | 19 + Oqtane.Server/Repository/ModuleRepository.cs | 23 +- .../Repository/PageModuleRepository.cs | 25 +- Oqtane.Server/Repository/PageRepository.cs | 23 +- .../Repository/PermissionRepository.cs | 236 +++++++++++ Oqtane.Server/Repository/TenantResolver.cs | 5 +- Oqtane.Server/Scripts/00.00.00.sql | 401 +++++++++++++----- .../Security/ClaimsPrincipalFactory.cs | 7 +- Oqtane.Server/Security/PermissionHandler.cs | 57 +++ .../Security/PermissionRequirement.cs | 17 + Oqtane.Server/Startup.cs | 25 +- Oqtane.Shared/Models/Module.cs | 5 +- Oqtane.Shared/Models/Page.cs | 7 +- Oqtane.Shared/Models/Permission.cs | 23 + Oqtane.Shared/Models/User.cs | 3 +- Oqtane.Shared/Security/UserSecurity.cs | 103 +++++ .../Shared/Constants.cs | 1 + 54 files changed, 1104 insertions(+), 388 deletions(-) create mode 100644 Oqtane.Server/Controllers/PermissionController.cs create mode 100644 Oqtane.Server/Repository/Interfaces/IPermissionRepository.cs create mode 100644 Oqtane.Server/Repository/PermissionRepository.cs create mode 100644 Oqtane.Server/Security/PermissionHandler.cs create mode 100644 Oqtane.Server/Security/PermissionRequirement.cs create mode 100644 Oqtane.Shared/Models/Permission.cs create mode 100644 Oqtane.Shared/Security/UserSecurity.cs rename {Oqtane.Client => Oqtane.Shared}/Shared/Constants.cs (95%) diff --git a/Oqtane.Client/Modules/Admin/Admin/Index.razor b/Oqtane.Client/Modules/Admin/Admin/Index.razor index 9065812c..1717112b 100644 --- a/Oqtane.Client/Modules/Admin/Admin/Index.razor +++ b/Oqtane.Client/Modules/Admin/Admin/Index.razor @@ -2,6 +2,7 @@ @using Oqtane.Modules @using Oqtane.Services @using Oqtane.Models; +@using Oqtane.Security @using Oqtane.Client.Modules.Controls @inherits ModuleBase @inject IPageService PageService @@ -10,7 +11,7 @@
    @foreach (var p in pages) { - if (p.IsNavigation && UserService.IsAuthorized(PageState.User, p.ViewPermissions)) + if (p.IsNavigation && UserSecurity.IsAuthorized(PageState.User, "View", p.Permissions)) { string url = NavigateUrl(p.Path);
  • diff --git a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor index ca8cef80..7eb5154e 100644 --- a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor @@ -3,6 +3,7 @@ @using Oqtane.Models @using Oqtane.Modules @using Oqtane.Shared +@using Oqtane.Security @using Oqtane.Client.Modules.Controls @inherits ModuleBase @inject IUriHelper UriHelper @@ -89,8 +90,8 @@ title = ModuleState.Title; containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync()); containertype = ModuleState.ContainerType; - viewpermissions = ModuleState.ViewPermissions; - editpermissions = ModuleState.EditPermissions; + viewpermissions = UserSecurity.GetPermissions("View", ModuleState.Permissions); + editpermissions = UserSecurity.GetPermissions("Edit", ModuleState.Permissions); pageid = ModuleState.PageId.ToString(); DynamicComponent = builder => @@ -108,8 +109,7 @@ private async Task SaveModule() { Module module = ModuleState; - module.ViewPermissions = viewpermissions; - module.EditPermissions = editpermissions; + module.Permissions = UserSecurity.SetPermissions("View", viewpermissions) + UserSecurity.SetPermissions("Edit", editpermissions); await ModuleService.UpdateModuleAsync(module); PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index ab6fbca1..de65c5ae 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -1,15 +1,16 @@ @using Microsoft.AspNetCore.Components.Routing +@using Oqtane.Client.Modules.Controls @using Oqtane.Models @using Oqtane.Services @using Oqtane.Modules @using Oqtane.Shared +@using Oqtane.Security @inherits ModuleBase @inject IUriHelper UriHelper @inject IPageService PageService @inject IThemeService ThemeService -@((MarkupString)message) - + - - - -
    @@ -144,7 +145,7 @@ } catch (Exception ex) { - message = "
    " + ex.Message + "


    "; + message = ex.Message; } } @@ -180,8 +181,7 @@ } System.Reflection.PropertyInfo property = type.GetProperty("Panes"); page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - page.ViewPermissions = viewpermissions; - page.EditPermissions = editpermissions; + page.Permissions = UserSecurity.SetPermissions("View", viewpermissions) + UserSecurity.SetPermissions("Edit", editpermissions); await PageService.AddPageAsync(page); PageState.Reload = Constants.ReloadSite; @@ -196,7 +196,7 @@ } catch (Exception ex) { - message = "
    " + ex.Message + "


    "; + message = ex.Message; } } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index 97d56b58..bfa1473f 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -1,15 +1,16 @@ @using Microsoft.AspNetCore.Components.Routing +@using Oqtane.Client.Modules.Controls @using Oqtane.Models @using Oqtane.Services @using Oqtane.Modules @using Oqtane.Shared -@using Oqtane.Client.Modules.Controls +@using Oqtane.Security @inherits ModuleBase @inject IUriHelper UriHelper @inject IPageService PageService @inject IThemeService ThemeService -@((MarkupString)message) + @@ -163,8 +164,8 @@ themetype = page.ThemeType; layouttype = page.LayoutType; icon = page.Icon; - viewpermissions = page.ViewPermissions; - editpermissions = page.EditPermissions; + viewpermissions = UserSecurity.GetPermissions("View", page.Permissions); + editpermissions = UserSecurity.GetPermissions("Edit", page.Permissions); createdby = page.CreatedBy; createdon = page.CreatedOn; modifiedby = page.ModifiedBy; @@ -173,7 +174,7 @@ } catch (Exception ex) { - message = "
    " + ex.Message + "


    "; + message = ex.Message; } } @@ -194,7 +195,7 @@ } catch (Exception ex) { - message = "
    " + ex.Message + "


    "; + message = ex.Message; } } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 5661b344..043c9c1f 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -1,15 +1,16 @@ @using Microsoft.AspNetCore.Components.Routing +@using Oqtane.Client.Modules.Controls @using Oqtane.Models @using Oqtane.Services @using Oqtane.Modules @using Oqtane.Shared -@using Oqtane.Client.Modules.Controls +@using Oqtane.Security @inherits ModuleBase @inject IUriHelper UriHelper @inject IPageService PageService @inject IThemeService ThemeService -@((MarkupString)message) +
    @@ -170,8 +171,8 @@ themetype = page.ThemeType; layouttype = page.LayoutType; icon = page.Icon; - viewpermissions = page.ViewPermissions; - editpermissions = page.EditPermissions; + viewpermissions = UserSecurity.GetPermissions("View", page.Permissions); + editpermissions = UserSecurity.GetPermissions("Edit", page.Permissions); createdby = page.CreatedBy; createdon = page.CreatedOn; modifiedby = page.ModifiedBy; @@ -180,7 +181,7 @@ } catch (Exception ex) { - message = "
    " + ex.Message + "


    "; + message = ex.Message; } } @@ -216,8 +217,7 @@ } System.Reflection.PropertyInfo property = type.GetProperty("Panes"); page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - page.ViewPermissions = viewpermissions; - page.EditPermissions = editpermissions; + page.Permissions = UserSecurity.SetPermissions("View", viewpermissions) + UserSecurity.SetPermissions("Edit", editpermissions); await PageService.UpdatePageAsync(page); PageState.Reload = Constants.ReloadSite; @@ -232,7 +232,7 @@ } catch (Exception ex) { - message = "
    " + ex.Message + "


    "; + message = ex.Message; } } } diff --git a/Oqtane.Client/Modules/Admin/Pages/Index.razor b/Oqtane.Client/Modules/Admin/Pages/Index.razor index f150ab34..cd972c59 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Index.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Index.razor @@ -1,7 +1,7 @@ -@using Oqtane.Services +@using Oqtane.Client.Modules.Controls +@using Oqtane.Services @using Oqtane.Models @using Oqtane.Modules -@using Oqtane.Client.Modules.Controls @inherits ModuleBase @inject IPageService PageService diff --git a/Oqtane.Client/Modules/Admin/Register/Index.razor b/Oqtane.Client/Modules/Admin/Register/Index.razor index a3ed92a7..3ef9ed16 100644 --- a/Oqtane.Client/Modules/Admin/Register/Index.razor +++ b/Oqtane.Client/Modules/Admin/Register/Index.razor @@ -9,7 +9,7 @@
    - +
    @@ -22,17 +22,17 @@ @code { public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Anonymous; } } - public string Username { get; set; } = ""; + public string Email { get; set; } = ""; public string Password { get; set; } = ""; private async Task RegisterUser() { User user = new User(); user.SiteId = PageState.Site.SiteId; - user.Username = Username; - user.DisplayName = Username; - user.Roles = "Administrators;"; - user.IsSuperUser = false; + user.Username = Email; + user.DisplayName = Email; + user.Email = Email; + user.IsHost = false; user.Password = Password; await UserService.AddUserAsync(user); UriHelper.NavigateTo(""); diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index 32612845..06165cbb 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -2,6 +2,8 @@ @using Oqtane.Models @using Oqtane.Services @using Oqtane.Modules +@using Oqtane.Shared +@using Oqtane.Security @inherits ModuleBase @inject IUriHelper UriHelper @inject ITenantService TenantService @@ -102,8 +104,7 @@ else Type type = Type.GetType(p.ThemeType); System.Reflection.PropertyInfo property = type.GetProperty("Panes"); p.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - p.ViewPermissions = "All Users"; - p.EditPermissions = "Administrators"; + p.Permissions = UserSecurity.SetPermissions("View", Constants.AllUsersRole) + UserSecurity.SetPermissions("Edit", Constants.AdminRole); await PageService.AddPageAsync(p); UriHelper.NavigateTo(url, true); diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index 3dc6ae12..deb120c0 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -2,6 +2,7 @@ @using Oqtane.Modules @using Oqtane.Services @using Oqtane.Shared +@using Oqtane.Security @inherits ModuleBase @inject IUserService UserService @@ -70,19 +71,16 @@ authorized = true; break; case SecurityAccessLevel.View: - authorized = UserService.IsAuthorized(PageState.User, ModuleState.ViewPermissions); + authorized = UserSecurity.IsAuthorized(PageState.User, "View", ModuleState.Permissions); break; case SecurityAccessLevel.Edit: - authorized = UserService.IsAuthorized(PageState.User, ModuleState.EditPermissions); + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions); break; case SecurityAccessLevel.Admin: - authorized = UserService.IsAuthorized(PageState.User, Constants.AdminRole); + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.AdminRole)); break; case SecurityAccessLevel.Host: - if (PageState.User != null) - { - authorized = PageState.User.IsSuperUser; - } + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.HostRole)); break; } } diff --git a/Oqtane.Client/Modules/Controls/ModuleMessage.razor b/Oqtane.Client/Modules/Controls/ModuleMessage.razor index 69d1c84d..5b006331 100644 --- a/Oqtane.Client/Modules/Controls/ModuleMessage.razor +++ b/Oqtane.Client/Modules/Controls/ModuleMessage.razor @@ -1,30 +1,22 @@ @using Oqtane.Modules @inherits ModuleBase -@if (authorized) +@if (Message != "") { -
    - @Message -
    +
    @Message


    } @code { - [Parameter] - public MessageType Type { get; set; } - [Parameter] public string Message { get; set; } - string type = "alert alert-success"; // optional - bool authorized = false; + [Parameter] + public MessageType Type { get; set; } + + string type = "alert alert-danger"; protected override void OnInitialized() { - if (PageState.User != null) - { - authorized = PageState.User.IsSuperUser; - } - switch (Type) { case MessageType.Success: diff --git a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs index aca530af..e5fb4e85 100644 --- a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs +++ b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs @@ -29,22 +29,22 @@ namespace Oqtane.Client.Modules.HtmlText.Services public async Task GetHtmlTextAsync(int ModuleId) { - return await http.GetJsonAsync(apiurl + "/" + ModuleId.ToString()); + return await http.GetJsonAsync(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString()); } public async Task AddHtmlTextAsync(HtmlTextInfo htmltext) { - await http.PostJsonAsync(apiurl, htmltext); + await http.PostJsonAsync(apiurl + "?entityid=" + htmltext.ModuleId.ToString(), htmltext); } public async Task UpdateHtmlTextAsync(HtmlTextInfo htmltext) { - await http.PutJsonAsync(apiurl + "/" + htmltext.HtmlTextId.ToString(), htmltext); + await http.PutJsonAsync(apiurl + "/" + htmltext.HtmlTextId.ToString() + "?entityid=" + htmltext.ModuleId.ToString(), htmltext); } - public async Task DeleteHtmlTextAsync(int HtmlTextId) + public async Task DeleteHtmlTextAsync(int ModuleId) { - await http.DeleteAsync(apiurl + "/" + HtmlTextId.ToString()); + await http.DeleteAsync(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString()); } } } diff --git a/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs b/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs index 9d3bfa98..fe880d87 100644 --- a/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs +++ b/Oqtane.Client/Modules/HtmlText/Services/IHtmlTextService.cs @@ -12,6 +12,6 @@ namespace Oqtane.Client.Modules.HtmlText.Services Task UpdateHtmlTextAsync(HtmlTextInfo htmltext); - Task DeleteHtmlTextAsync(int HtmlTextId); + Task DeleteHtmlTextAsync(int ModuleId); } } diff --git a/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs b/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs index 083aa7c5..c02016a5 100644 --- a/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs +++ b/Oqtane.Client/Providers/IdentityAuthenticationStateProvider.cs @@ -32,7 +32,8 @@ namespace Oqtane.Providers { identity = new ClaimsIdentity("Identity.Application"); identity.AddClaim(new Claim(ClaimTypes.Name, user.Username)); - foreach(string role in user.Roles.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) + identity.AddClaim(new Claim(ClaimTypes.PrimarySid, user.UserId.ToString())); + foreach (string role in user.Roles.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { identity.AddClaim(new Claim(ClaimTypes.Role, role)); } diff --git a/Oqtane.Client/Services/Interfaces/IUserService.cs b/Oqtane.Client/Services/Interfaces/IUserService.cs index e1626201..9b0a0ead 100644 --- a/Oqtane.Client/Services/Interfaces/IUserService.cs +++ b/Oqtane.Client/Services/Interfaces/IUserService.cs @@ -21,7 +21,5 @@ namespace Oqtane.Services Task LoginUserAsync(User User, bool SetCookie, bool IsPersistent); Task LogoutUserAsync(); - - bool IsAuthorized(User User, string AccessControlList); } } diff --git a/Oqtane.Client/Services/UserService.cs b/Oqtane.Client/Services/UserService.cs index ec35fc39..ab736094 100644 --- a/Oqtane.Client/Services/UserService.cs +++ b/Oqtane.Client/Services/UserService.cs @@ -67,78 +67,5 @@ namespace Oqtane.Services // best practices recommend post is preferrable to get for logout await http.PostJsonAsync(apiurl + "/logout", null); } - - // ACLs are stored in the format "!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]" where "!" designates Deny permissions - public bool IsAuthorized(User User, string AccessControlList) - { - bool isAllowed = false; - - if (User != null) - { - // super user always has full access - isAllowed = User.IsSuperUser; - } - - if (!isAllowed) - { - if (AccessControlList != null) - { - foreach (string permission in AccessControlList.Split(new[] { ';' })) - { - bool? allowed = VerifyPermission(User, permission); - if (allowed.HasValue) - { - isAllowed = allowed.Value; - break; - } - } - } - } - return isAllowed; - } - - private bool? VerifyPermission(User user, string permission) - { - bool? allowed = null; - //permissions strings are encoded with deny permissions at the beginning and grant permissions at the end for optimal performance - if (!String.IsNullOrEmpty(permission)) - { - // deny permission - if (permission.StartsWith("!")) - { - string denyRole = permission.Replace("!", ""); - if (denyRole == Constants.AllUsersRole || IsAllowed(user, denyRole)) - { - allowed = false; - } - } - else // grant permission - { - if (permission == Constants.AllUsersRole || IsAllowed(user, permission)) - { - allowed = true; - } - } - } - return allowed; - } - - private bool IsAllowed(User user, string permission) - { - if (user != null) - { - if ("[" + user.UserId + "]" == permission) - { - return true; - } - - var roles = user.Roles; - if (roles != null) - { - return roles.IndexOf(";" + permission + ";") != -1; - } - } - return false; - } } } diff --git a/Oqtane.Client/Shared/Container.razor b/Oqtane.Client/Shared/Container.razor index 907df9c8..92aa6e62 100644 --- a/Oqtane.Client/Shared/Container.razor +++ b/Oqtane.Client/Shared/Container.razor @@ -34,8 +34,7 @@ { // container does not exist with type specified builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); - builder.AddAttribute(1, "Type", MessageType.Error); - builder.AddAttribute(2, "Message", "Error Loading Module Container " + container); + builder.AddAttribute(1, "Message", "Error Loading Module Container " + container); builder.CloseComponent(); } } diff --git a/Oqtane.Client/Shared/Installer.razor b/Oqtane.Client/Shared/Installer.razor index 72e662e7..a4e13401 100644 --- a/Oqtane.Client/Shared/Installer.razor +++ b/Oqtane.Client/Shared/Installer.razor @@ -82,10 +82,10 @@
    @@ -115,7 +115,7 @@ private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm"); private string Username = ""; private string Password = ""; - private string HostUsername = "host"; + private string Email = ""; private string HostPassword = ""; private string Message = ""; @@ -164,11 +164,11 @@ { User user = new User(); user.SiteId = 1; - user.Username = HostUsername; - user.DisplayName = HostUsername; + user.Username = Email; + user.DisplayName = Email; + user.Email = Email; user.Password = HostPassword; - user.IsSuperUser = true; - user.Roles = ""; + user.IsHost = true; user = await UserService.AddUserAsync(user); UriHelper.NavigateTo("", true); diff --git a/Oqtane.Client/Shared/ModuleInstance.razor b/Oqtane.Client/Shared/ModuleInstance.razor index a1d3548e..8eb83f48 100644 --- a/Oqtane.Client/Shared/ModuleInstance.razor +++ b/Oqtane.Client/Shared/ModuleInstance.razor @@ -36,8 +36,7 @@ { // module does not exist with typename specified builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); - builder.AddAttribute(1, "Type", MessageType.Error); - builder.AddAttribute(2, "Message", "Error Loading Component For Module " + ModuleState.ModuleDefinitionName); + builder.AddAttribute(1, "Message", "Error Loading Component For Module " + ModuleState.ModuleDefinitionName); builder.CloseComponent(); } }; diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor index b2f803aa..3f245bf7 100644 --- a/Oqtane.Client/Shared/Pane.razor +++ b/Oqtane.Client/Shared/Pane.razor @@ -3,6 +3,7 @@ @using Oqtane.Modules @using Oqtane.Models @using Oqtane.Shared +@using Oqtane.Security @using System.Linq @inject IUserService UserService @inject IModuleService ModuleService @@ -27,7 +28,7 @@ protected override void OnInitialized() { - if (UserService.IsAuthorized(PageState.User, PageState.Page.EditPermissions) && Name != Constants.AdminPane) + if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions) && Name != Constants.AdminPane) { paneadminborder = "pane-admin-border"; panetitle = "
    " + Name + " Pane
    "; @@ -60,16 +61,16 @@ authorized = true; break; case SecurityAccessLevel.View: - authorized = UserService.IsAuthorized(PageState.User, module.ViewPermissions); + authorized = UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions); break; case SecurityAccessLevel.Edit: - authorized = UserService.IsAuthorized(PageState.User, module.EditPermissions); + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", module.Permissions); break; case SecurityAccessLevel.Admin: - authorized = UserService.IsAuthorized(PageState.User, Constants.AdminRole); + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.AdminRole)); break; case SecurityAccessLevel.Host: - authorized = PageState.User.IsSuperUser; + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.HostRole)); break; } if (authorized) @@ -103,7 +104,7 @@ if (module != null && module.Pane == Name) { // check if user is authorized to view module - if (UserService.IsAuthorized(PageState.User, module.ViewPermissions)) + if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions)) { builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer)); builder.AddAttribute(1, "Module", module); @@ -116,7 +117,7 @@ foreach (Module module in PageState.Modules.Where(item => item.Pane == Name).OrderBy(x => x.Order).ToArray()) { // check if user is authorized to view module - if (UserService.IsAuthorized(PageState.User, module.ViewPermissions)) + if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions)) { builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer)); builder.AddAttribute(1, "Module", module); diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index 995e5b55..b57a545e 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -4,6 +4,7 @@ @using System.Linq @using System.Collections.Generic @using Oqtane.Shared +@using Oqtane.Security @using Microsoft.AspNetCore.Components.Routing @inject AuthenticationStateProvider AuthenticationStateProvider @inject SiteState SiteState @@ -153,12 +154,12 @@ } // extract admin route elements from path - string[] segments = path.Split('/'); + string[] segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); int result; - if (segments.Length >= 3 && int.TryParse(segments[segments.Length - 3], out result)) + if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result)) { // path has moduleid and control specification ie. page/moduleid/control/ - control = segments[segments.Length - 2]; + control = segments[segments.Length - 1]; moduleid = result; path = path.Replace(moduleid.ToString() + "/" + control + "/", ""); } @@ -206,7 +207,7 @@ if (page != null) { // check if user is authorized to view page - if (UserService.IsAuthorized(user, page.ViewPermissions)) + if (UserSecurity.IsAuthorized(user, "View", page.Permissions)) { pagestate = new PageState(); pagestate.ModuleDefinitions = moduledefinitions; @@ -278,7 +279,7 @@ Dictionary querystring = new Dictionary(); if (path.IndexOf("?") != -1) { - foreach (string kvp in path.Substring(path.IndexOf("?") + 1).Split('&')) + foreach (string kvp in path.Substring(path.IndexOf("?") + 1).Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)) { if (kvp != "") { @@ -316,7 +317,7 @@ string typename = moduledefinition.ControlTypeTemplate; if (moduledefinition.ControlTypeRoutes != "") { - foreach (string route in moduledefinition.ControlTypeRoutes.Split(';')) + foreach (string route in moduledefinition.ControlTypeRoutes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { if (route.StartsWith(control + "=")) { diff --git a/Oqtane.Client/Shared/Theme.razor b/Oqtane.Client/Shared/Theme.razor index b9431f4d..ad9abdc9 100644 --- a/Oqtane.Client/Shared/Theme.razor +++ b/Oqtane.Client/Shared/Theme.razor @@ -22,8 +22,7 @@ { // theme does not exist with type specified builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl)); - builder.AddAttribute(1, "Type", MessageType.Error); - builder.AddAttribute(2, "Message", "Error Loading Page Theme " + PageState.Page.ThemeType); + builder.AddAttribute(1, "Message", "Error Loading Page Theme " + PageState.Page.ThemeType); builder.CloseComponent(); } }; diff --git a/Oqtane.Client/Shared/Utilities.cs b/Oqtane.Client/Shared/Utilities.cs index fc4524f7..f4a60e71 100644 --- a/Oqtane.Client/Shared/Utilities.cs +++ b/Oqtane.Client/Shared/Utilities.cs @@ -35,6 +35,7 @@ namespace Oqtane.Shared public static string EditUrl(string alias, string path, int moduleid, string action, string parameters) { string url = NavigateUrl(alias, path, ""); + if (url == "/") url = ""; if (moduleid != -1) { url += "/" + moduleid.ToString(); diff --git a/Oqtane.Client/Themes/Controls/ControlPanel.razor b/Oqtane.Client/Themes/Controls/ControlPanel.razor index 7a51c3db..9eb030bf 100644 --- a/Oqtane.Client/Themes/Controls/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/ControlPanel.razor @@ -3,6 +3,7 @@ @using Oqtane.Models @using Oqtane.Themes @using Oqtane.Shared +@using Oqtane.Security @inherits ThemeObjectBase @inject IUriHelper UriHelper @inject IUserService UserService @@ -44,7 +45,7 @@
    - + - +
    - - - - - - - - - - - - - - - - - - - - -
    - - - -
    - - - -
    - - - -
    - - - -
    - - - -
    + + + + + + + + + + + + + + + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    @DynamicComponent @@ -78,10 +70,11 @@ Dictionary containers = new Dictionary(); string title; string containertype; - string viewpermissions; - string editpermissions; + string permissions; string pageid; + PermissionGrid permissiongrid; + RenderFragment DynamicComponent { get; set; } object settings; @@ -90,8 +83,7 @@ title = ModuleState.Title; containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync()); containertype = ModuleState.ContainerType; - viewpermissions = UserSecurity.GetPermissions("View", ModuleState.Permissions); - editpermissions = UserSecurity.GetPermissions("Edit", ModuleState.Permissions); + permissions = ModuleState.Permissions; pageid = ModuleState.PageId.ToString(); DynamicComponent = builder => @@ -109,7 +101,7 @@ private async Task SaveModule() { Module module = ModuleState; - module.Permissions = UserSecurity.SetPermissions("View", viewpermissions) + UserSecurity.SetPermissions("Edit", editpermissions); + module.Permissions = permissiongrid.GetPermissions(); await ModuleService.UpdateModuleAsync(module); PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId); diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index de65c5ae..14c3db9c 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -99,18 +99,10 @@
    - + - -
    - - - +
    @@ -133,8 +125,9 @@ string themetype; string layouttype = ""; string icon = ""; - string viewpermissions = "All Users"; - string editpermissions = "Administrators"; + string permissions = ""; // need to set default permissions + + PermissionGrid permissiongrid; protected override void OnInitialized() { @@ -142,6 +135,11 @@ { themes = ThemeService.GetThemeTypes(PageState.Themes); panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes); + + List permissionstrings = new List(); + permissionstrings.Add(new PermissionString { PermissionName = "View", Permissions = Constants.AdminRole }); + permissionstrings.Add(new PermissionString { PermissionName = "Edit", Permissions = Constants.AdminRole }); + permissions = UserSecurity.SetPermissionStrings(permissionstrings); } catch (Exception ex) { @@ -181,7 +179,7 @@ } System.Reflection.PropertyInfo property = type.GetProperty("Panes"); page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - page.Permissions = UserSecurity.SetPermissions("View", viewpermissions) + UserSecurity.SetPermissions("Edit", editpermissions); + page.Permissions = permissiongrid.GetPermissions(); await PageService.AddPageAsync(page); PageState.Reload = Constants.ReloadSite; diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index bfa1473f..5c5da1ff 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -100,18 +100,10 @@ - + - - - - - - - - - + @@ -138,13 +130,14 @@ string themetype; string layouttype; string icon; - string viewpermissions; - string editpermissions; + string permissions; string createdby; DateTime createdon; string modifiedby; DateTime modifiedon; + PermissionGrid permissiongrid; + protected override void OnInitialized() { try @@ -164,8 +157,7 @@ themetype = page.ThemeType; layouttype = page.LayoutType; icon = page.Icon; - viewpermissions = UserSecurity.GetPermissions("View", page.Permissions); - editpermissions = UserSecurity.GetPermissions("Edit", page.Permissions); + permissions = page.Permissions; createdby = page.CreatedBy; createdon = page.CreatedOn; modifiedby = page.ModifiedBy; diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 043c9c1f..43c64ee5 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -100,18 +100,10 @@ - + - - - - - - - - - + @@ -138,13 +130,14 @@ string themetype; string layouttype; string icon; - string viewpermissions; - string editpermissions; + string permissions; string createdby; DateTime createdon; string modifiedby; DateTime modifiedon; + PermissionGrid permissiongrid; + protected override void OnInitialized() { try @@ -171,8 +164,7 @@ themetype = page.ThemeType; layouttype = page.LayoutType; icon = page.Icon; - viewpermissions = UserSecurity.GetPermissions("View", page.Permissions); - editpermissions = UserSecurity.GetPermissions("Edit", page.Permissions); + permissions = page.Permissions; createdby = page.CreatedBy; createdon = page.CreatedOn; modifiedby = page.ModifiedBy; @@ -217,7 +209,7 @@ } System.Reflection.PropertyInfo property = type.GetProperty("Panes"); page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - page.Permissions = UserSecurity.SetPermissions("View", viewpermissions) + UserSecurity.SetPermissions("Edit", editpermissions); + page.Permissions = permissiongrid.GetPermissions(); await PageService.UpdatePageAsync(page); PageState.Reload = Constants.ReloadSite; diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index 06165cbb..48fc1dc5 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -98,13 +98,18 @@ else p.Path = ""; p.Order = 1; p.IsNavigation = true; - p.ThemeType = "Oqtane.Client.Themes.Theme1.Theme1, Oqtane.Client"; + p.ThemeType = "Oqtane.Client.Themes.Theme1.Theme1, Oqtane.Client"; // TODO: should not hardcode p.LayoutType = ""; p.Icon = ""; Type type = Type.GetType(p.ThemeType); System.Reflection.PropertyInfo property = type.GetProperty("Panes"); p.Panes = (string)property.GetValue(Activator.CreateInstance(type), null); - p.Permissions = UserSecurity.SetPermissions("View", Constants.AllUsersRole) + UserSecurity.SetPermissions("Edit", Constants.AdminRole); + + List permissionstrings = new List(); + permissionstrings.Add(new PermissionString { PermissionName = "View", Permissions = Constants.AllUsersRole }); + permissionstrings.Add(new PermissionString { PermissionName = "Edit", Permissions = Constants.AdminRole }); + p.Permissions = UserSecurity.SetPermissionStrings(permissionstrings); + await PageService.AddPageAsync(p); UriHelper.NavigateTo(url, true); diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index deb120c0..d894894b 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -77,10 +77,10 @@ authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions); break; case SecurityAccessLevel.Admin: - authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.AdminRole)); + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole); break; case SecurityAccessLevel.Host: - authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.HostRole)); + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole); break; } } diff --git a/Oqtane.Client/Modules/Controls/PermissionGrid.razor b/Oqtane.Client/Modules/Controls/PermissionGrid.razor new file mode 100644 index 00000000..d330a9b6 --- /dev/null +++ b/Oqtane.Client/Modules/Controls/PermissionGrid.razor @@ -0,0 +1,196 @@ +@using Oqtane.Services +@using Oqtane.Modules +@using Oqtane.Models +@using Oqtane.Security +@using Oqtane.Shared +@inherits ModuleBase +@inject IRoleService RoleService +@inject IUserService UserService + +@if (roles != null) +{ +
    +
    +
    + + + + + @foreach (PermissionString permission in permissions) + { + + } + + @foreach (Role role in roles) + { + + + @foreach (PermissionString permission in permissions) + { + var p = permission; + + } + + } + +
    Role@permission.PermissionName @EntityName
    @role.Name
    +
    + @if (@users.Count != 0) + { +
    + + + + + @foreach (PermissionString permission in permissions) + { + + } + + + + @foreach (User user in users) + { + + + @foreach (PermissionString permission in permissions) + { + var p = permission; + + } + + } + +
    User@permission.PermissionName @EntityName
    @user.DisplayName
    +
    + } +
    + + + +
    +
    + +
    +} + +@code { + [Parameter] + public string EntityName { get; set; } + + [Parameter] + public string Permissions { get; set; } + + [Parameter] + public string PermissionNames { get; set; } // optional - can be used to specify permissions order or add custom permissions + + List roles; + List permissions = new List(); + List users = new List(); + string username = ""; + string message = ""; + + protected override async Task OnInitializedAsync() + { + if (string.IsNullOrEmpty(PermissionNames)) + { + PermissionNames = "View,Edit"; + } + roles = await RoleService.GetRolesAsync(ModuleState.SiteId); + roles.Insert(0, new Role { Name = Constants.AllUsersRole }); + + foreach (string permissionname in PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + { + permissions.Add(new PermissionString { PermissionName = permissionname, Permissions = "" }); + } + foreach (PermissionString permissionstring in UserSecurity.GetPermissionStrings(Permissions)) + { + if (permissions.Find(item => item.PermissionName == permissionstring.PermissionName) != null) + { + permissions[permissions.FindIndex(item => item.PermissionName == permissionstring.PermissionName)].Permissions = permissionstring.Permissions; + } + if (permissionstring.Permissions.Contains("[")) + { + foreach (string user in permissionstring.Permissions.Split(new char[] { '[' }, StringSplitOptions.RemoveEmptyEntries)) + { + if (user.Contains("]")) + { + int userid = int.Parse(user.Substring(0, user.IndexOf("]"))); + if (users.Where(item => item.UserId == userid).FirstOrDefault() == null) + { + users.Add(await UserService.GetUserAsync(userid, ModuleState.SiteId)); + } + } + } + } + } + } + + private bool GetPermissionValue(string Permissions, string SecurityKey) + { + if ((";" + Permissions + ";").Contains(";" + SecurityKey + ";")) + { + return true; + } + else + { + return false; + } + } + + private bool GetPermissionDisabled(string RoleName) + { + if (RoleName == Constants.AdminRole) + { + return true; + } + else + { + return false; + } + } + + private async Task AddUser() + { + if (users.Where(item => item.Username == username).FirstOrDefault() == null) + { + try + { + User user = await UserService.GetUserAsync(username, ModuleState.SiteId); + if (user != null) + { + users.Add(user); + } + } + catch + { + message = "Username Does Not Exist"; + } + } + username = ""; + } + + private void PermissionChanged(UIChangeEventArgs e, string PermissionName, string SecurityId) + { + bool selected = (bool)e.Value; + PermissionString permission = permissions.Find(item => item.PermissionName == PermissionName); + if (permission != null) + { + List ids = permission.Permissions.Split(';').ToList(); + if (selected) + { + ids.Add(SecurityId); + } + else + { + ids.Remove(SecurityId); + } + permissions[permissions.FindIndex(item => item.PermissionName == PermissionName)].Permissions = string.Join(";", ids.ToArray()); + } + } + + public string GetPermissions() + { + return UserSecurity.SetPermissionStrings(permissions); + } +} diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor index 3f245bf7..93b27c41 100644 --- a/Oqtane.Client/Shared/Pane.razor +++ b/Oqtane.Client/Shared/Pane.razor @@ -67,10 +67,10 @@ authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", module.Permissions); break; case SecurityAccessLevel.Admin: - authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.AdminRole)); + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole); break; case SecurityAccessLevel.Host: - authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", UserSecurity.SetPermissions("Edit", Constants.HostRole)); + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole); break; } if (authorized) diff --git a/Oqtane.Server/Controllers/AliasController.cs b/Oqtane.Server/Controllers/AliasController.cs index 9e9e4bae..b559c41e 100644 --- a/Oqtane.Server/Controllers/AliasController.cs +++ b/Oqtane.Server/Controllers/AliasController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -32,7 +33,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Alias Post([FromBody] Alias Alias) { if (ModelState.IsValid) @@ -44,7 +45,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Alias Put(int id, [FromBody] Alias Alias) { if (ModelState.IsValid) @@ -56,7 +57,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { Aliases.DeleteAlias(id); diff --git a/Oqtane.Server/Controllers/ModuleController.cs b/Oqtane.Server/Controllers/ModuleController.cs index a29e5059..1c60310a 100644 --- a/Oqtane.Server/Controllers/ModuleController.cs +++ b/Oqtane.Server/Controllers/ModuleController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -54,7 +55,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Module Post([FromBody] Module Module) { if (ModelState.IsValid) @@ -66,7 +67,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Module Put(int id, [FromBody] Module Module) { if (ModelState.IsValid) @@ -78,7 +79,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { Modules.DeleteModule(id); diff --git a/Oqtane.Server/Controllers/PageController.cs b/Oqtane.Server/Controllers/PageController.cs index 03c140e6..8f75bcf0 100644 --- a/Oqtane.Server/Controllers/PageController.cs +++ b/Oqtane.Server/Controllers/PageController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -39,7 +40,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Page Post([FromBody] Page Page) { if (ModelState.IsValid) @@ -51,7 +52,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Page Put(int id, [FromBody] Page Page) { if (ModelState.IsValid) @@ -63,7 +64,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { Pages.DeletePage(id); diff --git a/Oqtane.Server/Controllers/PageModuleController.cs b/Oqtane.Server/Controllers/PageModuleController.cs index 8ae9d032..061f60ac 100644 --- a/Oqtane.Server/Controllers/PageModuleController.cs +++ b/Oqtane.Server/Controllers/PageModuleController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -32,7 +33,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public PageModule Post([FromBody] PageModule PageModule) { if (ModelState.IsValid) @@ -44,7 +45,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public PageModule Put(int id, [FromBody] PageModule PageModule) { if (ModelState.IsValid) @@ -56,7 +57,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { PageModules.DeletePageModule(id); diff --git a/Oqtane.Server/Controllers/PermissionController.cs b/Oqtane.Server/Controllers/PermissionController.cs index 59466930..dc2bc614 100644 --- a/Oqtane.Server/Controllers/PermissionController.cs +++ b/Oqtane.Server/Controllers/PermissionController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -32,7 +33,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Permission Post([FromBody] Permission Permission) { if (ModelState.IsValid) @@ -44,7 +45,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Permission Put(int id, [FromBody] Permission Permission) { if (ModelState.IsValid) @@ -56,7 +57,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { Permissions.DeletePermission(id); diff --git a/Oqtane.Server/Controllers/RoleController.cs b/Oqtane.Server/Controllers/RoleController.cs index 7401b2bf..8ac711a3 100644 --- a/Oqtane.Server/Controllers/RoleController.cs +++ b/Oqtane.Server/Controllers/RoleController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -39,7 +40,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Role Post([FromBody] Role Role) { if (ModelState.IsValid) @@ -51,7 +52,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public Role Put(int id, [FromBody] Role Role) { if (ModelState.IsValid) @@ -63,7 +64,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { Roles.DeleteRole(id); diff --git a/Oqtane.Server/Controllers/SettingController.cs b/Oqtane.Server/Controllers/SettingController.cs index 4c674138..5dcec2d8 100644 --- a/Oqtane.Server/Controllers/SettingController.cs +++ b/Oqtane.Server/Controllers/SettingController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -32,7 +33,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize] + [Authorize(Roles = Constants.AdminRole)] public Setting Post([FromBody] Setting Setting) { if (ModelState.IsValid) @@ -44,7 +45,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize] + [Authorize(Roles = Constants.AdminRole)] public Setting Put(int id, [FromBody] Setting Setting) { if (ModelState.IsValid) @@ -56,7 +57,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { Settings.DeleteSetting(id); diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs index 4377b67a..802cac83 100644 --- a/Oqtane.Server/Controllers/SiteController.cs +++ b/Oqtane.Server/Controllers/SiteController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -32,7 +33,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize] + [Authorize(Roles = Constants.HostRole)] public Site Post([FromBody] Site Site) { if (ModelState.IsValid) @@ -44,7 +45,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize] + [Authorize(Roles = Constants.HostRole)] public Site Put(int id, [FromBody] Site Site) { if (ModelState.IsValid) @@ -56,7 +57,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize] + [Authorize(Roles = Constants.HostRole)] public void Delete(int id) { Sites.DeleteSite(id); diff --git a/Oqtane.Server/Controllers/TenantController.cs b/Oqtane.Server/Controllers/TenantController.cs index c3f41289..1711aae1 100644 --- a/Oqtane.Server/Controllers/TenantController.cs +++ b/Oqtane.Server/Controllers/TenantController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; using System.Collections.Generic; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -32,7 +33,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize] + [Authorize(Roles = Constants.HostRole)] public Tenant Post([FromBody] Tenant Tenant) { if (ModelState.IsValid) @@ -44,7 +45,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize] + [Authorize(Roles = Constants.HostRole)] public Tenant Put(int id, [FromBody] Tenant Tenant) { if (ModelState.IsValid) @@ -56,7 +57,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize] + [Authorize(Roles = Constants.HostRole)] public void Delete(int id) { Tenants.DeleteTenant(id); diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs index 535b2d38..3ad60d0c 100644 --- a/Oqtane.Server/Controllers/UserController.cs +++ b/Oqtane.Server/Controllers/UserController.cs @@ -178,7 +178,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public User Put(int id, [FromBody] User User) { if (ModelState.IsValid) @@ -190,7 +190,7 @@ namespace Oqtane.Controllers // DELETE api//5?siteid=x [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id, string siteid) { SiteUser siteuser = SiteUsers.GetSiteUser(id, int.Parse(siteid)); diff --git a/Oqtane.Server/Controllers/UserRoleController.cs b/Oqtane.Server/Controllers/UserRoleController.cs index 4bdfba30..752adddb 100644 --- a/Oqtane.Server/Controllers/UserRoleController.cs +++ b/Oqtane.Server/Controllers/UserRoleController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; +using Oqtane.Shared; namespace Oqtane.Controllers { @@ -39,7 +40,7 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public UserRole Post([FromBody] UserRole UserRole) { if (ModelState.IsValid) @@ -51,7 +52,7 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public UserRole Put(int id, [FromBody] UserRole UserRole) { if (ModelState.IsValid) @@ -63,7 +64,7 @@ namespace Oqtane.Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Roles = "Administrators")] + [Authorize(Roles = Constants.AdminRole)] public void Delete(int id) { UserRoles.DeleteUserRole(id); diff --git a/Oqtane.Server/Repository/PermissionRepository.cs b/Oqtane.Server/Repository/PermissionRepository.cs index ba2aeee3..67a72b0d 100644 --- a/Oqtane.Server/Repository/PermissionRepository.cs +++ b/Oqtane.Server/Repository/PermissionRepository.cs @@ -4,6 +4,8 @@ using System.Linq; using Oqtane.Models; using System.Text; using System; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Oqtane.Repository { @@ -136,18 +138,22 @@ namespace Oqtane.Repository // permissions are stored in the format "{permissionname:!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]}" where "!" designates Deny permissions public string EncodePermissions(int EntityId, List Permissions) { - string permissions = ""; + List permissionstrings = new List(); string permissionname = ""; + string permissions = ""; StringBuilder permissionsbuilder = new StringBuilder(); - string perm = ""; + string securityid = ""; foreach (Permission permission in Permissions.Where(item => item.EntityId == EntityId).OrderBy(item => item.PermissionName)) { // permission collections are grouped by permissionname if (permissionname != permission.PermissionName) { + permissions = permissionsbuilder.ToString(); + if (permissions != "") + { + permissionstrings.Add(new PermissionString { PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) }); + } permissionname = permission.PermissionName; - permissions += permissionsbuilder.ToString(); - permissions += ((permissions != "") ? "}" : "") + "{" + permissionname + ":"; permissionsbuilder = new StringBuilder(); } @@ -157,77 +163,76 @@ namespace Oqtane.Repository // encode permission if (permission.UserId == null) { - perm = prefix + permission.Role.Name + ";"; + securityid = prefix + permission.Role.Name + ";"; } else { - perm = prefix + "[" + permission.UserId.ToString() + "];"; + securityid = prefix + "[" + permission.UserId.ToString() + "];"; } - // insert Deny permissions at the beginning and append Grant permissions at the end + // insert deny permissions at the beginning and append grant permissions at the end if (prefix == "!") { - permissionsbuilder.Insert(0, perm); + permissionsbuilder.Insert(0, securityid); } else { - permissionsbuilder.Append(perm); + permissionsbuilder.Append(securityid); } } - if (permissionsbuilder.ToString() != "") + permissions = permissionsbuilder.ToString(); + if (permissions != "") { - permissions += permissionsbuilder.ToString() + "}"; + permissionstrings.Add(new PermissionString { PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) }); } - - return permissions; + return JsonSerializer.Serialize(permissionstrings); } - public List DecodePermissions(string Permissions, int SiteId, string EntityName, int EntityId) + public List DecodePermissions(string PermissionStrings, int SiteId, string EntityName, int EntityId) { - List roles = Roles.GetRoles(SiteId).ToList(); List permissions = new List(); - string perm = ""; - string permissionname; - string permissionstring; - foreach (string PermissionString in Permissions.Split(new char[] { '{' }, StringSplitOptions.RemoveEmptyEntries)) + List roles = Roles.GetRoles(SiteId).ToList(); + string securityid = ""; + foreach (PermissionString permissionstring in JsonSerializer.Deserialize>(PermissionStrings)) { - permissionname = PermissionString.Substring(0, PermissionString.IndexOf(":")); - permissionstring = PermissionString.Replace(permissionname + ":", "").Replace("}", ""); - foreach (string Perm in permissionstring.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) + foreach (string id in permissionstring.Permissions.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { - perm = Perm; + securityid = id; Permission permission = new Permission(); permission.SiteId = SiteId; permission.EntityName = EntityName; permission.EntityId = EntityId; - permission.PermissionName = permissionname; + permission.PermissionName = permissionstring.PermissionName; permission.RoleId = null; permission.UserId = null; permission.IsAuthorized = true; - if (perm.StartsWith("!")) + if (securityid.StartsWith("!")) { // deny permission - perm.Replace("!", ""); + securityid.Replace("!", ""); permission.IsAuthorized = false; } - if (perm.StartsWith("[") && perm.EndsWith("]")) + if (securityid.StartsWith("[") && securityid.EndsWith("]")) { // user id - perm = perm.Replace("[", "").Replace("]", ""); - permission.UserId = int.Parse(perm); + securityid = securityid.Replace("[", "").Replace("]", ""); + permission.UserId = int.Parse(securityid); } else { // role name - Role role = roles.Where(item => item.Name == perm).SingleOrDefault(); + Role role = roles.Where(item => item.Name == securityid).SingleOrDefault(); if (role != null) { permission.RoleId = role.RoleId; } } - permissions.Add(permission); + if (permission.UserId != null || permission.RoleId != null) + { + permissions.Add(permission); + } } } return permissions; diff --git a/Oqtane.Server/Security/IUserPermissions.cs b/Oqtane.Server/Security/IUserPermissions.cs new file mode 100644 index 00000000..587c68ea --- /dev/null +++ b/Oqtane.Server/Security/IUserPermissions.cs @@ -0,0 +1,9 @@ +using System.Security.Claims; + +namespace Oqtane.Security +{ + public interface IUserPermissions + { + bool IsAuthorized(ClaimsPrincipal User, string EntityName, int EntityId, string PermissionName); + } +} diff --git a/Oqtane.Server/Security/PermissionHandler.cs b/Oqtane.Server/Security/PermissionHandler.cs index 95d8d615..8332900d 100644 --- a/Oqtane.Server/Security/PermissionHandler.cs +++ b/Oqtane.Server/Security/PermissionHandler.cs @@ -1,22 +1,19 @@ -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; -using Oqtane.Models; -using Oqtane.Repository; + namespace Oqtane.Security { public class PermissionHandler : AuthorizationHandler { private readonly IHttpContextAccessor HttpContextAccessor; - private readonly IPermissionRepository Permissions; + private readonly IUserPermissions UserPermissions; - public PermissionHandler(IHttpContextAccessor HttpContextAccessor, IPermissionRepository Permissions) + public PermissionHandler(IHttpContextAccessor HttpContextAccessor, IUserPermissions UserPermissions) { this.HttpContextAccessor = HttpContextAccessor; - this.Permissions = Permissions; + this.UserPermissions = UserPermissions; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) @@ -26,27 +23,7 @@ namespace Oqtane.Security if (ctx != null && ctx.Request.Query.ContainsKey("entityid")) { int EntityId = int.Parse(ctx.Request.Query["entityid"]); - string permissions = Permissions.EncodePermissions(EntityId, Permissions.GetPermissions(requirement.EntityName, EntityId, requirement.PermissionName).ToList()); - - User user = new User(); - user.UserId = -1; - user.Roles = ""; - - if (context.User != null) - { - var idclaim = context.User.Claims.Where(item => item.Type == ClaimTypes.PrimarySid).FirstOrDefault(); - if (idclaim != null) - { - user.UserId = int.Parse(idclaim.Value); - foreach (var claim in context.User.Claims.Where(item => item.Type == ClaimTypes.Role)) - { - user.Roles += claim.Value + ";"; - } - if (user.Roles != "") user.Roles = ";" + user.Roles; - } - } - - if (UserSecurity.IsAuthorized(user, requirement.PermissionName, permissions)) + if (UserPermissions.IsAuthorized(context.User, requirement.EntityName, EntityId, requirement.PermissionName)) { context.Succeed(requirement); } diff --git a/Oqtane.Server/Security/UserPermissions.cs b/Oqtane.Server/Security/UserPermissions.cs new file mode 100644 index 00000000..6b28d6fd --- /dev/null +++ b/Oqtane.Server/Security/UserPermissions.cs @@ -0,0 +1,42 @@ +using Oqtane.Models; +using Oqtane.Repository; +using System.Linq; +using System.Security.Claims; + +namespace Oqtane.Security +{ + public class UserPermissions : IUserPermissions + { + private readonly IPermissionRepository Permissions; + + public UserPermissions(IPermissionRepository Permissions) + { + this.Permissions = Permissions; + } + + public bool IsAuthorized(ClaimsPrincipal User, string EntityName, int EntityId, string PermissionName) + { + string permissionstrings = Permissions.EncodePermissions(EntityId, Permissions.GetPermissions(EntityName, EntityId, PermissionName).ToList()); + + User user = new User(); + user.UserId = -1; + user.Roles = ""; + + if (User != null) + { + var idclaim = User.Claims.Where(item => item.Type == ClaimTypes.PrimarySid).FirstOrDefault(); + if (idclaim != null) + { + user.UserId = int.Parse(idclaim.Value); + foreach (var claim in User.Claims.Where(item => item.Type == ClaimTypes.Role)) + { + user.Roles += claim.Value + ";"; + } + if (user.Roles != "") user.Roles = ";" + user.Roles; + } + } + + return UserSecurity.IsAuthorized(user, PermissionName, permissionstrings); + } + } +} diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index f8b8fd87..4b441aff 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -169,6 +169,7 @@ namespace Oqtane.Server services.AddSingleton(); // register transient scoped core services + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -334,6 +335,7 @@ namespace Oqtane.Server services.AddSingleton(); // register transient scoped core services + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Oqtane.Shared/Models/PermissionString.cs b/Oqtane.Shared/Models/PermissionString.cs new file mode 100644 index 00000000..1a68e2ef --- /dev/null +++ b/Oqtane.Shared/Models/PermissionString.cs @@ -0,0 +1,8 @@ +namespace Oqtane.Models +{ + public class PermissionString + { + public string PermissionName { get; set; } + public string Permissions { get; set; } + } +} diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj index 95593fdd..5f73f172 100644 --- a/Oqtane.Shared/Oqtane.Shared.csproj +++ b/Oqtane.Shared/Oqtane.Shared.csproj @@ -22,6 +22,7 @@ + diff --git a/Oqtane.Shared/Security/UserSecurity.cs b/Oqtane.Shared/Security/UserSecurity.cs index 412a6907..8a1854fa 100644 --- a/Oqtane.Shared/Security/UserSecurity.cs +++ b/Oqtane.Shared/Security/UserSecurity.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; using Oqtane.Models; using Oqtane.Shared; @@ -6,38 +9,50 @@ namespace Oqtane.Security { public class UserSecurity { - // permission collections are stored in format {permissionname1:permissions}{permissionname2:permissions}... - public static string GetPermissions(string PermissionName, string Permissions) + public static List GetPermissionStrings(string PermissionStrings) + { + return JsonSerializer.Deserialize>(PermissionStrings); + } + + public static string SetPermissionStrings(List PermissionStrings) + { + return JsonSerializer.Serialize(PermissionStrings); + } + + public static string GetPermissions(string PermissionName, string PermissionStrings) { string permissions = ""; - foreach(string permission in Permissions.Split(new char[] { '{' }, StringSplitOptions.RemoveEmptyEntries)) + List permissionstrings = JsonSerializer.Deserialize>(PermissionStrings); + PermissionString permissionstring = permissionstrings.Where(item => item.PermissionName == PermissionName).FirstOrDefault(); + if (permissionstring != null) { - if (permission.StartsWith(PermissionName + ":")) - { - permissions = permission.Replace(PermissionName + ":", "").Replace("}", ""); - break; - } + permissions = permissionstring.Permissions; } return permissions; } - public static string SetPermissions(string PermissionName, string Permissions) + public static bool IsAuthorized(User User, string PermissionName, string PermissionStrings) { - return "{" + PermissionName + ":" + Permissions + "}"; + return IsAuthorized(User, GetPermissions(PermissionName, PermissionStrings)); } // permissions are stored in the format "!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]" where "!" designates Deny permissions - public static bool IsAuthorized(User User, string PermissionName, string Permissions) + public static bool IsAuthorized(User User, string Permissions) { - Permissions = GetPermissions(PermissionName, Permissions); - if (User == null) + bool authorized = false; + if (Permissions != "") { - return IsAuthorized(-1, "", Permissions); // user is not authenticated but may have access to resource - } - else - { - return IsAuthorized(User.UserId, User.Roles, Permissions); + if (User == null) + { + authorized = IsAuthorized(-1, "", Permissions); // user is not authenticated but may have access to resource + } + else + { + authorized = IsAuthorized(User.UserId, User.Roles, Permissions); + } + } + return authorized; } private static bool IsAuthorized(int UserId, string Roles, string Permissions) From 503bfff6e9d842046795d935e20c83f4bc6cf908 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 30 Aug 2019 10:07:14 -0400 Subject: [PATCH 30/44] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 0cd3f03e..25a528fd 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ Packaging - Need ability to package/install Themes Admin -- Need a permission grid UI component for pages/modules - Need fully functional administrative modules for all core entities ( user, role, site, etc… ) - Need ability to create a new Site and auto provision Admin pages/modules - Need ability to soft delete core entities From c651dedffdecb17194b157eaf4f3cc49229f224f Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 30 Aug 2019 10:45:44 -0400 Subject: [PATCH 31/44] Fix issue saving permissions associated to global roles --- .../Repository/Interfaces/IRoleRepository.cs | 1 + Oqtane.Server/Repository/PermissionRepository.cs | 2 +- Oqtane.Server/Repository/RoleRepository.cs | 13 +++++++++++++ Oqtane.Shared/Models/Role.cs | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Oqtane.Server/Repository/Interfaces/IRoleRepository.cs b/Oqtane.Server/Repository/Interfaces/IRoleRepository.cs index 61541336..a83d7194 100644 --- a/Oqtane.Server/Repository/Interfaces/IRoleRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/IRoleRepository.cs @@ -7,6 +7,7 @@ namespace Oqtane.Repository { IEnumerable GetRoles(); IEnumerable GetRoles(int SiteId); + IEnumerable GetRoles(int SiteId, bool IncludeGlobalRoles); Role AddRole(Role Role); Role UpdateRole(Role Role); Role GetRole(int RoleId); diff --git a/Oqtane.Server/Repository/PermissionRepository.cs b/Oqtane.Server/Repository/PermissionRepository.cs index 67a72b0d..682e797e 100644 --- a/Oqtane.Server/Repository/PermissionRepository.cs +++ b/Oqtane.Server/Repository/PermissionRepository.cs @@ -192,7 +192,7 @@ namespace Oqtane.Repository public List DecodePermissions(string PermissionStrings, int SiteId, string EntityName, int EntityId) { List permissions = new List(); - List roles = Roles.GetRoles(SiteId).ToList(); + List roles = Roles.GetRoles(SiteId, true).ToList(); string securityid = ""; foreach (PermissionString permissionstring in JsonSerializer.Deserialize>(PermissionStrings)) { diff --git a/Oqtane.Server/Repository/RoleRepository.cs b/Oqtane.Server/Repository/RoleRepository.cs index afb1fc09..fe99ecf8 100644 --- a/Oqtane.Server/Repository/RoleRepository.cs +++ b/Oqtane.Server/Repository/RoleRepository.cs @@ -38,6 +38,19 @@ namespace Oqtane.Repository } } + public IEnumerable GetRoles(int SiteId, bool IncludeGlobalRoles) + { + try + { + return db.Role.Where(item => item.SiteId == SiteId || item.SiteId == null).ToList(); + } + catch + { + throw; + } + } + + public Role AddRole(Role Role) { try diff --git a/Oqtane.Shared/Models/Role.cs b/Oqtane.Shared/Models/Role.cs index f892cabc..03da1f77 100644 --- a/Oqtane.Shared/Models/Role.cs +++ b/Oqtane.Shared/Models/Role.cs @@ -5,7 +5,7 @@ namespace Oqtane.Models public class Role : IAuditable { public int RoleId { get; set; } - public int SiteId { get; set; } + public int? SiteId { get; set; } public string Name { get; set; } public string Description { get; set; } public bool IsAutoAssigned { get; set; } From 838b48f91ea566cfe9bb83f69b7bac17737f3b52 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 30 Aug 2019 13:42:16 -0400 Subject: [PATCH 32/44] Settings authorization --- .../Controllers/SettingController.cs | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Oqtane.Server/Controllers/SettingController.cs b/Oqtane.Server/Controllers/SettingController.cs index 5dcec2d8..2d400cca 100644 --- a/Oqtane.Server/Controllers/SettingController.cs +++ b/Oqtane.Server/Controllers/SettingController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization; using Oqtane.Repository; using Oqtane.Models; using Oqtane.Shared; +using Oqtane.Security; namespace Oqtane.Controllers { @@ -11,10 +12,12 @@ namespace Oqtane.Controllers public class SettingController : Controller { private readonly ISettingRepository Settings; + private readonly IUserPermissions UserPermissions; - public SettingController(ISettingRepository Settings) + public SettingController(ISettingRepository Settings, IUserPermissions UserPermissions) { this.Settings = Settings; + this.UserPermissions = UserPermissions; } // GET: api/ @@ -33,10 +36,10 @@ namespace Oqtane.Controllers // POST api/ [HttpPost] - [Authorize(Roles = Constants.AdminRole)] + [Authorize] public Setting Post([FromBody] Setting Setting) { - if (ModelState.IsValid) + if (ModelState.IsValid && IsAuthorized(Setting.EntityName, Setting.EntityId)) { Setting = Settings.AddSetting(Setting); } @@ -45,10 +48,10 @@ namespace Oqtane.Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Roles = Constants.AdminRole)] + [Authorize] public Setting Put(int id, [FromBody] Setting Setting) { - if (ModelState.IsValid) + if (ModelState.IsValid && IsAuthorized(Setting.EntityName, Setting.EntityId)) { Setting = Settings.UpdateSetting(Setting); } @@ -62,5 +65,20 @@ namespace Oqtane.Controllers { Settings.DeleteSetting(id); } + + private bool IsAuthorized(string EntityName, int EntityId) + { + bool authorized = false; + switch (EntityName) + { + case "Module": + authorized = UserPermissions.IsAuthorized(User, EntityName, EntityId, "Edit"); + break; + default: + authorized = User.IsInRole(Constants.AdminRole); + break; + } + return authorized; + } } } From 8351ec2d7173c7f9135c35e412ebbb9bbe8b33ef Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 30 Aug 2019 22:27:49 -0400 Subject: [PATCH 33/44] Refactored IModule and ITheme interfaces for future compatibility scenarios. Added Permissions property to IModule interface to allow for explicit ordering and custom module permissions. --- .../Modules/Controls/PermissionGrid.razor | 11 +++--- Oqtane.Client/Modules/Counter/Module.cs | 22 +++++++----- Oqtane.Client/Modules/HtmlText/Module.cs | 22 +++++++----- Oqtane.Client/Modules/IModule.cs | 13 +++---- Oqtane.Client/Modules/Weather/Module.cs | 22 +++++++----- Oqtane.Client/Themes/ITheme.cs | 9 ++--- Oqtane.Client/Themes/Theme1/Theme.cs | 23 +++++++----- Oqtane.Client/Themes/Theme2/Theme.cs | 23 +++++++----- Oqtane.Client/Themes/Theme3/Theme.cs | 23 +++++++----- .../Repository/ModuleDefinitionRepository.cs | 36 ++++++++++++------- Oqtane.Server/Repository/ThemeRepository.cs | 31 ++++++++++------ Oqtane.Shared/Models/ModuleDefinition.cs | 1 + 12 files changed, 144 insertions(+), 92 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/PermissionGrid.razor b/Oqtane.Client/Modules/Controls/PermissionGrid.razor index d330a9b6..eed771a4 100644 --- a/Oqtane.Client/Modules/Controls/PermissionGrid.razor +++ b/Oqtane.Client/Modules/Controls/PermissionGrid.razor @@ -81,9 +81,7 @@ [Parameter] public string Permissions { get; set; } - [Parameter] - public string PermissionNames { get; set; } // optional - can be used to specify permissions order or add custom permissions - + string permissionnames = ""; List roles; List permissions = new List(); List users = new List(); @@ -92,14 +90,15 @@ protected override async Task OnInitializedAsync() { - if (string.IsNullOrEmpty(PermissionNames)) + permissionnames = PageState.ModuleDefinitions.Find(item => item.ModuleDefinitionName == ModuleState.ModuleDefinitionName).Permissions; + if (string.IsNullOrEmpty(permissionnames)) { - PermissionNames = "View,Edit"; + permissionnames = "View,Edit"; } roles = await RoleService.GetRolesAsync(ModuleState.SiteId); roles.Insert(0, new Role { Name = Constants.AllUsersRole }); - foreach (string permissionname in PermissionNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + foreach (string permissionname in permissionnames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { permissions.Add(new PermissionString { PermissionName = permissionname, Permissions = "" }); } diff --git a/Oqtane.Client/Modules/Counter/Module.cs b/Oqtane.Client/Modules/Counter/Module.cs index 63973db1..c7c95897 100644 --- a/Oqtane.Client/Modules/Counter/Module.cs +++ b/Oqtane.Client/Modules/Counter/Module.cs @@ -1,16 +1,22 @@ using Oqtane.Modules; +using System.Collections.Generic; namespace Oqtane.Client.Modules.Counter { public class Module : IModule { - public string Name { get { return "Counter"; } } - public string Description { get { return "Increments a counter"; } } - public string Version { get { return "1.0.0"; } } - public string Owner { get { return ""; } } - public string Url { get { return ""; } } - public string Contact { get { return ""; } } - public string License { get { return ""; } } - public string Dependencies { get { return ""; } } + public Dictionary Properties + { + get + { + Dictionary properties = new Dictionary + { + { "Name", "Counter" }, + { "Description", "Increments a counter" }, + { "Version", "1.0.0" } + }; + return properties; + } + } } } diff --git a/Oqtane.Client/Modules/HtmlText/Module.cs b/Oqtane.Client/Modules/HtmlText/Module.cs index 5fff736d..c21d8023 100644 --- a/Oqtane.Client/Modules/HtmlText/Module.cs +++ b/Oqtane.Client/Modules/HtmlText/Module.cs @@ -1,16 +1,22 @@ using Oqtane.Modules; +using System.Collections.Generic; namespace Oqtane.Client.Modules.HtmlText { public class Module : IModule { - public string Name { get { return "HtmlText"; } } - public string Description { get { return "Renders HTML or Text"; } } - public string Version { get { return "1.0.0"; } } - public string Owner { get { return ""; } } - public string Url { get { return ""; } } - public string Contact { get { return ""; } } - public string License { get { return ""; } } - public string Dependencies { get { return ""; } } + public Dictionary Properties + { + get + { + Dictionary properties = new Dictionary + { + { "Name", "HtmlText" }, + { "Description", "Renders HTML or Text" }, + { "Version", "1.0.0" } + }; + return properties; + } + } } } diff --git a/Oqtane.Client/Modules/IModule.cs b/Oqtane.Client/Modules/IModule.cs index 510c36a3..675378b8 100644 --- a/Oqtane.Client/Modules/IModule.cs +++ b/Oqtane.Client/Modules/IModule.cs @@ -1,14 +1,9 @@ -namespace Oqtane.Modules +using System.Collections.Generic; + +namespace Oqtane.Modules { public interface IModule { - string Name { get; } - string Description { get; } - string Version { get; } - string Owner { get; } - string Url { get; } - string Contact { get; } - string License { get; } - string Dependencies { get; } + Dictionary Properties { get; } } } diff --git a/Oqtane.Client/Modules/Weather/Module.cs b/Oqtane.Client/Modules/Weather/Module.cs index d816244b..e4134815 100644 --- a/Oqtane.Client/Modules/Weather/Module.cs +++ b/Oqtane.Client/Modules/Weather/Module.cs @@ -1,16 +1,22 @@ using Oqtane.Modules; +using System.Collections.Generic; namespace Oqtane.Client.Modules.Weather { public class Module : IModule { - public string Name { get { return "Weather"; } } - public string Description { get { return "Displays random weather using a service"; } } - public string Version { get { return "1.0.0"; } } - public string Owner { get { return ""; } } - public string Url { get { return ""; } } - public string Contact { get { return ""; } } - public string License { get { return ""; } } - public string Dependencies { get { return ""; } } + public Dictionary Properties + { + get + { + Dictionary properties = new Dictionary + { + { "Name", "Weather" }, + { "Description", "Displays random weather using a service" }, + { "Version", "1.0.0" } + }; + return properties; + } + } } } diff --git a/Oqtane.Client/Themes/ITheme.cs b/Oqtane.Client/Themes/ITheme.cs index 4a8ab2ab..134ec3a2 100644 --- a/Oqtane.Client/Themes/ITheme.cs +++ b/Oqtane.Client/Themes/ITheme.cs @@ -1,15 +1,10 @@ using System; +using System.Collections.Generic; namespace Oqtane.Themes { public interface ITheme { - string Name { get; } - string Version { get; } - string Owner { get; } - string Url { get; } - string Contact { get; } - string License { get; } - string Dependencies { get; } + Dictionary Properties { get; } } } diff --git a/Oqtane.Client/Themes/Theme1/Theme.cs b/Oqtane.Client/Themes/Theme1/Theme.cs index 715f75e5..3c1db0ca 100644 --- a/Oqtane.Client/Themes/Theme1/Theme.cs +++ b/Oqtane.Client/Themes/Theme1/Theme.cs @@ -1,13 +1,20 @@ -namespace Oqtane.Themes.Theme1 +using System.Collections.Generic; + +namespace Oqtane.Themes.Theme1 { public class Theme : ITheme { - public string Name { get { return "Theme1"; } } - public string Version { get { return "1.0.0"; } } - public string Owner { get { return ""; } } - public string Url { get { return ""; } } - public string Contact { get { return ""; } } - public string License { get { return ""; } } - public string Dependencies { get { return ""; } } + public Dictionary Properties + { + get + { + Dictionary properties = new Dictionary + { + { "Name", "Theme1" }, + { "Version", "1.0.0" } + }; + return properties; + } + } } } diff --git a/Oqtane.Client/Themes/Theme2/Theme.cs b/Oqtane.Client/Themes/Theme2/Theme.cs index 8107c75d..377bb1ad 100644 --- a/Oqtane.Client/Themes/Theme2/Theme.cs +++ b/Oqtane.Client/Themes/Theme2/Theme.cs @@ -1,13 +1,20 @@ -namespace Oqtane.Themes.Theme2 +using System.Collections.Generic; + +namespace Oqtane.Themes.Theme2 { public class Theme : ITheme { - public string Name { get { return "Theme2"; } } - public string Version { get { return "1.0.0"; } } - public string Owner { get { return ""; } } - public string Url { get { return ""; } } - public string Contact { get { return ""; } } - public string License { get { return ""; } } - public string Dependencies { get { return ""; } } + public Dictionary Properties + { + get + { + Dictionary properties = new Dictionary + { + { "Name", "Theme2" }, + { "Version", "1.0.0" } + }; + return properties; + } + } } } diff --git a/Oqtane.Client/Themes/Theme3/Theme.cs b/Oqtane.Client/Themes/Theme3/Theme.cs index 7edfd0d5..53def728 100644 --- a/Oqtane.Client/Themes/Theme3/Theme.cs +++ b/Oqtane.Client/Themes/Theme3/Theme.cs @@ -1,13 +1,20 @@ -namespace Oqtane.Themes.Theme3 +using System.Collections.Generic; + +namespace Oqtane.Themes.Theme3 { public class Theme : ITheme { - public string Name { get { return "Theme3"; } } - public string Version { get { return "1.0.0"; } } - public string Owner { get { return ""; } } - public string Url { get { return ""; } } - public string Contact { get { return ""; } } - public string License { get { return ""; } } - public string Dependencies { get { return ""; } } + public Dictionary Properties + { + get + { + Dictionary properties = new Dictionary + { + { "Name", "Theme3" }, + { "Version", "1.0.0" } + }; + return properties; + } + } } } diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index d626ead3..b02bee82 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -51,24 +51,26 @@ namespace Oqtane.Repository { /// determine if this module implements IModule Type moduletype = assembly.GetTypes() - .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(ModuleType)) - .Where(item => item.GetInterfaces().Contains(typeof(IModule))) - .FirstOrDefault(); + .Where(item => item.Namespace != null) + .Where(item => item.Namespace.StartsWith(ModuleType)) + .Where(item => item.GetInterfaces().Contains(typeof(IModule))) + .FirstOrDefault(); if (moduletype != null) { var moduleobject = Activator.CreateInstance(moduletype); + Dictionary properties = (Dictionary)moduletype.GetProperty("Properties").GetValue(moduleobject); moduledefinition = new ModuleDefinition { ModuleDefinitionName = QualifiedModuleType, - Name = (string)moduletype.GetProperty("Name").GetValue(moduleobject), - Description = (string)moduletype.GetProperty("Description").GetValue(moduleobject), - Version = (string)moduletype.GetProperty("Version").GetValue(moduleobject), - Owner = (string)moduletype.GetProperty("Owner").GetValue(moduleobject), - Url = (string)moduletype.GetProperty("Url").GetValue(moduleobject), - Contact = (string)moduletype.GetProperty("Contact").GetValue(moduleobject), - License = (string)moduletype.GetProperty("License").GetValue(moduleobject), - Dependencies = (string)moduletype.GetProperty("Dependencies").GetValue(moduleobject), + Name = GetProperty(properties, "Name"), + Description = GetProperty(properties, "Description"), + Version = GetProperty(properties, "Version"), + Owner = GetProperty(properties, "Owner"), + Url = GetProperty(properties, "Url"), + Contact = GetProperty(properties, "Contact"), + License = GetProperty(properties, "License"), + Dependencies = GetProperty(properties, "Dependencies"), + Permissions = GetProperty(properties, "Permissions"), ControlTypeTemplate = ModuleType + ".{Control}" + ", " + typename[1], ControlTypeRoutes = "", AssemblyName = assembly.FullName.Split(",")[0] @@ -87,6 +89,7 @@ namespace Oqtane.Repository Contact = "", License = "", Dependencies = "", + Permissions = "", ControlTypeTemplate = ModuleType + ".{Control}" + ", " + typename[1], ControlTypeRoutes = "", AssemblyName = assembly.FullName.Split(",")[0] @@ -118,5 +121,14 @@ namespace Oqtane.Repository return ModuleDefinitions; } + private string GetProperty(Dictionary Properties, string Key) + { + string Value = ""; + if (Properties.ContainsKey(Key)) + { + Value = Properties[Key]; + } + return Value; + } } } diff --git a/Oqtane.Server/Repository/ThemeRepository.cs b/Oqtane.Server/Repository/ThemeRepository.cs index 1b7ead1e..5cac43fc 100644 --- a/Oqtane.Server/Repository/ThemeRepository.cs +++ b/Oqtane.Server/Repository/ThemeRepository.cs @@ -49,23 +49,24 @@ namespace Oqtane.Repository if (index == -1) { /// determine if this theme implements ITheme - Type themeType = assembly.GetTypes() + Type themetype = assembly.GetTypes() .Where(item => item.Namespace != null) .Where(item => item.Namespace.StartsWith(Namespace)) .Where(item => item.GetInterfaces().Contains(typeof(ITheme))).FirstOrDefault(); - if (themeType != null) + if (themetype != null) { - var themeObject = Activator.CreateInstance(themeType); + var themeobject = Activator.CreateInstance(themetype); + Dictionary properties = (Dictionary)themetype.GetProperty("Properties").GetValue(themeobject); theme = new Theme { ThemeName = Namespace, - Name = (string)themeType.GetProperty("Name").GetValue(themeObject), - Version = (string)themeType.GetProperty("Version").GetValue(themeObject), - Owner = (string)themeType.GetProperty("Owner").GetValue(themeObject), - Url = (string)themeType.GetProperty("Url").GetValue(themeObject), - Contact = (string)themeType.GetProperty("Contact").GetValue(themeObject), - License = (string)themeType.GetProperty("License").GetValue(themeObject), - Dependencies = (string)themeType.GetProperty("Dependencies").GetValue(themeObject), + Name = GetProperty(properties, "Name"), + Version = GetProperty(properties, "Version"), + Owner = GetProperty(properties, "Owner"), + Url = GetProperty(properties, "Url"), + Contact = GetProperty(properties, "Contact"), + License = GetProperty(properties, "License"), + Dependencies = GetProperty(properties, "Dependencies"), ThemeControls = "", PaneLayouts = "", ContainerControls = "", @@ -122,5 +123,15 @@ namespace Oqtane.Repository { return Themes; } + + private string GetProperty(Dictionary Properties, string Key) + { + string Value = ""; + if (Properties.ContainsKey(Key)) + { + Value = Properties[Key]; + } + return Value; + } } } diff --git a/Oqtane.Shared/Models/ModuleDefinition.cs b/Oqtane.Shared/Models/ModuleDefinition.cs index 75ba1902..86d3dc54 100644 --- a/Oqtane.Shared/Models/ModuleDefinition.cs +++ b/Oqtane.Shared/Models/ModuleDefinition.cs @@ -11,6 +11,7 @@ public string Contact { get; set; } public string License { get; set; } public string Dependencies { get; set; } + public string Permissions { get; set; } public string ControlTypeTemplate { get; set; } public string ControlTypeRoutes { get; set; } public string AssemblyName { get; set; } From 6ad47159552ad501f8cd1a242099aa62bc5eaa99 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Sat, 31 Aug 2019 00:04:53 -0400 Subject: [PATCH 34/44] optimize for IEnumerable and remove unnecessary exception handling in repostory --- Oqtane.Server/Repository/AliasRepository.cs | 63 +++------- .../Interfaces/IPermissionRepository.cs | 4 +- Oqtane.Server/Repository/ModuleRepository.cs | 93 ++++----------- .../Repository/PageModuleRepository.cs | 89 ++++---------- Oqtane.Server/Repository/PageRepository.cs | 88 ++++---------- .../Repository/PermissionRepository.cs | 98 ++++------------ Oqtane.Server/Repository/RoleRepository.cs | 75 +++--------- Oqtane.Server/Repository/SettingRepository.cs | 59 ++-------- Oqtane.Server/Repository/SiteRepository.cs | 57 ++------- .../Repository/SiteUserRepository.cs | 81 +++---------- Oqtane.Server/Repository/TenantRepository.cs | 65 +++-------- Oqtane.Server/Repository/TenantResolver.cs | 22 +--- Oqtane.Server/Repository/UserRepository.cs | 66 ++--------- .../Repository/UserRoleRepository.cs | 85 +++----------- Oqtane.Server/Scripts/00.00.00.sql | 110 ++++++++++++++++++ 15 files changed, 322 insertions(+), 733 deletions(-) diff --git a/Oqtane.Server/Repository/AliasRepository.cs b/Oqtane.Server/Repository/AliasRepository.cs index 1ebda180..e8fd87b9 100644 --- a/Oqtane.Server/Repository/AliasRepository.cs +++ b/Oqtane.Server/Repository/AliasRepository.cs @@ -20,72 +20,37 @@ namespace Oqtane.Repository public IEnumerable GetAliases() { - try + return _cache.GetOrCreate("aliases", entry => { - return _cache.GetOrCreate("aliases", entry => - { - entry.SlidingExpiration = TimeSpan.FromMinutes(30); - return db.Alias.ToList(); - }); - } - catch - { - throw; - } + entry.SlidingExpiration = TimeSpan.FromMinutes(30); + return db.Alias.ToList(); + }); } public Alias AddAlias(Alias Alias) { - try - { - db.Alias.Add(Alias); - db.SaveChanges(); - return Alias; - } - catch - { - throw; - } + db.Alias.Add(Alias); + db.SaveChanges(); + return Alias; } public Alias UpdateAlias(Alias Alias) { - try - { - db.Entry(Alias).State = EntityState.Modified; - db.SaveChanges(); - return Alias; - } - catch - { - throw; - } + db.Entry(Alias).State = EntityState.Modified; + db.SaveChanges(); + return Alias; } public Alias GetAlias(int AliasId) { - try - { - return db.Alias.Find(AliasId); - } - catch - { - throw; - } + return db.Alias.Find(AliasId); } public void DeleteAlias(int AliasId) { - try - { - Alias alias = db.Alias.Find(AliasId); - db.Alias.Remove(alias); - db.SaveChanges(); - } - catch - { - throw; - } + Alias alias = db.Alias.Find(AliasId); + db.Alias.Remove(alias); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/Interfaces/IPermissionRepository.cs b/Oqtane.Server/Repository/Interfaces/IPermissionRepository.cs index c569d86b..4b4b01c5 100644 --- a/Oqtane.Server/Repository/Interfaces/IPermissionRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/IPermissionRepository.cs @@ -13,7 +13,7 @@ namespace Oqtane.Repository void UpdatePermissions(int SiteId, string EntityName, int EntityId, string Permissions); Permission GetPermission(int PermissionId); void DeletePermission(int PermissionId); - string EncodePermissions(int EntityId, List Permissions); - List DecodePermissions(string Permissions, int SiteId, string EntityName, int EntityId); + string EncodePermissions(int EntityId, IEnumerable Permissions); + IEnumerable DecodePermissions(string Permissions, int SiteId, string EntityName, int EntityId); } } diff --git a/Oqtane.Server/Repository/ModuleRepository.cs b/Oqtane.Server/Repository/ModuleRepository.cs index cc453ff7..2754161c 100644 --- a/Oqtane.Server/Repository/ModuleRepository.cs +++ b/Oqtane.Server/Repository/ModuleRepository.cs @@ -18,98 +18,55 @@ namespace Oqtane.Repository public IEnumerable GetModules() { - try - { - return db.Module.ToList(); - } - catch - { - throw; - } + return db.Module; } public IEnumerable GetModules(int SiteId, string ModuleDefinitionName) { - try + IEnumerable permissions = Permissions.GetPermissions(SiteId, "Module").ToList(); + IEnumerable modules = db.Module + .Where(item => item.SiteId == SiteId) + .Where(item => item.ModuleDefinitionName == ModuleDefinitionName); + foreach (Module module in modules) { - List permissions = Permissions.GetPermissions(SiteId, "Module").ToList(); - List modules = db.Module - .Where(item => item.SiteId == SiteId) - .Where(item => item.ModuleDefinitionName == ModuleDefinitionName) - .ToList(); - foreach (Module module in modules) - { - module.Permissions = Permissions.EncodePermissions(module.ModuleId, permissions); - } - return modules; - } - catch - { - throw; + module.Permissions = Permissions.EncodePermissions(module.ModuleId, permissions); } + return modules; } public Module AddModule(Module Module) { - try - { - db.Module.Add(Module); - db.SaveChanges(); - Permissions.UpdatePermissions(Module.SiteId, "Module", Module.ModuleId, Module.Permissions); - return Module; - } - catch - { - throw; - } + db.Module.Add(Module); + db.SaveChanges(); + Permissions.UpdatePermissions(Module.SiteId, "Module", Module.ModuleId, Module.Permissions); + return Module; } public Module UpdateModule(Module Module) { - try - { - db.Entry(Module).State = EntityState.Modified; - db.SaveChanges(); - Permissions.UpdatePermissions(Module.SiteId, "Module", Module.ModuleId, Module.Permissions); - return Module; - } - catch - { - throw; - } + db.Entry(Module).State = EntityState.Modified; + db.SaveChanges(); + Permissions.UpdatePermissions(Module.SiteId, "Module", Module.ModuleId, Module.Permissions); + return Module; } public Module GetModule(int ModuleId) { - try + Module module = db.Module.Find(ModuleId); + if (module != null) { - Module module = db.Module.Find(ModuleId); - if (module != null) - { - List permissions = Permissions.GetPermissions("Module", module.ModuleId).ToList(); - module.Permissions = Permissions.EncodePermissions(module.ModuleId, permissions); - } - return module; - } - catch - { - throw; + List permissions = Permissions.GetPermissions("Module", module.ModuleId).ToList(); + module.Permissions = Permissions.EncodePermissions(module.ModuleId, permissions); } + return module; } public void DeleteModule(int ModuleId) { - try - { - Module Module = db.Module.Find(ModuleId); - Permissions.UpdatePermissions(Module.SiteId, "Module", ModuleId, ""); - db.Module.Remove(Module); - db.SaveChanges(); - } - catch - { - throw; - } + Module Module = db.Module.Find(ModuleId); + Permissions.UpdatePermissions(Module.SiteId, "Module", ModuleId, ""); + db.Module.Remove(Module); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/PageModuleRepository.cs b/Oqtane.Server/Repository/PageModuleRepository.cs index 0a8aef19..9eb829d1 100644 --- a/Oqtane.Server/Repository/PageModuleRepository.cs +++ b/Oqtane.Server/Repository/PageModuleRepository.cs @@ -18,97 +18,54 @@ namespace Oqtane.Repository public IEnumerable GetPageModules() { - try - { - return db.PageModule.ToList(); - } - catch - { - throw; - } + return db.PageModule; } public IEnumerable GetPageModules(int PageId) { - try + IEnumerable pagemodules = db.PageModule.Where(item => item.PageId == PageId) + .Include(item => item.Module); // eager load modules + if (pagemodules != null && pagemodules.Any()) { - List pagemodules = db.PageModule.Where(item => item.PageId == PageId) - .Include(item => item.Module) // eager load modules - .ToList(); - if (pagemodules != null && pagemodules.Any()) + IEnumerable permissions = Permissions.GetPermissions(pagemodules.FirstOrDefault().Module.SiteId, "Module").ToList(); + foreach (PageModule pagemodule in pagemodules) { - List permissions = Permissions.GetPermissions(pagemodules.FirstOrDefault().Module.SiteId, "Module").ToList(); - foreach (PageModule pagemodule in pagemodules) - { - pagemodule.Module.Permissions = Permissions.EncodePermissions(pagemodule.ModuleId, permissions); - } + pagemodule.Module.Permissions = Permissions.EncodePermissions(pagemodule.ModuleId, permissions); } - return pagemodules; - } - catch - { - throw; } + return pagemodules; } public PageModule AddPageModule(PageModule PageModule) { - try - { - db.PageModule.Add(PageModule); - db.SaveChanges(); - return PageModule; - } - catch - { - throw; - } + db.PageModule.Add(PageModule); + db.SaveChanges(); + return PageModule; } public PageModule UpdatePageModule(PageModule PageModule) { - try - { - db.Entry(PageModule).State = EntityState.Modified; - db.SaveChanges(); - return PageModule; - } - catch - { - throw; - } + db.Entry(PageModule).State = EntityState.Modified; + db.SaveChanges(); + return PageModule; } public PageModule GetPageModule(int PageModuleId) { - try + PageModule pagemodule = db.PageModule.Include(item => item.Module) // eager load modules + .SingleOrDefault(item => item.PageModuleId == PageModuleId); + if (pagemodule != null) { - PageModule pagemodule = db.PageModule.Include(item => item.Module) // eager load modules - .SingleOrDefault(item => item.PageModuleId == PageModuleId); - if (pagemodule != null) - { - List permissions = Permissions.GetPermissions("Module", pagemodule.ModuleId).ToList(); - pagemodule.Module.Permissions = Permissions.EncodePermissions(pagemodule.ModuleId, permissions); - } - return pagemodule; - } - catch - { - throw; + IEnumerable permissions = Permissions.GetPermissions("Module", pagemodule.ModuleId); + pagemodule.Module.Permissions = Permissions.EncodePermissions(pagemodule.ModuleId, permissions); } + return pagemodule; } public void DeletePageModule(int PageModuleId) { - try - { - PageModule PageModule = db.PageModule.Find(PageModuleId); - db.PageModule.Remove(PageModule); - db.SaveChanges(); - } - catch - { - throw; - } + PageModule PageModule = db.PageModule.Find(PageModuleId); + db.PageModule.Remove(PageModule); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/PageRepository.cs b/Oqtane.Server/Repository/PageRepository.cs index 250f6390..5b849d1b 100644 --- a/Oqtane.Server/Repository/PageRepository.cs +++ b/Oqtane.Server/Repository/PageRepository.cs @@ -18,95 +18,53 @@ namespace Oqtane.Repository public IEnumerable GetPages() { - try - { - return db.Page.ToList(); - } - catch - { - throw; - } + return db.Page.ToList(); } public IEnumerable GetPages(int SiteId) { - try + IEnumerable permissions = Permissions.GetPermissions(SiteId, "Page").ToList(); + IEnumerable pages = db.Page.Where(item => item.SiteId == SiteId); + foreach(Page page in pages) { - List permissions = Permissions.GetPermissions(SiteId, "Page").ToList(); - List pages = db.Page.Where(item => item.SiteId == SiteId).ToList(); - foreach(Page page in pages) - { - page.Permissions = Permissions.EncodePermissions(page.PageId, permissions); - } - return pages; - } - catch - { - throw; + page.Permissions = Permissions.EncodePermissions(page.PageId, permissions); } + return pages; } public Page AddPage(Page Page) { - try - { - db.Page.Add(Page); - db.SaveChanges(); - Permissions.UpdatePermissions(Page.SiteId, "Page", Page.PageId, Page.Permissions); - return Page; - } - catch - { - throw; - } + db.Page.Add(Page); + db.SaveChanges(); + Permissions.UpdatePermissions(Page.SiteId, "Page", Page.PageId, Page.Permissions); + return Page; } public Page UpdatePage(Page Page) { - try - { - db.Entry(Page).State = EntityState.Modified; - db.SaveChanges(); - Permissions.UpdatePermissions(Page.SiteId, "Page", Page.PageId, Page.Permissions); - return Page; - } - catch - { - throw; - } + db.Entry(Page).State = EntityState.Modified; + db.SaveChanges(); + Permissions.UpdatePermissions(Page.SiteId, "Page", Page.PageId, Page.Permissions); + return Page; } public Page GetPage(int PageId) { - try + Page page = db.Page.Find(PageId); + if (page != null) { - Page page = db.Page.Find(PageId); - if (page != null) - { - List permissions = Permissions.GetPermissions("Page", page.PageId).ToList(); - page.Permissions = Permissions.EncodePermissions(page.PageId, permissions); - } - return page; - } - catch - { - throw; + IEnumerable permissions = Permissions.GetPermissions("Page", page.PageId); + page.Permissions = Permissions.EncodePermissions(page.PageId, permissions); } + return page; } public void DeletePage(int PageId) { - try - { - Page Page = db.Page.Find(PageId); - Permissions.UpdatePermissions(Page.SiteId, "Page", PageId, ""); - db.Page.Remove(Page); - db.SaveChanges(); - } - catch - { - throw; - } + Page Page = db.Page.Find(PageId); + Permissions.UpdatePermissions(Page.SiteId, "Page", PageId, ""); + db.Page.Remove(Page); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/PermissionRepository.cs b/Oqtane.Server/Repository/PermissionRepository.cs index 682e797e..a4b3f323 100644 --- a/Oqtane.Server/Repository/PermissionRepository.cs +++ b/Oqtane.Server/Repository/PermissionRepository.cs @@ -22,80 +22,46 @@ namespace Oqtane.Repository public IEnumerable GetPermissions(int SiteId, string EntityName) { - try - { - return db.Permission.Where(item => item.SiteId == SiteId) - .Where(item => item.EntityName == EntityName) - .Include(item => item.Role); // eager load roles - } - catch - { - throw; - } + return db.Permission.Where(item => item.SiteId == SiteId) + .Where(item => item.EntityName == EntityName) + .Include(item => item.Role); // eager load roles } public IEnumerable GetPermissions(string EntityName, int EntityId) { - try - { - return db.Permission.Where(item => item.EntityName == EntityName) - .Where(item => item.EntityId == EntityId) - .Include(item => item.Role); // eager load roles - } - catch - { - throw; - } + return db.Permission.Where(item => item.EntityName == EntityName) + .Where(item => item.EntityId == EntityId) + .Include(item => item.Role); // eager load roles } public IEnumerable GetPermissions(string EntityName, int EntityId, string PermissionName) { - try - { - return db.Permission.Where(item => item.EntityName == EntityName) - .Where(item => item.EntityId == EntityId) - .Where(item => item.PermissionName == PermissionName) - .Include(item => item.Role); // eager load roles - } - catch - { - throw; - } + return db.Permission.Where(item => item.EntityName == EntityName) + .Where(item => item.EntityId == EntityId) + .Where(item => item.PermissionName == PermissionName) + .Include(item => item.Role); // eager load roles } public Permission AddPermission(Permission Permission) { - try - { - db.Permission.Add(Permission); - db.SaveChanges(); - return Permission; - } - catch - { - throw; - } + db.Permission.Add(Permission); + db.SaveChanges(); + return Permission; } public Permission UpdatePermission(Permission Permission) { - try - { - db.Entry(Permission).State = EntityState.Modified; - db.SaveChanges(); - return Permission; - } - catch - { - throw; - } + db.Entry(Permission).State = EntityState.Modified; + db.SaveChanges(); + return Permission; } public void UpdatePermissions(int SiteId, string EntityName, int EntityId, string Permissions) { // get current permissions and delete - List permissions = db.Permission.Where(item => item.EntityName == EntityName) - .Where(item => item.EntityId == EntityId).ToList(); + IEnumerable permissions = db.Permission + .Where(item => item.EntityName == EntityName) + .Where(item => item.EntityId == EntityId); foreach(Permission permission in permissions) { db.Permission.Remove(permission); @@ -111,32 +77,18 @@ namespace Oqtane.Repository public Permission GetPermission(int PermissionId) { - try - { - return db.Permission.Find(PermissionId); - } - catch - { - throw; - } + return db.Permission.Find(PermissionId); } public void DeletePermission(int PermissionId) { - try - { - Permission Permission = db.Permission.Find(PermissionId); - db.Permission.Remove(Permission); - db.SaveChanges(); - } - catch - { - throw; - } + Permission Permission = db.Permission.Find(PermissionId); + db.Permission.Remove(Permission); + db.SaveChanges(); } // permissions are stored in the format "{permissionname:!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]}" where "!" designates Deny permissions - public string EncodePermissions(int EntityId, List Permissions) + public string EncodePermissions(int EntityId, IEnumerable Permissions) { List permissionstrings = new List(); string permissionname = ""; @@ -189,7 +141,7 @@ namespace Oqtane.Repository return JsonSerializer.Serialize(permissionstrings); } - public List DecodePermissions(string PermissionStrings, int SiteId, string EntityName, int EntityId) + public IEnumerable DecodePermissions(string PermissionStrings, int SiteId, string EntityName, int EntityId) { List permissions = new List(); List roles = Roles.GetRoles(SiteId, true).ToList(); diff --git a/Oqtane.Server/Repository/RoleRepository.cs b/Oqtane.Server/Repository/RoleRepository.cs index fe99ecf8..97958b07 100644 --- a/Oqtane.Server/Repository/RoleRepository.cs +++ b/Oqtane.Server/Repository/RoleRepository.cs @@ -16,93 +16,44 @@ namespace Oqtane.Repository public IEnumerable GetRoles() { - try - { - return db.Role.ToList(); - } - catch - { - throw; - } + return db.Role; } public IEnumerable GetRoles(int SiteId) { - try - { - return db.Role.Where(item => item.SiteId == SiteId).ToList(); - } - catch - { - throw; - } + return db.Role.Where(item => item.SiteId == SiteId); } public IEnumerable GetRoles(int SiteId, bool IncludeGlobalRoles) { - try - { - return db.Role.Where(item => item.SiteId == SiteId || item.SiteId == null).ToList(); - } - catch - { - throw; - } + return db.Role.Where(item => item.SiteId == SiteId || item.SiteId == null); } public Role AddRole(Role Role) { - try - { - db.Role.Add(Role); - db.SaveChanges(); - return Role; - } - catch - { - throw; - } + db.Role.Add(Role); + db.SaveChanges(); + return Role; } public Role UpdateRole(Role Role) { - try - { - db.Entry(Role).State = EntityState.Modified; - db.SaveChanges(); - return Role; - } - catch - { - throw; - } + db.Entry(Role).State = EntityState.Modified; + db.SaveChanges(); + return Role; } public Role GetRole(int RoleId) { - try - { - return db.Role.Find(RoleId); - } - catch - { - throw; - } + return db.Role.Find(RoleId); } public void DeleteRole(int RoleId) { - try - { - Role Role = db.Role.Find(RoleId); - db.Role.Remove(Role); - db.SaveChanges(); - } - catch - { - throw; - } + Role Role = db.Role.Find(RoleId); + db.Role.Remove(Role); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index a12040ec..b191c9c5 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -16,69 +16,34 @@ namespace Oqtane.Repository public IEnumerable GetSettings(string EntityName, int EntityId) { - try - { - return db.Setting.Where(item => item.EntityName == EntityName) - .Where(item => item.EntityId == EntityId).ToList(); - } - catch - { - throw; - } + return db.Setting.Where(item => item.EntityName == EntityName) + .Where(item => item.EntityId == EntityId); } public Setting AddSetting(Setting Setting) { - try - { - db.Setting.Add(Setting); - db.SaveChanges(); - return Setting; - } - catch - { - throw; - } + db.Setting.Add(Setting); + db.SaveChanges(); + return Setting; } public Setting UpdateSetting(Setting Setting) { - try - { - db.Entry(Setting).State = EntityState.Modified; - db.SaveChanges(); - return Setting; - } - catch - { - throw; - } + db.Entry(Setting).State = EntityState.Modified; + db.SaveChanges(); + return Setting; } public Setting GetSetting(int SettingId) { - try - { - return db.Setting.Find(SettingId); - } - catch - { - throw; - } + return db.Setting.Find(SettingId); } public void DeleteSetting(int SettingId) { - try - { - Setting Setting = db.Setting.Find(SettingId); - db.Setting.Remove(Setting); - db.SaveChanges(); - } - catch - { - throw; - } + Setting Setting = db.Setting.Find(SettingId); + db.Setting.Remove(Setting); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 88ec72df..3f200162 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -16,68 +16,33 @@ namespace Oqtane.Repository public IEnumerable GetSites() { - try - { - return db.Site.ToList(); - } - catch - { - throw; - } + return db.Site; } public Site AddSite(Site Site) { - try - { - db.Site.Add(Site); - db.SaveChanges(); - return Site; - } - catch - { - throw; - } + db.Site.Add(Site); + db.SaveChanges(); + return Site; } public Site UpdateSite(Site Site) { - try - { - db.Entry(Site).State = EntityState.Modified; - db.SaveChanges(); - return Site; - } - catch - { - throw; - } + db.Entry(Site).State = EntityState.Modified; + db.SaveChanges(); + return Site; } public Site GetSite(int siteId) { - try - { - return db.Site.Find(siteId); - } - catch - { - throw; - } + return db.Site.Find(siteId); } public void DeleteSite(int siteId) { - try - { - Site site = db.Site.Find(siteId); - db.Site.Remove(site); - db.SaveChanges(); - } - catch - { - throw; - } + Site site = db.Site.Find(siteId); + db.Site.Remove(site); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/SiteUserRepository.cs b/Oqtane.Server/Repository/SiteUserRepository.cs index f0209b48..4d7cb1b6 100644 --- a/Oqtane.Server/Repository/SiteUserRepository.cs +++ b/Oqtane.Server/Repository/SiteUserRepository.cs @@ -16,94 +16,45 @@ namespace Oqtane.Repository public IEnumerable GetSiteUsers() { - try - { - return db.SiteUser.ToList(); - } - catch - { - throw; - } + return db.SiteUser; } public IEnumerable GetSiteUsers(int SiteId) { - try - { - return db.SiteUser.Where(item => item.SiteId == SiteId) - .Include(item => item.User) // eager load users - .ToList(); - } - catch - { - throw; - } + return db.SiteUser.Where(item => item.SiteId == SiteId) + .Include(item => item.User); // eager load users } public SiteUser AddSiteUser(SiteUser SiteUser) { - try - { - db.SiteUser.Add(SiteUser); - db.SaveChanges(); - return SiteUser; - } - catch - { - throw; - } + db.SiteUser.Add(SiteUser); + db.SaveChanges(); + return SiteUser; } public SiteUser UpdateSiteUser(SiteUser SiteUser) { - try - { - db.Entry(SiteUser).State = EntityState.Modified; - db.SaveChanges(); - return SiteUser; - } - catch - { - throw; - } + db.Entry(SiteUser).State = EntityState.Modified; + db.SaveChanges(); + return SiteUser; } public SiteUser GetSiteUser(int SiteUserId) { - try - { - return db.SiteUser.Include(item => item.User) // eager load users - .SingleOrDefault(item => item.SiteUserId == SiteUserId); - } - catch - { - throw; - } + return db.SiteUser.Include(item => item.User) // eager load users + .SingleOrDefault(item => item.SiteUserId == SiteUserId); } public SiteUser GetSiteUser(int SiteId, int UserId) { - try - { - return db.SiteUser.Where(item => item.SiteId == SiteId).Where(item => item.UserId == UserId).FirstOrDefault(); - } - catch - { - throw; - } + return db.SiteUser.Where(item => item.SiteId == SiteId) + .Where(item => item.UserId == UserId).FirstOrDefault(); } public void DeleteSiteUser(int SiteUserId) { - try - { - SiteUser SiteUser = db.SiteUser.Find(SiteUserId); - db.SiteUser.Remove(SiteUser); - db.SaveChanges(); - } - catch - { - throw; - } + SiteUser SiteUser = db.SiteUser.Find(SiteUserId); + db.SiteUser.Remove(SiteUser); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/TenantRepository.cs b/Oqtane.Server/Repository/TenantRepository.cs index 58d7df30..e64a57e3 100644 --- a/Oqtane.Server/Repository/TenantRepository.cs +++ b/Oqtane.Server/Repository/TenantRepository.cs @@ -21,72 +21,37 @@ namespace Oqtane.Repository public IEnumerable GetTenants() { - try + return _cache.GetOrCreate("tenants", entry => { - return _cache.GetOrCreate("tenants", entry => - { - entry.SlidingExpiration = TimeSpan.FromMinutes(30); - return db.Tenant.ToList(); - }); - } - catch - { - throw; - } + entry.SlidingExpiration = TimeSpan.FromMinutes(30); + return db.Tenant.ToList(); + }); } public Tenant AddTenant(Tenant Tenant) { - try - { - db.Tenant.Add(Tenant); - db.SaveChanges(); - return Tenant; - } - catch - { - throw; - } + db.Tenant.Add(Tenant); + db.SaveChanges(); + return Tenant; } public Tenant UpdateTenant(Tenant Tenant) { - try - { - db.Entry(Tenant).State = EntityState.Modified; - db.SaveChanges(); - return Tenant; - } - catch - { - throw; - } + db.Entry(Tenant).State = EntityState.Modified; + db.SaveChanges(); + return Tenant; } public Tenant GetTenant(int TenantId) { - try - { - return db.Tenant.Find(TenantId); - } - catch - { - throw; - } + return db.Tenant.Find(TenantId); } public void DeleteTenant(int TenantId) - { - try - { - Tenant tenant = db.Tenant.Find(TenantId); - db.Tenant.Remove(tenant); - db.SaveChanges(); - } - catch - { - throw; - } + { + Tenant tenant = db.Tenant.Find(TenantId); + db.Tenant.Remove(tenant); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/TenantResolver.cs b/Oqtane.Server/Repository/TenantResolver.cs index 3c8de2f8..579c99b9 100644 --- a/Oqtane.Server/Repository/TenantResolver.cs +++ b/Oqtane.Server/Repository/TenantResolver.cs @@ -35,28 +35,14 @@ namespace Oqtane.Repository public Alias GetAlias() { - try - { - IEnumerable aliases = _aliasrepository.GetAliases(); // cached - return aliases.Where(item => item.Name == aliasname).FirstOrDefault(); - } - catch - { - throw; - } + IEnumerable aliases = _aliasrepository.GetAliases(); // cached + return aliases.Where(item => item.Name == aliasname).FirstOrDefault(); } public Tenant GetTenant() { - try - { - IEnumerable tenants = _tenantrepository.GetTenants(); // cached - return tenants.Where(item => item.TenantId == GetAlias().TenantId).FirstOrDefault(); - } - catch - { - throw; - } + IEnumerable tenants = _tenantrepository.GetTenants(); // cached + return tenants.Where(item => item.TenantId == GetAlias().TenantId).FirstOrDefault(); } } } \ No newline at end of file diff --git a/Oqtane.Server/Repository/UserRepository.cs b/Oqtane.Server/Repository/UserRepository.cs index c31b73d4..e182dae4 100644 --- a/Oqtane.Server/Repository/UserRepository.cs +++ b/Oqtane.Server/Repository/UserRepository.cs @@ -16,80 +16,38 @@ namespace Oqtane.Repository public IEnumerable GetUsers() { - try - { - return db.User.ToList(); - } - catch - { - throw; - } + return db.User; } public User AddUser(User user) { - try - { - db.User.Add(user); - db.SaveChanges(); - return user; - } - catch - { - throw; - } + db.User.Add(user); + db.SaveChanges(); + return user; } public User UpdateUser(User user) { - try - { - db.Entry(user).State = EntityState.Modified; - db.SaveChanges(); - return user; - } - catch - { - throw; - } + db.Entry(user).State = EntityState.Modified; + db.SaveChanges(); + return user; } public User GetUser(int userId) { - try - { - return db.User.Find(userId); - } - catch - { - throw; - } + return db.User.Find(userId); } public User GetUser(string Username) { - try - { - return db.User.Where(item => item.Username == Username).FirstOrDefault(); - } - catch - { - throw; - } + return db.User.Where(item => item.Username == Username).FirstOrDefault(); } public void DeleteUser(int userId) { - try - { - User user = db.User.Find(userId); - db.User.Remove(user); - db.SaveChanges(); - } - catch - { - throw; - } + User user = db.User.Find(userId); + db.User.Remove(user); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Repository/UserRoleRepository.cs b/Oqtane.Server/Repository/UserRoleRepository.cs index 82911356..e752c832 100644 --- a/Oqtane.Server/Repository/UserRoleRepository.cs +++ b/Oqtane.Server/Repository/UserRoleRepository.cs @@ -16,97 +16,46 @@ namespace Oqtane.Repository public IEnumerable GetUserRoles() { - try - { - return db.UserRole.ToList(); - } - catch - { - throw; - } + return db.UserRole; } public IEnumerable GetUserRoles(int UserId) { - try - { - return db.UserRole.Where(item => item.UserId == UserId) - .Include(item => item.Role) // eager load roles - .ToList(); - } - catch - { - throw; - } + return db.UserRole.Where(item => item.UserId == UserId) + .Include(item => item.Role); // eager load roles } public IEnumerable GetUserRoles(int UserId, int SiteId) { - try - { - return db.UserRole.Where(item => item.UserId == UserId) - .Include(item => item.Role) // eager load roles - .Where(item => item.Role.SiteId == SiteId) - .ToList(); - } - catch - { - throw; - } + return db.UserRole.Where(item => item.UserId == UserId) + .Include(item => item.Role) // eager load roles + .Where(item => item.Role.SiteId == SiteId); } public UserRole AddUserRole(UserRole UserRole) { - try - { - db.UserRole.Add(UserRole); - db.SaveChanges(); - return UserRole; - } - catch - { - throw; - } + db.UserRole.Add(UserRole); + db.SaveChanges(); + return UserRole; } public UserRole UpdateUserRole(UserRole UserRole) { - try - { - db.Entry(UserRole).State = EntityState.Modified; - db.SaveChanges(); - return UserRole; - } - catch - { - throw; - } + db.Entry(UserRole).State = EntityState.Modified; + db.SaveChanges(); + return UserRole; } public UserRole GetUserRole(int UserRoleId) { - try - { - return db.UserRole.Include(item => item.Role) // eager load roles - .SingleOrDefault(item => item.UserRoleId == UserRoleId); - } - catch - { - throw; - } + return db.UserRole.Include(item => item.Role) // eager load roles + .SingleOrDefault(item => item.UserRoleId == UserRoleId); } public void DeleteUserRole(int UserRoleId) { - try - { - UserRole UserRole = db.UserRole.Find(UserRoleId); - db.UserRole.Remove(UserRole); - db.SaveChanges(); - } - catch - { - throw; - } + UserRole UserRole = db.UserRole.Find(UserRoleId); + db.UserRole.Remove(UserRole); + db.SaveChanges(); } } } diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql index 6e34d641..094073f4 100644 --- a/Oqtane.Server/Scripts/00.00.00.sql +++ b/Oqtane.Server/Scripts/00.00.00.sql @@ -232,6 +232,38 @@ REFERENCES [dbo].[Module] ([ModuleId]) ON DELETE CASCADE GO +ALTER TABLE dbo.Role ADD CONSTRAINT FK_Role_Site FOREIGN KEY (SiteId) +REFERENCES dbo.Site (SiteId) +ON DELETE CASCADE +GO + +ALTER TABLE dbo.UserRole ADD CONSTRAINT FK_UserRole_User FOREIGN KEY (UserId) +REFERENCES dbo.[User] (UserId) +ON DELETE CASCADE +GO + +ALTER TABLE dbo.UserRole ADD CONSTRAINT FK_UserRole_Role FOREIGN KEY (RoleId) +REFERENCES dbo.Role (RoleId) +GO + +ALTER TABLE dbo.Permission ADD CONSTRAINT FK_Permission_Site FOREIGN KEY (SiteId) +REFERENCES dbo.Site (SiteId) +ON DELETE CASCADE +GO + +ALTER TABLE dbo.Permission ADD CONSTRAINT FK_Permission_User FOREIGN KEY (UserId) +REFERENCES dbo.[User] (UserId) +GO + +ALTER TABLE dbo.Permission ADD CONSTRAINT FK_Permission_Role FOREIGN KEY (RoleId) +REFERENCES dbo.Role (RoleId) +GO + +ALTER TABLE dbo.PageModule ADD CONSTRAINT FK_PageModule_Page FOREIGN KEY (PageId) +REFERENCES dbo.Page (PageId) +ON DELETE CASCADE +GO + /* Create indexes @@ -246,6 +278,44 @@ CREATE UNIQUE NONCLUSTERED INDEX IX_Setting ON dbo.Setting ) ON [PRIMARY] GO +CREATE UNIQUE NONCLUSTERED INDEX IX_User ON dbo.[User] + ( + Username + ) ON [PRIMARY] +GO + +CREATE UNIQUE NONCLUSTERED INDEX IX_SiteUser ON dbo.SiteUser + ( + SiteId, + UserId + ) ON [PRIMARY] +GO + +CREATE UNIQUE NONCLUSTERED INDEX IX_Permission ON dbo.Permission + ( + SiteId, + EntityName, + EntityId, + PermissionName, + RoleId, + UserId + ) ON [PRIMARY] +GO + +CREATE UNIQUE NONCLUSTERED INDEX IX_Page ON dbo.Page + ( + SiteId, + [Path] + ) ON [PRIMARY] +GO + +CREATE UNIQUE NONCLUSTERED INDEX IX_UserRole ON dbo.UserRole + ( + RoleId, + UserId + ) ON [PRIMARY] +GO + /* Create seed data @@ -293,6 +363,8 @@ VALUES (1, 1, N'Page1', N'', N'Oqtane.Client.Themes.Theme1.Theme1, Oqtane.Client GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 1, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 1, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 1, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -307,6 +379,8 @@ VALUES (3, 1, N'Page3', N'page3', N'Oqtane.Client.Themes.Theme3.Theme3, Oqtane.C GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 3, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 3, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 3, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -328,6 +402,8 @@ VALUES (6, 1, N'Login', N'login', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.C GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 6, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 6, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 6, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -335,6 +411,8 @@ VALUES (7, 1, N'Register', N'register', N'Oqtane.Client.Themes.Theme2.Theme2, Oq GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 7, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 7, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 7, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -370,6 +448,8 @@ VALUES (12, 2, N'Page1', N'', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Clien GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 12, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 12, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 12, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -377,6 +457,8 @@ VALUES (13, 2, N'Page2', N'page2', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane. GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 13, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 13, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 13, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -384,6 +466,8 @@ VALUES (14, 2, N'Login', N'login', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane. GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 14, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 14, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 14, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -391,6 +475,8 @@ VALUES (15, 2, N'Register', N'register', N'Oqtane.Client.Themes.Theme2.Theme2, O GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 15, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 15, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Page', 15, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -410,6 +496,8 @@ VALUES (1, 1, N'Oqtane.Client.Modules.Weather, Oqtane.Client', '', getdate(), '' GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 1, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 1, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 1, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -417,6 +505,8 @@ VALUES (2, 1, N'Oqtane.Client.Modules.Counter, Oqtane.Client', '', getdate(), '' GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 2, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 2, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 2, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -424,6 +514,8 @@ VALUES (3, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', '', getdate(), ' GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 3, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 3, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 3, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -431,6 +523,8 @@ VALUES (4, 1, N'Oqtane.Client.Modules.Weather, Oqtane.Client', '', getdate(), '' GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 4, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 4, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 4, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -438,6 +532,8 @@ VALUES (5, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', '', getdate(), ' GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 5, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 5, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 5, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -445,6 +541,8 @@ VALUES (6, 1, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', '', getdate(), ' GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 6, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 6, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 6, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -466,6 +564,8 @@ VALUES (9, 1, N'Oqtane.Client.Modules.Admin.Login, Oqtane.Client', '', getdate() GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 9, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 9, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 9, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -473,6 +573,8 @@ VALUES (10, 1, N'Oqtane.Client.Modules.Admin.Register, Oqtane.Client', '', getda GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 10, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 10, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 10, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -515,6 +617,8 @@ VALUES (16, 2, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', '', getdate(), GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 16, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 16, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 16, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -522,6 +626,8 @@ VALUES (17, 2, N'Oqtane.Client.Modules.HtmlText, Oqtane.Client', '', getdate(), GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 17, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 17, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 17, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -529,6 +635,8 @@ VALUES (18, 2, N'Oqtane.Client.Modules.Admin.Login, Oqtane.Client', '', getdate( GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 18, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 18, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 18, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -536,6 +644,8 @@ VALUES (19, 2, N'Oqtane.Client.Modules.Admin.Register, Oqtane.Client', '', getda GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 19, 'View', -1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 19, 'View', 3, null, 1, '', getdate(), '', getdate()) +GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (2, 'Module', 19, 'Edit', 3, null, 1, '', getdate(), '', getdate()) GO INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) From 368d0e1eeee5970b477ea4463874055150c458fc Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Sat, 31 Aug 2019 11:10:15 -0400 Subject: [PATCH 35/44] Fixed installation script issue --- Oqtane.Server/Scripts/00.00.00.sql | 51 ++++++++++++++---------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql index 094073f4..b8b8ad32 100644 --- a/Oqtane.Server/Scripts/00.00.00.sql +++ b/Oqtane.Server/Scripts/00.00.00.sql @@ -199,71 +199,66 @@ GO Create foreign key relationships */ -ALTER TABLE [dbo].[Module] WITH CHECK ADD CONSTRAINT [FK_Module_Site] FOREIGN KEY([SiteId]) +ALTER TABLE [dbo].[Module] WITH CHECK ADD CONSTRAINT [FK_Module_Site] FOREIGN KEY([SiteId]) REFERENCES [dbo].[Site] ([SiteId]) ON DELETE CASCADE GO -ALTER TABLE [dbo].[Page] WITH CHECK ADD CONSTRAINT [FK_Page_Site] FOREIGN KEY([SiteId]) +ALTER TABLE [dbo].[Page] WITH CHECK ADD CONSTRAINT [FK_Page_Site] FOREIGN KEY([SiteId]) REFERENCES [dbo].[Site] ([SiteId]) ON DELETE CASCADE GO -ALTER TABLE [dbo].[PageModule] WITH CHECK ADD CONSTRAINT [FK_PageModule_Module] FOREIGN KEY([ModuleId]) +ALTER TABLE [dbo].[PageModule] WITH CHECK ADD CONSTRAINT [FK_PageModule_Module] FOREIGN KEY([ModuleId]) REFERENCES [dbo].[Module] ([ModuleId]) GO -ALTER TABLE [dbo].[PageModule] WITH CHECK ADD CONSTRAINT [FK_PageModule_Page] FOREIGN KEY([PageId]) +ALTER TABLE [dbo].[PageModule] WITH CHECK ADD CONSTRAINT [FK_PageModule_Page] FOREIGN KEY([PageId]) REFERENCES [dbo].[Page] ([PageId]) ON DELETE CASCADE GO -ALTER TABLE [dbo].[SiteUser] WITH CHECK ADD CONSTRAINT [FK_SiteUser_Site] FOREIGN KEY([SiteId]) +ALTER TABLE [dbo].[SiteUser] WITH CHECK ADD CONSTRAINT [FK_SiteUser_Site] FOREIGN KEY([SiteId]) REFERENCES [dbo].[Site] ([SiteId]) ON DELETE CASCADE GO -ALTER TABLE [dbo].[SiteUser] WITH CHECK ADD CONSTRAINT [FK_SiteUser_User] FOREIGN KEY([UserId]) +ALTER TABLE [dbo].[SiteUser] WITH CHECK ADD CONSTRAINT [FK_SiteUser_User] FOREIGN KEY([UserId]) REFERENCES [dbo].[User] ([UserId]) GO -ALTER TABLE [dbo].[HtmlText] WITH CHECK ADD CONSTRAINT [FK_HtmlText_Module] FOREIGN KEY([ModuleId]) +ALTER TABLE [dbo].[HtmlText] WITH CHECK ADD CONSTRAINT [FK_HtmlText_Module] FOREIGN KEY([ModuleId]) REFERENCES [dbo].[Module] ([ModuleId]) ON DELETE CASCADE GO -ALTER TABLE dbo.Role ADD CONSTRAINT FK_Role_Site FOREIGN KEY (SiteId) -REFERENCES dbo.Site (SiteId) +ALTER TABLE [dbo].[Role] WITH CHECK ADD CONSTRAINT [FK_Role_Site] FOREIGN KEY ([SiteId]) +REFERENCES [dbo].[Site] ([SiteId]) ON DELETE CASCADE GO -ALTER TABLE dbo.UserRole ADD CONSTRAINT FK_UserRole_User FOREIGN KEY (UserId) -REFERENCES dbo.[User] (UserId) -ON DELETE CASCADE -GO - -ALTER TABLE dbo.UserRole ADD CONSTRAINT FK_UserRole_Role FOREIGN KEY (RoleId) -REFERENCES dbo.Role (RoleId) -GO - -ALTER TABLE dbo.Permission ADD CONSTRAINT FK_Permission_Site FOREIGN KEY (SiteId) -REFERENCES dbo.Site (SiteId) +ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_User] FOREIGN KEY ([UserId]) +REFERENCES [dbo].[User] ([UserId]) ON DELETE CASCADE GO -ALTER TABLE dbo.Permission ADD CONSTRAINT FK_Permission_User FOREIGN KEY (UserId) -REFERENCES dbo.[User] (UserId) +ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_Role] FOREIGN KEY ([RoleId]) +REFERENCES [dbo].[Role] ([RoleId]) GO -ALTER TABLE dbo.Permission ADD CONSTRAINT FK_Permission_Role FOREIGN KEY (RoleId) -REFERENCES dbo.Role (RoleId) -GO - -ALTER TABLE dbo.PageModule ADD CONSTRAINT FK_PageModule_Page FOREIGN KEY (PageId) -REFERENCES dbo.Page (PageId) +ALTER TABLE [dbo].[Permission] WITH CHECK ADD CONSTRAINT [FK_Permission_Site] FOREIGN KEY ([SiteId]) +REFERENCES [dbo].[Site] ([SiteId]) ON DELETE CASCADE GO +ALTER TABLE [dbo].[Permission] WITH CHECK ADD CONSTRAINT [FK_Permission_User] FOREIGN KEY ([UserId]) +REFERENCES [dbo].[User] ([UserId]) +GO + +ALTER TABLE [dbo].[Permission] WITH CHECK ADD CONSTRAINT [FK_Permission_Role] FOREIGN KEY ([RoleId]) +REFERENCES [dbo].[Role] ([RoleId]) +GO + /* Create indexes From da890f32d16c87b13cb71de52862998b875e3ef1 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 2 Sep 2019 14:21:31 -0400 Subject: [PATCH 36/44] Added support for Deny permissions to PermissionGrid --- .../Modules/Controls/PermissionGrid.razor | 47 ++++++++++---- .../Modules/Controls/TriStateCheckBox.razor | 60 ++++++++++++++++++ Oqtane.Client/wwwroot/images/checked.png | Bin 0 -> 427 bytes Oqtane.Client/wwwroot/images/null.png | Bin 0 -> 177 bytes Oqtane.Client/wwwroot/images/unchecked.png | Bin 0 -> 438 bytes Oqtane.Server/Scripts/00.00.00.sql | 27 ++++++++ Oqtane.Server/wwwroot/images/checked.png | Bin 0 -> 427 bytes Oqtane.Server/wwwroot/images/null.png | Bin 0 -> 177 bytes Oqtane.Server/wwwroot/images/unchecked.png | Bin 0 -> 438 bytes 9 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 Oqtane.Client/Modules/Controls/TriStateCheckBox.razor create mode 100644 Oqtane.Client/wwwroot/images/checked.png create mode 100644 Oqtane.Client/wwwroot/images/null.png create mode 100644 Oqtane.Client/wwwroot/images/unchecked.png create mode 100644 Oqtane.Server/wwwroot/images/checked.png create mode 100644 Oqtane.Server/wwwroot/images/null.png create mode 100644 Oqtane.Server/wwwroot/images/unchecked.png diff --git a/Oqtane.Client/Modules/Controls/PermissionGrid.razor b/Oqtane.Client/Modules/Controls/PermissionGrid.razor index eed771a4..f1762af4 100644 --- a/Oqtane.Client/Modules/Controls/PermissionGrid.razor +++ b/Oqtane.Client/Modules/Controls/PermissionGrid.razor @@ -28,7 +28,9 @@ @foreach (PermissionString permission in permissions) { var p = permission; - + + + } } @@ -51,12 +53,15 @@ @foreach (User user in users) { + string userid = "[" + user.UserId.ToString() + "]"; @user.DisplayName @foreach (PermissionString permission in permissions) { var p = permission; - + + + } } @@ -125,15 +130,22 @@ } } - private bool GetPermissionValue(string Permissions, string SecurityKey) + private bool? GetPermissionValue(string Permissions, string SecurityKey) { - if ((";" + Permissions + ";").Contains(";" + SecurityKey + ";")) + if ((";" + Permissions + ";").Contains(";" + "!" + SecurityKey + ";")) { - return true; + return false; // deny permission } else { - return false; + if ((";" + Permissions + ";").Contains(";" + SecurityKey + ";")) + { + return true; // grant permission + } + else + { + return null; // not specified + } } } @@ -169,20 +181,27 @@ username = ""; } - private void PermissionChanged(UIChangeEventArgs e, string PermissionName, string SecurityId) + private void PermissionChanged(bool? Value, string PermissionName, string SecurityId) { - bool selected = (bool)e.Value; + bool? selected = Value; PermissionString permission = permissions.Find(item => item.PermissionName == PermissionName); if (permission != null) { List ids = permission.Permissions.Split(';').ToList(); - if (selected) + + ids.Remove(SecurityId); // remove grant permission + ids.Remove("!" + SecurityId); // remove deny permission + + switch (selected) { - ids.Add(SecurityId); - } - else - { - ids.Remove(SecurityId); + case true: + ids.Add(SecurityId); // add grant permission + break; + case false: + ids.Add("!" + SecurityId); // add deny permission + break; + case null: + break; // permission not specified } permissions[permissions.FindIndex(item => item.PermissionName == PermissionName)].Permissions = string.Join(";", ids.ToArray()); } diff --git a/Oqtane.Client/Modules/Controls/TriStateCheckBox.razor b/Oqtane.Client/Modules/Controls/TriStateCheckBox.razor new file mode 100644 index 00000000..9c75e34d --- /dev/null +++ b/Oqtane.Client/Modules/Controls/TriStateCheckBox.razor @@ -0,0 +1,60 @@ + + +@code { + [Parameter] + public bool? Value { get; set; } + + [Parameter] + public bool Disabled { get; set; } + + [Parameter] + public Action OnChange { get; set; } + + bool? value = null; + string title; + string src = ""; + + protected override void OnInitialized() + { + value = Value; + SetImage(); + } + + private void SetValue() + { + switch (value) + { + case true: + value = false; + break; + case false: + value = null; + break; + case null: + value = true; + break; + } + SetImage(); + OnChange(value); + } + + private void SetImage() + { + switch (value) + { + case true: + src = "images/checked.png"; + title = "Permission Granted"; + break; + case false: + src = "images/unchecked.png"; + title = "Permission Denied"; + break; + case null: + src = "images/null.png"; + title = ""; + break; + } + StateHasChanged(); + } +} diff --git a/Oqtane.Client/wwwroot/images/checked.png b/Oqtane.Client/wwwroot/images/checked.png new file mode 100644 index 0000000000000000000000000000000000000000..a4100c70a27c17c9da8ae3001183f6c335a2bdda GIT binary patch literal 427 zcmV;c0aX5pP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E-^XO*0N*(00A3GL_t(IPh-&ZF--E^pZd%FP~v}5u-A^H zkJ>)QNem#(UZ+z3lY>Ee8NjAtkt7C#^pa$N&*}94-lx*we3A?RY25zm(ErXmv*2PR z88G4g!v9aczxW?^E*~yNv;kRH8vnol_33}%)pitdq6`Q=oBRLq_vim-JY0?;hhad> z`BIcX0%4H9kG?zi-xnBw$l@T3VZfzNH~;T?edK@OnQSn>|K0+i?Jxd^oXvx)LB<#c zM4m7DfA+)G|JOg?{a<@?!v9adzx*%0)`6l48Dkg#!l1Zb`+VpBU;lpppN_@f$QY{u zAPfqJl#A8>ebB-K9pf~BSPVA6?@;!lvI6;>1s;*b z3=BeG%-Ex}lN~51S>hT|5}cn_Ql40p%21G)nOCBhms+A=qGzCIXnEz@rWBweJx>?M z5DWk0AOHW`JJ;6!tuHe0(2p?Q$*`pSN<$#C8}EW?j1E#c9F{-@|9Ke7MVA=K*OvML PbuxIm`njxgN@xNACvh`; literal 0 HcmV?d00001 diff --git a/Oqtane.Client/wwwroot/images/unchecked.png b/Oqtane.Client/wwwroot/images/unchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..566e60a8e19044766052c5859586b5bfec830853 GIT binary patch literal 438 zcmV;n0ZIOeP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E-^XO*0N*(00AaRL_t(IPo0xJYr;SPhVyq?{3oKAh`MKR zS2w>F{YyHCIJtC-v<^a3D3W&YE3sgpO5f%^@n~`vFdd%ZKHleY?-9d%c(k2T>H8(0 zM;4w6g}}whAsCPGF&M}>MZoaI_u=(= za*i;3oXv1rEZ|lua$XS-hR?elylz*F-EtYn=@ci&!CS2s+p852hA;a)ynY|SWO5Bx ztIEDq0b%$j3=ytY+Av8K@UwX`!{^N=wOFk{6n49Fbh0S+aFCt+MG?rh6L%J!P?C5Z zMc|J{;;E8t6Y)CRE!K^OoKpm!!y(+1!pOSS!h5|g$BG~;SAl5;y2X2VjgfVE_OC07*qoM6N<$g1LygEC2ui literal 0 HcmV?d00001 diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql index b8b8ad32..2f97a61e 100644 --- a/Oqtane.Server/Scripts/00.00.00.sql +++ b/Oqtane.Server/Scripts/00.00.00.sql @@ -179,6 +179,28 @@ CREATE TABLE [dbo].[Setting]( ) GO +CREATE TABLE [dbo].[Profile]( + [ProfileId] [int] IDENTITY(1,1) NOT NULL, + [SiteId] [int] NULL, + [Name] [nvarchar](50) NOT NULL, + [Category] [nvarchar](50) NOT NULL, + [ViewOrder] [int] NOT NULL, + [MaxLength] [int] NOT NULL, + [DefaultValue] [nvarchar](2000) NULL, + [IsRequired] [bit] NOT NULL, + [IsPrivate] [bit] NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_Profile] PRIMARY KEY CLUSTERED + ( + [ProfileId] ASC + ) +) + +GO + CREATE TABLE [dbo].[HtmlText]( [HtmlTextId] [int] IDENTITY(1,1) NOT NULL, [ModuleId] [int] NOT NULL, @@ -259,6 +281,11 @@ ALTER TABLE [dbo].[Permission] WITH CHECK ADD CONSTRAINT [FK_Permission_Role] FO REFERENCES [dbo].[Role] ([RoleId]) GO +ALTER TABLE [dbo].[Profile] WITH NOCHECK ADD CONSTRAINT [FK_Profile_Sites] FOREIGN KEY([SiteId]) +REFERENCES [dbo].[Site] ([SiteId]) +ON DELETE CASCADE +GO + /* Create indexes diff --git a/Oqtane.Server/wwwroot/images/checked.png b/Oqtane.Server/wwwroot/images/checked.png new file mode 100644 index 0000000000000000000000000000000000000000..a4100c70a27c17c9da8ae3001183f6c335a2bdda GIT binary patch literal 427 zcmV;c0aX5pP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E-^XO*0N*(00A3GL_t(IPh-&ZF--E^pZd%FP~v}5u-A^H zkJ>)QNem#(UZ+z3lY>Ee8NjAtkt7C#^pa$N&*}94-lx*we3A?RY25zm(ErXmv*2PR z88G4g!v9aczxW?^E*~yNv;kRH8vnol_33}%)pitdq6`Q=oBRLq_vim-JY0?;hhad> z`BIcX0%4H9kG?zi-xnBw$l@T3VZfzNH~;T?edK@OnQSn>|K0+i?Jxd^oXvx)LB<#c zM4m7DfA+)G|JOg?{a<@?!v9adzx*%0)`6l48Dkg#!l1Zb`+VpBU;lpppN_@f$QY{u zAPfqJl#A8>ebB-K9pf~BSPVA6?@;!lvI6;>1s;*b z3=BeG%-Ex}lN~51S>hT|5}cn_Ql40p%21G)nOCBhms+A=qGzCIXnEz@rWBweJx>?M z5DWk0AOHW`JJ;6!tuHe0(2p?Q$*`pSN<$#C8}EW?j1E#c9F{-@|9Ke7MVA=K*OvML PbuxIm`njxgN@xNACvh`; literal 0 HcmV?d00001 diff --git a/Oqtane.Server/wwwroot/images/unchecked.png b/Oqtane.Server/wwwroot/images/unchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..566e60a8e19044766052c5859586b5bfec830853 GIT binary patch literal 438 zcmV;n0ZIOeP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E-^XO*0N*(00AaRL_t(IPo0xJYr;SPhVyq?{3oKAh`MKR zS2w>F{YyHCIJtC-v<^a3D3W&YE3sgpO5f%^@n~`vFdd%ZKHleY?-9d%c(k2T>H8(0 zM;4w6g}}whAsCPGF&M}>MZoaI_u=(= za*i;3oXv1rEZ|lua$XS-hR?elylz*F-EtYn=@ci&!CS2s+p852hA;a)ynY|SWO5Bx ztIEDq0b%$j3=ytY+Av8K@UwX`!{^N=wOFk{6n49Fbh0S+aFCt+MG?rh6L%J!P?C5Z zMc|J{;;E8t6Y)CRE!K^OoKpm!!y(+1!pOSS!h5|g$BG~;SAl5;y2X2VjgfVE_OC07*qoM6N<$g1LygEC2ui literal 0 HcmV?d00001 From 1e4c07889bf4e5c797c904149719114f8295bb65 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Tue, 3 Sep 2019 20:39:29 -0400 Subject: [PATCH 37/44] Dynamic user profile per tenant --- .../Admin/ModuleDefinitions/Index.razor | 2 +- .../Modules/Admin/ModuleSettings/Index.razor | 8 +- Oqtane.Client/Modules/Admin/Pages/Add.razor | 3 +- .../Modules/Admin/Pages/Delete.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Edit.razor | 2 +- Oqtane.Client/Modules/Admin/Pages/Index.razor | 2 +- .../Modules/Admin/Profile/Index.razor | 116 ++++++++++++++++ Oqtane.Client/Modules/Admin/Roles/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Sites/Add.razor | 2 +- Oqtane.Client/Modules/Admin/Sites/Index.razor | 2 +- .../Modules/Admin/Themes/Index.razor | 2 +- .../Modules/Controls/PermissionGrid.razor | 122 ++++++++-------- .../Services/Interfaces/IProfileService.cs | 21 +++ .../Services/Interfaces/ISettingService.cs | 10 +- Oqtane.Client/Services/ProfileService.cs | 59 ++++++++ Oqtane.Client/Services/SettingService.cs | 130 +++++++----------- Oqtane.Client/Startup.cs | 1 + Oqtane.Client/Themes/Controls/Profile.razor | 7 +- .../Controllers/ProfileController.cs | 73 ++++++++++ .../Repository/Context/TenantDBContext.cs | 1 + .../Interfaces/IProfileRepository.cs | 15 ++ Oqtane.Server/Repository/ProfileRepository.cs | 53 +++++++ Oqtane.Server/Scripts/00.00.00.sql | 52 +++++++ Oqtane.Server/Startup.cs | 2 + Oqtane.Shared/Models/Profile.cs | 24 ++++ 25 files changed, 558 insertions(+), 155 deletions(-) create mode 100644 Oqtane.Client/Modules/Admin/Profile/Index.razor create mode 100644 Oqtane.Client/Services/Interfaces/IProfileService.cs create mode 100644 Oqtane.Client/Services/ProfileService.cs create mode 100644 Oqtane.Server/Controllers/ProfileController.cs create mode 100644 Oqtane.Server/Repository/Interfaces/IProfileRepository.cs create mode 100644 Oqtane.Server/Repository/ProfileRepository.cs create mode 100644 Oqtane.Shared/Models/Profile.cs diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor index 4d3f8de3..87c2beff 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor @@ -12,7 +12,7 @@ } else { - +
    diff --git a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor index 80ebca10..90fb186e 100644 --- a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor @@ -11,7 +11,8 @@ @inject IModuleService ModuleService @inject IPageModuleService PageModuleService -
    Name
    +
    + + + -
    @@ -20,6 +21,8 @@
    @@ -55,7 +58,8 @@
    + + @DynamicComponent diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index 14c3db9c..b5ea1d43 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -11,7 +11,8 @@ @inject IThemeService ThemeService - + +
    diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index 5c5da1ff..a6327769 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -12,7 +12,7 @@ - +
    diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 43c64ee5..4eaa0287 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -12,7 +12,7 @@ - +
    } @@ -65,7 +65,7 @@ string displayname = ""; string email = ""; List profiles; - List settings; + Dictionary settings; string category = ""; protected override async Task OnInitializedAsync() @@ -103,12 +103,7 @@ user.DisplayName = displayname; user.Email = email; await UserService.UpdateUserAsync(user); - - foreach (Profile profile in profiles) - { - string value = SettingService.GetSetting(settings, profile.Name, ""); - await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId, profile.Name, value); - } + await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId); UriHelper.NavigateTo(""); } @@ -126,6 +121,6 @@ private void ProfileChanged(UIChangeEventArgs e, string SettingName) { string value = (string)e.Value; - settings = SettingService.SetSetting(settings, "User", PageState.User.UserId, SettingName, value); + settings = SettingService.SetSetting(settings, SettingName, value); } } diff --git a/Oqtane.Client/Services/Interfaces/ISettingService.cs b/Oqtane.Client/Services/Interfaces/ISettingService.cs index 56fccb43..66647129 100644 --- a/Oqtane.Client/Services/Interfaces/ISettingService.cs +++ b/Oqtane.Client/Services/Interfaces/ISettingService.cs @@ -6,32 +6,34 @@ namespace Oqtane.Services { public interface ISettingService { - Task> GetHostSettingsAsync(); + Task> GetHostSettingsAsync(); - Task UpdateHostSettingsAsync(List HostSettings, string SettingName, string SettingValue); + Task UpdateHostSettingsAsync(Dictionary HostSettings); - Task> GetSiteSettingsAsync(int SiteId); + Task> GetSiteSettingsAsync(int SiteId); - Task UpdateSiteSettingsAsync(List SiteSettings, int SiteId, string SettingName, string SettingValue); + Task UpdateSiteSettingsAsync(Dictionary SiteSettings, int SiteId); - Task> GetPageSettingsAsync(int PageId); + Task> GetPageSettingsAsync(int PageId); - Task UpdatePageSettingsAsync(List PageSettings, int PageId, string SettingName, string SettingValue); + Task UpdatePageSettingsAsync(Dictionary PageSettings, int PageId); - Task> GetPageModuleSettingsAsync(int PageModuleId); + Task> GetPageModuleSettingsAsync(int PageModuleId); - Task UpdatePageModuleSettingsAsync(List PageModuleSettings, int PageModuleId, string SettingName, string SettingValue); + Task UpdatePageModuleSettingsAsync(Dictionary PageModuleSettings, int PageModuleId); - Task> GetModuleSettingsAsync(int ModuleId); + Task> GetModuleSettingsAsync(int ModuleId); - Task UpdateModuleSettingsAsync(List ModuleSettings, int ModuleId, string SettingName, string SettingValue); + Task UpdateModuleSettingsAsync(Dictionary ModuleSettings, int ModuleId); - Task> GetUserSettingsAsync(int UserId); + Task> GetUserSettingsAsync(int UserId); - Task UpdateUserSettingsAsync(List UserSettings, int UserId, string SettingName, string SettingValue); + Task UpdateUserSettingsAsync(Dictionary UserSettings, int UserId); + Task> GetSettingsAsync(string EntityName, int EntityId); + + Task UpdateSettingsAsync(Dictionary Settings, string EntityName, int EntityId); - Task> GetSettingsAsync(string EntityName, int EntityId); Task GetSettingAsync(int SettingId); @@ -39,13 +41,11 @@ namespace Oqtane.Services Task UpdateSettingAsync(Setting Setting); - Task UpdateSettingsAsync(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue); - Task DeleteSettingAsync(int SettingId); - string GetSetting(List Settings, string SettingName, string DefaultValue); + string GetSetting(Dictionary Settings, string SettingName, string DefaultValue); - List SetSetting(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue); + Dictionary SetSetting(Dictionary Settings, string SettingName, string SettingValue); } } diff --git a/Oqtane.Client/Services/SettingService.cs b/Oqtane.Client/Services/SettingService.cs index 02a53dfe..f36b4d67 100644 --- a/Oqtane.Client/Services/SettingService.cs +++ b/Oqtane.Client/Services/SettingService.cs @@ -26,72 +26,101 @@ namespace Oqtane.Services get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Setting"); } } - public async Task> GetHostSettingsAsync() + public async Task> GetHostSettingsAsync() { return await GetSettingsAsync("Host", -1); } - public async Task UpdateHostSettingsAsync(List HostSettings, string SettingName, string SettingValue) + public async Task UpdateHostSettingsAsync(Dictionary HostSettings) { - return await UpdateSettingsAsync(HostSettings, "Host", -1, SettingName, SettingValue); + await UpdateSettingsAsync(HostSettings, "Host", -1); } - public async Task> GetSiteSettingsAsync(int SiteId) + public async Task> GetSiteSettingsAsync(int SiteId) { return await GetSettingsAsync("Site", SiteId); } - public async Task UpdateSiteSettingsAsync(List SiteSettings, int SiteId, string SettingName, string SettingValue) + public async Task UpdateSiteSettingsAsync(Dictionary SiteSettings, int SiteId) { - return await UpdateSettingsAsync(SiteSettings, "Site", SiteId, SettingName, SettingValue); + await UpdateSettingsAsync(SiteSettings, "Site", SiteId); } - public async Task> GetPageSettingsAsync(int PageId) + public async Task> GetPageSettingsAsync(int PageId) { return await GetSettingsAsync("Page", PageId); } - public async Task UpdatePageSettingsAsync(List PageSettings, int PageId, string SettingName, string SettingValue) + public async Task UpdatePageSettingsAsync(Dictionary PageSettings, int PageId) { - return await UpdateSettingsAsync(PageSettings, "Page", PageId, SettingName, SettingValue); + await UpdateSettingsAsync(PageSettings, "Page", PageId); } - public async Task> GetPageModuleSettingsAsync(int PageModuleId) + public async Task> GetPageModuleSettingsAsync(int PageModuleId) { return await GetSettingsAsync("PageModule", PageModuleId); } - public async Task UpdatePageModuleSettingsAsync(List PageModuleSettings, int PageModuleId, string SettingName, string SettingValue) + public async Task UpdatePageModuleSettingsAsync(Dictionary PageModuleSettings, int PageModuleId) { - return await UpdateSettingsAsync(PageModuleSettings, "PageModule", PageModuleId, SettingName, SettingValue); + await UpdateSettingsAsync(PageModuleSettings, "PageModule", PageModuleId); } - public async Task> GetModuleSettingsAsync(int ModuleId) + public async Task> GetModuleSettingsAsync(int ModuleId) { return await GetSettingsAsync("Module", ModuleId); } - public async Task UpdateModuleSettingsAsync(List ModuleSettings, int ModuleId, string SettingName, string SettingValue) + public async Task UpdateModuleSettingsAsync(Dictionary ModuleSettings, int ModuleId) { - return await UpdateSettingsAsync(ModuleSettings, "Module", ModuleId, SettingName, SettingValue); + await UpdateSettingsAsync(ModuleSettings, "Module", ModuleId); } - public async Task> GetUserSettingsAsync(int UserId) + public async Task> GetUserSettingsAsync(int UserId) { return await GetSettingsAsync("User", UserId); } - public async Task UpdateUserSettingsAsync(List UserSettings, int UserId, string SettingName, string SettingValue) + public async Task UpdateUserSettingsAsync(Dictionary UserSettings, int UserId) { - return await UpdateSettingsAsync(UserSettings, "User", UserId, SettingName, SettingValue); + await UpdateSettingsAsync(UserSettings, "User", UserId); } - public async Task> GetSettingsAsync(string EntityName, int EntityId) + public async Task> GetSettingsAsync(string EntityName, int EntityId) { + Dictionary dictionary = new Dictionary(); List Settings = await http.GetJsonAsync>(apiurl + "?entityname=" + EntityName + "&entityid=" + EntityId.ToString()); - return Settings.OrderBy(item => item.SettingName).ToList(); + foreach(Setting setting in Settings.OrderBy(item => item.SettingName).ToList()) + { + dictionary.Add(setting.SettingName, setting.SettingValue); + } + return dictionary; } + public async Task UpdateSettingsAsync(Dictionary Settings, string EntityName, int EntityId) + { + List settings = await http.GetJsonAsync>(apiurl + "?entityname=" + EntityName + "&entityid=" + EntityId.ToString()); + foreach (KeyValuePair kvp in Settings) + { + Setting setting = settings.Where(item => item.SettingName == kvp.Key).FirstOrDefault(); + if (setting == null) + { + setting = new Setting(); + setting.EntityName = EntityName; + setting.EntityId = EntityId; + setting.SettingName = kvp.Key; + setting.SettingValue = kvp.Value; + setting = await AddSettingAsync(setting); + } + else + { + setting.SettingValue = kvp.Value; + setting = await UpdateSettingAsync(setting); + } + } + } + + public async Task GetSettingAsync(int SettingId) { return await http.GetJsonAsync(apiurl + "/" + SettingId.ToString()); @@ -107,53 +136,31 @@ namespace Oqtane.Services return await http.PutJsonAsync(apiurl + "/" + Setting.SettingId.ToString(), Setting); } - public async Task UpdateSettingsAsync(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue) - { - Setting setting = Settings.Where(item => item.SettingName == SettingName).FirstOrDefault(); - if (setting == null || setting.SettingId == -1) - { - setting = new Setting(); - setting.EntityName = EntityName; - setting.EntityId = EntityId; - setting.SettingName = SettingName; - setting.SettingValue = SettingValue; - setting = await AddSettingAsync(setting); - } - else - { - setting.SettingValue = SettingValue; - setting = await UpdateSettingAsync(setting); - } - return setting; - } - public async Task DeleteSettingAsync(int SettingId) { await http.DeleteAsync(apiurl + "/" + SettingId.ToString()); } - public string GetSetting(List Settings, string SettingName, string DefaultValue) + public string GetSetting(Dictionary Settings, string SettingName, string DefaultValue) { string value = DefaultValue; - Setting setting = Settings.Where(item => item.SettingName == SettingName).FirstOrDefault(); - if (setting != null) + if (Settings.ContainsKey(SettingName)) { - value = setting.SettingValue; + value = Settings[SettingName]; } return value; } - public List SetSetting(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue) + public Dictionary SetSetting(Dictionary Settings, string SettingName, string SettingValue) { - int index = Settings.FindIndex(item => item.EntityName == EntityName && item.EntityId == EntityId && item.SettingName == SettingName); - if (index != -1) - { - Settings[index].SettingValue = SettingValue; + if (Settings.ContainsKey(SettingName)) + { + Settings[SettingName] = SettingValue; } else { - Settings.Add(new Setting { SettingId = -1, EntityName = EntityName, EntityId = EntityId, SettingName = SettingName, SettingValue = SettingValue }); + Settings.Add(SettingName, SettingValue); } return Settings; } From 22420f2b43322bccc1757bc670ea90886eb55e8b Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Thu, 5 Sep 2019 13:44:27 -0400 Subject: [PATCH 40/44] Edit mode improvements --- Oqtane.Client/Modules/Admin/Pages/Add.razor | 13 ++++ .../Modules/Admin/Pages/Delete.razor | 13 ++++ Oqtane.Client/Modules/Admin/Pages/Edit.razor | 14 ++++ Oqtane.Client/Modules/Admin/Pages/Index.razor | 2 +- .../Modules/Admin/Profile/Index.razor | 3 +- Oqtane.Client/Modules/IModuleControl.cs | 7 +- Oqtane.Client/Modules/ModuleBase.cs | 6 +- Oqtane.Client/Shared/Container.razor | 8 ++- Oqtane.Client/Shared/PageState.cs | 1 + Oqtane.Client/Shared/Pane.razor | 70 +++++++++++-------- Oqtane.Client/Shared/SiteRouter.razor | 33 +++++++-- .../Themes/Controls/ControlPanel.razor | 2 + .../Themes/Controls/ModuleActions.razor | 2 +- Oqtane.Server/Scripts/00.00.00.sql | 69 +++++++++--------- Oqtane.Shared/Models/Module.cs | 16 ++++- Oqtane.Shared/Models/Page.cs | 1 + .../Modules/SecurityAccessLevel.cs | 0 Oqtane.Shared/Shared/Constants.cs | 1 + 18 files changed, 179 insertions(+), 82 deletions(-) rename {Oqtane.Client => Oqtane.Shared}/Modules/SecurityAccessLevel.cs (100%) diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index b5ea1d43..606e1f1b 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -62,6 +62,17 @@ + + + + + + + + + + + +
    diff --git a/Oqtane.Client/Modules/Admin/Pages/Index.razor b/Oqtane.Client/Modules/Admin/Pages/Index.razor index cd972c59..ad7f0afe 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Index.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Index.razor @@ -12,7 +12,7 @@ else { - +
    diff --git a/Oqtane.Client/Modules/Admin/Profile/Index.razor b/Oqtane.Client/Modules/Admin/Profile/Index.razor new file mode 100644 index 00000000..32cebad4 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/Profile/Index.razor @@ -0,0 +1,116 @@ +@using Microsoft.AspNetCore.Components.Routing +@using Oqtane.Client.Modules.Controls +@using Oqtane.Modules +@using Oqtane.Models +@using Oqtane.Services +@inherits ModuleBase +@inject IUriHelper UriHelper +@inject IUserService UserService +@inject IProfileService ProfileService +@inject ISettingService SettingService + + + +@if (profiles != null) +{ +
     
    + + + + + + + + + + @foreach (Profile profile in profiles) + { + var p = profile; + if (p.Category != category) + { + + + + category = p.Category; + } + + + + + } +
    + + + +
    + + + +
    + @p.Category +
    + + + +
    + + +} + +@code { + public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } } + + string message = ""; + string displayname = ""; + string email = ""; + List profiles; + List settings; + string category = ""; + + protected override async Task OnInitializedAsync() + { + try + { + displayname = PageState.User.DisplayName; + email = PageState.User.Email; + profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId); + settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId); + } + catch (Exception ex) + { + message = ex.Message; + } + } + + private string GetProfileValue(string SettingName, string DefaultValue) + { + return SettingService.GetSetting(settings, SettingName, DefaultValue); + } + + private async Task SaveUser() + { + User user = PageState.User; + user.DisplayName = displayname; + user.Email = email; + await UserService.UpdateUserAsync(user); + + foreach (Profile profile in profiles) + { + string value = SettingService.GetSetting(settings, profile.Name, ""); + await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId, profile.Name, value); + } + + UriHelper.NavigateTo(""); + } + + private void Cancel() + { + UriHelper.NavigateTo(NavigateUrl("")); // navigate to home + } + + private void ProfileChanged(UIChangeEventArgs e, string SettingName) + { + string value = (string)e.Value; + settings = SettingService.SetSetting(settings, "User", PageState.User.UserId, SettingName, value); + } +} diff --git a/Oqtane.Client/Modules/Admin/Roles/Index.razor b/Oqtane.Client/Modules/Admin/Roles/Index.razor index c21f185d..012f2052 100644 --- a/Oqtane.Client/Modules/Admin/Roles/Index.razor +++ b/Oqtane.Client/Modules/Admin/Roles/Index.razor @@ -11,7 +11,7 @@ } else { - +
    diff --git a/Oqtane.Client/Modules/Admin/Sites/Add.razor b/Oqtane.Client/Modules/Admin/Sites/Add.razor index 48fc1dc5..d55e955f 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Add.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Add.razor @@ -17,7 +17,7 @@ } else { -
    Name
    +
    +
    diff --git a/Oqtane.Client/Modules/Admin/Sites/Index.razor b/Oqtane.Client/Modules/Admin/Sites/Index.razor index 8c57d292..f80dd108 100644 --- a/Oqtane.Client/Modules/Admin/Sites/Index.razor +++ b/Oqtane.Client/Modules/Admin/Sites/Index.razor @@ -12,7 +12,7 @@ } else { - +
    diff --git a/Oqtane.Client/Modules/Admin/Themes/Index.razor b/Oqtane.Client/Modules/Admin/Themes/Index.razor index 743215ee..34855ec8 100644 --- a/Oqtane.Client/Modules/Admin/Themes/Index.razor +++ b/Oqtane.Client/Modules/Admin/Themes/Index.razor @@ -11,7 +11,7 @@ } else { -
    Name
    +
    diff --git a/Oqtane.Client/Modules/Controls/PermissionGrid.razor b/Oqtane.Client/Modules/Controls/PermissionGrid.razor index f1762af4..e2f40f00 100644 --- a/Oqtane.Client/Modules/Controls/PermissionGrid.razor +++ b/Oqtane.Client/Modules/Controls/PermissionGrid.razor @@ -10,73 +10,71 @@ @if (roles != null) {
    -
    -
    -
    Name
    - +
    + + + + @foreach (PermissionString permission in permissions) + { + + } + + @foreach (Role role in roles) + { + + + @foreach (PermissionString permission in permissions) + { + var p = permission; + + } + + } + +
    Role@permission.PermissionName @EntityName
    @role.Name + +
    + @if (@users.Count != 0) + { + + + + + @foreach (PermissionString permission in permissions) + { + + } + + + + @foreach (User user in users) + { + string userid = "[" + user.UserId.ToString() + "]"; - + @foreach (PermissionString permission in permissions) { - + var p = permission; + } - @foreach (Role role in roles) - { - - - @foreach (PermissionString permission in permissions) - { - var p = permission; - - } - - } - -
    User@permission.PermissionName @EntityName
    Role@user.DisplayName@permission.PermissionName @EntityName + +
    @role.Name - -
    - - @if (@users.Count != 0) - { -
    - - - - - @foreach (PermissionString permission in permissions) - { - - } - - - - @foreach (User user in users) - { - string userid = "[" + user.UserId.ToString() + "]"; - - - @foreach (PermissionString permission in permissions) - { - var p = permission; - - } - - } - -
    User@permission.PermissionName @EntityName
    @user.DisplayName - -
    -
    - } -
    - - - -
    -
    - - + } +
    + } + + + + + + + + +
    +
    + } @code { diff --git a/Oqtane.Client/Services/Interfaces/IProfileService.cs b/Oqtane.Client/Services/Interfaces/IProfileService.cs new file mode 100644 index 00000000..e5f70bac --- /dev/null +++ b/Oqtane.Client/Services/Interfaces/IProfileService.cs @@ -0,0 +1,21 @@ +using Oqtane.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Oqtane.Services +{ + public interface IProfileService + { + Task> GetProfilesAsync(); + + Task> GetProfilesAsync(int SiteId); + + Task GetProfileAsync(int ProfileId); + + Task AddProfileAsync(Profile Profile); + + Task UpdateProfileAsync(Profile Profile); + + Task DeleteProfileAsync(int ProfileId); + } +} diff --git a/Oqtane.Client/Services/Interfaces/ISettingService.cs b/Oqtane.Client/Services/Interfaces/ISettingService.cs index c6b617c5..56fccb43 100644 --- a/Oqtane.Client/Services/Interfaces/ISettingService.cs +++ b/Oqtane.Client/Services/Interfaces/ISettingService.cs @@ -26,6 +26,10 @@ namespace Oqtane.Services Task UpdateModuleSettingsAsync(List ModuleSettings, int ModuleId, string SettingName, string SettingValue); + Task> GetUserSettingsAsync(int UserId); + + Task UpdateUserSettingsAsync(List UserSettings, int UserId, string SettingName, string SettingValue); + Task> GetSettingsAsync(string EntityName, int EntityId); @@ -35,9 +39,13 @@ namespace Oqtane.Services Task UpdateSettingAsync(Setting Setting); + Task UpdateSettingsAsync(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue); + Task DeleteSettingAsync(int SettingId); string GetSetting(List Settings, string SettingName, string DefaultValue); - } + + List SetSetting(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue); + } } diff --git a/Oqtane.Client/Services/ProfileService.cs b/Oqtane.Client/Services/ProfileService.cs new file mode 100644 index 00000000..4024c143 --- /dev/null +++ b/Oqtane.Client/Services/ProfileService.cs @@ -0,0 +1,59 @@ +using Oqtane.Models; +using System.Threading.Tasks; +using System.Net.Http; +using System.Linq; +using Microsoft.AspNetCore.Components; +using System.Collections.Generic; +using Oqtane.Shared; + +namespace Oqtane.Services +{ + public class ProfileService : ServiceBase, IProfileService + { + private readonly HttpClient http; + private readonly SiteState sitestate; + private readonly IUriHelper urihelper; + + public ProfileService(HttpClient http, SiteState sitestate, IUriHelper urihelper) + { + this.http = http; + this.sitestate = sitestate; + this.urihelper = urihelper; + } + + private string apiurl + { + get { return CreateApiUrl(sitestate.Alias, urihelper.GetAbsoluteUri(), "Profile"); } + } + + public async Task> GetProfilesAsync() + { + return await http.GetJsonAsync>(apiurl); + } + + public async Task> GetProfilesAsync(int SiteId) + { + List Profiles = await http.GetJsonAsync>(apiurl + "?siteid=" + SiteId.ToString()); + return Profiles.OrderBy(item => item.ViewOrder).ToList(); + } + + public async Task GetProfileAsync(int ProfileId) + { + return await http.GetJsonAsync(apiurl + "/" + ProfileId.ToString()); + } + + public async Task AddProfileAsync(Profile Profile) + { + return await http.PostJsonAsync(apiurl, Profile); + } + + public async Task UpdateProfileAsync(Profile Profile) + { + return await http.PutJsonAsync(apiurl + "/" + Profile.SiteId.ToString(), Profile); + } + public async Task DeleteProfileAsync(int ProfileId) + { + await http.DeleteAsync(apiurl + "/" + ProfileId.ToString()); + } + } +} diff --git a/Oqtane.Client/Services/SettingService.cs b/Oqtane.Client/Services/SettingService.cs index f6bfaac2..02a53dfe 100644 --- a/Oqtane.Client/Services/SettingService.cs +++ b/Oqtane.Client/Services/SettingService.cs @@ -33,22 +33,7 @@ namespace Oqtane.Services public async Task UpdateHostSettingsAsync(List HostSettings, string SettingName, string SettingValue) { - Setting setting = HostSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); - if (setting == null) - { - setting = new Setting(); - setting.EntityName = "Host"; - setting.EntityId = -1; - setting.SettingName = SettingName; - setting.SettingValue = SettingValue; - setting = await AddSettingAsync(setting); - } - else - { - setting.SettingValue = SettingValue; - setting = await UpdateSettingAsync(setting); - } - return setting; + return await UpdateSettingsAsync(HostSettings, "Host", -1, SettingName, SettingValue); } public async Task> GetSiteSettingsAsync(int SiteId) @@ -58,22 +43,7 @@ namespace Oqtane.Services public async Task UpdateSiteSettingsAsync(List SiteSettings, int SiteId, string SettingName, string SettingValue) { - Setting setting = SiteSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); - if (setting == null) - { - setting = new Setting(); - setting.EntityName = "Site"; - setting.EntityId = SiteId; - setting.SettingName = SettingName; - setting.SettingValue = SettingValue; - setting = await AddSettingAsync(setting); - } - else - { - setting.SettingValue = SettingValue; - setting = await UpdateSettingAsync(setting); - } - return setting; + return await UpdateSettingsAsync(SiteSettings, "Site", SiteId, SettingName, SettingValue); } public async Task> GetPageSettingsAsync(int PageId) @@ -83,22 +53,7 @@ namespace Oqtane.Services public async Task UpdatePageSettingsAsync(List PageSettings, int PageId, string SettingName, string SettingValue) { - Setting setting = PageSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); - if (setting == null) - { - setting = new Setting(); - setting.EntityName = "Page"; - setting.EntityId = PageId; - setting.SettingName = SettingName; - setting.SettingValue = SettingValue; - setting = await AddSettingAsync(setting); - } - else - { - setting.SettingValue = SettingValue; - setting = await UpdateSettingAsync(setting); - } - return setting; + return await UpdateSettingsAsync(PageSettings, "Page", PageId, SettingName, SettingValue); } public async Task> GetPageModuleSettingsAsync(int PageModuleId) @@ -108,22 +63,7 @@ namespace Oqtane.Services public async Task UpdatePageModuleSettingsAsync(List PageModuleSettings, int PageModuleId, string SettingName, string SettingValue) { - Setting setting = PageModuleSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); - if (setting == null) - { - setting = new Setting(); - setting.EntityName = "PageModule"; - setting.EntityId = PageModuleId; - setting.SettingName = SettingName; - setting.SettingValue = SettingValue; - setting = await AddSettingAsync(setting); - } - else - { - setting.SettingValue = SettingValue; - setting = await UpdateSettingAsync(setting); - } - return setting; + return await UpdateSettingsAsync(PageModuleSettings, "PageModule", PageModuleId, SettingName, SettingValue); } public async Task> GetModuleSettingsAsync(int ModuleId) @@ -133,22 +73,17 @@ namespace Oqtane.Services public async Task UpdateModuleSettingsAsync(List ModuleSettings, int ModuleId, string SettingName, string SettingValue) { - Setting setting = ModuleSettings.Where(item => item.SettingName == SettingName).FirstOrDefault(); - if (setting == null) - { - setting = new Setting(); - setting.EntityName = "Module"; - setting.EntityId = ModuleId; - setting.SettingName = SettingName; - setting.SettingValue = SettingValue; - setting = await AddSettingAsync(setting); - } - else - { - setting.SettingValue = SettingValue; - setting = await UpdateSettingAsync(setting); - } - return setting; + return await UpdateSettingsAsync(ModuleSettings, "Module", ModuleId, SettingName, SettingValue); + } + + public async Task> GetUserSettingsAsync(int UserId) + { + return await GetSettingsAsync("User", UserId); + } + + public async Task UpdateUserSettingsAsync(List UserSettings, int UserId, string SettingName, string SettingValue) + { + return await UpdateSettingsAsync(UserSettings, "User", UserId, SettingName, SettingValue); } public async Task> GetSettingsAsync(string EntityName, int EntityId) @@ -171,6 +106,27 @@ namespace Oqtane.Services { return await http.PutJsonAsync(apiurl + "/" + Setting.SettingId.ToString(), Setting); } + + public async Task UpdateSettingsAsync(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue) + { + Setting setting = Settings.Where(item => item.SettingName == SettingName).FirstOrDefault(); + if (setting == null || setting.SettingId == -1) + { + setting = new Setting(); + setting.EntityName = EntityName; + setting.EntityId = EntityId; + setting.SettingName = SettingName; + setting.SettingValue = SettingValue; + setting = await AddSettingAsync(setting); + } + else + { + setting.SettingValue = SettingValue; + setting = await UpdateSettingAsync(setting); + } + return setting; + } + public async Task DeleteSettingAsync(int SettingId) { await http.DeleteAsync(apiurl + "/" + SettingId.ToString()); @@ -187,5 +143,19 @@ namespace Oqtane.Services } return value; } + + public List SetSetting(List Settings, string EntityName, int EntityId, string SettingName, string SettingValue) + { + int index = Settings.FindIndex(item => item.EntityName == EntityName && item.EntityId == EntityId && item.SettingName == SettingName); + if (index != -1) + { + Settings[index].SettingValue = SettingValue; + } + else + { + Settings.Add(new Setting { SettingId = -1, EntityName = EntityName, EntityId = EntityId, SettingName = SettingName, SettingValue = SettingValue }); + } + return Settings; + } } } diff --git a/Oqtane.Client/Startup.cs b/Oqtane.Client/Startup.cs index 754ca6ad..2b8f456b 100644 --- a/Oqtane.Client/Startup.cs +++ b/Oqtane.Client/Startup.cs @@ -46,6 +46,7 @@ namespace Oqtane.Client services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/Oqtane.Client/Themes/Controls/Profile.razor b/Oqtane.Client/Themes/Controls/Profile.razor index 0ff591a3..90808163 100644 --- a/Oqtane.Client/Themes/Controls/Profile.razor +++ b/Oqtane.Client/Themes/Controls/Profile.razor @@ -7,7 +7,7 @@ ... - + @@ -21,6 +21,11 @@ { UriHelper.NavigateTo(NavigateUrl("register")); } + + private void UpdateProfile() + { + UriHelper.NavigateTo(NavigateUrl("profile")); + } } diff --git a/Oqtane.Server/Controllers/ProfileController.cs b/Oqtane.Server/Controllers/ProfileController.cs new file mode 100644 index 00000000..7281b2a0 --- /dev/null +++ b/Oqtane.Server/Controllers/ProfileController.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using Oqtane.Repository; +using Oqtane.Models; +using Oqtane.Shared; + +namespace Oqtane.Controllers +{ + [Route("{site}/api/[controller]")] + public class ProfileController : Controller + { + private readonly IProfileRepository Profiles; + + public ProfileController(IProfileRepository Profiles) + { + this.Profiles = Profiles; + } + + // GET: api/?siteid=x + [HttpGet] + public IEnumerable Get(string siteid) + { + if (siteid == "") + { + return Profiles.GetProfiles(); + } + else + { + return Profiles.GetProfiles(int.Parse(siteid)); + } + } + + // GET api//5 + [HttpGet("{id}")] + public Profile Get(int id) + { + return Profiles.GetProfile(id); + } + + // POST api/ + [HttpPost] + [Authorize(Roles = Constants.AdminRole)] + public Profile Post([FromBody] Profile Profile) + { + if (ModelState.IsValid) + { + Profile = Profiles.AddProfile(Profile); + } + return Profile; + } + + // PUT api//5 + [HttpPut("{id}")] + [Authorize(Roles = Constants.AdminRole)] + public Profile Put(int id, [FromBody] Profile Profile) + { + if (ModelState.IsValid) + { + Profile = Profiles.UpdateProfile(Profile); + } + return Profile; + } + + // DELETE api//5 + [HttpDelete("{id}")] + [Authorize(Roles = Constants.AdminRole)] + public void Delete(int id) + { + Profiles.DeleteProfile(id); + } + } +} diff --git a/Oqtane.Server/Repository/Context/TenantDBContext.cs b/Oqtane.Server/Repository/Context/TenantDBContext.cs index f214302b..6cf6a7b9 100644 --- a/Oqtane.Server/Repository/Context/TenantDBContext.cs +++ b/Oqtane.Server/Repository/Context/TenantDBContext.cs @@ -11,6 +11,7 @@ namespace Oqtane.Repository public virtual DbSet PageModule { get; set; } public virtual DbSet Module { get; set; } public virtual DbSet User { get; set; } + public virtual DbSet Profile { get; set; } public virtual DbSet SiteUser { get; set; } public virtual DbSet Role { get; set; } public virtual DbSet UserRole { get; set; } diff --git a/Oqtane.Server/Repository/Interfaces/IProfileRepository.cs b/Oqtane.Server/Repository/Interfaces/IProfileRepository.cs new file mode 100644 index 00000000..51f4c142 --- /dev/null +++ b/Oqtane.Server/Repository/Interfaces/IProfileRepository.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public interface IProfileRepository + { + IEnumerable GetProfiles(); + IEnumerable GetProfiles(int SiteId); + Profile AddProfile(Profile Profile); + Profile UpdateProfile(Profile Profile); + Profile GetProfile(int ProfileId); + void DeleteProfile(int ProfileId); + } +} diff --git a/Oqtane.Server/Repository/ProfileRepository.cs b/Oqtane.Server/Repository/ProfileRepository.cs new file mode 100644 index 00000000..b6902dda --- /dev/null +++ b/Oqtane.Server/Repository/ProfileRepository.cs @@ -0,0 +1,53 @@ +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using Oqtane.Models; + +namespace Oqtane.Repository +{ + public class ProfileRepository : IProfileRepository + { + private TenantDBContext db; + + public ProfileRepository(TenantDBContext context) + { + db = context; + } + + public IEnumerable GetProfiles() + { + return db.Profile; + } + + public IEnumerable GetProfiles(int SiteId) + { + return db.Profile.Where(item => item.SiteId == SiteId); + } + + public Profile AddProfile(Profile Profile) + { + db.Profile.Add(Profile); + db.SaveChanges(); + return Profile; + } + + public Profile UpdateProfile(Profile Profile) + { + db.Entry(Profile).State = EntityState.Modified; + db.SaveChanges(); + return Profile; + } + + public Profile GetProfile(int ProfileId) + { + return db.Profile.Find(ProfileId); + } + + public void DeleteProfile(int ProfileId) + { + Profile Profile = db.Profile.Find(ProfileId); + db.Profile.Remove(Profile); + db.SaveChanges(); + } + } +} diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql index 2f97a61e..406e9a23 100644 --- a/Oqtane.Server/Scripts/00.00.00.sql +++ b/Oqtane.Server/Scripts/00.00.00.sql @@ -183,6 +183,8 @@ CREATE TABLE [dbo].[Profile]( [ProfileId] [int] IDENTITY(1,1) NOT NULL, [SiteId] [int] NULL, [Name] [nvarchar](50) NOT NULL, + [Title] [nvarchar](50) NOT NULL, + [Description] [nvarchar](256) NULL, [Category] [nvarchar](50) NOT NULL, [ViewOrder] [int] NOT NULL, [MaxLength] [int] NOT NULL, @@ -378,6 +380,35 @@ GO SET IDENTITY_INSERT [dbo].[Role] OFF GO +SET IDENTITY_INSERT [dbo].[Profile] ON +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (1, 1, 'FirstName', 'First Name', 'Your First Or Given Name', 'Name', 1, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (2, 1, 'LastName', 'Last Name', 'Your Last Or family Name', 'Name', 2, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (3, 1, 'Street', 'Street', 'Street Or Building Address', 'Address', 3, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (4, 1, 'City', 'City', 'City', 'Address', 4, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (5, 1, 'Region', 'Region', 'State Or Province', 'Address', 5, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (6, 1, 'Country', 'Country', 'Country', 'Address', 6, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (7, 1, 'PostalCode', 'Postal Code', 'Postal Code Or Zip Code', 'Address', 7, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Profile]([ProfileId], [SiteId], [Name], [Title], [Description], [Category], [ViewOrder], [MaxLength], [DefaultValue], [IsRequired], [IsPrivate], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (8, 1, 'Phone', 'Phone Number', 'Phone Number', 'Contact', 8, 50, '', 1, 0, '', getdate(), '', getdate()) +GO +SET IDENTITY_INSERT [dbo].[Profile] OFF +GO + SET IDENTITY_INSERT [dbo].[Page] ON GO INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) @@ -508,6 +539,15 @@ INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 16, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Page] ([PageId], [SiteId], [Name], [Path], [ThemeType], [Icon], [Panes], [ParentId], [Order], [IsNavigation], [LayoutType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (17, 1, N'Profile', N'profile', N'Oqtane.Client.Themes.Theme2.Theme2, Oqtane.Client', N'', N'Top;Bottom', NULL, 1, 0, N'', '', getdate(), '', getdate()) +GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 17, 'View', -1, null, 1, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 17, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Page', 17, 'Edit', 1, null, 1, '', getdate(), '', getdate()) +GO SET IDENTITY_INSERT [dbo].[Page] OFF GO @@ -677,6 +717,15 @@ INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], GO INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 20, 'Edit', 1, null, 1, '', getdate(), '', getdate()) GO +INSERT [dbo].[Module] ([ModuleId], [SiteId], [ModuleDefinitionName], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (21, 1, N'Oqtane.Client.Modules.Admin.Profile, Oqtane.Client', '', getdate(), '', getdate()) +GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 21, 'View', -1, null, 1, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 21, 'View', 1, null, 1, '', getdate(), '', getdate()) +GO +INSERT [dbo].[Permission] ([SiteId], [EntityName], [EntityId], [PermissionName], [RoleId], [UserId], [IsAuthorized], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (1, 'Module', 21, 'Edit', 1, null, 1, '', getdate(), '', getdate()) +GO SET IDENTITY_INSERT [dbo].[Module] OFF GO @@ -742,6 +791,9 @@ GO INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) VALUES (20, 16, 20, N'Role Management', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) GO +INSERT [dbo].[PageModule] ([PageModuleId], [PageId], [ModuleId], [Title], [Pane], [Order], [ContainerType], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn]) +VALUES (21, 17, 21, N'User Profile', N'Top', 0, N'Oqtane.Client.Themes.Theme2.Container2, Oqtane.Client', '', getdate(), '', getdate()) +GO SET IDENTITY_INSERT [dbo].[PageModule] OFF GO diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 4b441aff..516e63cb 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -91,6 +91,7 @@ namespace Oqtane.Server services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -178,6 +179,7 @@ namespace Oqtane.Server services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Oqtane.Shared/Models/Profile.cs b/Oqtane.Shared/Models/Profile.cs new file mode 100644 index 00000000..cd82553f --- /dev/null +++ b/Oqtane.Shared/Models/Profile.cs @@ -0,0 +1,24 @@ +using System; + +namespace Oqtane.Models +{ + public class Profile : IAuditable + { + public int ProfileId { get; set; } + public int SiteId { get; set; } + public string Name { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public string Category { get; set; } + public int ViewOrder { get; set; } + public int MaxLength { get; set; } + public string DefaultValue { get; set; } + public bool IsRequired { get; set; } + public bool IsPrivate { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + } +} From e1cc1ce9733b60781b27a8bd523d0ad1eb3455fa Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Wed, 4 Sep 2019 11:07:48 -0400 Subject: [PATCH 38/44] Add Edit Mode for Administration --- .../Modules/Admin/Profile/Index.razor | 47 ++-- .../Modules/Controls/ActionLink.razor | 51 ++--- Oqtane.Client/Shared/Container.razor | 2 +- Oqtane.Client/Shared/ModuleInstance.razor | 2 +- Oqtane.Client/Shared/PageState.cs | 1 + Oqtane.Client/Shared/Pane.razor | 4 +- Oqtane.Client/Shared/PaneLayout.razor | 2 +- Oqtane.Client/Shared/SiteRouter.razor | 4 + Oqtane.Client/Shared/Theme.razor | 2 +- .../Themes/Controls/ControlPanel.razor | 201 ++++++++++-------- .../Themes/Controls/ModuleActions.razor | 109 +++++----- Oqtane.Server/Repository/ProfileRepository.cs | 2 +- Oqtane.Server/Scripts/00.00.00.sql | 16 +- Oqtane.Shared/Models/Profile.cs | 2 +- 14 files changed, 253 insertions(+), 192 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Profile/Index.razor b/Oqtane.Client/Modules/Admin/Profile/Index.razor index 32cebad4..cf68fdf6 100644 --- a/Oqtane.Client/Modules/Admin/Profile/Index.razor +++ b/Oqtane.Client/Modules/Admin/Profile/Index.razor @@ -11,7 +11,7 @@ -@if (profiles != null) +@if (PageState.User != null && profiles != null) { @@ -55,6 +55,7 @@
    +

    } @code { @@ -71,10 +72,17 @@ { try { - displayname = PageState.User.DisplayName; - email = PageState.User.Email; - profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId); - settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId); + if (PageState.User != null) + { + displayname = PageState.User.DisplayName; + email = PageState.User.Email; + profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId); + settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId); + } + else + { + message = "Current User Is Not Logged In"; + } } catch (Exception ex) { @@ -89,23 +97,30 @@ private async Task SaveUser() { - User user = PageState.User; - user.DisplayName = displayname; - user.Email = email; - await UserService.UpdateUserAsync(user); - - foreach (Profile profile in profiles) + try { - string value = SettingService.GetSetting(settings, profile.Name, ""); - await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId, profile.Name, value); - } + User user = PageState.User; + user.DisplayName = displayname; + user.Email = email; + await UserService.UpdateUserAsync(user); - UriHelper.NavigateTo(""); + foreach (Profile profile in profiles) + { + string value = SettingService.GetSetting(settings, profile.Name, ""); + await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId, profile.Name, value); + } + + UriHelper.NavigateTo(""); + } + catch (Exception ex) + { + message = ex.Message; + } } private void Cancel() { - UriHelper.NavigateTo(NavigateUrl("")); // navigate to home + UriHelper.NavigateTo(NavigateUrl("")); } private void ProfileChanged(UIChangeEventArgs e, string SettingName) diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index d894894b..264a02bd 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -34,7 +34,7 @@ string style = ""; bool authorized = false; - protected override void OnInitialized() + protected override void OnParametersSet() { text = Action; if (!String.IsNullOrEmpty(Text)) @@ -49,39 +49,42 @@ if (!string.IsNullOrEmpty(Class)) { - classname = Class; + classname = Class; } if (!string.IsNullOrEmpty(Style)) { - style = Style; + style = Style; } url = EditUrl(Action, parameters); - string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameClass(ModuleState.ModuleType) + ",", Action + ","); - Type moduleType = Type.GetType(typename); - if (moduleType != null) + if (PageState.EditMode) { - var moduleobject = Activator.CreateInstance(moduleType); - SecurityAccessLevel SecurityAccessLevel = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); - switch (SecurityAccessLevel) + string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameClass(ModuleState.ModuleType) + ",", Action + ","); + Type moduleType = Type.GetType(typename); + if (moduleType != null) { - case SecurityAccessLevel.Anonymous: - authorized = true; - break; - case SecurityAccessLevel.View: - authorized = UserSecurity.IsAuthorized(PageState.User, "View", ModuleState.Permissions); - break; - case SecurityAccessLevel.Edit: - authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions); - break; - case SecurityAccessLevel.Admin: - authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole); - break; - case SecurityAccessLevel.Host: - authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole); - break; + var moduleobject = Activator.CreateInstance(moduleType); + SecurityAccessLevel SecurityAccessLevel = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); + switch (SecurityAccessLevel) + { + case SecurityAccessLevel.Anonymous: + authorized = true; + break; + case SecurityAccessLevel.View: + authorized = UserSecurity.IsAuthorized(PageState.User, "View", ModuleState.Permissions); + break; + case SecurityAccessLevel.Edit: + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions); + break; + case SecurityAccessLevel.Admin: + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole); + break; + case SecurityAccessLevel.Host: + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole); + break; + } } } } diff --git a/Oqtane.Client/Shared/Container.razor b/Oqtane.Client/Shared/Container.razor index 92aa6e62..6a1233bb 100644 --- a/Oqtane.Client/Shared/Container.razor +++ b/Oqtane.Client/Shared/Container.razor @@ -18,7 +18,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInitialized() + protected override void OnParametersSet() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Shared/ModuleInstance.razor b/Oqtane.Client/Shared/ModuleInstance.razor index 8eb83f48..d1f8ef2e 100644 --- a/Oqtane.Client/Shared/ModuleInstance.razor +++ b/Oqtane.Client/Shared/ModuleInstance.razor @@ -13,7 +13,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInitialized() + protected override void OnParametersSet() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Shared/PageState.cs b/Oqtane.Client/Shared/PageState.cs index 1de78738..8e70bd82 100644 --- a/Oqtane.Client/Shared/PageState.cs +++ b/Oqtane.Client/Shared/PageState.cs @@ -19,6 +19,7 @@ namespace Oqtane.Shared public Dictionary QueryString { get; set; } public int ModuleId { get; set; } public string Control { get; set; } + public bool EditMode { get; set; } public int Reload { get; set; } } } diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor index 93b27c41..bf40cd24 100644 --- a/Oqtane.Client/Shared/Pane.razor +++ b/Oqtane.Client/Shared/Pane.razor @@ -26,9 +26,9 @@ string paneadminborder = ""; string panetitle = ""; - protected override void OnInitialized() + protected override void OnParametersSet() { - if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions) && Name != Constants.AdminPane) + if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions) && Name != Constants.AdminPane) { paneadminborder = "pane-admin-border"; panetitle = "
    " + Name + " Pane
    "; diff --git a/Oqtane.Client/Shared/PaneLayout.razor b/Oqtane.Client/Shared/PaneLayout.razor index 9fe4f572..268d9ecc 100644 --- a/Oqtane.Client/Shared/PaneLayout.razor +++ b/Oqtane.Client/Shared/PaneLayout.razor @@ -9,7 +9,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInitialized() + protected override void OnParametersSet() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index b57a545e..fad531c3 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -86,11 +86,13 @@ List modules; int moduleid = -1; string control = ""; + bool editmode = false; int reload = 0; if (PageState != null) { reload = PageState.Reload; + editmode = PageState.EditMode; } if (PageState == null || reload == Constants.ReloadApplication) @@ -188,6 +190,7 @@ { page = pages.Where(item => item.Path == path).FirstOrDefault(); reload = Constants.ReloadPage; + editmode = false; } user = null; @@ -238,6 +241,7 @@ modules = PageState.Modules; } pagestate.Modules = modules; + pagestate.EditMode = editmode; pagestate.Reload = 0; OnStateChange?.Invoke(pagestate); diff --git a/Oqtane.Client/Shared/Theme.razor b/Oqtane.Client/Shared/Theme.razor index ad9abdc9..fd29a0df 100644 --- a/Oqtane.Client/Shared/Theme.razor +++ b/Oqtane.Client/Shared/Theme.razor @@ -8,7 +8,7 @@ RenderFragment DynamicComponent { get; set; } - protected override void OnInitialized() + protected override void OnParametersSet() { DynamicComponent = builder => { diff --git a/Oqtane.Client/Themes/Controls/ControlPanel.razor b/Oqtane.Client/Themes/Controls/ControlPanel.razor index 9eb030bf..3372fb8f 100644 --- a/Oqtane.Client/Themes/Controls/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/ControlPanel.razor @@ -12,67 +12,83 @@ @inject IModuleService ModuleService @inject IPageModuleService PageModuleService -
    - x -
    - -
    -
    -
    - - @if (moduledefinitions != null) - { - + + @foreach (var moduledefinition in moduledefinitions) + { + + } + + } +
    +
    + + - } +
    +
    + + +
    +
    + + +
    +
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - + + @if (PageState.EditMode) + { + + + } + else + { + + } + +} @code { - string display = "display: none"; List moduledefinitions; Dictionary containers = new Dictionary(); int pagemanagementmoduleid = -1; @@ -83,45 +99,47 @@ protected override async Task OnInitializedAsync() { - moduledefinitions = PageState.ModuleDefinitions; - containers = ThemeService.GetContainerTypes(PageState.Themes); - List modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId, Constants.PageManagementModule); - if (modules.Count > 0) - { - pagemanagementmoduleid = modules.FirstOrDefault().ModuleId; - } if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions)) { - display = "display: inline"; + moduledefinitions = PageState.ModuleDefinitions; + containers = ThemeService.GetContainerTypes(PageState.Themes); + List modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId, Constants.PageManagementModule); + if (modules.Count > 0) + { + pagemanagementmoduleid = modules.FirstOrDefault().ModuleId; + } } } private async Task AddModule() { - Module module = new Module(); - module.SiteId = PageState.Site.SiteId; - module.ModuleDefinitionName = moduledefinitionname; - module.Permissions = PageState.Page.Permissions; - await ModuleService.AddModuleAsync(module); - - List modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId, moduledefinitionname); - int ModuleId = modules.LastOrDefault().ModuleId; - - PageModule pagemodule = new PageModule(); - pagemodule.PageId = PageState.Page.PageId; - pagemodule.ModuleId = ModuleId; - if (title == "") + if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions)) { - title = moduledefinitions.Where(item => item.ModuleDefinitionName == moduledefinitionname).FirstOrDefault().Name; - } - pagemodule.Title = title; - pagemodule.Pane = pane; - pagemodule.Order = 0; - pagemodule.ContainerType = containertype; - await PageModuleService.AddPageModuleAsync(pagemodule); + Module module = new Module(); + module.SiteId = PageState.Site.SiteId; + module.ModuleDefinitionName = moduledefinitionname; + module.Permissions = PageState.Page.Permissions; + await ModuleService.AddModuleAsync(module); - PageState.Reload = Constants.ReloadPage; - UriHelper.NavigateTo(NavigateUrl()); + List modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId, moduledefinitionname); + int ModuleId = modules.LastOrDefault().ModuleId; + + PageModule pagemodule = new PageModule(); + pagemodule.PageId = PageState.Page.PageId; + pagemodule.ModuleId = ModuleId; + if (title == "") + { + title = moduledefinitions.Where(item => item.ModuleDefinitionName == moduledefinitionname).FirstOrDefault().Name; + } + pagemodule.Title = title; + pagemodule.Pane = pane; + pagemodule.Order = 0; + pagemodule.ContainerType = containertype; + await PageModuleService.AddPageModuleAsync(pagemodule); + + PageState.Reload = Constants.ReloadPage; + UriHelper.NavigateTo(NavigateUrl()); + } } private string PageUrl(string action) @@ -144,4 +162,21 @@ } return url; } + + private void EditMode() + { + if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions)) + { + if (PageState.EditMode) + { + PageState.EditMode = false; + } + else + { + PageState.EditMode = true; + } + PageState.Reload = Constants.ReloadPage; + UriHelper.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + PageState.EditMode.ToString().ToLower())); + } + } } \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor index a37dec34..f1d62b4b 100644 --- a/Oqtane.Client/Themes/Controls/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor @@ -8,75 +8,78 @@ @inject IUserService UserService @inject IPageModuleService PageModuleService -
    - +
    + + + +
    @@ -123,6 +134,7 @@ string parentid; string order = ""; string isnavigation = "True"; + string editmode = "False"; string themetype; string layouttype = ""; string icon = ""; @@ -166,6 +178,7 @@ page.Path = path; page.Order = (order == null ? 1 : Int32.Parse(order)); page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation)); + page.EditMode = (editmode == null ? true : Boolean.Parse(editmode)); page.ThemeType = themetype; page.LayoutType = (layouttype == null ? "" : layouttype); page.Icon = (icon == null ? "" : icon); diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor index a6327769..40749f3b 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor @@ -62,6 +62,17 @@
    + + + +
    @@ -127,6 +138,7 @@ string parentid; string order; string isnavigation; + string editmode; string themetype; string layouttype; string icon; @@ -154,6 +166,7 @@ order = page.Order.ToString(); isnavigation = page.IsNavigation.ToString(); + editmode = page.EditMode.ToString(); themetype = page.ThemeType; layouttype = page.LayoutType; icon = page.Icon; diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index 4eaa0287..3b25fb35 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -62,6 +62,17 @@
    + + + +
    @@ -127,6 +138,7 @@ string parentid; string order; string isnavigation; + string editmode; string themetype; string layouttype; string icon; @@ -161,6 +173,7 @@ } order = page.Order.ToString(); isnavigation = page.IsNavigation.ToString(); + editmode = page.EditMode.ToString(); themetype = page.ThemeType; layouttype = page.LayoutType; icon = page.Icon; @@ -195,6 +208,7 @@ page.Path = path; page.Order = (order == null ? 1 : Int32.Parse(order)); page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation)); + page.EditMode = (editmode == null ? true : Boolean.Parse(editmode)); page.ThemeType = themetype; page.LayoutType = (layouttype == null ? "" : layouttype); page.Icon = (icon == null ? "" : icon); diff --git a/Oqtane.Client/Modules/Admin/Pages/Index.razor b/Oqtane.Client/Modules/Admin/Pages/Index.razor index ad7f0afe..7f4c861b 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Index.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Index.razor @@ -11,7 +11,7 @@ } else { - + diff --git a/Oqtane.Client/Modules/Admin/Profile/Index.razor b/Oqtane.Client/Modules/Admin/Profile/Index.razor index aa1ca756..5139bd11 100644 --- a/Oqtane.Client/Modules/Admin/Profile/Index.razor +++ b/Oqtane.Client/Modules/Admin/Profile/Index.razor @@ -55,7 +55,8 @@
    -

    +
    +
    } @code { diff --git a/Oqtane.Client/Modules/IModuleControl.cs b/Oqtane.Client/Modules/IModuleControl.cs index ebb8dcd4..96e59364 100644 --- a/Oqtane.Client/Modules/IModuleControl.cs +++ b/Oqtane.Client/Modules/IModuleControl.cs @@ -2,8 +2,9 @@ { public interface IModuleControl { - string Title { get; } - SecurityAccessLevel SecurityAccessLevel { get; } - string Actions { get; } // can be specified as a comma delimited set of values + SecurityAccessLevel SecurityAccessLevel { get; } // defines the security access level for this control - defaults to View + string Title { get; } // title to display for this control - defaults to module title + string Actions { get; } // allows for routing by configuration rather than by convention ( comma delimited ) - defaults to using component file name + string ContainerType { get; } // container for embedding control - defaults to AdminContainer } } diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index 06948293..af18ead7 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -12,12 +12,14 @@ namespace Oqtane.Modules [CascadingParameter] protected Module ModuleState { get; set; } - public virtual string Title { get { return ""; } } - public virtual SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } set { } } // default security + public virtual string Title { get { return ""; } } + public virtual string Actions { get { return ""; } } + public virtual string ContainerType { get { return ""; } } + public string NavigateUrl() { return NavigateUrl(PageState.Page.Path); diff --git a/Oqtane.Client/Shared/Container.razor b/Oqtane.Client/Shared/Container.razor index 6a1233bb..d19019d5 100644 --- a/Oqtane.Client/Shared/Container.razor +++ b/Oqtane.Client/Shared/Container.razor @@ -27,7 +27,7 @@ Type containerType = Type.GetType(container); if (containerType != null) { - builder.OpenComponent(0, containerType); + builder.OpenComponent(0, containerType); builder.CloseComponent(); } else @@ -49,7 +49,11 @@ container = ModuleState.ContainerType; if (PageState.ModuleId != -1 && PageState.Control != "") { - container = Constants.DefaultAdminContainer; + container = ModuleState.AdminContainerType; + if (container == "") + { + container = Constants.DefaultAdminContainer; + } } } return Task.CompletedTask; diff --git a/Oqtane.Client/Shared/PageState.cs b/Oqtane.Client/Shared/PageState.cs index 8e70bd82..37721465 100644 --- a/Oqtane.Client/Shared/PageState.cs +++ b/Oqtane.Client/Shared/PageState.cs @@ -20,6 +20,7 @@ namespace Oqtane.Shared public int ModuleId { get; set; } public string Control { get; set; } public bool EditMode { get; set; } + public bool DesignMode { get; set; } public int Reload { get; set; } } } diff --git a/Oqtane.Client/Shared/Pane.razor b/Oqtane.Client/Shared/Pane.razor index bf40cd24..51cec2d0 100644 --- a/Oqtane.Client/Shared/Pane.razor +++ b/Oqtane.Client/Shared/Pane.razor @@ -9,10 +9,13 @@ @inject IModuleService ModuleService @inject IModuleDefinitionService ModuleDefinitionService -
    - @((MarkupString)panetitle) - @DynamicComponent -
    +
    + @if (panetitle != "") + { + @((MarkupString)panetitle) + } + @DynamicComponent +
    @code { [CascadingParameter] @@ -28,11 +31,16 @@ protected override void OnParametersSet() { - if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions) && Name != Constants.AdminPane) + if (PageState.DesignMode && UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions) && Name != Constants.AdminPane) { paneadminborder = "pane-admin-border"; panetitle = "
    " + Name + " Pane
    "; } + else + { + paneadminborder = ""; + panetitle = ""; + } DynamicComponent = builder => { @@ -51,38 +59,38 @@ Type moduleType = Type.GetType(typename); if (moduleType != null) { - var moduleobject = Activator.CreateInstance(moduleType); - // verify security access level for this module control - SecurityAccessLevel SecurityAccessLevel = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); bool authorized = false; - switch (SecurityAccessLevel) + if (PageState.Control == "Settings") { - case SecurityAccessLevel.Anonymous: - authorized = true; - break; - case SecurityAccessLevel.View: - authorized = UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions); - break; - case SecurityAccessLevel.Edit: - authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", module.Permissions); - break; - case SecurityAccessLevel.Admin: - authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole); - break; - case SecurityAccessLevel.Host: - authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole); - break; + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions); + } + else + { + // verify security access level for this module control + switch (module.SecurityAccessLevel) + { + case SecurityAccessLevel.Anonymous: + authorized = true; + break; + case SecurityAccessLevel.View: + authorized = UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions); + break; + case SecurityAccessLevel.Edit: + authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", module.Permissions); + break; + case SecurityAccessLevel.Admin: + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole); + break; + case SecurityAccessLevel.Host: + authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole); + break; + } } if (authorized) { - if (PageState.Control != "Settings") + if (PageState.Control != "Settings" && module.ControlTitle != "") { - // get module control title - string title = (string)moduleType.GetProperty("Title").GetValue(moduleobject); - if (title != "") - { - module.Title = title; - } + module.Title = module.ControlTitle; } builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer)); builder.AddAttribute(1, "Module", module); diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index fad531c3..4a4e29fa 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -1,6 +1,7 @@ @using System @using Oqtane.Services @using Oqtane.Models +@using Oqtane.Modules @using System.Linq @using System.Collections.Generic @using Oqtane.Shared @@ -25,10 +26,10 @@ @code { - [CascadingParameter] + [CascadingParameter] PageState PageState { get; set; } - [Parameter] + [Parameter] public Action OnStateChange { get; set; } PageState pagestate; @@ -58,7 +59,7 @@ } protected override async Task OnParametersSetAsync() - { + { if (PageState == null) { // misconfigured api calls should not be processed through the router @@ -68,7 +69,7 @@ } else { - System.Diagnostics.Debug.WriteLine(this.GetType().FullName + ": Error: " + _absoluteUri + " is not mapped to a Controller"); + System.Diagnostics.Debug.WriteLine(this.GetType().FullName + ": Error: API call to " + _absoluteUri + " is not mapped to a Controller"); } } } @@ -87,12 +88,14 @@ int moduleid = -1; string control = ""; bool editmode = false; + bool designmode = false; int reload = 0; if (PageState != null) { reload = PageState.Reload; editmode = PageState.EditMode; + designmode = PageState.DesignMode; } if (PageState == null || reload == Constants.ReloadApplication) @@ -190,7 +193,8 @@ { page = pages.Where(item => item.Path == path).FirstOrDefault(); reload = Constants.ReloadPage; - editmode = false; + editmode = page.EditMode; + designmode = false; } user = null; @@ -242,7 +246,8 @@ } pagestate.Modules = modules; pagestate.EditMode = editmode; - pagestate.Reload = 0; + pagestate.DesignMode = designmode; + pagestate.Reload = Constants.ReloadReset; OnStateChange?.Invoke(pagestate); } @@ -330,6 +335,22 @@ } } module.ModuleType = typename.Replace("{Control}", control); + + // get IModuleControl properties + typename = module.ModuleType; + if (control == "Settings") + { + typename = Constants.DefaultSettingsControl; + } + Type moduletype = Type.GetType(typename); + if (moduletype != null) + { + var moduleobject = Activator.CreateInstance(moduletype); + module.SecurityAccessLevel = (SecurityAccessLevel)moduletype.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null); + module.ControlTitle = (string)moduletype.GetProperty("Title").GetValue(moduleobject); + module.Actions = (string)moduletype.GetProperty("Actions").GetValue(moduleobject); + module.AdminContainerType = (string)moduletype.GetProperty("ContainerType").GetValue(moduleobject); + } } // ensure module's pane exists in current page and if not, assign it to the Admin pane diff --git a/Oqtane.Client/Themes/Controls/ControlPanel.razor b/Oqtane.Client/Themes/Controls/ControlPanel.razor index 3372fb8f..4b6947cf 100644 --- a/Oqtane.Client/Themes/Controls/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/ControlPanel.razor @@ -170,10 +170,12 @@ if (PageState.EditMode) { PageState.EditMode = false; + PageState.DesignMode = false; } else { PageState.EditMode = true; + PageState.DesignMode = true; } PageState.Reload = Constants.ReloadPage; UriHelper.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + PageState.EditMode.ToString().ToLower())); diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor index f1d62b4b..b45d46d1 100644 --- a/Oqtane.Client/Themes/Controls/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor @@ -8,7 +8,7 @@ @inject IUserService UserService @inject IPageModuleService PageModuleService -@if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions)) +@if (PageState.DesignMode && UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions)) {