Merge pull request #2834 from sbwalker/dev

ability to specify if a module definition is enabled for a site
This commit is contained in:
Shaun Walker 2023-05-24 09:40:20 -04:00 committed by GitHub
commit f7c49588fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 129 additions and 57 deletions

View File

@ -33,7 +33,16 @@
<input id="categories" class="form-control" @bind="@_categories" maxlength="200" required />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="isenabled" HelpText="Is module 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">
<div class="container">
@ -199,6 +208,7 @@
private string _name;
private string _description = "";
private string _categories;
private string _isenabled;
private string _moduledefinitionname = "";
private string _version;
private string _packagename = "";
@ -234,6 +244,7 @@
_name = moduleDefinition.Name;
_description = moduleDefinition.Description;
_categories = moduleDefinition.Categories;
_isenabled = moduleDefinition.IsEnabled.ToString();
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
_version = moduleDefinition.Version;
_packagename = moduleDefinition.PackageName;
@ -297,6 +308,7 @@
{
moduledefinition.Categories = _categories;
}
moduledefinition.IsEnabled = (_isenabled == null ? true : Boolean.Parse(_isenabled));
moduledefinition.PermissionList = _permissionGrid.GetPermissionList();
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);

View File

@ -43,6 +43,7 @@ else
<th style="width: 1px;">&nbsp;</th>
<th>@SharedLocalizer["Name"]</th>
<th>@SharedLocalizer["Version"]</th>
<th>@Localizer["Enabled"]</th>
<th>@Localizer["InUse"]</th>
<th>@SharedLocalizer["Expires"]</th>
<th style="width: 1px;">&nbsp;</th>
@ -57,6 +58,16 @@ else
</td>
<td>@context.Name</td>
<td>@context.Version</td>
<td>
@if (context.IsEnabled)
{
<span>@SharedLocalizer["Yes"]</span>
}
else
{
<span>@SharedLocalizer["No"]</span>
}
</td>
<td>
@if (context.AssemblyName == Constants.ClientId || PageState.Modules.Where(m => m.ModuleDefinition?.ModuleDefinitionId == context.ModuleDefinitionId).FirstOrDefault() != null)
{

View File

@ -219,4 +219,10 @@
<data name="Message.DuplicateName" xml:space="preserve">
<value>A Module With The Name Specified Already Exists</value>
</data>
<data name="IsEnabled.HelpText" xml:space="preserve">
<value>Is module enabled for this site?</value>
</data>
<data name="IsEnabled.Text" xml:space="preserve">
<value>Enabled?</value>
</data>
</root>

View File

@ -145,7 +145,7 @@
<value>Delete Module</value>
</data>
<data name="InUse" xml:space="preserve">
<value>In Use</value>
<value>In Use?</value>
</data>
<data name="EditModule.Text" xml:space="preserve">
<value>Edit</value>
@ -153,4 +153,7 @@
<data name="Modules" xml:space="preserve">
<value>Modules</value>
</data>
<data name="Enabled" xml:space="preserve">
<value>Enabled?</value>
</data>
</root>

View File

@ -144,7 +144,7 @@
}
@foreach (var moduledefinition in _moduleDefinitions)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.PermissionList))
if (moduledefinition.IsEnabled && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.PermissionList))
{
if (moduledefinition.Runtimes == "" || moduledefinition.Runtimes.Contains(PageState.Runtime.ToString()))
{

View File

@ -255,9 +255,8 @@ namespace Oqtane.Controllers
_modules.DeleteModule(moduleToRemove.ModuleId);
}
// remove module definition
_moduleDefinitions.DeleteModuleDefinition(id);
_moduleDefinitions.DeleteModuleDefinition(id, siteid);
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId, SyncEventActions.Delete);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Definition {ModuleDefinitionName} Deleted", moduledefinition.Name);
}

View File

@ -9,7 +9,7 @@ namespace Oqtane.Repository
IEnumerable<ModuleDefinition> GetModuleDefinitions(int siteId);
ModuleDefinition GetModuleDefinition(int moduleDefinitionId, int siteId);
void UpdateModuleDefinition(ModuleDefinition moduleDefinition);
void DeleteModuleDefinition(int moduleDefinitionId);
void DeleteModuleDefinition(int moduleDefinitionId, int siteId);
ModuleDefinition FilterModuleDefinition(ModuleDefinition moduleDefinition);
}
}

View File

@ -6,6 +6,7 @@ using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Oqtane.Infrastructure;
using Oqtane.Models;
using Oqtane.Modules;
using Oqtane.Shared;
@ -17,13 +18,16 @@ namespace Oqtane.Repository
private MasterDBContext _db;
private readonly IMemoryCache _cache;
private readonly IPermissionRepository _permissions;
private readonly ITenantManager _tenants;
private readonly ISettingRepository _settings;
private readonly string settingprefix = "SiteEnabled:";
public ModuleDefinitionRepository(MasterDBContext context, IMemoryCache cache, IPermissionRepository permissions, ISettingRepository settings)
public ModuleDefinitionRepository(MasterDBContext context, IMemoryCache cache, IPermissionRepository permissions, ITenantManager tenants, ISettingRepository settings)
{
_db = context;
_cache = cache;
_permissions = permissions;
_tenants = tenants;
_settings = settings;
}
@ -48,16 +52,29 @@ namespace Oqtane.Repository
_db.Entry(moduleDefinition).State = EntityState.Modified;
_db.SaveChanges();
_permissions.UpdatePermissions(moduleDefinition.SiteId, EntityNames.ModuleDefinition, moduleDefinition.ModuleDefinitionId, moduleDefinition.PermissionList);
_cache.Remove("moduledefinitions");
var settingname = $"{settingprefix}{_tenants.GetAlias().SiteKey}";
var setting = _settings.GetSetting(EntityNames.ModuleDefinition, moduleDefinition.ModuleDefinitionId, settingname);
if (setting == null)
{
_settings.AddSetting(new Setting { EntityName = EntityNames.ModuleDefinition, EntityId = moduleDefinition.ModuleDefinitionId, SettingName = settingname, SettingValue = moduleDefinition.IsEnabled.ToString(), IsPrivate = true });
}
else
{
setting.SettingValue = moduleDefinition.IsEnabled.ToString();
_settings.UpdateSetting(setting);
}
_cache.Remove($"moduledefinitions:{moduleDefinition.SiteId}");
}
public void DeleteModuleDefinition(int moduleDefinitionId)
public void DeleteModuleDefinition(int moduleDefinitionId,int siteId)
{
ModuleDefinition moduleDefinition = _db.ModuleDefinition.Find(moduleDefinitionId);
_settings.DeleteSettings(EntityNames.ModuleDefinition, moduleDefinitionId);
_db.ModuleDefinition.Remove(moduleDefinition);
_db.SaveChanges();
_cache.Remove("moduledefinitions");
_cache.Remove($"moduledefinitions:{siteId}");
}
public ModuleDefinition FilterModuleDefinition(ModuleDefinition moduleDefinition)
@ -80,6 +97,7 @@ namespace Oqtane.Repository
ModuleDefinition.ControlTypeTemplate = moduleDefinition.ControlTypeTemplate;
ModuleDefinition.IsPortable = moduleDefinition.IsPortable;
ModuleDefinition.Resources = moduleDefinition.Resources;
ModuleDefinition.IsEnabled = moduleDefinition.IsEnabled;
}
return ModuleDefinition;
@ -91,63 +109,21 @@ namespace Oqtane.Repository
List<ModuleDefinition> moduleDefinitions;
if (siteId != -1)
{
moduleDefinitions = _cache.GetOrCreate("moduledefinitions", entry =>
moduleDefinitions = _cache.GetOrCreate($"moduledefinitions:{siteId}", entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
return LoadModuleDefinitions();
return ProcessModuleDefinitions(siteId);
});
// get all module definition permissions for site
List<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.ModuleDefinition).ToList();
// populate module definition permissions
foreach (ModuleDefinition moduledefinition in moduleDefinitions)
{
moduledefinition.SiteId = siteId;
if (permissions.Count == 0)
{
// no module definition permissions exist for this site
moduledefinition.PermissionList = ClonePermissions(siteId, moduledefinition.PermissionList);
_permissions.UpdatePermissions(siteId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId, moduledefinition.PermissionList);
}
else
{
if (permissions.Any(item => item.EntityId == moduledefinition.ModuleDefinitionId))
{
moduledefinition.PermissionList = permissions.Where(item => item.EntityId == moduledefinition.ModuleDefinitionId).ToList();
}
else
{
// permissions for module definition do not exist for this site
moduledefinition.PermissionList = ClonePermissions(siteId, moduledefinition.PermissionList);
_permissions.UpdatePermissions(siteId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId, moduledefinition.PermissionList);
}
}
}
// clean up any orphaned permissions
var ids = new HashSet<int>(moduleDefinitions.Select(item => item.ModuleDefinitionId));
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
}
}
}
else
else // called during startup
{
moduleDefinitions = LoadModuleDefinitions();
return ProcessModuleDefinitions(-1);
}
return moduleDefinitions;
}
private List<ModuleDefinition> LoadModuleDefinitions()
private List<ModuleDefinition> ProcessModuleDefinitions(int siteId)
{
// get module assemblies
List<ModuleDefinition> moduleDefinitions = LoadModuleDefinitionsFromAssemblies();
@ -197,6 +173,65 @@ namespace Oqtane.Repository
_db.SaveChanges();
}
if (siteId != -1)
{
// get all module definition permissions for site
List<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.ModuleDefinition).ToList();
// get settings for site
var settings = _settings.GetSettings(EntityNames.ModuleDefinition).ToList();
// populate module definition permissions
foreach (ModuleDefinition moduledefinition in moduleDefinitions)
{
moduledefinition.SiteId = siteId;
var setting = settings.FirstOrDefault(item => item.EntityId == moduledefinition.ModuleDefinitionId && item.SettingName == $"{settingprefix}{_tenants.GetAlias().SiteKey}");
if (setting != null)
{
moduledefinition.IsEnabled = bool.Parse(setting.SettingValue);
}
else
{
moduledefinition.IsEnabled = moduledefinition.IsAutoEnabled;
}
if (permissions.Count == 0)
{
// no module definition permissions exist for this site
moduledefinition.PermissionList = ClonePermissions(siteId, moduledefinition.PermissionList);
_permissions.UpdatePermissions(siteId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId, moduledefinition.PermissionList);
}
else
{
if (permissions.Any(item => item.EntityId == moduledefinition.ModuleDefinitionId))
{
moduledefinition.PermissionList = permissions.Where(item => item.EntityId == moduledefinition.ModuleDefinitionId).ToList();
}
else
{
// permissions for module definition do not exist for this site
moduledefinition.PermissionList = ClonePermissions(siteId, moduledefinition.PermissionList);
_permissions.UpdatePermissions(siteId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId, moduledefinition.PermissionList);
}
}
}
// clean up any orphaned permissions
var ids = new HashSet<int>(moduleDefinitions.Select(item => item.ModuleDefinitionId));
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 moduleDefinitions;
}

View File

@ -110,10 +110,16 @@ namespace Oqtane.Models
[NotMapped]
public List<Resource> Resources { get; set; } // added in 4.0.0
[NotMapped]
public bool IsAutoEnabled { get; set; } = true; // added in 4.0.0
// internal properties
[NotMapped]
public int SiteId { get; set; }
[NotMapped]
public bool IsEnabled { get; set; }
[NotMapped]
public string ControlTypeTemplate { get; set; }