Add support for IsPublic to all Setting types, enable Url Mapping for internal links

This commit is contained in:
Shaun Walker
2021-12-18 10:35:22 -05:00
parent e22606ae79
commit 6a2ff369ea
15 changed files with 329 additions and 259 deletions

View File

@ -476,12 +476,12 @@
site = await SiteService.UpdateSiteAsync(site); site = await SiteService.UpdateSiteAsync(site);
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId); var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
SettingService.SetSetting(settings, "SMTPHost", _smtphost); SettingService.SetSetting(settings, "SMTPHost", _smtphost, false);
SettingService.SetSetting(settings, "SMTPPort", _smtpport); SettingService.SetSetting(settings, "SMTPPort", _smtpport, false);
SettingService.SetSetting(settings, "SMTPSSL", _smtpssl); SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, false);
SettingService.SetSetting(settings, "SMTPUsername", _smtpusername); SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, false);
SettingService.SetSetting(settings, "SMTPPassword", _smtppassword); SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, false);
SettingService.SetSetting(settings, "SMTPSender", _smtpsender); SettingService.SetSetting(settings, "SMTPSender", _smtpsender, false);
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId); await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))

View File

@ -40,10 +40,10 @@ else
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.UrlMappingId.ToString())" ResourceKey="Edit" /></td> <td><ActionLink Action="Edit" Parameters="@($"id=" + context.UrlMappingId.ToString())" ResourceKey="Edit" /></td>
<td><ActionDialog Header="Delete Url Mapping" Message="@string.Format(Localizer["Confirm.DeleteUrlMapping"], context.Url)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUrlMapping(context))" ResourceKey="DeleteUrlMapping" /></td> <td><ActionDialog Header="Delete Url Mapping" Message="@string.Format(Localizer["Confirm.DeleteUrlMapping"], context.Url)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUrlMapping(context))" ResourceKey="DeleteUrlMapping" /></td>
<td> <td>
<a href="" onclick="@(() => BrowseUrl(context.Url))">@context.Url</a> <a href="@context.Url">@context.Url</a>
@if (_mapped) @if (_mapped)
{ {
@((MarkupString)"<br />&gt;&gt;&nbsp;")<a href="" onclick="@(() => BrowseUrl(context.MappedUrl))">@context.MappedUrl</a> @((MarkupString)"<br />&gt;&gt;&nbsp;")<a href="@context.MappedUrl">@context.MappedUrl</a>
} }
</td> </td>
<td>@context.Requests</td> <td>@context.Requests</td>
@ -96,11 +96,6 @@ else
} }
} }
private void BrowseUrl(string url)
{
NavigationManager.NavigateTo(url, true);
}
private async Task DeleteUrlMapping(UrlMapping urlMapping) private async Task DeleteUrlMapping(UrlMapping urlMapping)
{ {
try try

View File

@ -24,6 +24,14 @@ namespace Oqtane.Services
/// <returns></returns> /// <returns></returns>
Task<UrlMapping> GetUrlMappingAsync(int urlMappingId); Task<UrlMapping> GetUrlMappingAsync(int urlMappingId);
/// <summary>
/// Get one specific <see cref="UrlMapping"/>
/// </summary>
/// <param name="siteId">ID-reference of a <see cref="Site"/></param>
/// <param name="url">A url</param>
/// <returns></returns>
Task<UrlMapping> GetUrlMappingAsync(int siteId, string url);
/// <summary> /// <summary>
/// Add / save a new <see cref="UrlMapping"/> to the database. /// Add / save a new <see cref="UrlMapping"/> to the database.
/// </summary> /// </summary>

View File

@ -131,22 +131,13 @@ namespace Oqtane.Services
foreach (KeyValuePair<string, string> kvp in settings) foreach (KeyValuePair<string, string> kvp in settings)
{ {
string value = kvp.Value; string value = kvp.Value;
bool ispublic = false; bool ispublic = true;
if (value.StartsWith("[Public]"))
{
switch (entityName)
{
case EntityNames.Site:
case EntityNames.ModuleDefinition:
ispublic = true;
break;
default:
ispublic = false;
break;
}
value = value.Substring(8); // remove [Public]
}
if (value.StartsWith("[Private]"))
{
value = value.Substring(9); // remove [Private]
ispublic = false;
}
Setting setting = settingsList.FirstOrDefault(item => item.SettingName.Equals(kvp.Key, StringComparison.OrdinalIgnoreCase)); Setting setting = settingsList.FirstOrDefault(item => item.SettingName.Equals(kvp.Key, StringComparison.OrdinalIgnoreCase));
if (setting == null) if (setting == null)
@ -205,7 +196,7 @@ namespace Oqtane.Services
public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue) public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue)
{ {
return SetSetting(settings, settingName, settingValue, false); return SetSetting(settings, settingName, settingValue, true);
} }
public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue, bool isPublic) public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue, bool isPublic)
@ -214,7 +205,7 @@ namespace Oqtane.Services
{ {
settings = new Dictionary<string, string>(); settings = new Dictionary<string, string>();
} }
settingValue = (isPublic) ? "[Public]" + settingValue : settingValue; settingValue = (isPublic) ? settingValue : "[Private]" + settingValue;
if (settings.ContainsKey(settingName)) if (settings.ContainsKey(settingName))
{ {
settings[settingName] = settingValue; settings[settingName] = settingValue;

View File

@ -5,6 +5,7 @@ using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Oqtane.Documentation; using Oqtane.Documentation;
using Oqtane.Shared; using Oqtane.Shared;
using System.Net;
namespace Oqtane.Services namespace Oqtane.Services
{ {
@ -33,6 +34,11 @@ namespace Oqtane.Services
return await GetJsonAsync<UrlMapping>($"{Apiurl}/{urlMappingId}"); return await GetJsonAsync<UrlMapping>($"{Apiurl}/{urlMappingId}");
} }
public async Task<UrlMapping> GetUrlMappingAsync(int siteId, string url)
{
return await GetJsonAsync<UrlMapping>($"{Apiurl}/url/{siteId}?url={WebUtility.UrlEncode(url)}");
}
public async Task<UrlMapping> AddUrlMappingAsync(UrlMapping role) public async Task<UrlMapping> AddUrlMappingAsync(UrlMapping role)
{ {
return await PostJsonAsync<UrlMapping>(Apiurl, role); return await PostJsonAsync<UrlMapping>(Apiurl, role);

View File

@ -9,6 +9,7 @@
@inject IPageService PageService @inject IPageService PageService
@inject IUserService UserService @inject IUserService UserService
@inject IModuleService ModuleService @inject IModuleService ModuleService
@inject IUrlMappingService UrlMappingService
@inject ILogService LogService @inject ILogService LogService
@implements IHandleAfterRender @implements IHandleAfterRender
@ -83,133 +84,133 @@
var querystring = ParseQueryString(route.Query); var querystring = ParseQueryString(route.Query);
// reload the client application if there is a forced reload or the user navigated to a site with a different alias // reload the client application if there is a forced reload or the user navigated to a site with a different alias
if (querystring.ContainsKey("reload") || (!route.AbsolutePath.Substring(1).ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path))) if (querystring.ContainsKey("reload") || (!route.AbsolutePath.Substring(1).ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path)))
{ {
NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true); NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true);
return; return;
} }
else else
{ {
// the refresh parameter is used to refresh the PageState // the refresh parameter is used to refresh the PageState
if (querystring.ContainsKey("refresh")) if (querystring.ContainsKey("refresh"))
{ {
refresh = UI.Refresh.Site; refresh = UI.Refresh.Site;
} }
} }
if (PageState != null) if (PageState != null)
{ {
editmode = PageState.EditMode; editmode = PageState.EditMode;
lastsyncdate = PageState.LastSyncDate; lastsyncdate = PageState.LastSyncDate;
} }
// process any sync events // process any sync events
var sync = await SyncService.GetSyncAsync(lastsyncdate); var sync = await SyncService.GetSyncAsync(lastsyncdate);
lastsyncdate = sync.SyncDate; lastsyncdate = sync.SyncDate;
if (sync.SyncEvents.Any()) if (sync.SyncEvents.Any())
{ {
// reload client application if server was restarted or site runtime/rendermode was modified // reload client application if server was restarted or site runtime/rendermode was modified
if (PageState != null && sync.SyncEvents.Exists(item => (item.TenantId == -1 || item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId) && item.Reload)) if (PageState != null && sync.SyncEvents.Exists(item => (item.TenantId == -1 || item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId) && item.Reload))
{ {
NavigationManager.NavigateTo(_absoluteUri, true); NavigationManager.NavigateTo(_absoluteUri, true);
return; return;
} }
if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId)) if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId))
{ {
refresh = UI.Refresh.Site; refresh = UI.Refresh.Site;
} }
} }
if (refresh == UI.Refresh.Site || PageState == null || PageState.Alias.SiteId != SiteState.Alias.SiteId) if (refresh == UI.Refresh.Site || PageState == null || PageState.Alias.SiteId != SiteState.Alias.SiteId)
{ {
site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId); site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId);
refresh = UI.Refresh.Site; refresh = UI.Refresh.Site;
} }
else else
{ {
site = PageState.Site; site = PageState.Site;
} }
if (site != null) if (site != null)
{ {
if (PageState == null || refresh == UI.Refresh.Site) if (PageState == null || refresh == UI.Refresh.Site)
{ {
// get user // get user
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
if (authState.User.Identity.IsAuthenticated) if (authState.User.Identity.IsAuthenticated)
{ {
user = await UserService.GetUserAsync(authState.User.Identity.Name, site.SiteId); user = await UserService.GetUserAsync(authState.User.Identity.Name, site.SiteId);
user.IsAuthenticated = authState.User.Identity.IsAuthenticated; user.IsAuthenticated = authState.User.Identity.IsAuthenticated;
} }
} }
else else
{ {
user = PageState.User; user = PageState.User;
} }
// process any sync events for user // process any sync events for user
if (refresh != UI.Refresh.Site && user != null && sync.SyncEvents.Any()) if (refresh != UI.Refresh.Site && user != null && sync.SyncEvents.Any())
{ {
if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.User && item.EntityId == user.UserId)) if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.User && item.EntityId == user.UserId))
{ {
refresh = UI.Refresh.Site; refresh = UI.Refresh.Site;
} }
} }
if (PageState == null || refresh == UI.Refresh.Site) if (PageState == null || refresh == UI.Refresh.Site)
{ {
pages = await PageService.GetPagesAsync(site.SiteId); pages = await PageService.GetPagesAsync(site.SiteId);
} }
else else
{ {
pages = PageState.Pages; pages = PageState.Pages;
} }
if (PageState == null || refresh == UI.Refresh.Site) if (PageState == null || refresh == UI.Refresh.Site)
{ {
page = pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase)); page = pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase));
} }
else else
{ {
page = PageState.Page; page = PageState.Page;
} }
// get the page if the path has changed // get the page if the path has changed
if (page == null || page.Path != route.PagePath) if (page == null || page.Path != route.PagePath)
{ {
page = pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase)); page = pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase));
// if the home page path does not exist then use the first page in the collection (a future enhancement would allow the admin to specify the home page) // if the home page path does not exist then use the first page in the collection (a future enhancement would allow the admin to specify the home page)
if (page == null && route.PagePath == "") if (page == null && route.PagePath == "")
{ {
page = pages.FirstOrDefault(); page = pages.FirstOrDefault();
} }
editmode = false; editmode = false;
} }
if (page != null) if (page != null)
{ {
if (PageState == null) if (PageState == null)
{ {
editmode = false; editmode = false;
} }
// check if user is authorized to view page // check if user is authorized to view page
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.Permissions)) if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.Permissions))
{ {
page = await ProcessPage(page, site, user); page = await ProcessPage(page, site, user);
if (PageState == null || refresh == UI.Refresh.Site) if (PageState == null || refresh == UI.Refresh.Site)
{ {
modules = await ModuleService.GetModulesAsync(site.SiteId); modules = await ModuleService.GetModulesAsync(site.SiteId);
} }
else else
{ {
modules = PageState.Modules; modules = PageState.Modules;
} }
(page, modules) = ProcessModules(page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType); (page, modules) = ProcessModules(page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
_pagestate = new PageState _pagestate = new PageState
{ {
Alias = SiteState.Alias, Alias = SiteState.Alias,
Site = site, Site = site,
@ -228,25 +229,33 @@
VisitorId = VisitorId VisitorId = VisitorId
}; };
OnStateChange?.Invoke(_pagestate); OnStateChange?.Invoke(_pagestate);
} }
} }
else else // page not found
{ {
if (user == null) var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.SiteUrl + "/" + route.PagePath);
{ if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
// redirect to login page {
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + route.AbsolutePath)); NavigationManager.NavigateTo(urlMapping.MappedUrl, false);
} }
else else // not mapped
{ {
await LogService.Log(null, null, user.UserId, GetType().AssemblyQualifiedName, Utilities.GetTypeNameLastSegment(GetType().AssemblyQualifiedName, 1), LogFunction.Security, LogLevel.Error, null, "Page Does Not Exist Or User Is Not Authorized To View Page {Path}", route.PagePath); if (user == null)
if (route.PagePath != "") {
{ // redirect to login page if user not logged in as they may need to be authenticated
// redirect to home page NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + route.AbsolutePath));
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", "")); }
} else
} {
await LogService.Log(null, null, user.UserId, GetType().AssemblyQualifiedName, Utilities.GetTypeNameLastSegment(GetType().AssemblyQualifiedName, 1), LogFunction.Security, LogLevel.Error, null, "Page Does Not Exist Or User Is Not Authorized To View Page {Path}", route.PagePath);
if (route.PagePath != "")
{
// redirect to home page
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", ""));
}
}
}
} }
} }
else else

View File

@ -75,6 +75,7 @@ namespace Oqtane.Controllers
module.ModuleDefinition = moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName); module.ModuleDefinition = moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName);
module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId) module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId)
.Where(item => item.IsPublic || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.Permissions))
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
modules.Add(module); modules.Add(module);
@ -101,7 +102,8 @@ namespace Oqtane.Controllers
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(module.SiteId).ToList(); List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(module.SiteId).ToList();
module.ModuleDefinition = moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName); module.ModuleDefinition = moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName);
module.Settings = _settings.GetSettings(EntityNames.Module, id) module.Settings = _settings.GetSettings(EntityNames.Module, id)
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); .Where(item => item.IsPublic || _userPermissions.IsAuthorized(User, PermissionNames.Edit, module.Permissions))
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
return module; return module;
} }
else else

View File

@ -57,6 +57,7 @@ namespace Oqtane.Controllers
if (_userPermissions.IsAuthorized(User, PermissionNames.View, page.Permissions)) if (_userPermissions.IsAuthorized(User, PermissionNames.View, page.Permissions))
{ {
page.Settings = settings.Where(item => item.EntityId == page.PageId) page.Settings = settings.Where(item => item.EntityId == page.PageId)
.Where(item => item.IsPublic || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.Permissions))
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
pages.Add(page); pages.Add(page);
} }
@ -85,15 +86,16 @@ namespace Oqtane.Controllers
{ {
page = _pages.GetPage(id, int.Parse(userid)); page = _pages.GetPage(id, int.Parse(userid));
} }
if (_userPermissions.IsAuthorized(User,PermissionNames.View, page.Permissions)) if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User,PermissionNames.View, page.Permissions))
{ {
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId) page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); .Where(item => item.IsPublic || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.Permissions))
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
return page; return page;
} }
else else
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {Page}", page); _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {PageId} {UserId}", id, userid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null; return null;
} }
@ -104,24 +106,16 @@ namespace Oqtane.Controllers
public Page Get(string path, int siteid) public Page Get(string path, int siteid)
{ {
Page page = _pages.GetPage(WebUtility.UrlDecode(path), siteid); Page page = _pages.GetPage(WebUtility.UrlDecode(path), siteid);
if (page != null && page.SiteId == _alias.SiteId) if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, page.Permissions))
{ {
if (_userPermissions.IsAuthorized(User,PermissionNames.View, page.Permissions)) page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
{ .Where(item => item.IsPublic || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.Permissions))
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId) .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue); return page;
return page;
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {Page}", page);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
} }
else else
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {Path} for Site {SiteId}", path, siteid); _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {SiteId} {Path}", siteid, path);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null; return null;
} }

View File

@ -20,6 +20,7 @@ namespace Oqtane.Controllers
private readonly ISyncManager _syncManager; private readonly ISyncManager _syncManager;
private readonly ILogManager _logger; private readonly ILogManager _logger;
private readonly Alias _alias; private readonly Alias _alias;
private readonly string _visitorCookie;
public SettingController(ISettingRepository settings, IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger) public SettingController(ISettingRepository settings, IPageModuleRepository pageModules, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
{ {
@ -29,39 +30,25 @@ namespace Oqtane.Controllers
_syncManager = syncManager; _syncManager = syncManager;
_logger = logger; _logger = logger;
_alias = tenantManager.GetAlias(); _alias = tenantManager.GetAlias();
_visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString();
} }
// GET: api/<controller> // GET: api/<controller>
[HttpGet] [HttpGet]
public IEnumerable<Setting> Get(string entityName, int entityid) public IEnumerable<Setting> Get(string entityName, int entityId)
{ {
List<Setting> settings = new List<Setting>(); List<Setting> settings = new List<Setting>();
if (IsAuthorized(entityName, entityid, PermissionNames.View)) if (IsAuthorized(entityName, entityId, PermissionNames.View))
{ {
settings = _settings.GetSettings(entityName, entityid).ToList(); settings = _settings.GetSettings(entityName, entityId).ToList();
if (FilterPublic(entityName, entityId))
// ispublic filter
switch (entityName)
{ {
case EntityNames.Tenant: settings = settings.Where(item => item.IsPublic).ToList();
case EntityNames.ModuleDefinition:
case EntityNames.Host:
if (!User.IsInRole(RoleNames.Host))
{
settings = settings.Where(item => item.IsPublic).ToList();
}
break;
case EntityNames.Site:
if (!User.IsInRole(RoleNames.Admin))
{
settings = settings.Where(item => item.IsPublic).ToList();
}
break;
} }
} }
else else
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Settings {EntityName} {EntityId}", entityName, entityid); _logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Settings {EntityName} {EntityId}", entityName, entityId);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
} }
return settings; return settings;
@ -74,30 +61,15 @@ namespace Oqtane.Controllers
Setting setting = _settings.GetSetting(entityName, id); Setting setting = _settings.GetSetting(entityName, id);
if (IsAuthorized(setting.EntityName, setting.EntityId, PermissionNames.View)) if (IsAuthorized(setting.EntityName, setting.EntityId, PermissionNames.View))
{ {
// ispublic filter if (FilterPublic(entityName, id) && !setting.IsPublic)
switch (entityName)
{ {
case EntityNames.Tenant: setting = null;
case EntityNames.ModuleDefinition:
case EntityNames.Host:
if (!User.IsInRole(RoleNames.Host) && !setting.IsPublic)
{
setting = null;
}
break;
case EntityNames.Site:
if (!User.IsInRole(RoleNames.Admin) && !setting.IsPublic)
{
setting = null;
}
break;
} }
return setting; return setting;
} }
else else
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Setting {Setting}", setting); _logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Setting {EntityName} {SettingId}", entityName, id);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null; return null;
} }
@ -204,20 +176,67 @@ namespace Oqtane.Controllers
} }
break; break;
case EntityNames.Visitor: case EntityNames.Visitor:
var visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString(); authorized = User.IsInRole(RoleNames.Admin);
if (int.TryParse(Request.Cookies[visitorCookie], out int visitorId)) if (!authorized)
{ {
authorized = (visitorId == entityId); if (int.TryParse(Request.Cookies[_visitorCookie], out int visitorId))
{
authorized = (visitorId == entityId);
}
}
break;
default: // custom entity
if (permissionName == PermissionNames.Edit)
{
authorized = User.IsInRole(RoleNames.Admin);
} }
else else
{ {
authorized = User.IsInRole(RoleNames.Admin); authorized = true;
} }
break; break;
} }
return authorized; return authorized;
} }
private bool FilterPublic(string entityName, int entityId)
{
bool filter = false;
switch (entityName)
{
case EntityNames.Tenant:
case EntityNames.ModuleDefinition:
case EntityNames.Host:
filter = !User.IsInRole(RoleNames.Host);
break;
case EntityNames.Site:
filter = !User.IsInRole(RoleNames.Admin);
break;
case EntityNames.Page:
case EntityNames.Module:
case EntityNames.Folder:
filter = !_userPermissions.IsAuthorized(User, entityName, entityId, PermissionNames.Edit);
break;
case EntityNames.User:
filter = !User.IsInRole(RoleNames.Admin) && _userPermissions.GetUser(User).UserId != entityId;
break;
case EntityNames.Visitor:
if (!User.IsInRole(RoleNames.Admin))
{
filter = true;
if (int.TryParse(Request.Cookies[_visitorCookie], out int visitorId))
{
filter = (visitorId != entityId);
}
}
break;
default: // custom entity
filter = !User.IsInRole(RoleNames.Admin);
break;
}
return filter;
}
private void AddSyncEvent(string EntityName) private void AddSyncEvent(string EntityName)
{ {
switch (EntityName) switch (EntityName)

View File

@ -44,12 +44,9 @@ namespace Oqtane.Controllers
var site = _sites.GetSite(id); var site = _sites.GetSite(id);
if (site.SiteId == _alias.SiteId) if (site.SiteId == _alias.SiteId)
{ {
var settings = _settings.GetSettings(EntityNames.Site, site.SiteId); site.Settings = _settings.GetSettings(EntityNames.Site, site.SiteId)
if (!User.IsInRole(RoleNames.Admin)) .Where(item => item.IsPublic || User.IsInRole(RoleNames.Admin))
{ .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
settings = settings.Where(item => item.IsPublic);
}
site.Settings = settings.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
return site; return site;
} }
else else

View File

@ -48,7 +48,7 @@ namespace Oqtane.Controllers
public UrlMapping Get(int id) public UrlMapping Get(int id)
{ {
var urlMapping = _urlMappings.GetUrlMapping(id); var urlMapping = _urlMappings.GetUrlMapping(id);
if (urlMapping != null && (urlMapping.SiteId == _alias.SiteId)) if (urlMapping != null && urlMapping.SiteId == _alias.SiteId)
{ {
return urlMapping; return urlMapping;
} }
@ -60,6 +60,23 @@ namespace Oqtane.Controllers
} }
} }
// GET api/<controller>/url/x?url=y
[HttpGet("url/{siteid}")]
public UrlMapping Get(int siteid, string url)
{
var urlMapping = _urlMappings.GetUrlMapping(siteid, WebUtility.UrlDecode(url));
if (urlMapping != null && urlMapping.SiteId == _alias.SiteId)
{
return urlMapping;
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized UrlMapping Get Attempt {SiteId} {Url}", siteid, url);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// POST api/<controller> // POST api/<controller>
[HttpPost] [HttpPost]
[Authorize(Roles = RoleNames.Admin)] [Authorize(Roles = RoleNames.Admin)]

View File

@ -47,15 +47,14 @@ namespace Oqtane.Controllers
[HttpGet("{id}")] [HttpGet("{id}")]
public Visitor Get(int id) public Visitor Get(int id)
{ {
bool authorized; bool authorized = User.IsInRole(RoleNames.Admin);
var visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString(); if (!authorized)
if (int.TryParse(Request.Cookies[visitorCookie], out int visitorId))
{ {
authorized = (visitorId == id); var visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString();
} if (int.TryParse(Request.Cookies[visitorCookie], out int visitorId))
else {
{ authorized = (visitorId == id);
authorized = User.IsInRole(RoleNames.Admin); }
} }
var visitor = _visitors.GetVisitor(id); var visitor = _visitors.GetVisitor(id);

View File

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Databases.Interfaces;
using Oqtane.Migrations.EntityBuilders;
using Oqtane.Repository;
using Oqtane.Shared;
namespace Oqtane.Migrations.Tenant
{
[DbContext(typeof(TenantDBContext))]
[Migration("Tenant.03.00.02.01")]
public class UpdateSettingIsPublic : MultiDatabaseMigration
{
public UpdateSettingIsPublic(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase);
settingEntityBuilder.UpdateColumn("IsPublic", "1", "bool", "SettingName NOT LIKE 'SMTP%'");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase);
settingEntityBuilder.UpdateColumn("IsPublic", "0", "bool", "SettingName NOT LIKE 'SMTP%'");
}
}
}

View File

@ -130,30 +130,9 @@ namespace Oqtane.Pages
// page does not exist // page does not exist
var url = route.SiteUrl + "/" + route.PagePath; var url = route.SiteUrl + "/" + route.PagePath;
var urlMapping = _urlMappings.GetUrlMapping(site.SiteId, url); var urlMapping = _urlMappings.GetUrlMapping(site.SiteId, url);
if (urlMapping == null) if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
{ {
if (site.CaptureBrokenUrls) return RedirectPermanent(urlMapping.MappedUrl);
{
urlMapping = new UrlMapping();
urlMapping.SiteId = site.SiteId;
urlMapping.Url = url;
urlMapping.MappedUrl = "";
urlMapping.Requests = 1;
urlMapping.CreatedOn = DateTime.UtcNow;
urlMapping.RequestedOn = DateTime.UtcNow;
_urlMappings.AddUrlMapping(urlMapping);
}
}
else
{
urlMapping.Requests += 1;
urlMapping.RequestedOn = DateTime.UtcNow;
_urlMappings.UpdateUrlMapping(urlMapping);
if (!string.IsNullOrEmpty(urlMapping.MappedUrl))
{
return RedirectPermanent(urlMapping.MappedUrl);
}
} }
} }
} }

View File

@ -9,12 +9,14 @@ namespace Oqtane.Repository
public class UrlMappingRepository : IUrlMappingRepository public class UrlMappingRepository : IUrlMappingRepository
{ {
private TenantDBContext _db; private TenantDBContext _db;
private readonly ISiteRepository _sites;
public UrlMappingRepository(TenantDBContext context) public UrlMappingRepository(TenantDBContext context, ISiteRepository sites)
{ {
_db = context; _db = context;
_sites = sites;
} }
public IEnumerable<UrlMapping> GetUrlMappings(int siteId, bool isMapped) public IEnumerable<UrlMapping> GetUrlMappings(int siteId, bool isMapped)
{ {
if (isMapped) if (isMapped)
@ -60,7 +62,29 @@ namespace Oqtane.Repository
public UrlMapping GetUrlMapping(int siteId, string url) public UrlMapping GetUrlMapping(int siteId, string url)
{ {
return _db.UrlMapping.Where(item => item.SiteId == siteId && item.Url == url).FirstOrDefault(); var urlMapping = _db.UrlMapping.Where(item => item.SiteId == siteId && item.Url == url).FirstOrDefault();
if (urlMapping == null)
{
var site = _sites.GetSite(siteId);
if (site.CaptureBrokenUrls)
{
urlMapping = new UrlMapping();
urlMapping.SiteId = siteId;
urlMapping.Url = url;
urlMapping.MappedUrl = "";
urlMapping.Requests = 1;
urlMapping.CreatedOn = DateTime.UtcNow;
urlMapping.RequestedOn = DateTime.UtcNow;
urlMapping = AddUrlMapping(urlMapping);
}
}
else
{
urlMapping.Requests += 1;
urlMapping.RequestedOn = DateTime.UtcNow;
urlMapping = UpdateUrlMapping(urlMapping);
}
return urlMapping;
} }
public void DeleteUrlMapping(int urlMappingId) public void DeleteUrlMapping(int urlMappingId)