477 lines
22 KiB
C#
477 lines
22 KiB
C#
using System.Collections.Generic;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Oqtane.Models;
|
|
using Oqtane.Shared;
|
|
using System.Linq;
|
|
using Oqtane.Security;
|
|
using System.Net;
|
|
using Oqtane.Enums;
|
|
using Oqtane.Infrastructure;
|
|
using Oqtane.Repository;
|
|
using System.Xml.Linq;
|
|
using Microsoft.AspNetCore.Diagnostics;
|
|
|
|
namespace Oqtane.Controllers
|
|
{
|
|
[Route(ControllerRoutes.ApiRoute)]
|
|
public class PageController : Controller
|
|
{
|
|
private readonly IPageRepository _pages;
|
|
private readonly IModuleRepository _modules;
|
|
private readonly IPageModuleRepository _pageModules;
|
|
private readonly IPermissionRepository _permissionRepository;
|
|
private readonly ISettingRepository _settings;
|
|
private readonly IUserPermissions _userPermissions;
|
|
private readonly IUrlMappingRepository _urlMappings;
|
|
private readonly ISyncManager _syncManager;
|
|
private readonly ILogManager _logger;
|
|
private readonly Alias _alias;
|
|
|
|
public PageController(IPageRepository pages, IModuleRepository modules, IPageModuleRepository pageModules, IPermissionRepository permissionRepository, ISettingRepository settings, IUserPermissions userPermissions, IUrlMappingRepository urlMappings, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
|
{
|
|
_pages = pages;
|
|
_modules = modules;
|
|
_pageModules = pageModules;
|
|
_permissionRepository = permissionRepository;
|
|
_settings = settings;
|
|
_userPermissions = userPermissions;
|
|
_urlMappings = urlMappings;
|
|
_syncManager = syncManager;
|
|
_logger = logger;
|
|
_alias = tenantManager.GetAlias();
|
|
}
|
|
|
|
// GET: api/<controller>?siteid=x
|
|
[HttpGet]
|
|
public IEnumerable<Page> Get(string siteid)
|
|
{
|
|
List<Page> pages = new List<Page>();
|
|
|
|
int SiteId;
|
|
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
|
{
|
|
List<Setting> settings = _settings.GetSettings(EntityNames.Page).ToList();
|
|
|
|
foreach (Page page in _pages.GetPages(SiteId))
|
|
{
|
|
if (_userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
|
|
{
|
|
page.Settings = settings.Where(item => item.EntityId == page.PageId)
|
|
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
|
|
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
|
pages.Add(page);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {SiteId}", siteid);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
pages = null;
|
|
}
|
|
|
|
return pages;
|
|
}
|
|
|
|
// GET api/<controller>/5
|
|
[HttpGet("{id}")]
|
|
public Page Get(int id)
|
|
{
|
|
var page = _pages.GetPage(id);
|
|
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
|
|
{
|
|
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
|
|
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
|
|
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
|
return page;
|
|
}
|
|
else
|
|
{
|
|
if (page != null)
|
|
{
|
|
_logger.Log(LogLevel.Warning, this, LogFunction.Security, "Unauthorized Page Get Attempt {PageId}", id);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
}
|
|
else
|
|
{
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// GET api/<controller>/path/x?path=y
|
|
[HttpGet("path/{siteid}")]
|
|
public Page Get(string path, int siteid)
|
|
{
|
|
Page page = _pages.GetPage(WebUtility.UrlDecode(path), siteid);
|
|
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
|
|
{
|
|
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
|
|
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
|
|
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
|
return page;
|
|
}
|
|
else
|
|
{
|
|
if (page != null)
|
|
{
|
|
_logger.Log(LogLevel.Warning, this, LogFunction.Security, "Unauthorized Page Get Attempt {SiteId} {Path}", siteid, path);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
}
|
|
else
|
|
{
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// POST api/<controller>
|
|
[HttpPost]
|
|
[Authorize(Roles = RoleNames.Registered)]
|
|
public Page Post([FromBody] Page page)
|
|
{
|
|
if (ModelState.IsValid && page.SiteId == _alias.SiteId)
|
|
{
|
|
List<Permission> permissions;
|
|
if (page.ParentId != null)
|
|
{
|
|
permissions = _pages.GetPage(page.ParentId.Value).PermissionList;
|
|
}
|
|
else
|
|
{
|
|
permissions = new List<Permission> {
|
|
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
|
};
|
|
}
|
|
|
|
if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, permissions))
|
|
{
|
|
page = _pages.AddPage(page);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Page Added {Page}", page);
|
|
|
|
if (!page.Path.StartsWith("admin/"))
|
|
{
|
|
var modules = _modules.GetModules(page.SiteId).Where(item => item.AllPages).ToList();
|
|
foreach (Module module in modules)
|
|
{
|
|
var pageModule = _pageModules.GetPageModules(page.SiteId).FirstOrDefault(item => item.ModuleId == module.ModuleId);
|
|
_pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType });
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger.Log(LogLevel.Warning, this, LogFunction.Create, "User Not Authorized To Add Page {Page}", page);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
page = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Post Attempt {Page}", page);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
page = null;
|
|
}
|
|
return page;
|
|
}
|
|
|
|
// POST api/<controller>/5?userid=x
|
|
[HttpPost("{id}")]
|
|
[Authorize(Roles = RoleNames.Registered)]
|
|
public Page Post(int id, string userid)
|
|
{
|
|
Page page = null;
|
|
Page parent = _pages.GetPage(id);
|
|
User user = _userPermissions.GetUser(User);
|
|
if (parent != null && parent.SiteId == _alias.SiteId && parent.IsPersonalizable && user.UserId == int.Parse(userid))
|
|
{
|
|
var path = Utilities.GetFriendlyUrl(user.Username);
|
|
page = _pages.GetPage(parent.Path + "/" + path, parent.SiteId);
|
|
if (page == null)
|
|
{
|
|
page = new Page();
|
|
page.SiteId = parent.SiteId;
|
|
page.ParentId = parent.PageId;
|
|
page.Name = user.Username;
|
|
page.Path = parent.Path + "/" + path;
|
|
page.Title = ((!string.IsNullOrEmpty(user.DisplayName)) ? user.DisplayName : user.Username) + " - " + parent.Name;
|
|
page.Order = 0;
|
|
page.IsNavigation = false;
|
|
page.Url = "";
|
|
page.ThemeType = parent.ThemeType;
|
|
page.DefaultContainerType = parent.DefaultContainerType;
|
|
page.Icon = parent.Icon;
|
|
page.PermissionList = new List<Permission>()
|
|
{
|
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
|
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
|
};
|
|
page.IsPersonalizable = false;
|
|
page.UserId = int.Parse(userid);
|
|
page = _pages.AddPage(page);
|
|
|
|
// copy modules
|
|
List<PageModule> pagemodules = _pageModules.GetPageModules(page.SiteId).ToList();
|
|
foreach (PageModule pm in pagemodules.Where(item => item.PageId == parent.PageId && !item.IsDeleted))
|
|
{
|
|
Module module = new Module();
|
|
module.SiteId = page.SiteId;
|
|
module.PageId = page.PageId;
|
|
module.ModuleDefinitionName = pm.Module.ModuleDefinitionName;
|
|
module.AllPages = false;
|
|
module.PermissionList = new List<Permission>()
|
|
{
|
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
|
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
|
};
|
|
module = _modules.AddModule(module);
|
|
|
|
string content = _modules.ExportModule(pm.ModuleId);
|
|
if (content != "")
|
|
{
|
|
_modules.ImportModule(module.ModuleId, content);
|
|
}
|
|
|
|
PageModule pagemodule = new PageModule();
|
|
pagemodule.PageId = page.PageId;
|
|
pagemodule.ModuleId = module.ModuleId;
|
|
pagemodule.Title = pm.Title;
|
|
pagemodule.Pane = pm.Pane;
|
|
pagemodule.Order = pm.Order;
|
|
pagemodule.ContainerType = pm.ContainerType;
|
|
|
|
_pageModules.AddPageModule(pagemodule);
|
|
}
|
|
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
|
|
|
// set user personalized page path
|
|
var setting = new Setting { EntityName = EntityNames.User, EntityId = page.UserId.Value, SettingName = $"PersonalizedPagePath:{page.SiteId}:{parent.PageId}", SettingValue = path, IsPrivate = false };
|
|
_settings.AddSetting(setting);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.User, user.UserId, SyncEventActions.Update);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Post Attempt {PageId} By User {UserId}", id, userid);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
page = null;
|
|
}
|
|
return page;
|
|
}
|
|
|
|
// PUT api/<controller>/5
|
|
[HttpPut("{id}")]
|
|
[Authorize(Roles = RoleNames.Registered)]
|
|
public Page Put(int id, [FromBody] Page page)
|
|
{
|
|
// get current page
|
|
var currentPage = _pages.GetPage(page.PageId, false);
|
|
|
|
if (ModelState.IsValid && page.SiteId == _alias.SiteId && page.PageId == id && currentPage != null && _userPermissions.IsAuthorized(User, page.SiteId, EntityNames.Page, page.PageId, PermissionNames.Edit))
|
|
{
|
|
// get current page permissions
|
|
var currentPermissions = _permissionRepository.GetPermissions(page.SiteId, EntityNames.Page, page.PageId).ToList();
|
|
|
|
// preserve new path and deleted status
|
|
var newPath = page.Path;
|
|
var deleted = page.IsDeleted;
|
|
page.Path = currentPage.Path;
|
|
page.IsDeleted = currentPage.IsDeleted;
|
|
|
|
// update page
|
|
UpdatePage(page, page.PageId, page.Path, newPath, deleted);
|
|
|
|
// get differences between current and new page permissions
|
|
var added = GetPermissionsDifferences(page.PermissionList, currentPermissions);
|
|
var removed = GetPermissionsDifferences(currentPermissions, page.PermissionList);
|
|
|
|
// synchronize module permissions
|
|
if (added.Count > 0 || removed.Count > 0)
|
|
{
|
|
foreach (PageModule pageModule in _pageModules.GetPageModules(page.SiteId).Where(item => item.PageId == page.PageId).ToList())
|
|
{
|
|
var modulePermissions = _permissionRepository.GetPermissions(pageModule.Module.SiteId, EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
|
// permissions added
|
|
foreach (Permission permission in added)
|
|
{
|
|
if (!modulePermissions.Any(item => item.PermissionName == permission.PermissionName
|
|
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized))
|
|
{
|
|
_permissionRepository.AddPermission(new Permission
|
|
{
|
|
SiteId = page.SiteId,
|
|
EntityName = EntityNames.Module,
|
|
EntityId = pageModule.ModuleId,
|
|
PermissionName = permission.PermissionName,
|
|
RoleId = permission.RoleId,
|
|
UserId = permission.UserId,
|
|
IsAuthorized = permission.IsAuthorized
|
|
});
|
|
}
|
|
}
|
|
|
|
// permissions removed
|
|
foreach (Permission permission in removed)
|
|
{
|
|
var modulePermission = modulePermissions.FirstOrDefault(item => item.PermissionName == permission.PermissionName
|
|
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized);
|
|
if (modulePermission != null)
|
|
{
|
|
_permissionRepository.DeletePermission(modulePermission.PermissionId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// update child paths
|
|
if (page.ParentId != currentPage.ParentId)
|
|
{
|
|
foreach (Page _page in _pages.GetPages(page.SiteId).Where(item => item.Path.StartsWith(currentPage.Path)).ToList())
|
|
{
|
|
_page.Path = _page.Path.Replace(currentPage.Path, page.Path);
|
|
_pages.UpdatePage(_page);
|
|
}
|
|
}
|
|
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
|
|
|
// personalized page
|
|
if (page.UserId != null && currentPage.Path != page.Path)
|
|
{
|
|
// set user personalized page path
|
|
var settingName = $"PersonalizedPagePath:{page.SiteId}:{page.ParentId}";
|
|
var path = page.Path.Substring(page.Path.LastIndexOf("/") + 1);
|
|
var settings = _settings.GetSettings(EntityNames.User, page.UserId.Value).ToList();
|
|
var setting = settings.FirstOrDefault(item => item.SettingName == settingName);
|
|
if (setting == null)
|
|
{
|
|
setting = new Setting { EntityName = EntityNames.User, EntityId = page.UserId.Value, SettingName = settingName, SettingValue = path, IsPrivate = false };
|
|
_settings.AddSetting(setting);
|
|
}
|
|
else
|
|
{
|
|
setting.SettingValue = path;
|
|
_settings.UpdateSetting(setting);
|
|
}
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.User, page.UserId.Value, SyncEventActions.Update);
|
|
}
|
|
|
|
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Page Updated {Page}", page);
|
|
}
|
|
else
|
|
{
|
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Put Attempt {Page}", page);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
page = null;
|
|
}
|
|
return page;
|
|
}
|
|
|
|
private void UpdatePage(Page page, int pageId, string oldPath, string newPath, bool deleted)
|
|
{
|
|
var update = (page.PageId == pageId);
|
|
if (oldPath != newPath)
|
|
{
|
|
var urlMapping = _urlMappings.GetUrlMapping(page.SiteId, page.Path);
|
|
if (urlMapping != null)
|
|
{
|
|
urlMapping.MappedUrl = newPath + page.Path.Substring(oldPath.Length);
|
|
_urlMappings.UpdateUrlMapping(urlMapping);
|
|
}
|
|
|
|
page.Path = newPath + page.Path.Substring(oldPath.Length);
|
|
update = true;
|
|
}
|
|
if (deleted != page.IsDeleted)
|
|
{
|
|
page.IsDeleted = deleted;
|
|
update = true;
|
|
}
|
|
if (update)
|
|
{
|
|
_pages.UpdatePage(page);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Page, page.PageId, SyncEventActions.Update);
|
|
}
|
|
|
|
// update any children
|
|
foreach (var _page in _pages.GetPages(page.SiteId).Where(item => item.ParentId == page.PageId))
|
|
{
|
|
UpdatePage(_page, pageId, oldPath, newPath, deleted);
|
|
}
|
|
}
|
|
|
|
private List<Permission> GetPermissionsDifferences(List<Permission> permissions1, List<Permission> permissions2)
|
|
{
|
|
var differences = new List<Permission>();
|
|
foreach (Permission p in permissions1)
|
|
{
|
|
if (!permissions2.Any(item => item.PermissionName == p.PermissionName && item.RoleId == p.RoleId && item.UserId == p.UserId && item.IsAuthorized == p.IsAuthorized))
|
|
{
|
|
differences.Add(p);
|
|
}
|
|
}
|
|
return differences;
|
|
}
|
|
|
|
// PUT api/<controller>/?siteid=x&pageid=y&parentid=z
|
|
[HttpPut]
|
|
[Authorize(Roles = RoleNames.Registered)]
|
|
public void Put(int siteid, int pageid, int? parentid)
|
|
{
|
|
if (siteid == _alias.SiteId && _pages.GetPage(pageid, false) != null && _userPermissions.IsAuthorized(User, siteid, EntityNames.Page, pageid, PermissionNames.Edit))
|
|
{
|
|
int order = 1;
|
|
List<Page> pages = _pages.GetPages(siteid).ToList();
|
|
foreach (Page page in pages.Where(item => item.ParentId == parentid).OrderBy(item => item.Order))
|
|
{
|
|
if (page.Order != order)
|
|
{
|
|
page.Order = order;
|
|
_pages.UpdatePage(page);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Page, page.PageId, SyncEventActions.Update);
|
|
}
|
|
order += 2;
|
|
}
|
|
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Site, siteid, SyncEventActions.Refresh);
|
|
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Page Order Updated {SiteId} {PageId} {ParentId}", siteid, pageid, parentid);
|
|
}
|
|
else
|
|
{
|
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Put Attempt {SiteId} {PageId} {ParentId}", siteid, pageid, parentid);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
}
|
|
}
|
|
|
|
// DELETE api/<controller>/5
|
|
[HttpDelete("{id}")]
|
|
[Authorize(Roles = RoleNames.Registered)]
|
|
public void Delete(int id)
|
|
{
|
|
Page page = _pages.GetPage(id);
|
|
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, page.SiteId, EntityNames.Page, page.PageId, PermissionNames.Edit))
|
|
{
|
|
_pages.DeletePage(page.PageId);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Page, page.PageId, SyncEventActions.Delete);
|
|
_syncManager.AddSyncEvent(_alias, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Page Deleted {PageId}", page.PageId);
|
|
}
|
|
else
|
|
{
|
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Delete Attempt {PageId}", id);
|
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|