allow themes to define usage permissions similar to modules
This commit is contained in:
@ -14,7 +14,7 @@
|
|||||||
@if (_initialized)
|
@if (_initialized)
|
||||||
{
|
{
|
||||||
<TabStrip>
|
<TabStrip>
|
||||||
<TabPanel Name="Definition" ResourceKey="Definition" Heading="Definition">
|
<TabPanel Name="Module" ResourceKey="Module" Heading="Module">
|
||||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -236,11 +236,10 @@
|
|||||||
private DateTime _createdon;
|
private DateTime _createdon;
|
||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
private DateTime _modifiedon;
|
private DateTime _modifiedon;
|
||||||
private List<Page> _pagesWithModules;
|
|
||||||
|
|
||||||
#pragma warning disable 649
|
|
||||||
private PermissionGrid _permissionGrid;
|
private PermissionGrid _permissionGrid;
|
||||||
#pragma warning restore 649
|
|
||||||
|
private List<Page> _pagesWithModules;
|
||||||
|
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private List<Language> _languages;
|
private List<Language> _languages;
|
||||||
|
|||||||
@ -269,8 +269,16 @@
|
|||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) || (_parent != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, _parent.PermissionList)))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) || (_parent != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, _parent.PermissionList)))
|
||||||
{
|
{
|
||||||
_themetype = PageState.Site.DefaultThemeType;
|
_themetype = PageState.Site.DefaultThemeType;
|
||||||
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
var themes = new List<Theme>();
|
||||||
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
foreach (var theme in PageState.Site.Themes)
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, theme.PermissionList))
|
||||||
|
{
|
||||||
|
themes.Add(theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_themes = ThemeService.GetThemeControls(themes);
|
||||||
|
_containers = ThemeService.GetContainerControls(themes, _themetype);
|
||||||
_containertype = PageState.Site.DefaultContainerType;
|
_containertype = PageState.Site.DefaultContainerType;
|
||||||
_children = new List<Page>();
|
_children = new List<Page>();
|
||||||
foreach (Page p in _pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
|
foreach (Page p in _pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
|
||||||
|
|||||||
@ -443,8 +443,16 @@
|
|||||||
{
|
{
|
||||||
_themetype = PageState.Site.DefaultThemeType;
|
_themetype = PageState.Site.DefaultThemeType;
|
||||||
}
|
}
|
||||||
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
var themes = new List<Theme>();
|
||||||
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
foreach (var theme in PageState.Site.Themes)
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, theme.PermissionList))
|
||||||
|
{
|
||||||
|
themes.Add(theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_themes = ThemeService.GetThemeControls(themes);
|
||||||
|
_containers = ThemeService.GetContainerControls(themes, _themetype);
|
||||||
_containertype = _page.DefaultContainerType;
|
_containertype = _page.DefaultContainerType;
|
||||||
if (string.IsNullOrEmpty(_containertype))
|
if (string.IsNullOrEmpty(_containertype))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -592,9 +592,17 @@
|
|||||||
{
|
{
|
||||||
_faviconfileid = site.FaviconFileId.Value;
|
_faviconfileid = site.FaviconFileId.Value;
|
||||||
}
|
}
|
||||||
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
var themes = new List<Theme>();
|
||||||
|
foreach (var theme in PageState.Site.Themes)
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, theme.PermissionList))
|
||||||
|
{
|
||||||
|
themes.Add(theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_themes = ThemeService.GetThemeControls(themes);
|
||||||
_themetype = (!string.IsNullOrEmpty(site.DefaultThemeType)) ? site.DefaultThemeType : Constants.DefaultTheme;
|
_themetype = (!string.IsNullOrEmpty(site.DefaultThemeType)) ? site.DefaultThemeType : Constants.DefaultTheme;
|
||||||
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
_containers = ThemeService.GetContainerControls(themes, _themetype);
|
||||||
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
|
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
|
||||||
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
|
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
|
||||||
_cookieconsent = SettingService.GetSetting(settings, "CookieConsent", string.Empty);
|
_cookieconsent = SettingService.GetSetting(settings, "CookieConsent", string.Empty);
|
||||||
|
|||||||
@ -216,7 +216,7 @@ else
|
|||||||
_tenantid = _tenants.First(item => item.Name == TenantNames.Master).TenantId.ToString();
|
_tenantid = _tenants.First(item => item.Name == TenantNames.Master).TenantId.ToString();
|
||||||
}
|
}
|
||||||
_urls = PageState.Alias.Name;
|
_urls = PageState.Alias.Name;
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
_themeList = await ThemeService.GetThemesAsync(PageState.Site.SiteId);
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
if (_themes.Any(item => item.TypeName == Constants.DefaultTheme))
|
if (_themes.Any(item => item.TypeName == Constants.DefaultTheme))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -195,7 +195,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themes = await ThemeService.GetThemesAsync();
|
_themes = await ThemeService.GetThemesAsync(PageState.Site.SiteId);
|
||||||
await LoadPackages();
|
await LoadPackages();
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,84 +9,98 @@
|
|||||||
|
|
||||||
@if (_initialized)
|
@if (_initialized)
|
||||||
{
|
{
|
||||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
<TabStrip>
|
||||||
<div class="container">
|
<TabPanel Name="Theme" ResourceKey="Theme" Heading="Theme">
|
||||||
<div class="row mb-1 align-items-center">
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<Label Class="col-sm-3" For="name" HelpText="The name of the module" ResourceKey="Name">Name: </Label>
|
<div class="container">
|
||||||
<div class="col-sm-9">
|
<div class="row mb-1 align-items-center">
|
||||||
<input id="name" class="form-control" @bind="@_name" />
|
<Label Class="col-sm-3" For="name" HelpText="The name of the theme" ResourceKey="Name">Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="name" class="form-control" @bind="@_name" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="isenabled" HelpText="Is theme enabled for this site?" ResourceKey="IsEnabled">Enabled? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="isenabled" class="form-select" @bind="@_isenabled" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<Section Name="Information" ResourceKey="Information" Heading="Information">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="themename" class="form-control" @bind="@_themeName" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="packagename" HelpText="The unique name of the package from which this theme was installed. This value must be specified within the theme's ITheme interface specification." ResourceKey="PackageName">Package Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="url" HelpText="The url of the theme" ResourceKey="Url">Url: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="url" class="form-control" @bind="@_url" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="contact" class="form-control" @bind="@_contact" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
@if (_license.StartsWith("http") || _license.StartsWith("/") || _license.StartsWith("~"))
|
||||||
|
{
|
||||||
|
<a href="@_license.Replace("~", PageState?.Alias.BaseUrl + "/Themes/" + Utilities.GetTypeName(_themeName))" class="btn btn-info" style="text-decoration: none !important" target="_new">@Localizer["View License"]</a>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<br />
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveTheme">@SharedLocalizer["Save"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel Name="Permissions" ResourceKey="Permissions" Heading="Permissions">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<PermissionGrid EntityName="@EntityNames.Theme" PermissionNames="@PermissionNames.Utilize" PermissionList="@_permissions" @ref="_permissionGrid" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<br />
|
||||||
<Label Class="col-sm-3" For="isenabled" HelpText="Is theme enabled for this site?" ResourceKey="IsEnabled">Enabled? </Label>
|
<button type="button" class="btn btn-success" @onclick="SaveTheme">@SharedLocalizer["Save"]</button>
|
||||||
<div class="col-sm-9">
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
<select id="isenabled" class="form-select" @bind="@_isenabled" required>
|
</TabPanel>
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
</TabStrip>
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<Section Name="Information" ResourceKey="Information" Heading="Information">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="themename" class="form-control" @bind="@_themeName" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="packagename" HelpText="The unique name of the package from which this theme was installed. This value must be specified within the theme's ITheme interface specification." ResourceKey="PackageName">Package Name: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="url" HelpText="The url of the theme" ResourceKey="Url">Url: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="url" class="form-control" @bind="@_url" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="contact" class="form-control" @bind="@_contact" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
@if (_license.StartsWith("http") || _license.StartsWith("/") || _license.StartsWith("~"))
|
|
||||||
{
|
|
||||||
<a href="@_license.Replace("~", PageState?.Alias.BaseUrl + "/Themes/" + Utilities.GetTypeName(_themeName))" class="btn btn-info" style="text-decoration: none !important" target="_new">@Localizer["View License"]</a>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
<br />
|
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveTheme">@SharedLocalizer["Save"]</button>
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@ -103,11 +117,14 @@
|
|||||||
private string _url = "";
|
private string _url = "";
|
||||||
private string _contact = "";
|
private string _contact = "";
|
||||||
private string _license = "";
|
private string _license = "";
|
||||||
|
private List<Permission> _permissions = null;
|
||||||
private string _createdby;
|
private string _createdby;
|
||||||
private DateTime _createdon;
|
private DateTime _createdon;
|
||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
private DateTime _modifiedon;
|
private DateTime _modifiedon;
|
||||||
|
|
||||||
|
private PermissionGrid _permissionGrid;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
@ -126,6 +143,7 @@
|
|||||||
_url = theme.Url;
|
_url = theme.Url;
|
||||||
_contact = theme.Contact;
|
_contact = theme.Contact;
|
||||||
_license = theme.License;
|
_license = theme.License;
|
||||||
|
_permissions = theme.PermissionList;
|
||||||
_createdby = theme.CreatedBy;
|
_createdby = theme.CreatedBy;
|
||||||
_createdon = theme.CreatedOn;
|
_createdon = theme.CreatedOn;
|
||||||
_modifiedby = theme.ModifiedBy;
|
_modifiedby = theme.ModifiedBy;
|
||||||
@ -152,6 +170,7 @@
|
|||||||
var theme = await ThemeService.GetThemeAsync(_themeId, ModuleState.SiteId);
|
var theme = await ThemeService.GetThemeAsync(_themeId, ModuleState.SiteId);
|
||||||
theme.Name = _name;
|
theme.Name = _name;
|
||||||
theme.IsEnabled = (_isenabled == null ? true : bool.Parse(_isenabled));
|
theme.IsEnabled = (_isenabled == null ? true : bool.Parse(_isenabled));
|
||||||
|
theme.PermissionList = _permissionGrid.GetPermissionList();
|
||||||
await ThemeService.UpdateThemeAsync(theme);
|
await ThemeService.UpdateThemeAsync(theme);
|
||||||
await logger.LogInformation("Theme Saved {Theme}", theme);
|
await logger.LogInformation("Theme Saved {Theme}", theme);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
|||||||
@ -78,7 +78,7 @@ else
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themes = await ThemeService.GetThemesAsync();
|
_themes = await ThemeService.GetThemesAsync(PageState.Site.SiteId);
|
||||||
_packages = await PackageService.GetPackageUpdatesAsync("theme");
|
_packages = await PackageService.GetPackageUpdatesAsync("theme");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -161,7 +161,7 @@ else
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
|
await ThemeService.DeleteThemeAsync(Theme.ThemeId, PageState.Site.SiteId);
|
||||||
AddModuleMessage(Localizer["Success.Theme.Delete"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Theme.Delete"], MessageType.Success);
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -183,8 +183,8 @@
|
|||||||
<data name="Runtimes.Text" xml:space="preserve">
|
<data name="Runtimes.Text" xml:space="preserve">
|
||||||
<value>Runtimes: </value>
|
<value>Runtimes: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Definition.Heading" xml:space="preserve">
|
<data name="Module.Heading" xml:space="preserve">
|
||||||
<value>Definition</value>
|
<value>Module</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Information.Heading" xml:space="preserve">
|
<data name="Information.Heading" xml:space="preserve">
|
||||||
<value>Information</value>
|
<value>Information</value>
|
||||||
|
|||||||
@ -180,4 +180,10 @@
|
|||||||
<data name="View License" xml:space="preserve">
|
<data name="View License" xml:space="preserve">
|
||||||
<value>View License</value>
|
<value>View License</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Theme.Heading" xml:space="preserve">
|
||||||
|
<value>Themex</value>
|
||||||
|
</data>
|
||||||
|
<data name="Permissions.Heading" xml:space="preserve">
|
||||||
|
<value>Permissionsx</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@ -17,8 +17,9 @@ namespace Oqtane.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of available themes
|
/// Returns a list of available themes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<Theme>> GetThemesAsync();
|
Task<List<Theme>> GetThemesAsync(int siteId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a specific theme
|
/// Returns a specific theme
|
||||||
@ -69,9 +70,10 @@ namespace Oqtane.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes a theme
|
/// Deletes a theme
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="themeName"></param>
|
/// <param name="themeId"></param>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task DeleteThemeAsync(string themeName);
|
Task DeleteThemeAsync(int themeId, int siteId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new theme
|
/// Creates a new theme
|
||||||
@ -103,9 +105,9 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
private string ApiUrl => CreateApiUrl("Theme");
|
private string ApiUrl => CreateApiUrl("Theme");
|
||||||
|
|
||||||
public async Task<List<Theme>> GetThemesAsync()
|
public async Task<List<Theme>> GetThemesAsync(int siteId)
|
||||||
{
|
{
|
||||||
List<Theme> themes = await GetJsonAsync<List<Theme>>(ApiUrl);
|
List<Theme> themes = await GetJsonAsync<List<Theme>>($"{ApiUrl}?siteid={siteId}");
|
||||||
return themes.OrderBy(item => item.Name).ToList();
|
return themes.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
public async Task<Theme> GetThemeAsync(int themeId, int siteId)
|
public async Task<Theme> GetThemeAsync(int themeId, int siteId)
|
||||||
@ -139,9 +141,9 @@ namespace Oqtane.Services
|
|||||||
await PutJsonAsync($"{ApiUrl}/{theme.ThemeId}", theme);
|
await PutJsonAsync($"{ApiUrl}/{theme.ThemeId}", theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteThemeAsync(string themeName)
|
public async Task DeleteThemeAsync(int themeId, int siteId)
|
||||||
{
|
{
|
||||||
await DeleteAsync($"{ApiUrl}/{themeName}");
|
await DeleteAsync($"{ApiUrl}/{themeId}?siteid={siteId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Theme> CreateThemeAsync(Theme theme)
|
public async Task<Theme> CreateThemeAsync(Theme theme)
|
||||||
|
|||||||
@ -252,7 +252,7 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized ModuleDefinition Delete Attempt {ModuleDefinitionId}", id);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized ModuleDefinition Delete Attempt {ModuleDefinitionId} {SiteId}", id, siteid);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,9 @@ using System.Text.Json;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
using Oqtane.Security;
|
||||||
|
using System.Security.Policy;
|
||||||
|
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||||
|
|
||||||
@ -26,30 +29,50 @@ namespace Oqtane.Controllers
|
|||||||
private readonly IInstallationManager _installationManager;
|
private readonly IInstallationManager _installationManager;
|
||||||
private readonly IWebHostEnvironment _environment;
|
private readonly IWebHostEnvironment _environment;
|
||||||
private readonly ITenantManager _tenantManager;
|
private readonly ITenantManager _tenantManager;
|
||||||
|
private readonly IUserPermissions _userPermissions;
|
||||||
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 IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
public ThemeController(IThemeRepository themes, IInstallationManager installationManager, IWebHostEnvironment environment, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger, IServiceProvider serviceProvider)
|
public ThemeController(IThemeRepository themes, IInstallationManager installationManager, IWebHostEnvironment environment, ITenantManager tenantManager, IUserPermissions userPermissions, ISyncManager syncManager, ILogManager logger, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
_themes = themes;
|
_themes = themes;
|
||||||
_installationManager = installationManager;
|
_installationManager = installationManager;
|
||||||
_environment = environment;
|
_environment = environment;
|
||||||
_tenantManager = tenantManager;
|
_tenantManager = tenantManager;
|
||||||
|
_userPermissions = userPermissions;
|
||||||
_syncManager = syncManager;
|
_syncManager = syncManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_alias = tenantManager.GetAlias();
|
_alias = tenantManager.GetAlias();
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: api/<controller>
|
// GET: api/<controller>?siteid=x
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Roles = RoleNames.Registered)]
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
public IEnumerable<Theme> Get()
|
public IEnumerable<Theme> Get(string siteid)
|
||||||
{
|
{
|
||||||
return _themes.GetThemes();
|
int SiteId;
|
||||||
}
|
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
||||||
|
{
|
||||||
|
List<Theme> themes = new List<Theme>();
|
||||||
|
foreach (Theme theme in _themes.GetThemes(SiteId))
|
||||||
|
{
|
||||||
|
if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, theme.PermissionList))
|
||||||
|
{
|
||||||
|
themes.Add(theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return themes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Theme Get Attempt {SiteId}", siteid);
|
||||||
|
HttpContext.Response.StatusCode = (int) HttpStatusCode.Forbidden;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GET api/<controller>/5?siteid=x
|
// GET api/<controller>/5?siteid=x
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
@ -58,7 +81,24 @@ namespace Oqtane.Controllers
|
|||||||
int SiteId;
|
int SiteId;
|
||||||
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
||||||
{
|
{
|
||||||
return _themes.GetTheme(id, SiteId);
|
Theme theme = _themes.GetTheme(id, SiteId);
|
||||||
|
if (theme != null && _userPermissions.IsAuthorized(User, PermissionNames.Utilize, theme.PermissionList))
|
||||||
|
{
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (theme != null)
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Theme Get Attempt {ThemeId} {SiteId}", id, siteid);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -86,14 +126,13 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE api/<controller>/xxx
|
// DELETE api/<controller>/5?siteid=x
|
||||||
[HttpDelete("{themename}")]
|
[HttpDelete("{themename}")]
|
||||||
[Authorize(Roles = RoleNames.Host)]
|
[Authorize(Roles = RoleNames.Host)]
|
||||||
public void Delete(string themename)
|
public void Delete(int id, int siteid)
|
||||||
{
|
{
|
||||||
List<Theme> themes = _themes.GetThemes().ToList();
|
Theme theme = _themes.GetTheme(id, siteid);
|
||||||
Theme theme = themes.Where(item => item.ThemeName == themename).FirstOrDefault();
|
if (theme != null && theme.SiteId == _alias.SiteId && Utilities.GetAssemblyName(theme.ThemeName) != Constants.ClientId)
|
||||||
if (theme != null && Utilities.GetAssemblyName(theme.ThemeName) != Constants.ClientId)
|
|
||||||
{
|
{
|
||||||
// remove theme assets
|
// remove theme assets
|
||||||
if (_installationManager.UninstallPackage(theme.PackageName))
|
if (_installationManager.UninstallPackage(theme.PackageName))
|
||||||
@ -126,7 +165,7 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Theme Delete Attempt {Themename}", themename);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Theme Delete Attempt {ThemeId} {SiteId}", id, siteid);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -386,6 +386,7 @@ namespace Oqtane.Repository
|
|||||||
moduledefinition.Categories = "Common";
|
moduledefinition.Categories = "Common";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// default permissions
|
||||||
if (moduledefinition.Categories == "Admin")
|
if (moduledefinition.Categories == "Admin")
|
||||||
{
|
{
|
||||||
var shortName = moduledefinition.ModuleDefinitionName.Replace("Oqtane.Modules.Admin.", "").Replace(", Oqtane.Client", "");
|
var shortName = moduledefinition.ModuleDefinitionName.Replace("Oqtane.Modules.Admin.", "").Replace(", Oqtane.Client", "");
|
||||||
@ -455,18 +456,21 @@ namespace Oqtane.Repository
|
|||||||
private List<Permission> ClonePermissions(int siteId, List<Permission> permissionList)
|
private List<Permission> ClonePermissions(int siteId, List<Permission> permissionList)
|
||||||
{
|
{
|
||||||
var permissions = new List<Permission>();
|
var permissions = new List<Permission>();
|
||||||
foreach (var p in permissionList)
|
if (permissionList != null)
|
||||||
{
|
{
|
||||||
var permission = new Permission();
|
foreach (var p in permissionList)
|
||||||
permission.SiteId = siteId;
|
{
|
||||||
permission.EntityName = p.EntityName;
|
var permission = new Permission();
|
||||||
permission.EntityId = p.EntityId;
|
permission.SiteId = siteId;
|
||||||
permission.PermissionName = p.PermissionName;
|
permission.EntityName = p.EntityName;
|
||||||
permission.RoleId = null;
|
permission.EntityId = p.EntityId;
|
||||||
permission.RoleName = p.RoleName;
|
permission.PermissionName = p.PermissionName;
|
||||||
permission.UserId = p.UserId;
|
permission.RoleId = null;
|
||||||
permission.IsAuthorized = p.IsAuthorized;
|
permission.RoleName = p.RoleName;
|
||||||
permissions.Add(permission);
|
permission.UserId = p.UserId;
|
||||||
|
permission.IsAuthorized = p.IsAuthorized;
|
||||||
|
permissions.Add(permission);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,7 +135,7 @@ namespace Oqtane.Repository
|
|||||||
if (site != null)
|
if (site != null)
|
||||||
{
|
{
|
||||||
// initialize theme Assemblies
|
// initialize theme Assemblies
|
||||||
site.Themes = _themeRepository.GetThemes().ToList();
|
site.Themes = _themeRepository.GetThemes(site.SiteId).ToList();
|
||||||
|
|
||||||
// initialize module Assemblies
|
// initialize module Assemblies
|
||||||
var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId);
|
var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId);
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace Oqtane.Repository
|
|||||||
{
|
{
|
||||||
public interface IThemeRepository
|
public interface IThemeRepository
|
||||||
{
|
{
|
||||||
IEnumerable<Theme> GetThemes();
|
IEnumerable<Theme> GetThemes(int siteId);
|
||||||
Theme GetTheme(int themeId, int siteId);
|
Theme GetTheme(int themeId, int siteId);
|
||||||
void UpdateTheme(Theme theme);
|
void UpdateTheme(Theme theme);
|
||||||
void DeleteTheme(int themeId);
|
void DeleteTheme(int themeId);
|
||||||
@ -26,24 +26,25 @@ namespace Oqtane.Repository
|
|||||||
{
|
{
|
||||||
private MasterDBContext _db;
|
private MasterDBContext _db;
|
||||||
private readonly IMemoryCache _cache;
|
private readonly IMemoryCache _cache;
|
||||||
|
private readonly IPermissionRepository _permissions;
|
||||||
private readonly ITenantManager _tenants;
|
private readonly ITenantManager _tenants;
|
||||||
private readonly ISettingRepository _settings;
|
private readonly ISettingRepository _settings;
|
||||||
private readonly IServerStateManager _serverState;
|
private readonly IServerStateManager _serverState;
|
||||||
private readonly string settingprefix = "SiteEnabled:";
|
private readonly string settingprefix = "SiteEnabled:";
|
||||||
|
|
||||||
public ThemeRepository(MasterDBContext context, IMemoryCache cache, ITenantManager tenants, ISettingRepository settings, IServerStateManager serverState)
|
public ThemeRepository(MasterDBContext context, IMemoryCache cache, IPermissionRepository permissions, ITenantManager tenants, ISettingRepository settings, IServerStateManager serverState)
|
||||||
{
|
{
|
||||||
_db = context;
|
_db = context;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
|
_permissions = permissions;
|
||||||
_tenants = tenants;
|
_tenants = tenants;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
_serverState = serverState;
|
_serverState = serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Theme> GetThemes()
|
public IEnumerable<Theme> GetThemes(int siteId)
|
||||||
{
|
{
|
||||||
// for consistency siteid should be passed in as parameter, but this would require breaking change
|
return LoadThemes(siteId);
|
||||||
return LoadThemes(_tenants.GetAlias().SiteId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Theme GetTheme(int themeId, int siteId)
|
public Theme GetTheme(int themeId, int siteId)
|
||||||
@ -56,6 +57,7 @@ namespace Oqtane.Repository
|
|||||||
{
|
{
|
||||||
_db.Entry(theme).State = EntityState.Modified;
|
_db.Entry(theme).State = EntityState.Modified;
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
|
_permissions.UpdatePermissions(theme.SiteId, EntityNames.Theme, theme.ThemeId, theme.PermissionList);
|
||||||
|
|
||||||
var settingname = $"{settingprefix}{_tenants.GetAlias().SiteKey}";
|
var settingname = $"{settingprefix}{_tenants.GetAlias().SiteKey}";
|
||||||
var setting = _settings.GetSetting(EntityNames.Theme, theme.ThemeId, settingname);
|
var setting = _settings.GetSetting(EntityNames.Theme, theme.ThemeId, settingname);
|
||||||
@ -96,6 +98,7 @@ namespace Oqtane.Repository
|
|||||||
Theme.ThemeSettingsType = theme.ThemeSettingsType;
|
Theme.ThemeSettingsType = theme.ThemeSettingsType;
|
||||||
Theme.ContainerSettingsType = theme.ContainerSettingsType;
|
Theme.ContainerSettingsType = theme.ContainerSettingsType;
|
||||||
Theme.PackageName = theme.PackageName;
|
Theme.PackageName = theme.PackageName;
|
||||||
|
Theme.PermissionList = theme.PermissionList;
|
||||||
Theme.Fingerprint = Utilities.GenerateSimpleHash(theme.ModifiedOn.ToString("yyyyMMddHHmm"));
|
Theme.Fingerprint = Utilities.GenerateSimpleHash(theme.ModifiedOn.ToString("yyyyMMddHHmm"));
|
||||||
Themes.Add(Theme);
|
Themes.Add(Theme);
|
||||||
}
|
}
|
||||||
@ -176,6 +179,9 @@ namespace Oqtane.Repository
|
|||||||
var siteKey = _tenants.GetAlias().SiteKey;
|
var siteKey = _tenants.GetAlias().SiteKey;
|
||||||
var assemblies = new List<string>();
|
var assemblies = new List<string>();
|
||||||
|
|
||||||
|
// get all module definition permissions for site
|
||||||
|
List<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.Theme).ToList();
|
||||||
|
|
||||||
// get settings for site
|
// get settings for site
|
||||||
var settings = _settings.GetSettings(EntityNames.Theme).ToList();
|
var settings = _settings.GetSettings(EntityNames.Theme).ToList();
|
||||||
|
|
||||||
@ -212,6 +218,26 @@ namespace Oqtane.Repository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (permissions.Count == 0)
|
||||||
|
{
|
||||||
|
// no module definition permissions exist for this site
|
||||||
|
theme.PermissionList = ClonePermissions(siteId, theme.PermissionList);
|
||||||
|
_permissions.UpdatePermissions(siteId, EntityNames.Theme, theme.ThemeId, theme.PermissionList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (permissions.Any(item => item.EntityId == theme.ThemeId))
|
||||||
|
{
|
||||||
|
theme.PermissionList = permissions.Where(item => item.EntityId == theme.ThemeId).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// permissions for theme do not exist for this site
|
||||||
|
theme.PermissionList = ClonePermissions(siteId, theme.PermissionList);
|
||||||
|
_permissions.UpdatePermissions(siteId, EntityNames.Theme, theme.ThemeId, theme.PermissionList);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache site assemblies
|
// cache site assemblies
|
||||||
@ -220,6 +246,20 @@ namespace Oqtane.Repository
|
|||||||
{
|
{
|
||||||
if (!serverState.Assemblies.Contains(assembly)) serverState.Assemblies.Add(assembly);
|
if (!serverState.Assemblies.Contains(assembly)) serverState.Assemblies.Add(assembly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clean up any orphaned permissions
|
||||||
|
var ids = new HashSet<int>(Themes.Select(item => item.ThemeId));
|
||||||
|
foreach (var permission in permissions.Where(item => !ids.Contains(item.EntityId)))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_permissions.DeletePermission(permission.PermissionId);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// multi-threading can cause a race condition to occur
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Themes;
|
return Themes;
|
||||||
@ -295,6 +335,14 @@ namespace Oqtane.Repository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// default permissions
|
||||||
|
theme.PermissionList = new List<Permission>
|
||||||
|
{
|
||||||
|
new Permission(PermissionNames.Utilize, RoleNames.Admin, true),
|
||||||
|
new Permission(PermissionNames.Utilize, RoleNames.Registered, true)
|
||||||
|
};
|
||||||
|
|
||||||
Debug.WriteLine($"Oqtane Info: Registering Theme {theme.ThemeName}");
|
Debug.WriteLine($"Oqtane Info: Registering Theme {theme.ThemeName}");
|
||||||
themes.Add(theme);
|
themes.Add(theme);
|
||||||
index = themes.FindIndex(item => item.ThemeName == qualifiedThemeType);
|
index = themes.FindIndex(item => item.ThemeName == qualifiedThemeType);
|
||||||
@ -335,5 +383,27 @@ namespace Oqtane.Repository
|
|||||||
}
|
}
|
||||||
return themes;
|
return themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Permission> ClonePermissions(int siteId, List<Permission> permissionList)
|
||||||
|
{
|
||||||
|
var permissions = new List<Permission>();
|
||||||
|
if (permissionList != null)
|
||||||
|
{
|
||||||
|
foreach (var p in permissionList)
|
||||||
|
{
|
||||||
|
var permission = new Permission();
|
||||||
|
permission.SiteId = siteId;
|
||||||
|
permission.EntityName = p.EntityName;
|
||||||
|
permission.EntityId = p.EntityId;
|
||||||
|
permission.PermissionName = p.PermissionName;
|
||||||
|
permission.RoleId = null;
|
||||||
|
permission.RoleName = p.RoleName;
|
||||||
|
permission.UserId = p.UserId;
|
||||||
|
permission.IsAuthorized = p.IsAuthorized;
|
||||||
|
permissions.Add(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,7 +144,7 @@ namespace Oqtane.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
// themes
|
// themes
|
||||||
site.Themes = _themes.FilterThemes(_themes.GetThemes().ToList());
|
site.Themes = _themes.FilterThemes(_themes.GetThemes(site.SiteId).ToList());
|
||||||
|
|
||||||
// installation date used for fingerprinting static assets
|
// installation date used for fingerprinting static assets
|
||||||
site.Fingerprint = Utilities.GenerateSimpleHash(_configManager.GetSetting("InstallationDate", DateTime.UtcNow.ToString("yyyyMMddHHmm")));
|
site.Fingerprint = Utilities.GenerateSimpleHash(_configManager.GetSetting("InstallationDate", DateTime.UtcNow.ToString("yyyyMMddHHmm")));
|
||||||
|
|||||||
@ -94,6 +94,9 @@ namespace Oqtane.Models
|
|||||||
[NotMapped]
|
[NotMapped]
|
||||||
public List<ThemeControl> Containers { get; set; }
|
public List<ThemeControl> Containers { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public List<Permission> PermissionList { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public string Template { get; set; }
|
public string Template { get; set; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user