diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index 0c97da2c..6c275498 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -9,83 +9,94 @@ @if (_themeList != null) { - - - - - - - - - - - - + + + + + + + + + + + + + + + + + +
- - - -
- - - -
- - - - @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) + + + + + + + + - - - - + + + + - - - - - - - - - -
+ + + +
+ + + - - @foreach (Page page in _children) - { - - } - + } -
- - - +
+ + + + @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) + { + -
- - - -
- - - -
+ } +
+ + + +
+ + + +
+ + + +
+ + + +
@@ -180,6 +191,7 @@ private List _children; private int _childid = -1; private string _isnavigation = "True"; + private string _isclickable = "True"; private string _url; private string _ispersonalizable = "False"; private string _themetype = string.Empty; @@ -351,6 +363,7 @@ } page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation)); + page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); page.Url = _url; page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor index d012f87f..58554c53 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor @@ -10,90 +10,101 @@ @if (_themeList != null) { -
- - - - - - - - - - - + + + + + + + + + + + + + + + + + +
- - - -
- - - -
- - - - @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) + + + + + + + + - - - - + + + + - - - - - - - - - -
+ + + +
+ + + - - @foreach (Page page in _children) - { - - } - + if (page.PageId != _pageId) + { + + } } -
- - - +
+ + + + @if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">")) + { + -
- - - -
- - - -
+ } +
+ + + +
+ + + +
+ + + +
+ + + +
@@ -195,6 +206,7 @@ private List _children; private int _childid = -1; private string _isnavigation; + private string _isclickable; private string _url; private string _ispersonalizable; private string _themetype; @@ -247,6 +259,7 @@ _currentparentid = _parentid; _isnavigation = page.IsNavigation.ToString(); + _isclickable = page.IsClickable.ToString(); _url = page.Url; _ispersonalizable = page.IsPersonalizable.ToString(); _themetype = page.ThemeType; @@ -427,6 +440,7 @@ } } page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation)); + page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable)); page.Url = _url; page.ThemeType = (_themetype != "-") ? _themetype : string.Empty; if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType) diff --git a/Oqtane.Client/Modules/Admin/Roles/Add.razor b/Oqtane.Client/Modules/Admin/Roles/Add.razor index c5bc2a38..5567622c 100644 --- a/Oqtane.Client/Modules/Admin/Roles/Add.razor +++ b/Oqtane.Client/Modules/Admin/Roles/Add.razor @@ -4,39 +4,44 @@ @inject IRoleService RoleService @inject IStringLocalizer Localizer -
- - - - - - - - - - - - -
- - - -
- - - -
- - - -
- -@Localizer["Cancel"] +
+ + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + @Localizer["Cancel"] +
@code { + private ElementReference form; + private bool validated = false; + private string _name = string.Empty; private string _description = string.Empty; private string _isautoassigned = "False"; @@ -45,24 +50,33 @@ private async Task SaveRole() { - var role = new Role(); - role.SiteId = PageState.Page.SiteId; - role.Name = _name; - role.Description = _description; - role.IsAutoAssigned = (_isautoassigned == null ? false : Boolean.Parse(_isautoassigned)); - role.IsSystem = false; - - try + validated = true; + var interop = new Interop(JSRuntime); + if (await interop.FormValid(form)) { - role = await RoleService.AddRoleAsync(role); - await logger.LogInformation("Role Added {Role}", role); + var role = new Role(); + role.SiteId = PageState.Page.SiteId; + role.Name = _name; + role.Description = _description; + role.IsAutoAssigned = (_isautoassigned == null ? false : Boolean.Parse(_isautoassigned)); + role.IsSystem = false; - NavigationManager.NavigateTo(NavigateUrl()); + try + { + role = await RoleService.AddRoleAsync(role); + await logger.LogInformation("Role Added {Role}", role); + + NavigationManager.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Adding Role {Role} {Error}", role, ex.Message); + AddModuleMessage(Localizer["Error Adding Role"], MessageType.Error); + } } - catch (Exception ex) + else { - await logger.LogError(ex, "Error Adding Role {Role} {Error}", role, ex.Message); - AddModuleMessage(Localizer["Error Adding Role"], MessageType.Error); + AddModuleMessage(Localizer["Please Provide All Required Information"], MessageType.Warning); } } diff --git a/Oqtane.Client/Modules/Admin/Roles/Edit.razor b/Oqtane.Client/Modules/Admin/Roles/Edit.razor index bac812c9..a92cbd86 100644 --- a/Oqtane.Client/Modules/Admin/Roles/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Roles/Edit.razor @@ -4,43 +4,54 @@ @inject IRoleService RoleService @inject IStringLocalizer Localizer - - - - - - - - - - - - - -
- - - -
- - - -
- - - -
- -@Localizer["Cancel"] +
+ + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + @Localizer["Cancel"] +

+ +
@code { + private ElementReference form; + private bool validated = false; + private int _roleid; private string _name = string.Empty; private string _description = string.Empty; private string _isautoassigned = "False"; + private string _createdby; + private DateTime _createdon; + private string _modifiedby; + private DateTime _modifiedon; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; @@ -55,6 +66,10 @@ _name = role.Name; _description = role.Description; _isautoassigned = role.IsAutoAssigned.ToString(); + _createdby = role.CreatedBy; + _createdon = role.CreatedOn; + _modifiedby = role.ModifiedBy; + _modifiedon = role.ModifiedOn; } } catch (Exception ex) @@ -66,22 +81,31 @@ private async Task SaveRole() { - var role = await RoleService.GetRoleAsync(_roleid); - role.Name = _name; - role.Description = _description; - role.IsAutoAssigned = (_isautoassigned != null && Boolean.Parse(_isautoassigned)); - role.IsSystem = false; + validated = true; + var interop = new Interop(JSRuntime); + if (await interop.FormValid(form)) + { + var role = await RoleService.GetRoleAsync(_roleid); + role.Name = _name; + role.Description = _description; + role.IsAutoAssigned = (_isautoassigned != null && Boolean.Parse(_isautoassigned)); + role.IsSystem = false; - try - { - role = await RoleService.UpdateRoleAsync(role); - await logger.LogInformation("Role Saved {Role}", role); - NavigationManager.NavigateTo(NavigateUrl()); + try + { + role = await RoleService.UpdateRoleAsync(role); + await logger.LogInformation("Role Saved {Role}", role); + NavigationManager.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Saving Role {Role} {Error}", role, ex.Message); + AddModuleMessage(Localizer["Error Saving Role"], MessageType.Error); + } } - catch (Exception ex) + else { - await logger.LogError(ex, "Error Saving Role {Role} {Error}", role, ex.Message); - AddModuleMessage(Localizer["Error Saving Role"], MessageType.Error); + AddModuleMessage(Localizer["Please Provide All Required Information"], MessageType.Warning); } } } diff --git a/Oqtane.Client/Modules/Admin/Roles/Index.razor b/Oqtane.Client/Modules/Admin/Roles/Index.razor index 0bfadcc1..0a81c2fc 100644 --- a/Oqtane.Client/Modules/Admin/Roles/Index.razor +++ b/Oqtane.Client/Modules/Admin/Roles/Index.razor @@ -33,6 +33,27 @@ else public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; protected override async Task OnParametersSetAsync() + { + await GetRoles(); + } + + private async Task DeleteRole(Role role) + { + try + { + await RoleService.DeleteRoleAsync(role.RoleId); + await logger.LogInformation("Role Deleted {Role}", role); + await GetRoles(); + StateHasChanged(); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Deleting Role {Role} {Error}", role, ex.Message); + AddModuleMessage(Localizer["Error Deleting Role"], MessageType.Error); + } + } + + private async Task GetRoles() { if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) { @@ -44,19 +65,4 @@ else _roles = await RoleService.GetRolesAsync(PageState.Site.SiteId); } } - - private async Task DeleteRole(Role role) - { - try - { - await RoleService.DeleteRoleAsync(role.RoleId); - await logger.LogInformation("Role Deleted {Role}", role); - StateHasChanged(); - } - catch (Exception ex) - { - await logger.LogError(ex, "Error Deleting Role {Role} {Error}", role, ex.Message); - AddModuleMessage(Localizer["Error Deleting Role"], MessageType.Error); - } - } } diff --git a/Oqtane.Client/Modules/Admin/Site/Index.razor b/Oqtane.Client/Modules/Admin/Site/Index.razor index f82e1a4f..807e3f2e 100644 --- a/Oqtane.Client/Modules/Admin/Site/Index.razor +++ b/Oqtane.Client/Modules/Admin/Site/Index.razor @@ -369,7 +369,7 @@ var tenants = await TenantService.GetTenantsAsync(); var _databases = await DatabaseService.GetDatabasesAsync(); var tenant = tenants.Find(item => item.TenantId == site.TenantId); - if (_tenant != null) + if (tenant != null) { _tenant = tenant.Name; _database = _databases.Find(item => item.DBType == tenant.DBType)?.Name; diff --git a/Oqtane.Client/Modules/Admin/Sql/Index.razor b/Oqtane.Client/Modules/Admin/Sql/Index.razor index 5edd39ab..931ade02 100644 --- a/Oqtane.Client/Modules/Admin/Sql/Index.razor +++ b/Oqtane.Client/Modules/Admin/Sql/Index.razor @@ -2,6 +2,7 @@ @inherits ModuleBase @inject NavigationManager NavigationManager @inject ITenantService TenantService +@inject IDatabaseService DatabaseService @inject ISqlService SqlService @inject IStringLocalizer Localizer @@ -11,19 +12,37 @@ } else { - +
+ + + + + @if (_tenantid != "-1") + { + + + + @@ -34,6 +53,7 @@ else + }
+ + + +
- + - + +
+ + +

@@ -47,6 +67,8 @@ else @code { private List _tenants; private string _tenantid = "-1"; + private string _database = string.Empty; + private string _connectionstring = string.Empty; private string _sql = string.Empty; private string _results = string.Empty; @@ -54,20 +76,59 @@ else protected override async Task OnInitializedAsync() { - _tenants = await TenantService.GetTenantsAsync(); + try + { + _tenants = await TenantService.GetTenantsAsync(); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Loading Tenants {Error}", ex.Message); + AddModuleMessage(ex.Message, MessageType.Error); + } + } + + private async void TenantChanged(ChangeEventArgs e) + { + try + { + _tenantid = (string)e.Value; + var tenants = await TenantService.GetTenantsAsync(); + var _databases = await DatabaseService.GetDatabasesAsync(); + var tenant = tenants.Find(item => item.TenantId == int.Parse(_tenantid)); + if (tenant != null) + { + _database = _databases.Find(item => item.DBType == tenant.DBType)?.Name; + _connectionstring = tenant.DBConnectionString; + } + StateHasChanged(); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Loading Tenant {TenantId} {Error}", _tenantid, ex.Message); + AddModuleMessage(ex.Message, MessageType.Error); + } } private async Task Execute() { - if (_tenantid != "-1" && !string.IsNullOrEmpty(_sql)) + try { - var sqlquery = new SqlQuery { TenantId = int.Parse(_tenantid), Query = _sql }; - sqlquery = await SqlService.ExecuteQueryAsync(sqlquery); - _results = DisplayResults(sqlquery.Results); + if (_tenantid != "-1" && !string.IsNullOrEmpty(_sql)) + { + var sqlquery = new SqlQuery { TenantId = int.Parse(_tenantid), Query = _sql }; + sqlquery = await SqlService.ExecuteQueryAsync(sqlquery); + _results = DisplayResults(sqlquery.Results); + AddModuleMessage(Localizer["SQL Query Executed"], MessageType.Success); + } + else + { + AddModuleMessage(Localizer["You Must Select A Tenant And Provide A Valid SQL Query"], MessageType.Warning); + } } - else + catch (Exception ex) { - AddModuleMessage(Localizer["You Must Select A Tenant And Provide A SQL Query"], MessageType.Warning); + await logger.LogError(ex, "Error Executing SQL Query {SQL} {Error}", _sql, ex.Message); + AddModuleMessage(ex.Message, MessageType.Error); } } diff --git a/Oqtane.Client/Services/ServiceBase.cs b/Oqtane.Client/Services/ServiceBase.cs index 805ca2b7..66762fde 100644 --- a/Oqtane.Client/Services/ServiceBase.cs +++ b/Oqtane.Client/Services/ServiceBase.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Components; using Oqtane.Documentation; using Oqtane.Models; using Oqtane.Shared; @@ -22,6 +20,7 @@ namespace Oqtane.Services protected ServiceBase(HttpClient client, SiteState siteState) { _http = client; + RemoveAuthorizationPolicyHeaders(); _siteState = siteState; } @@ -98,12 +97,17 @@ namespace Oqtane.Services } protected void AddRequestHeader(string name, string value) + { + RemoveRequestHeader(name); + _http.DefaultRequestHeaders.Add(name, value); + } + + protected void RemoveRequestHeader(string name) { if (_http.DefaultRequestHeaders.Contains(name)) { _http.DefaultRequestHeaders.Remove(name); } - _http.DefaultRequestHeaders.Add(name, value); } protected void AddAntiForgeryToken() @@ -124,6 +128,17 @@ namespace Oqtane.Services } } + public void RemoveAuthorizationPolicyHeaders() + { + foreach (var param in _http.DefaultRequestHeaders) + { + if (param.Key.StartsWith("auth") && param.Key.EndsWith("id")) + { + _http.DefaultRequestHeaders.Remove(param.Key); + } + } + } + protected async Task GetAsync(string uri) { var response = await _http.GetAsync(uri); @@ -243,6 +258,7 @@ namespace Oqtane.Services protected ServiceBase(HttpClient client) { _http = client; + RemoveAuthorizationPolicyHeaders(); } [Obsolete("This method is obsolete. Use CreateApiUrl(string serviceName, Alias alias) in conjunction with ControllerRoutes.ApiRoute in Controllers instead.", false)] diff --git a/Oqtane.Client/Themes/Controls/Theme/MenuBase.cs b/Oqtane.Client/Themes/Controls/Theme/MenuBase.cs index c63f0dc8..85a9b776 100644 --- a/Oqtane.Client/Themes/Controls/Theme/MenuBase.cs +++ b/Oqtane.Client/Themes/Controls/Theme/MenuBase.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Oqtane.Models; using Oqtane.Security; @@ -17,7 +17,14 @@ namespace Oqtane.Themes.Controls protected string GetUrl(Page page) { - return string.IsNullOrEmpty(page.Url) ? NavigateUrl(page.Path) : page.Url; + if (page.IsClickable) + { + return string.IsNullOrEmpty(page.Url) ? NavigateUrl(page.Path) : page.Url; + } + else + { + return "javascript:void(0)"; + } } private IEnumerable GetMenuPages() diff --git a/Oqtane.Server/Controllers/ModuleControllerBase.cs b/Oqtane.Server/Controllers/ModuleControllerBase.cs index 14ed583a..18687ee8 100644 --- a/Oqtane.Server/Controllers/ModuleControllerBase.cs +++ b/Oqtane.Server/Controllers/ModuleControllerBase.cs @@ -9,7 +9,8 @@ namespace Oqtane.Controllers public class ModuleControllerBase : Controller { protected readonly ILogManager _logger; - // querystring parameters for policy authorization and validation + + // parameters for policy authorization and validation protected Dictionary _authEntityId = new Dictionary(StringComparer.OrdinalIgnoreCase); protected int _entityId = -1; // legacy support @@ -17,7 +18,7 @@ namespace Oqtane.Controllers { _logger = logger; - // populate policy authorization dictionary from querystring and headers + // populate policy authorization dictionary from querystring int value; foreach (var param in accessor.HttpContext.Request.Query) { @@ -25,12 +26,16 @@ namespace Oqtane.Controllers { _authEntityId.Add(param.Key.Substring(4, param.Key.Length - 6), value); } - } - foreach (var param in accessor.HttpContext.Request.Headers) + } + // if policy authorization dictionary is empty populate from headers + if (_authEntityId.Count == 0) { - if (param.Key.StartsWith("auth") && param.Key.EndsWith("id") && int.TryParse(param.Value, out value)) + foreach (var param in accessor.HttpContext.Request.Headers) { - _authEntityId.Add(param.Key.Substring(4, param.Key.Length - 6), value); + if (param.Key.StartsWith("auth") && param.Key.EndsWith("id") && int.TryParse(param.Value, out value)) + { + _authEntityId.Add(param.Key.Substring(4, param.Key.Length - 6), value); + } } } diff --git a/Oqtane.Server/Controllers/SqlController.cs b/Oqtane.Server/Controllers/SqlController.cs index 16df8935..10922007 100644 --- a/Oqtane.Server/Controllers/SqlController.cs +++ b/Oqtane.Server/Controllers/SqlController.cs @@ -52,7 +52,7 @@ namespace Oqtane.Controllers } catch (Exception ex) { - _logger.Log(LogLevel.Error, this, LogFunction.Other, "Sql Query {Query} Executed on Tenant {TenantId} Results In An Error {Error}", sqlquery.Query, sqlquery.TenantId, ex.Message); + _logger.Log(LogLevel.Error, this, LogFunction.Other, "Sql Query {Query} Executed on Tenant {TenantId} Resulted In An Error {Error}", sqlquery.Query, sqlquery.TenantId, ex.Message); } sqlquery.Results = results; return sqlquery; diff --git a/Oqtane.Server/Migrations/Tenant/02010100_AddPageIsClickable.cs b/Oqtane.Server/Migrations/Tenant/02010100_AddPageIsClickable.cs new file mode 100644 index 00000000..f1d85e45 --- /dev/null +++ b/Oqtane.Server/Migrations/Tenant/02010100_AddPageIsClickable.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Databases.Interfaces; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations.Tenant +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.02.01.01.00")] + public class AddPageIsClickable : MultiDatabaseMigration + { + public AddPageIsClickable(IDatabase database) : base(database) + { + } + + protected override void Up(MigrationBuilder migrationBuilder) + { + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); + + pageEntityBuilder.AddBooleanColumn("IsClickable"); + pageEntityBuilder.UpdateColumn("IsClickable", "true"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase); + + pageEntityBuilder.DropColumn("IsClickable"); + } + } +} diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 9487f391..98c5feab 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -768,7 +768,8 @@ namespace Oqtane.Repository Icon = pagetemplate.Icon, Permissions = pagetemplate.PagePermissions, IsPersonalizable = pagetemplate.IsPersonalizable, - UserId = null + UserId = null, + IsClickable = true }; page = _pageRepository.AddPage(page); diff --git a/Oqtane.Shared/Models/Page.cs b/Oqtane.Shared/Models/Page.cs index 08dac7d7..0ceb2dbb 100644 --- a/Oqtane.Shared/Models/Page.cs +++ b/Oqtane.Shared/Models/Page.cs @@ -68,6 +68,7 @@ namespace Oqtane.Models /// public string Icon { get; set; } public bool IsNavigation { get; set; } + public bool IsClickable { get; set; } public int? UserId { get; set; } public bool IsPersonalizable { get; set; }