Skip to content

Commit

Permalink
Merge pull request #2834 from sbwalker/dev
Browse files Browse the repository at this point in the history
ability to specify if a module definition is enabled for a site
  • Loading branch information
sbwalker authored May 24, 2023
2 parents 31907f2 + c0e6f06 commit f7c4958
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 57 deletions.
14 changes: 13 additions & 1 deletion Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -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 = "";
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,15 @@
<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>
</data>
<data name="Modules" xml:space="preserve">
<value>Modules</value>
</data>
<data name="Enabled" xml:space="preserve">
<value>Enabled?</value>
</data>
</root>
2 changes: 1 addition & 1 deletion Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
{
Expand Down
3 changes: 1 addition & 2 deletions Oqtane.Server/Controllers/ModuleDefinitionController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public interface IModuleDefinitionRepository
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);
}
}
137 changes: 86 additions & 51 deletions Oqtane.Server/Repository/ModuleDefinitionRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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)
Expand All @@ -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;
Expand All @@ -91,63 +109,21 @@ public List<ModuleDefinition> LoadModuleDefinitions(int siteId)
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();
Expand Down Expand Up @@ -197,6 +173,65 @@ private List<ModuleDefinition> LoadModuleDefinitions()
_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;
}

Expand Down
6 changes: 6 additions & 0 deletions Oqtane.Shared/Models/ModuleDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,16 @@ public ModuleDefinition()
[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; }

Expand Down

0 comments on commit f7c4958

Please sign in to comment.