Merge branch 'feature/web-plugins' of github.com:ONLYOFFICE/DocSpace into feature/web-plugins

This commit is contained in:
Timofey Boyko 2023-09-29 10:36:31 +03:00
commit aa26f284fa
9 changed files with 399 additions and 61 deletions

View File

@ -62,13 +62,11 @@ public class DbWebPluginService
return await Queries.WebPluginByNameAsync(dbContext, tenantId, name); return await Queries.WebPluginByNameAsync(dbContext, tenantId, name);
} }
public async Task<List<DbWebPlugin>> GetAsync(int tenantId, bool? enabled = null) public async Task<List<DbWebPlugin>> GetAsync(int tenantId)
{ {
await using var dbContext = _dbContextFactory.CreateDbContext(); await using var dbContext = _dbContextFactory.CreateDbContext();
return enabled.HasValue return await Queries.WebPluginsAsync(dbContext, tenantId).ToListAsync();
? await Queries.WebPluginsByStatusAsync(dbContext, tenantId, enabled.Value).ToListAsync()
: await Queries.WebPluginsAsync(dbContext, tenantId).ToListAsync();
} }
public async Task UpdateAsync(int tenantId, int id, bool enabled) public async Task UpdateAsync(int tenantId, int id, bool enabled)
@ -95,14 +93,6 @@ static file class Queries
.AsNoTracking() .AsNoTracking()
.Where(r => r.TenantId == tenantId)); .Where(r => r.TenantId == tenantId));
public static readonly Func<WebPluginDbContext, int, bool, IAsyncEnumerable<DbWebPlugin>>
WebPluginsByStatusAsync = EF.CompileAsyncQuery(
(WebPluginDbContext ctx, int tenantId, bool enabled) =>
ctx.WebPlugins
.AsNoTracking()
.Where(r => r.TenantId == tenantId)
.Where(r => r.Enabled == enabled));
public static readonly Func<WebPluginDbContext, int, int, Task<DbWebPlugin>> public static readonly Func<WebPluginDbContext, int, int, Task<DbWebPlugin>>
WebPluginByIdAsync = EF.CompileAsyncQuery( WebPluginByIdAsync = EF.CompileAsyncQuery(
(WebPluginDbContext ctx, int tenantId, int id) => (WebPluginDbContext ctx, int tenantId, int id) =>

View File

@ -451,8 +451,9 @@
"plugins": { "plugins": {
"enabled": "true", "enabled": "true",
"extension": ".zip", "extension": ".zip",
"max-size": 5242880, "maxSize": 5242880,
"allow": ["upload", "delete"] "allow": ["upload", "delete"],
"assetExtensions": [".jpg", ".jpeg", ".png", ".svg"]
}, },
"aws": { "aws": {
"cloudWatch": { "cloudWatch": {

View File

@ -134,6 +134,16 @@
"type": "disc", "type": "disc",
"path": "$STORAGE_ROOT\\Studio\\{0}\\webplugins", "path": "$STORAGE_ROOT\\Studio\\{0}\\webplugins",
"virtualpath": "~/studio/{0}/webplugins" "virtualpath": "~/studio/{0}/webplugins"
},
{
"name": "systemwebplugins",
"data": "00000000-0000-0000-0000-000000000000",
"type": "disc",
"path": "$STORAGE_ROOT\\Studio\\webplugins",
"virtualpath": "~/studio/webplugins",
"appendTenantId": false,
"disableMigrate": true,
"disableEncryption": true
} }
] ]
} }

View File

@ -186,7 +186,7 @@ class PluginStore {
...this.pluginFrame.contentWindow.Plugins[plugin.pluginName], ...this.pluginFrame.contentWindow.Plugins[plugin.pluginName],
}); });
newPlugin.createBy = newPlugin.createBy.displayName; // newPlugin.createBy = newPlugin.createBy.displayName;
newPlugin.scopes = newPlugin.scopes.split(","); newPlugin.scopes = newPlugin.scopes.split(",");
newPlugin.iconUrl = getPluginUrl(newPlugin.url, ""); newPlugin.iconUrl = getPluginUrl(newPlugin.url, "");
@ -226,7 +226,7 @@ class PluginStore {
if (!plugin || !plugin.enabled) return; if (!plugin || !plugin.enabled) return;
if (plugin.scopes.includes(PluginScopes.API)) { if (plugin.scopes.includes(PluginScopes.API)) {
plugin.setAPI(origin, proxy, prefix); plugin.setAPI && plugin.setAPI(origin, proxy, prefix);
} }
if (plugin.onLoadCallback) { if (plugin.onLoadCallback) {

View File

@ -49,8 +49,10 @@ public class WebPluginsController : BaseSettingsController
} }
[HttpPost("webplugins")] [HttpPost("webplugins")]
public async Task<WebPluginDto> AddWebPluginFromFile() public async Task<WebPluginDto> AddWebPluginFromFile(bool system)
{ {
var tenantId = system ? Tenant.DefaultTenant : Tenant.Id;
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings); await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
if (HttpContext.Request.Form?.Files == null || HttpContext.Request.Form.Files.Count == 0) if (HttpContext.Request.Form?.Files == null || HttpContext.Request.Form.Files.Count == 0)
@ -65,11 +67,11 @@ public class WebPluginsController : BaseSettingsController
var file = HttpContext.Request.Form.Files[0] ?? throw new ArgumentException("Input file is null"); var file = HttpContext.Request.Form.Files[0] ?? throw new ArgumentException("Input file is null");
var plugin = await _webPluginManager.AddWebPluginFromFile(Tenant.Id, file); var plugin = await _webPluginManager.AddWebPluginFromFileAsync(tenantId, file);
var outDto = _mapper.Map<DbWebPlugin, WebPluginDto>(plugin); var outDto = _mapper.Map<DbWebPlugin, WebPluginDto>(plugin);
var urlTemplate = await _webPluginManager.GetPluginUrlTemplate(Tenant.Id); var urlTemplate = await _webPluginManager.GetPluginUrlTemplateAsync(tenantId);
outDto.Url = string.Format(urlTemplate, outDto.Name); outDto.Url = string.Format(urlTemplate, outDto.Name);
@ -79,17 +81,37 @@ public class WebPluginsController : BaseSettingsController
[HttpGet("webplugins")] [HttpGet("webplugins")]
public async Task<IEnumerable<WebPluginDto>> GetWebPluginsAsync(bool? enabled = null) public async Task<IEnumerable<WebPluginDto>> GetWebPluginsAsync(bool? enabled = null)
{ {
var plugins = await _webPluginManager.GetWebPluginsAsync(Tenant.Id, enabled); var plugins = new List<DbWebPlugin>();
var outDto = _mapper.Map<IEnumerable<DbWebPlugin>, IEnumerable<WebPluginDto>>(plugins); plugins.AddRange(await _webPluginManager.GetSystemWebPluginsAsync());
if (outDto != null && outDto.Any()) plugins.AddRange(await _webPluginManager.GetWebPluginsAsync(Tenant.Id));
var outDto = _mapper.Map<List<DbWebPlugin>, List<WebPluginDto>>(plugins);
if (enabled.HasValue)
{ {
var urlTemplate = await _webPluginManager.GetPluginUrlTemplate(Tenant.Id); outDto = outDto.Where(i => i.Enabled == enabled).ToList();
}
if (outDto.Any())
{
string urlTemplate = null;
string systemUrlTemplate = null;
foreach (var dto in outDto) foreach (var dto in outDto)
{ {
dto.Url = string.Format(urlTemplate, dto.Name); if (dto.System && systemUrlTemplate == null)
{
systemUrlTemplate = await _webPluginManager.GetPluginUrlTemplateAsync(Tenant.DefaultTenant);
}
if (!dto.System && urlTemplate == null)
{
urlTemplate = await _webPluginManager.GetPluginUrlTemplateAsync(Tenant.Id);
}
dto.Url = string.Format(dto.System ? systemUrlTemplate : urlTemplate, dto.Name);
} }
} }
@ -105,7 +127,7 @@ public class WebPluginsController : BaseSettingsController
if (outDto != null) if (outDto != null)
{ {
var urlTemplate = await _webPluginManager.GetPluginUrlTemplate(Tenant.Id); var urlTemplate = await _webPluginManager.GetPluginUrlTemplateAsync(Tenant.Id);
outDto.Url = string.Format(urlTemplate, outDto.Name); outDto.Url = string.Format(urlTemplate, outDto.Name);
} }
@ -128,4 +150,39 @@ public class WebPluginsController : BaseSettingsController
await _webPluginManager.DeleteWebPluginAsync(Tenant.Id, id); await _webPluginManager.DeleteWebPluginAsync(Tenant.Id, id);
} }
[HttpGet("webplugins/system/{name}")]
public async Task<WebPluginDto> GetSystemWebPluginByNameAsync(string name)
{
var plugin = await _webPluginManager.GetSystemWebPluginAsync(name);
var outDto = _mapper.Map<DbWebPlugin, WebPluginDto>(plugin);
if (outDto != null)
{
var urlTemplate = await _webPluginManager.GetPluginUrlTemplateAsync(Tenant.DefaultTenant);
outDto.Url = string.Format(urlTemplate, outDto.Name);
}
return outDto;
}
[HttpPut("webplugins/system/{name}")]
public async Task UpdateSystemWebPluginAsync(string name, WebPluginRequestsDto inDto)
{
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
await _webPluginManager.UpdateSystemWebPluginAsync(name, inDto.Enabled);
}
[HttpDelete("webplugins/system/{name}")]
public async Task DeleteSystemWebPluginAsync(string name)
{
await _permissionContext.DemandPermissionsAsync(SecutiryConstants.EditPortalSettings);
await _webPluginManager.DeleteSystemWebPluginAsync(name);
}
} }

View File

@ -416,6 +416,7 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Protobuf Include="protos\web_plugin_cache_item.proto" />
<Protobuf Include="protos\sms_key_cache_key.proto" /> <Protobuf Include="protos\sms_key_cache_key.proto" />
<Protobuf Include="protos\tenant_logo_cache_item.proto" /> <Protobuf Include="protos\tenant_logo_cache_item.proto" />
<Protobuf Include="protos\mail_service_helper_cache.proto" /> <Protobuf Include="protos\mail_service_helper_cache.proto" />

View File

@ -26,29 +26,77 @@
namespace ASC.Web.Core; namespace ASC.Web.Core;
[Singletone]
public class WebPluginCache
{
private readonly ICache _сache;
private readonly ICacheNotify<WebPluginCacheItem> _notify;
private readonly TimeSpan _cacheExpiration = TimeSpan.FromDays(1);
public WebPluginCache(ICacheNotify<WebPluginCacheItem> notify, ICache cache)
{
_сache = cache;
_notify = notify;
_notify.Subscribe((i) => _сache.Remove(i.Key), CacheNotifyAction.Remove);
}
public List<DbWebPlugin> Get(string key)
{
return _сache.Get<List<DbWebPlugin>>(key);
}
public void Insert(string key, object value)
{
_notify.Publish(new WebPluginCacheItem { Key = key }, CacheNotifyAction.Remove);
_сache.Insert(key, value, _cacheExpiration);
}
public void Remove(string key)
{
_notify.Publish(new WebPluginCacheItem { Key = key }, CacheNotifyAction.Remove);
_сache.Remove(key);
}
}
[Scope] [Scope]
public class WebPluginManager public class WebPluginManager
{ {
private const string StorageSystemModuleName = "systemwebplugins";
private const string StorageModuleName = "webplugins"; private const string StorageModuleName = "webplugins";
private const string ConfigFileName = "config.json"; private const string ConfigFileName = "config.json";
private const string PluginFileName = "plugin.js"; private const string PluginFileName = "plugin.js";
private const string AssetsFolderName = "assets"; private const string AssetsFolderName = "assets";
private readonly CoreBaseSettings _coreBaseSettings;
private readonly SettingsManager _settingsManager;
private readonly DbWebPluginService _webPluginService; private readonly DbWebPluginService _webPluginService;
private readonly WebPluginSettings _webPluginSettings; private readonly WebPluginSettings _webPluginSettings;
private readonly WebPluginCache _webPluginCache;
private readonly StorageFactory _storageFactory; private readonly StorageFactory _storageFactory;
private readonly AuthContext _authContext; private readonly AuthContext _authContext;
private readonly ILogger<WebPluginManager> _log;
public WebPluginManager( public WebPluginManager(
CoreBaseSettings coreBaseSettings,
SettingsManager settingsManager,
DbWebPluginService webPluginService, DbWebPluginService webPluginService,
WebPluginSettings webPluginSettings, WebPluginSettings webPluginSettings,
WebPluginCache webPluginCache,
StorageFactory storageFactory, StorageFactory storageFactory,
AuthContext authContext) AuthContext authContext,
ILogger<WebPluginManager> log)
{ {
_coreBaseSettings = coreBaseSettings;
_settingsManager = settingsManager;
_webPluginService = webPluginService; _webPluginService = webPluginService;
_webPluginSettings = webPluginSettings; _webPluginSettings = webPluginSettings;
_webPluginCache = webPluginCache;
_storageFactory = storageFactory; _storageFactory = storageFactory;
_authContext = authContext; _authContext = authContext;
_log = log;
} }
private void DemandWebPlugins(string action = null) private void DemandWebPlugins(string action = null)
@ -58,25 +106,76 @@ public class WebPluginManager
throw new SecurityException("Plugins disabled"); throw new SecurityException("Plugins disabled");
} }
if (!string.IsNullOrWhiteSpace(action) && !_webPluginSettings.Allow.Contains(action)) if (!string.IsNullOrWhiteSpace(action) && _webPluginSettings.Allow.Any() && !_webPluginSettings.Allow.Contains(action))
{ {
throw new SecurityException("Forbidden action"); throw new SecurityException("Forbidden action");
} }
} }
public async Task<string> GetPluginUrlTemplate(int tenantId) private async Task<IDataStore> GetPluginStorageAsync(int tenantId)
{ {
var storage = await _storageFactory.GetStorageAsync(tenantId, StorageModuleName); var module = tenantId == Tenant.DefaultTenant ? StorageSystemModuleName : StorageModuleName;
var storage = await _storageFactory.GetStorageAsync(tenantId, module);
return storage;
}
private static string GetCacheKey(int tenantId)
{
return $"{StorageModuleName}:{tenantId}";
}
public async Task<string> GetPluginUrlTemplateAsync(int tenantId)
{
var storage = await GetPluginStorageAsync(tenantId);
var uri = await storage.GetUriAsync(Path.Combine("{0}", PluginFileName)); var uri = await storage.GetUriAsync(Path.Combine("{0}", PluginFileName));
return uri?.ToString() ?? string.Empty; return uri?.ToString() ?? string.Empty;
} }
public async Task<DbWebPlugin> AddWebPluginFromFile(int tenantId, IFormFile file) public async Task<DbWebPlugin> AddWebPluginFromFileAsync(int tenantId, IFormFile file)
{ {
DemandWebPlugins("upload"); DemandWebPlugins("upload");
var system = tenantId == Tenant.DefaultTenant;
if (system && !_coreBaseSettings.Standalone)
{
throw new SecurityException("System plugin");
}
var webPlugin = await SaveWebPluginToStorageAsync(tenantId, file);
webPlugin.TenantId = tenantId;
webPlugin.Enabled = true;
webPlugin.System = system;
if (!system)
{
var existingPlugin = await _webPluginService.GetByNameAsync(tenantId, webPlugin.Name);
if (existingPlugin != null)
{
webPlugin.Id = existingPlugin.Id;
}
webPlugin.CreateBy = _authContext.CurrentAccount.ID;
webPlugin.CreateOn = DateTime.UtcNow;
webPlugin = await _webPluginService.SaveAsync(webPlugin);
}
var key = GetCacheKey(tenantId);
_webPluginCache.Remove(key);
return webPlugin;
}
private async Task<DbWebPlugin> SaveWebPluginToStorageAsync(int tenantId, IFormFile file)
{
if (Path.GetExtension(file.FileName)?.ToLowerInvariant() != _webPluginSettings.Extension) if (Path.GetExtension(file.FileName)?.ToLowerInvariant() != _webPluginSettings.Extension)
{ {
throw new ArgumentException("Wrong file extension"); throw new ArgumentException("Wrong file extension");
@ -87,7 +186,7 @@ public class WebPluginManager
throw new ArgumentException("File size exceeds limit"); throw new ArgumentException("File size exceeds limit");
} }
var storage = await _storageFactory.GetStorageAsync(tenantId, StorageModuleName); var storage = await GetPluginStorageAsync(tenantId);
DbWebPlugin webPlugin = null; DbWebPlugin webPlugin = null;
Uri uri = null; Uri uri = null;
@ -114,34 +213,24 @@ public class WebPluginManager
webPlugin = System.Text.Json.JsonSerializer.Deserialize<DbWebPlugin>(configContent, options); webPlugin = System.Text.Json.JsonSerializer.Deserialize<DbWebPlugin>(configContent, options);
if (webPlugin == null || string.IsNullOrEmpty(webPlugin.Name)) if (webPlugin == null)
{ {
throw new ArgumentException("Wrong plugin archive"); throw new ArgumentException("Wrong plugin archive");
} }
//TODO: think about special characters var nameRegex = new Regex(@"^[a-z0-9_.-]+$");
webPlugin.Name = webPlugin.Name.Replace(" ", string.Empty).ToLowerInvariant();
var existingPlugin = await _webPluginService.GetByNameAsync(tenantId, webPlugin.Name); if (string.IsNullOrEmpty(webPlugin.Name) || !nameRegex.IsMatch(webPlugin.Name) || webPlugin.Name.StartsWith('.'))
if (existingPlugin != null)
{ {
if (webPlugin.Version == existingPlugin.Version) throw new ArgumentException("Wrong plugin name");
{
throw new ArgumentException("Plugin already exist");
}
webPlugin.Id = existingPlugin.Id;
await storage.DeleteDirectoryAsync(string.Empty, webPlugin.Name);
} }
webPlugin.TenantId = tenantId; if (await storage.IsDirectoryAsync(webPlugin.Name))
webPlugin.CreateBy = _authContext.CurrentAccount.ID; {
webPlugin.CreateOn = DateTime.UtcNow; await storage.DeleteDirectoryAsync(webPlugin.Name);
webPlugin.Enabled = true; }
webPlugin.System = false;
webPlugin = await _webPluginService.SaveAsync(webPlugin); uri = await storage.SaveAsync(Path.Combine(webPlugin.Name, ConfigFileName), stream);
} }
using (var stream = zipFile.GetInputStream(pluginFile)) using (var stream = zipFile.GetInputStream(pluginFile))
@ -153,6 +242,13 @@ public class WebPluginManager
{ {
if (zipEntry.IsFile && zipEntry.Name.StartsWith(AssetsFolderName)) if (zipEntry.IsFile && zipEntry.Name.StartsWith(AssetsFolderName))
{ {
var ext = Path.GetExtension(zipEntry.Name);
if (_webPluginSettings.AssetExtensions.Any() && !_webPluginSettings.AssetExtensions.Contains(ext))
{
continue;
}
using (var stream = zipFile.GetInputStream(zipEntry)) using (var stream = zipFile.GetInputStream(zipEntry))
{ {
uri = await storage.SaveAsync(Path.Combine(webPlugin.Name, zipEntry.Name), stream); uri = await storage.SaveAsync(Path.Combine(webPlugin.Name, zipEntry.Name), stream);
@ -164,11 +260,20 @@ public class WebPluginManager
return webPlugin; return webPlugin;
} }
public async Task<IEnumerable<DbWebPlugin>> GetWebPluginsAsync(int tenantId, bool? enabled = null) public async Task<List<DbWebPlugin>> GetWebPluginsAsync(int tenantId)
{ {
DemandWebPlugins(); DemandWebPlugins();
var plugins = await _webPluginService.GetAsync(tenantId, enabled); var key = GetCacheKey(tenantId);
var plugins = _webPluginCache.Get(key);
if (plugins == null)
{
plugins = await _webPluginService.GetAsync(tenantId);
_webPluginCache.Insert(key, plugins);
}
return plugins; return plugins;
} }
@ -188,12 +293,11 @@ public class WebPluginManager
var plugin = await _webPluginService.GetByIdAsync(tenantId, id) ?? throw new ItemNotFoundException("Plugin not found"); var plugin = await _webPluginService.GetByIdAsync(tenantId, id) ?? throw new ItemNotFoundException("Plugin not found");
if (plugin.System)
{
throw new SecurityException("System plugin");
}
await _webPluginService.UpdateAsync(tenantId, plugin.Id, enabled); await _webPluginService.UpdateAsync(tenantId, plugin.Id, enabled);
var key = GetCacheKey(tenantId);
_webPluginCache.Remove(key);
} }
public async Task DeleteWebPluginAsync(int tenantId, int id) public async Task DeleteWebPluginAsync(int tenantId, int id)
@ -202,15 +306,158 @@ public class WebPluginManager
var plugin = await _webPluginService.GetByIdAsync(tenantId, id) ?? throw new ItemNotFoundException("Plugin not found"); var plugin = await _webPluginService.GetByIdAsync(tenantId, id) ?? throw new ItemNotFoundException("Plugin not found");
if (plugin.System) await _webPluginService.DeleteAsync(tenantId, plugin.Id);
var storage = await GetPluginStorageAsync(tenantId);
await storage.DeleteDirectoryAsync(plugin.Name);
var key = GetCacheKey(tenantId);
_webPluginCache.Remove(key);
}
public async Task<List<DbWebPlugin>> GetSystemWebPluginsAsync()
{
var key = GetCacheKey(Tenant.DefaultTenant);
var systemPlugins = _webPluginCache.Get(key);
if (systemPlugins == null)
{
systemPlugins = await GetSystemWebPluginsFromStorageAsync();
_webPluginCache.Insert(key, systemPlugins);
}
return systemPlugins;
}
private async Task<List<DbWebPlugin>> GetSystemWebPluginsFromStorageAsync()
{
var systemPlugins = new List<DbWebPlugin>();
var systemWebPluginSettings = await _settingsManager.LoadForDefaultTenantAsync<SystemWebPluginSettings>();
var disabledPlugins = systemWebPluginSettings?.DisabledPlugins ?? new List<string>();
var storage = await GetPluginStorageAsync(Tenant.DefaultTenant);
var configFiles = await storage.ListFilesRelativeAsync(string.Empty, string.Empty, ConfigFileName, true).ToArrayAsync();
foreach (var path in configFiles)
{
try
{
using var readStream = await storage.GetReadStreamAsync(path);
using var reader = new StreamReader(readStream);
var configContent = reader.ReadToEnd();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var webPlugin = System.Text.Json.JsonSerializer.Deserialize<DbWebPlugin>(configContent, options);
webPlugin.TenantId = Tenant.DefaultTenant;
webPlugin.System = true;
webPlugin.Enabled = !disabledPlugins.Contains(webPlugin.Name);
systemPlugins.Add(webPlugin);
}
catch (Exception e)
{
_log.ErrorWithException(e);
}
}
return systemPlugins;
}
public async Task<DbWebPlugin> GetSystemWebPluginAsync(string name)
{
var systemWebPluginSettings = await _settingsManager.LoadForDefaultTenantAsync<SystemWebPluginSettings>();
var disabledPlugins = systemWebPluginSettings?.DisabledPlugins ?? new List<string>();
var storage = await GetPluginStorageAsync(Tenant.DefaultTenant);
var path = Path.Combine(name, ConfigFileName);
if (!await storage.IsFileAsync(path))
{
throw new ItemNotFoundException("Plugin not found");
}
using var readStream = await storage.GetReadStreamAsync(path);
using var reader = new StreamReader(readStream);
var configContent = reader.ReadToEnd();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var webPlugin = System.Text.Json.JsonSerializer.Deserialize<DbWebPlugin>(configContent, options);
webPlugin.TenantId = Tenant.DefaultTenant;
webPlugin.System = true;
webPlugin.Enabled = !disabledPlugins.Contains(webPlugin.Name);
return webPlugin;
}
public async Task UpdateSystemWebPluginAsync(string name, bool enabled)
{
DemandWebPlugins();
var systemWebPluginSettings = await _settingsManager.LoadForDefaultTenantAsync<SystemWebPluginSettings>();
var disabledPlugins = systemWebPluginSettings?.DisabledPlugins ?? new List<string>();
if (enabled)
{
disabledPlugins.Remove(name);
}
else
{
disabledPlugins.Add(name);
}
systemWebPluginSettings.DisabledPlugins = disabledPlugins.Any() ? disabledPlugins : null;
await _settingsManager.SaveForDefaultTenantAsync(systemWebPluginSettings);
var key = GetCacheKey(Tenant.DefaultTenant);
_webPluginCache.Remove(key);
}
public async Task DeleteSystemWebPluginAsync(string name)
{
DemandWebPlugins("delete");
if (!_coreBaseSettings.Standalone)
{ {
throw new SecurityException("System plugin"); throw new SecurityException("System plugin");
} }
await _webPluginService.DeleteAsync(tenantId, plugin.Id); var storage = await GetPluginStorageAsync(Tenant.DefaultTenant);
var storage = await _storageFactory.GetStorageAsync(tenantId, StorageModuleName); if (!await storage.IsDirectoryAsync(name))
{
throw new ItemNotFoundException("Plugin not found");
}
await storage.DeleteDirectoryAsync(string.Empty, plugin.Name); await UpdateSystemWebPluginAsync(name, true);
await storage.DeleteDirectoryAsync(name);
} }
} }

View File

@ -38,6 +38,8 @@ public class WebPluginSettings
private long _maxSize; private long _maxSize;
private string _extension; private string _extension;
private string[] _allow; private string[] _allow;
private string[] _assetExtensions;
private string _systemUrl;
public bool Enabled public bool Enabled
{ {
@ -61,4 +63,26 @@ public class WebPluginSettings
get => _allow ?? Array.Empty<string>(); get => _allow ?? Array.Empty<string>();
set => _allow = value; set => _allow = value;
} }
public string[] AssetExtensions
{
get => _assetExtensions ?? Array.Empty<string>();
set => _assetExtensions = value;
}
} }
public class SystemWebPluginSettings : ISettings<SystemWebPluginSettings>
{
public List<string> DisabledPlugins { get; set; }
[JsonIgnore]
public Guid ID
{
get { return new Guid("{33039FD8-CF74-46B5-9AF2-2B3D4B651F31}"); }
}
public SystemWebPluginSettings GetDefault()
{
return new SystemWebPluginSettings();
}
}

View File

@ -0,0 +1,8 @@

syntax = "proto3";
package ASC.Web.Core;
message WebPluginCacheItem {
string key = 1;
}