diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor index a209342e1..6d54d0698 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor @@ -33,7 +33,16 @@ - +
+ +
+ +
+
+
@@ -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); diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor index 1df05879b..ff9a96cc1 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor @@ -43,6 +43,7 @@ else   @SharedLocalizer["Name"] @SharedLocalizer["Version"] + @Localizer["Enabled"] @Localizer["InUse"] @SharedLocalizer["Expires"]   @@ -57,6 +58,16 @@ else @context.Name @context.Version + + @if (context.IsEnabled) + { + @SharedLocalizer["Yes"] + } + else + { + @SharedLocalizer["No"] + } + @if (context.AssemblyName == Constants.ClientId || PageState.Modules.Where(m => m.ModuleDefinition?.ModuleDefinitionId == context.ModuleDefinitionId).FirstOrDefault() != null) { diff --git a/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Edit.resx b/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Edit.resx index 8e3bf1d49..b9f8b825c 100644 --- a/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Edit.resx +++ b/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Edit.resx @@ -219,4 +219,10 @@ A Module With The Name Specified Already Exists + + Is module enabled for this site? + + + Enabled? + \ No newline at end of file diff --git a/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Index.resx b/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Index.resx index 817b22dbc..9e3b9cc2c 100644 --- a/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Index.resx @@ -145,7 +145,7 @@ Delete Module - In Use + In Use? Edit @@ -153,4 +153,7 @@ Modules + + Enabled? + \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor index 58a7144d8..b37c69059 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor @@ -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())) { diff --git a/Oqtane.Server/Controllers/ModuleDefinitionController.cs b/Oqtane.Server/Controllers/ModuleDefinitionController.cs index a0e6a6a2a..4c662eb36 100644 --- a/Oqtane.Server/Controllers/ModuleDefinitionController.cs +++ b/Oqtane.Server/Controllers/ModuleDefinitionController.cs @@ -255,9 +255,8 @@ public void Delete(int id, int siteid) _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); } diff --git a/Oqtane.Server/Repository/Interfaces/IModuleDefinitionRepository.cs b/Oqtane.Server/Repository/Interfaces/IModuleDefinitionRepository.cs index eb4f45d9f..b18ec9936 100644 --- a/Oqtane.Server/Repository/Interfaces/IModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/IModuleDefinitionRepository.cs @@ -9,7 +9,7 @@ public interface IModuleDefinitionRepository IEnumerable 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); } } diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index 53b9c663e..b02a9267d 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -6,6 +6,7 @@ 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 @@ public class ModuleDefinitionRepository : IModuleDefinitionRepository 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 @@ public void UpdateModuleDefinition(ModuleDefinition moduleDefinition) _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 @@ public ModuleDefinition FilterModuleDefinition(ModuleDefinition moduleDefinition ModuleDefinition.ControlTypeTemplate = moduleDefinition.ControlTypeTemplate; ModuleDefinition.IsPortable = moduleDefinition.IsPortable; ModuleDefinition.Resources = moduleDefinition.Resources; + ModuleDefinition.IsEnabled = moduleDefinition.IsEnabled; } return ModuleDefinition; @@ -91,63 +109,21 @@ public List LoadModuleDefinitions(int siteId) List 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 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(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 LoadModuleDefinitions() + private List ProcessModuleDefinitions(int siteId) { // get module assemblies List moduleDefinitions = LoadModuleDefinitionsFromAssemblies(); @@ -197,6 +173,65 @@ private List LoadModuleDefinitions() _db.SaveChanges(); } + if (siteId != -1) + { + // get all module definition permissions for site + List 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(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; } diff --git a/Oqtane.Shared/Models/ModuleDefinition.cs b/Oqtane.Shared/Models/ModuleDefinition.cs index f287428e8..b3c3339a9 100644 --- a/Oqtane.Shared/Models/ModuleDefinition.cs +++ b/Oqtane.Shared/Models/ModuleDefinition.cs @@ -110,10 +110,16 @@ public ModuleDefinition() [NotMapped] public List 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; }