From c87a831b890520a17a2e551bdd5ed39d8a54733d Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Wed, 8 Dec 2021 13:14:44 +0300 Subject: [PATCH 01/10] Files: optimization --- .../ASC.ElasticSearch/Engine/BaseIndexer.cs | 5 +- .../ASC.ElasticSearch/Engine/Client.cs | 5 +- .../ASC.ElasticSearch/Service/Launcher.cs | 5 +- .../ASC.ElasticSearch/Service/Settings.cs | 36 +-- .../Core/Core/Dao/TeamlabDao/FileDao.cs | 5 +- .../Core/Core/Search/FactoryIndexerFile.cs | 5 +- .../Core/Core/Search/FactoryIndexerFolder.cs | 5 +- .../Thirdparty/ProviderDao/ProviderDaoBase.cs | 33 +-- .../Core/Thirdparty/RegexDaoSelectorBase.cs | 6 +- web/ASC.Web.Core/Files/FileUtility.cs | 220 +++++++++++++----- 10 files changed, 212 insertions(+), 113 deletions(-) diff --git a/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs b/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs index dc8e677944..5666d80941 100644 --- a/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs +++ b/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs @@ -36,7 +36,6 @@ using System.Threading.Tasks; using ASC.Common; using ASC.Common.Caching; using ASC.Common.Logging; -using ASC.Common.Utils; using ASC.Core; using ASC.Core.Common.EF; using ASC.Core.Common.EF.Context; @@ -103,14 +102,14 @@ namespace ASC.ElasticSearch DbContextManager dbContextManager, TenantManager tenantManager, BaseIndexerHelper baseIndexerHelper, - ConfigurationExtension configurationExtension, + SettingsHelper settingsHelper, IServiceProvider serviceProvider) { Client = client; Log = log.CurrentValue; TenantManager = tenantManager; BaseIndexerHelper = baseIndexerHelper; - Settings = Settings.GetInstance(configurationExtension); + Settings = settingsHelper.Settings; ServiceProvider = serviceProvider; LazyWebstudioDbContext = new Lazy(() => dbContextManager.Value); } diff --git a/common/services/ASC.ElasticSearch/Engine/Client.cs b/common/services/ASC.ElasticSearch/Engine/Client.cs index 7061f25c29..38b7c21285 100644 --- a/common/services/ASC.ElasticSearch/Engine/Client.cs +++ b/common/services/ASC.ElasticSearch/Engine/Client.cs @@ -29,7 +29,6 @@ using System.Text; using ASC.Common; using ASC.Common.Logging; -using ASC.Common.Utils; using ASC.Core; using ASC.Core.Tenants; using ASC.ElasticSearch.Service; @@ -54,11 +53,11 @@ namespace ASC.ElasticSearch private CoreConfiguration CoreConfiguration { get; } private Settings Settings { get; } - public Client(IOptionsMonitor option, CoreConfiguration coreConfiguration, ConfigurationExtension configurationExtension) + public Client(IOptionsMonitor option, CoreConfiguration coreConfiguration, SettingsHelper settingsHelper) { Log = option.Get("ASC.Indexer"); CoreConfiguration = coreConfiguration; - Settings = Settings.GetInstance(configurationExtension); + Settings = settingsHelper.Settings; } public ElasticClient Instance diff --git a/common/services/ASC.ElasticSearch/Service/Launcher.cs b/common/services/ASC.ElasticSearch/Service/Launcher.cs index b4d0dab5f8..b8e35eac30 100644 --- a/common/services/ASC.ElasticSearch/Service/Launcher.cs +++ b/common/services/ASC.ElasticSearch/Service/Launcher.cs @@ -32,7 +32,6 @@ using System.Threading.Tasks; using ASC.Common; using ASC.Common.Caching; using ASC.Common.Logging; -using ASC.Common.Utils; using ASC.ElasticSearch.Service; using Microsoft.Extensions.DependencyInjection; @@ -58,14 +57,14 @@ namespace ASC.ElasticSearch ICacheNotify notify, ICacheNotify indexNotify, IServiceProvider serviceProvider, - ConfigurationExtension configurationExtension) + SettingsHelper settingsHelper) { Log = options.Get("ASC.Indexer"); Notify = notify; IndexNotify = indexNotify; ServiceProvider = serviceProvider; CancellationTokenSource = new CancellationTokenSource(); - var settings = Settings.GetInstance(configurationExtension); + var settings = settingsHelper.Settings; Period = TimeSpan.FromMinutes(settings.Period.Value); } diff --git a/common/services/ASC.ElasticSearch/Service/Settings.cs b/common/services/ASC.ElasticSearch/Service/Settings.cs index b90b31a7d5..5d7f4f43b2 100644 --- a/common/services/ASC.ElasticSearch/Service/Settings.cs +++ b/common/services/ASC.ElasticSearch/Service/Settings.cs @@ -30,23 +30,29 @@ using ASC.Common.Utils; namespace ASC.ElasticSearch.Service { [Singletone] + public class SettingsHelper + { + public Settings Settings { get; set; } + public SettingsHelper(ConfigurationExtension configuration) + { + var cfg = configuration.GetSetting("elastic"); + + Settings = new Settings + { + Scheme = cfg.Scheme ?? "http", + Host = cfg.Host ?? "localhost", + Port = cfg.Port ?? 9200, + Period = cfg.Period ?? 1, + MaxContentLength = cfg.MaxContentLength ?? 100 * 1024 * 1024L, + MaxFileSize = cfg.MaxFileSize ?? 10 * 1024 * 1024L, + Threads = cfg.Threads ?? 1, + HttpCompression = cfg.HttpCompression ?? true + }; + } + } + public class Settings { - public static Settings GetInstance(ConfigurationExtension configuration) - { - var result = new Settings(); - var cfg = configuration.GetSetting("elastic"); - result.Scheme = cfg.Scheme ?? "http"; - result.Host = cfg.Host ?? "localhost"; - result.Port = cfg.Port ?? 9200; - result.Period = cfg.Period ?? 1; - result.MaxContentLength = cfg.MaxContentLength ?? 100 * 1024 * 1024L; - result.MaxFileSize = cfg.MaxFileSize ?? 10 * 1024 * 1024L; - result.Threads = cfg.Threads ?? 1; - result.HttpCompression = cfg.HttpCompression ?? true; - return result; - } - public string Host { get; set; } public int? Port { get; set; } diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs index 9b31953663..c32b5d1ba7 100644 --- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs +++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs @@ -34,7 +34,6 @@ using System.Threading.Tasks; using ASC.Common; using ASC.Common.Caching; -using ASC.Common.Utils; using ASC.Core; using ASC.Core.Common.EF; using ASC.Core.Common.EF.Context; @@ -100,7 +99,7 @@ namespace ASC.Files.Core.Data ChunkedUploadSessionHolder chunkedUploadSessionHolder, ProviderFolderDao providerFolderDao, CrossDao crossDao, - ConfigurationExtension configurationExtension) + SettingsHelper settingsHelper) : base( dbContextManager, dbContextManager1, @@ -126,7 +125,7 @@ namespace ASC.Files.Core.Data ChunkedUploadSessionHolder = chunkedUploadSessionHolder; ProviderFolderDao = providerFolderDao; CrossDao = crossDao; - Settings = Settings.GetInstance(configurationExtension); + Settings = settingsHelper.Settings; } public void InvalidateCache(int fileId) diff --git a/products/ASC.Files/Core/Core/Search/FactoryIndexerFile.cs b/products/ASC.Files/Core/Core/Search/FactoryIndexerFile.cs index 653a9ecdc1..8657ba9f83 100644 --- a/products/ASC.Files/Core/Core/Search/FactoryIndexerFile.cs +++ b/products/ASC.Files/Core/Core/Search/FactoryIndexerFile.cs @@ -31,7 +31,6 @@ using System.Threading.Tasks; using ASC.Common; using ASC.Common.Caching; using ASC.Common.Logging; -using ASC.Common.Utils; using ASC.Core; using ASC.Core.Common.EF.Model; using ASC.ElasticSearch; @@ -60,11 +59,11 @@ namespace ASC.Web.Files.Core.Search IServiceProvider serviceProvider, IDaoFactory daoFactory, ICache cache, - ConfigurationExtension configurationExtension) + SettingsHelper settingsHelper) : base(options, tenantManager, searchSettingsHelper, factoryIndexer, baseIndexer, serviceProvider, cache) { DaoFactory = daoFactory; - Settings = Settings.GetInstance(configurationExtension); + Settings = settingsHelper.Settings; } public override void IndexAll() diff --git a/products/ASC.Files/Core/Core/Search/FactoryIndexerFolder.cs b/products/ASC.Files/Core/Core/Search/FactoryIndexerFolder.cs index 512492e721..2b0b51931a 100644 --- a/products/ASC.Files/Core/Core/Search/FactoryIndexerFolder.cs +++ b/products/ASC.Files/Core/Core/Search/FactoryIndexerFolder.cs @@ -32,7 +32,6 @@ using System.Threading.Tasks; using ASC.Common; using ASC.Common.Caching; using ASC.Common.Logging; -using ASC.Common.Utils; using ASC.Core; using ASC.Core.Common.EF.Model; using ASC.ElasticSearch; @@ -61,11 +60,11 @@ namespace ASC.Web.Files.Core.Search IServiceProvider serviceProvider, IDaoFactory daoFactory, ICache cache, - ConfigurationExtension configurationExtension) + SettingsHelper settingsHelper) : base(options, tenantManager, searchSettingsHelper, factoryIndexer, baseIndexer, serviceProvider, cache) { DaoFactory = daoFactory; - Settings = Settings.GetInstance(configurationExtension); + Settings = settingsHelper.Settings; } public override void IndexAll() diff --git a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderDaoBase.cs b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderDaoBase.cs index 755ebbb443..5995bafadc 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderDaoBase.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderDaoBase.cs @@ -46,7 +46,20 @@ namespace ASC.Files.Thirdparty.ProviderDao { internal class ProviderDaoBase : ThirdPartyProviderDao, IDisposable { - private readonly List Selectors; + private List selectors; + private List Selectors + { + get => selectors ??= new List + { + //Fill in selectors + ServiceProvider.GetService(), + ServiceProvider.GetService(), + ServiceProvider.GetService(), + ServiceProvider.GetService(), + ServiceProvider.GetService(), + ServiceProvider.GetService() + }; + } private int tenantID; private int TenantID { get => tenantID != 0 ? tenantID : (tenantID = TenantManager.GetCurrentTenant().TenantId); } @@ -63,17 +76,6 @@ namespace ASC.Files.Thirdparty.ProviderDao SecurityDao = securityDao; TagDao = tagDao; CrossDao = crossDao; - - Selectors = new List - { - //Fill in selectors - ServiceProvider.GetService(), - ServiceProvider.GetService(), - ServiceProvider.GetService(), - ServiceProvider.GetService(), - ServiceProvider.GetService(), - ServiceProvider.GetService() - }; } protected IServiceProvider ServiceProvider { get; } @@ -160,8 +162,11 @@ namespace ASC.Files.Thirdparty.ProviderDao } public void Dispose() - { - Selectors.ForEach(r => r.Dispose()); + { + if (selectors != null) + { + selectors.ForEach(r => r.Dispose()); + } } } } \ No newline at end of file diff --git a/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs b/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs index 2bfdd3aa7a..b4f42ceee2 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/RegexDaoSelectorBase.cs @@ -40,9 +40,10 @@ namespace ASC.Files.Thirdparty { private IServiceProvider ServiceProvider { get; } private IDaoFactory DaoFactory { get; } - public Regex Selector { get; set; } protected internal abstract string Name { get; } - protected internal abstract string Id { get; } + protected internal abstract string Id { get; } + public Regex Selector { get => selector ??= new Regex(@"^" + Id + @"-(?'id'\d+)(-(?'path'.*)){0,1}$", RegexOptions.Singleline | RegexOptions.Compiled); } + private Regex selector; private Dictionary> Providers { get; set; } @@ -52,7 +53,6 @@ namespace ASC.Files.Thirdparty { ServiceProvider = serviceProvider; DaoFactory = daoFactory; - Selector = new Regex(@"^" + Id + @"-(?'id'\d+)(-(?'path'.*)){0,1}$", RegexOptions.Singleline | RegexOptions.Compiled); Providers = new Dictionary>(); } diff --git a/web/ASC.Web.Core/Files/FileUtility.cs b/web/ASC.Web.Core/Files/FileUtility.cs index 58849013b2..0edcd11e9d 100644 --- a/web/ASC.Web.Core/Files/FileUtility.cs +++ b/web/ASC.Web.Core/Files/FileUtility.cs @@ -38,6 +38,143 @@ using Microsoft.Extensions.Configuration; namespace ASC.Web.Core.Files { + [Singletone] + public class FileUtilityConfiguration + { + private IConfiguration Configuration { get; } + + public FileUtilityConfiguration(IConfiguration configuration) + { + Configuration = configuration; + } + + private List extsIndexing; + public List ExtsIndexing { get => extsIndexing ??= (Configuration.GetSection("files:index").Get() ?? new string[] { }).ToList(); } + + private List extsImagePreviewed; + public List ExtsImagePreviewed { get => extsImagePreviewed ??= (Configuration.GetSection("files:viewed-images").Get() ?? new string[] { }).ToList(); } + + private List extsMediaPreviewed; + public List ExtsMediaPreviewed { get => extsMediaPreviewed ??= (Configuration.GetSection("files:viewed-media").Get() ?? new string[] { }).ToList(); } + + private List extsWebPreviewed; + public List ExtsWebPreviewed + { + get + { + return extsWebPreviewed ??= (Configuration.GetSection("files:docservice:viewed-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsWebEdited; + public List ExtsWebEdited + { + get + { + return extsWebEdited ??= (Configuration.GetSection("files:docservice:edited-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsWebEncrypt; + public List ExtsWebEncrypt { get => extsWebEncrypt ??= (Configuration.GetSection("files:docservice:encrypted-docs").Get() ?? new string[] { }).ToList(); } + + private List extsWebReviewed; + public List ExtsWebReviewed + { + get + { + return extsWebReviewed ??= (Configuration.GetSection("files:docservice:reviewed-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsWebCustomFilterEditing; + public List ExtsWebCustomFilterEditing + { + get + { + return extsWebCustomFilterEditing ??= (Configuration.GetSection("files:docservice:customfilter-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsWebRestrictedEditing; + public List ExtsWebRestrictedEditing + { + get + { + return extsWebRestrictedEditing ??= (Configuration.GetSection("files:docservice:formfilling-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsWebCommented; + public List ExtsWebCommented + { + get + { + return extsWebCommented ??= (Configuration.GetSection("files:docservice:commented-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsWebTemplate; + public List ExtsWebTemplate + { + get + { + return extsWebTemplate ??= (Configuration.GetSection("files:docservice:template-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsMustConvert; + public List ExtsMustConvert + { + get + { + return extsMustConvert ??= (Configuration.GetSection("files:docservice:convert-docs").Get() ?? new string[] { }).ToList(); + } + } + + private List extsCoAuthoring; + public List ExtsCoAuthoring + { + get => extsCoAuthoring ??= (Configuration.GetSection("files:docservice:coauthor-docs").Get() ?? new string[] { }).ToList(); + } + + public Dictionary InternalExtension + { + get => new Dictionary + { + { FileType.Document, Configuration["files:docservice:internal-doc"] ?? ".docx" }, + { FileType.Spreadsheet, Configuration["files:docservice:internal-xls"] ?? ".xlsx" }, + { FileType.Presentation, Configuration["files:docservice:internal-ppt"] ?? ".pptx" } + }; + } + + internal string GetSignatureSecret() + { + var result = Configuration["files:docservice:secret:value"] ?? ""; + + var regex = new Regex(@"^\s+$"); + + if (regex.IsMatch(result)) + result = ""; + + return result; + } + + internal string GetSignatureHeader() + { + var result = (Configuration["files:docservice:secret:header"] ?? "").Trim(); + if (string.IsNullOrEmpty(result)) + result = "Authorization"; + return result; + } + + + internal bool GetCanForcesave() + { + return !bool.TryParse(Configuration["files:docservice:forcesave"] ?? "", out var canForcesave) || canForcesave; + } + } + [Scope] public class FileUtility { @@ -45,11 +182,11 @@ namespace ASC.Web.Core.Files private FilesDbContext FilesDbContext { get => LazyFilesDbContext.Value; } public FileUtility( - IConfiguration configuration, + FileUtilityConfiguration fileUtilityConfiguration, FilesLinkUtility filesLinkUtility, DbContextManager dbContextManager) { - Configuration = configuration; + FileUtilityConfiguration = fileUtilityConfiguration; FilesLinkUtility = filesLinkUtility; LazyFilesDbContext = new Lazy(() => dbContextManager.Get("files")); CanForcesave = GetCanForcesave(); @@ -219,16 +356,12 @@ namespace ASC.Web.Core.Files } } - private List extsIndexing; - private List ExtsIndexing { get => extsIndexing ??= (Configuration.GetSection("files:index").Get() ?? new string[] { }).ToList(); } + private List ExtsIndexing { get => FileUtilityConfiguration.ExtsIndexing; } - private List extsImagePreviewed; - public List ExtsImagePreviewed { get => extsImagePreviewed ??= (Configuration.GetSection("files:viewed-images").Get() ?? new string[] { }).ToList(); } + public List ExtsImagePreviewed { get => FileUtilityConfiguration.ExtsImagePreviewed; } - private List extsMediaPreviewed; - public List ExtsMediaPreviewed { get => extsMediaPreviewed ??= (Configuration.GetSection("files:viewed-media").Get() ?? new string[] { }).ToList(); } + public List ExtsMediaPreviewed { get => FileUtilityConfiguration.ExtsMediaPreviewed; } - private List extsWebPreviewed; public List ExtsWebPreviewed { get @@ -238,11 +371,10 @@ namespace ASC.Web.Core.Files return new List(); } - return extsWebPreviewed ??= (Configuration.GetSection("files:docservice:viewed-docs").Get() ?? new string[] { }).ToList(); + return FileUtilityConfiguration.ExtsWebPreviewed; } } - private List extsWebEdited; public List ExtsWebEdited { get @@ -252,14 +384,12 @@ namespace ASC.Web.Core.Files return new List(); } - return extsWebEdited ??= (Configuration.GetSection("files:docservice:edited-docs").Get() ?? new string[] { }).ToList(); + return FileUtilityConfiguration.ExtsWebEdited; } } - private List extsWebEncrypt; - public List ExtsWebEncrypt { get => extsWebEncrypt ??= (Configuration.GetSection("files:docservice:encrypted-docs").Get() ?? new string[] { }).ToList(); } + public List ExtsWebEncrypt { get => FileUtilityConfiguration.ExtsWebEncrypt; } - private List extsWebReviewed; public List ExtsWebReviewed { get @@ -269,11 +399,10 @@ namespace ASC.Web.Core.Files return new List(); } - return extsWebReviewed ??= (Configuration.GetSection("files:docservice:reviewed-docs").Get() ?? new string[] { }).ToList(); + return FileUtilityConfiguration.ExtsWebReviewed; } } - private List extsWebCustomFilterEditing; public List ExtsWebCustomFilterEditing { get @@ -283,11 +412,10 @@ namespace ASC.Web.Core.Files return new List(); } - return extsWebCustomFilterEditing ??= (Configuration.GetSection("files:docservice:customfilter-docs").Get() ?? new string[] { }).ToList(); + return FileUtilityConfiguration.ExtsWebCustomFilterEditing; } } - private List extsWebRestrictedEditing; public List ExtsWebRestrictedEditing { get @@ -297,11 +425,10 @@ namespace ASC.Web.Core.Files return new List(); } - return extsWebRestrictedEditing ??= (Configuration.GetSection("files:docservice:formfilling-docs").Get() ?? new string[] { }).ToList(); + return FileUtilityConfiguration.ExtsWebRestrictedEditing; } } - private List extsWebCommented; public List ExtsWebCommented { get @@ -311,20 +438,15 @@ namespace ASC.Web.Core.Files return new List(); } - return extsWebCommented ??= (Configuration.GetSection("files:docservice:commented-docs").Get() ?? new string[] { }).ToList(); + return FileUtilityConfiguration.ExtsWebCommented; } } - private List extsWebTemplate; public List ExtsWebTemplate { - get - { - return extsWebTemplate ??= (Configuration.GetSection("files:docservice:template-docs").Get() ?? new string[] { }).ToList(); - } + get => FileUtilityConfiguration.ExtsWebTemplate; } - private List extsMustConvert; public List ExtsMustConvert { get @@ -334,17 +456,16 @@ namespace ASC.Web.Core.Files return new List(); } - return extsMustConvert ??= (Configuration.GetSection("files:docservice:convert-docs").Get() ?? new string[] { }).ToList(); + return FileUtilityConfiguration.ExtsMustConvert; } } - private List extsCoAuthoring; public List ExtsCoAuthoring { - get => extsCoAuthoring ??= (Configuration.GetSection("files:docservice:coauthor-docs").Get() ?? new string[] { }).ToList(); + get => FileUtilityConfiguration.ExtsCoAuthoring; } - private IConfiguration Configuration { get; } + private FileUtilityConfiguration FileUtilityConfiguration { get; } private FilesLinkUtility FilesLinkUtility { get; } public static readonly List ExtsArchive = new List @@ -419,15 +540,7 @@ namespace ASC.Web.Core.Files ".xlt", ".xltm", ".xltx", ".pot", ".potm", ".potx", }; - public Dictionary InternalExtension - { - get => new Dictionary - { - { FileType.Document, Configuration["files:docservice:internal-doc"] ?? ".docx" }, - { FileType.Spreadsheet, Configuration["files:docservice:internal-xls"] ?? ".xlsx" }, - { FileType.Presentation, Configuration["files:docservice:internal-ppt"] ?? ".pptx" } - }; - } + public Dictionary InternalExtension => FileUtilityConfiguration.InternalExtension; public enum CsvDelimiter { @@ -441,32 +554,13 @@ namespace ASC.Web.Core.Files public string SignatureSecret { get => GetSignatureSecret(); } public string SignatureHeader { get => GetSignatureHeader(); } - private string GetSignatureSecret() - { - var result = Configuration["files:docservice:secret:value"] ?? ""; + private string GetSignatureSecret() => FileUtilityConfiguration.GetSignatureSecret(); - var regex = new Regex(@"^\s+$"); - - if (regex.IsMatch(result)) - result = ""; - - return result; - } - - private string GetSignatureHeader() - { - var result = (Configuration["files:docservice:secret:header"] ?? "").Trim(); - if (string.IsNullOrEmpty(result)) - result = "Authorization"; - return result; - } + private string GetSignatureHeader() => FileUtilityConfiguration.GetSignatureHeader(); public readonly bool CanForcesave; - private bool GetCanForcesave() - { - return !bool.TryParse(Configuration["files:docservice:forcesave"] ?? "", out var canForcesave) || canForcesave; - } + private bool GetCanForcesave() => FileUtilityConfiguration.GetCanForcesave(); #endregion } From 8abd9ef42b0e76f0e5c913b30b54dcf6f22e9775 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Wed, 8 Dec 2021 22:17:39 +0300 Subject: [PATCH 02/10] Nlog: fixed configs --- config/nlog.config | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/config/nlog.config b/config/nlog.config index cbb27ab68f..6483b10802 100644 --- a/config/nlog.config +++ b/config/nlog.config @@ -3,7 +3,6 @@ - @@ -11,9 +10,9 @@ - - - + + + From 0bd39bfc19f66b78782218e2ffadaed317e5ccf4 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Wed, 8 Dec 2021 22:18:04 +0300 Subject: [PATCH 03/10] Core: optimization --- common/ASC.Core.Common/EF/Context/BaseDbContext.cs | 2 +- common/ASC.Core.Common/EF/Context/ConfigureDbContext.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/ASC.Core.Common/EF/Context/BaseDbContext.cs b/common/ASC.Core.Common/EF/Context/BaseDbContext.cs index 027c0c3128..771201928c 100644 --- a/common/ASC.Core.Common/EF/Context/BaseDbContext.cs +++ b/common/ASC.Core.Common/EF/Context/BaseDbContext.cs @@ -58,7 +58,7 @@ namespace ASC.Core.Common.EF { optionsBuilder.UseLoggerFactory(LoggerFactory); optionsBuilder.EnableSensitiveDataLogging(); - Provider = GetProviderByConnectionString(); + Provider = GetProviderByConnectionString(); switch (Provider) { case Provider.MySql: diff --git a/common/ASC.Core.Common/EF/Context/ConfigureDbContext.cs b/common/ASC.Core.Common/EF/Context/ConfigureDbContext.cs index 71f865134d..a77ab7943f 100644 --- a/common/ASC.Core.Common/EF/Context/ConfigureDbContext.cs +++ b/common/ASC.Core.Common/EF/Context/ConfigureDbContext.cs @@ -15,18 +15,20 @@ namespace ASC.Core.Common.EF public const string baseName = "default"; private EFLoggerFactory LoggerFactory { get; } private ConfigurationExtension Configuration { get; } + private string MigrateAssembly { get; } public ConfigureDbContext(EFLoggerFactory loggerFactory, ConfigurationExtension configuration) { LoggerFactory = loggerFactory; Configuration = configuration; + MigrateAssembly = Configuration["testAssembly"]; } public void Configure(string name, T context) { context.LoggerFactory = LoggerFactory; context.ConnectionStringSettings = Configuration.GetConnectionStrings(name) ?? Configuration.GetConnectionStrings(baseName); - context.MigrateAssembly = Configuration["testAssembly"]; + context.MigrateAssembly = MigrateAssembly; } public void Configure(T context) From 0771a54c47741dbd53165d94972c00ae77223fc6 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Thu, 9 Dec 2021 20:23:06 +0300 Subject: [PATCH 04/10] Optimization --- common/ASC.Data.Storage/PathUtils.cs | 2 +- web/ASC.Web.Core/Files/FileUtility.cs | 30 ++++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/common/ASC.Data.Storage/PathUtils.cs b/common/ASC.Data.Storage/PathUtils.cs index 9b7deb7738..6291a3e477 100644 --- a/common/ASC.Data.Storage/PathUtils.cs +++ b/common/ASC.Data.Storage/PathUtils.cs @@ -83,7 +83,7 @@ namespace ASC.Data.Storage virtPath = ""; } - if (virtPath.StartsWith("~") && !Uri.IsWellFormedUriString(virtPath, UriKind.Absolute)) + if (virtPath.StartsWith('~') && !Uri.IsWellFormedUriString(virtPath, UriKind.Absolute)) { var rootPath = "/"; if (!string.IsNullOrEmpty(WebHostEnvironment?.WebRootPath) && WebHostEnvironment?.WebRootPath.Length > 1) diff --git a/web/ASC.Web.Core/Files/FileUtility.cs b/web/ASC.Web.Core/Files/FileUtility.cs index 0edcd11e9d..b46a985db6 100644 --- a/web/ASC.Web.Core/Files/FileUtility.cs +++ b/web/ASC.Web.Core/Files/FileUtility.cs @@ -254,52 +254,62 @@ namespace ASC.Web.Core.Files public bool CanImageView(string fileName) { - return ExtsImagePreviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsImagePreviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanMediaView(string fileName) { - return ExtsMediaPreviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsMediaPreviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanWebView(string fileName) { - return ExtsWebPreviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsWebPreviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanWebEdit(string fileName) { - return ExtsWebEdited.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsWebEdited.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanWebReview(string fileName) { - return ExtsWebReviewed.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsWebReviewed.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanWebCustomFilterEditing(string fileName) { - return ExtsWebCustomFilterEditing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsWebCustomFilterEditing.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanWebRestrictedEditing(string fileName) { - return ExtsWebRestrictedEditing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsWebRestrictedEditing.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanWebComment(string fileName) { - return ExtsWebCommented.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsWebCommented.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanCoAuhtoring(string fileName) { - return ExtsCoAuthoring.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsCoAuthoring.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } public bool CanIndex(string fileName) { - return ExtsIndexing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase); + var ext = GetFileExtension(fileName); + return ExtsIndexing.Exists(r => r.Equals(ext, StringComparison.OrdinalIgnoreCase)); } #endregion From 30c138ef8be6066f90f2ef3e6215d997c9ee2415 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Fri, 10 Dec 2021 17:02:44 +0300 Subject: [PATCH 05/10] Files: optimization configuration --- .../Core/Helpers/ThirdpartyConfiguration.cs | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/products/ASC.Files/Core/Helpers/ThirdpartyConfiguration.cs b/products/ASC.Files/Core/Helpers/ThirdpartyConfiguration.cs index 46b01171cb..201f663950 100644 --- a/products/ASC.Files/Core/Helpers/ThirdpartyConfiguration.cs +++ b/products/ASC.Files/Core/Helpers/ThirdpartyConfiguration.cs @@ -37,10 +37,29 @@ using Microsoft.Extensions.Configuration; namespace ASC.Web.Files.Helpers { + [Singletone] + public class ThirdpartyConfigurationData + { + private IConfiguration Configuration { get; } + + private List thirdPartyProviders; + public List ThirdPartyProviders + { + get + { + return thirdPartyProviders ??= (Configuration.GetSection("files:thirdparty:enable").Get() ?? new string[] { }).ToList(); + } + } + public ThirdpartyConfigurationData(IConfiguration configuration) + { + Configuration = configuration; + } + } + [Scope(Additional = typeof(BaseLoginProviderExtension))] public class ThirdpartyConfiguration { - private IConfiguration Configuration { get; } + private ThirdpartyConfigurationData Configuration { get; } private Lazy BoxLoginProvider { get; } private Lazy DropboxLoginProvider { get; } private Lazy OneDriveLoginProvider { get; } @@ -48,7 +67,7 @@ namespace ASC.Web.Files.Helpers private Lazy GoogleLoginProvider { get; } public ThirdpartyConfiguration( - IConfiguration configuration, + ThirdpartyConfigurationData configuration, ConsumerFactory consumerFactory) { Configuration = configuration; @@ -58,14 +77,10 @@ namespace ASC.Web.Files.Helpers DocuSignLoginProvider = new Lazy(() => consumerFactory.Get()); GoogleLoginProvider = new Lazy(() => consumerFactory.Get()); } - - private IEnumerable thirdPartyProviders; - public IEnumerable ThirdPartyProviders + + public List ThirdPartyProviders { - get - { - return thirdPartyProviders ??= (Configuration.GetSection("files:thirdparty:enable").Get() ?? new string[] { }).ToList(); - } + get => Configuration.ThirdPartyProviders; } public bool SupportInclusion(IDaoFactory daoFactory) @@ -80,7 +95,7 @@ namespace ASC.Web.Files.Helpers { get { - return ThirdPartyProviders.Contains("box") && BoxLoginProvider.Value.IsEnabled; + return ThirdPartyProviders.Exists(r => r == "box") && BoxLoginProvider.Value.IsEnabled; } } @@ -88,7 +103,7 @@ namespace ASC.Web.Files.Helpers { get { - return ThirdPartyProviders.Contains("dropboxv2") && DropboxLoginProvider.Value.IsEnabled; + return ThirdPartyProviders.Exists(r => r == "dropboxv2") && DropboxLoginProvider.Value.IsEnabled; } } @@ -96,38 +111,38 @@ namespace ASC.Web.Files.Helpers { get { - return ThirdPartyProviders.Contains("onedrive") && OneDriveLoginProvider.Value.IsEnabled; + return ThirdPartyProviders.Exists(r => r == "onedrive") && OneDriveLoginProvider.Value.IsEnabled; } } public bool SupportSharePointInclusion { - get { return ThirdPartyProviders.Contains("sharepoint"); } + get { return ThirdPartyProviders.Exists(r => r == "sharepoint"); } } public bool SupportWebDavInclusion { - get { return ThirdPartyProviders.Contains("webdav"); } + get { return ThirdPartyProviders.Exists(r => r == "webdav"); } } public bool SupportNextcloudInclusion { - get { return ThirdPartyProviders.Contains("nextcloud"); } + get { return ThirdPartyProviders.Exists(r => r == "nextcloud"); } } public bool SupportOwncloudInclusion { - get { return ThirdPartyProviders.Contains("owncloud"); } + get { return ThirdPartyProviders.Exists(r => r == "owncloud"); } } public bool SupportkDriveInclusion { - get { return ThirdPartyProviders.Contains("kdrive"); } + get { return ThirdPartyProviders.Exists(r => r == "kdrive"); } } public bool SupportYandexInclusion { - get { return ThirdPartyProviders.Contains("yandex"); } + get { return ThirdPartyProviders.Exists(r => r == "yandex"); } } public string DropboxAppKey @@ -144,7 +159,7 @@ namespace ASC.Web.Files.Helpers { get { - return ThirdPartyProviders.Contains("docusign") && DocuSignLoginProvider.Value.IsEnabled; + return ThirdPartyProviders.Exists(r => r == "docusign") && DocuSignLoginProvider.Value.IsEnabled; } } @@ -152,7 +167,7 @@ namespace ASC.Web.Files.Helpers { get { - return ThirdPartyProviders.Contains("google") && GoogleLoginProvider.Value.IsEnabled; + return ThirdPartyProviders.Exists(r => r == "google") && GoogleLoginProvider.Value.IsEnabled; } } From a62a555217dfddd253ea26e7fc73a1a527810c91 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Fri, 10 Dec 2021 17:04:33 +0300 Subject: [PATCH 06/10] Files: tagDao. Precompiled queries --- .../Core/Core/Dao/TeamlabDao/TagDao.cs | 1288 +++++++++-------- 1 file changed, 664 insertions(+), 624 deletions(-) diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs index b2c91b5588..2f139e86fe 100644 --- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs +++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs @@ -1,89 +1,92 @@ -/* - * - * (c) Copyright Ascensio System Limited 2010-2018 - * - * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU - * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). - * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that - * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. - * - * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR - * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html - * - * You can contact Ascensio System SIA by email at sales@onlyoffice.com - * - * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display - * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. - * - * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains - * relevant author attributions when distributing the software. If the display of the logo in its graphic - * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" - * in every copy of the program you distribute. - * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. - * -*/ - - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; +/* + * + * (c) Copyright Ascensio System Limited 2010-2018 + * + * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). + * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that + * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. + * + * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html + * + * You can contact Ascensio System SIA by email at sales@onlyoffice.com + * + * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display + * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. + * + * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains + * relevant author attributions when distributing the software. If the display of the logo in its graphic + * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" + * in every copy of the program you distribute. + * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. + * +*/ + + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using System.Text.RegularExpressions; -using ASC.Common; +using ASC.Common; using ASC.Common.Caching; -using ASC.Core; -using ASC.Core.Common.EF; +using ASC.Core; +using ASC.Core.Common.EF; using ASC.Core.Common.EF.Context; -using ASC.Core.Common.Settings; -using ASC.Core.Tenants; -using ASC.Files.Core.EF; -using ASC.Web.Studio.Core; -using ASC.Web.Studio.UserControls.Statistics; +using ASC.Core.Common.Settings; +using ASC.Core.Tenants; +using ASC.Files.Core.EF; +using ASC.Web.Studio.Core; +using ASC.Web.Studio.UserControls.Statistics; using ASC.Web.Studio.Utility; -namespace ASC.Files.Core.Data + +using Microsoft.EntityFrameworkCore; + +namespace ASC.Files.Core.Data { - [Scope] - internal class TagDao : AbstractDao, ITagDao - { - private static readonly object syncRoot = new object(); - - public TagDao( - UserManager userManager, + [Scope] + internal class TagDao : AbstractDao, ITagDao + { + private static readonly object syncRoot = new object(); + + public TagDao( + UserManager userManager, DbContextManager dbContextManager, - DbContextManager dbContextManager1, - TenantManager tenantManager, - TenantUtil tenantUtil, - SetupInfo setupInfo, - TenantExtra tenantExtra, - TenantStatisticsProvider tenantStatisticProvider, - CoreBaseSettings coreBaseSettings, - CoreConfiguration coreConfiguration, - SettingsManager settingsManager, - AuthContext authContext, + DbContextManager dbContextManager1, + TenantManager tenantManager, + TenantUtil tenantUtil, + SetupInfo setupInfo, + TenantExtra tenantExtra, + TenantStatisticsProvider tenantStatisticProvider, + CoreBaseSettings coreBaseSettings, + CoreConfiguration coreConfiguration, + SettingsManager settingsManager, + AuthContext authContext, IServiceProvider serviceProvider, - ICache cache) + ICache cache) : base(dbContextManager, - dbContextManager1, - userManager, - tenantManager, - tenantUtil, - setupInfo, - tenantExtra, - tenantStatisticProvider, - coreBaseSettings, - coreConfiguration, - settingsManager, - authContext, + dbContextManager1, + userManager, + tenantManager, + tenantUtil, + setupInfo, + tenantExtra, + tenantStatisticProvider, + coreBaseSettings, + coreConfiguration, + settingsManager, + authContext, serviceProvider, - cache) - { - } - - public IEnumerable GetTags(Guid subject, TagType tagType, IEnumerable> fileEntries) - { - var filesId = new HashSet(); - var foldersId = new HashSet(); + cache) + { + } + + public IEnumerable GetTags(Guid subject, TagType tagType, IEnumerable> fileEntries) + { + var filesId = new HashSet(); + var foldersId = new HashSet(); foreach (var f in fileEntries) { @@ -97,26 +100,26 @@ namespace ASC.Files.Core.Data foldersId.Add(id); } } - - var q = Query(FilesDbContext.Tag) - .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) - .Where(r => r.Link.TenantId == r.Tag.TenantId) - .Where(r => r.Tag.Flag == tagType) - .Where(r => r.Link.EntryType == FileEntryType.File && filesId.Contains(r.Link.EntryId) + + var q = Query(FilesDbContext.Tag) + .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => r.Tag.Flag == tagType) + .Where(r => r.Link.EntryType == FileEntryType.File && filesId.Contains(r.Link.EntryId) || r.Link.EntryType == FileEntryType.Folder && foldersId.Contains(r.Link.EntryId)); if (subject != Guid.Empty) { q = q.Where(r => r.Link.CreateBy == subject); } - - return FromQuery(q); + + return FromQuery(q); } - - public IDictionary> GetTags(Guid subject, IEnumerable tagType, IEnumerable> fileEntries) - { - var filesId = new HashSet(); - var foldersId = new HashSet(); + + public IDictionary> GetTags(Guid subject, IEnumerable tagType, IEnumerable> fileEntries) + { + var filesId = new HashSet(); + var foldersId = new HashSet(); foreach (var f in fileEntries) { @@ -150,7 +153,7 @@ namespace ASC.Files.Core.Data .ToDictionary(r => r.Key, r => r.AsEnumerable()); } - return new Dictionary>(); + return new Dictionary>(); } public IEnumerable GetTags(TagType tagType, IEnumerable> fileEntries) @@ -158,193 +161,193 @@ namespace ASC.Files.Core.Data return GetTags(Guid.Empty, tagType, fileEntries); } - - public IEnumerable GetTags(T entryID, FileEntryType entryType, TagType tagType) - { - var q = Query(FilesDbContext.Tag) - .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) - .Where(r => r.Link.TenantId == r.Tag.TenantId) - .Where(r => r.Link.EntryType == entryType) - .Where(r => r.Link.EntryId == MappingID(entryID).ToString()) - .Where(r => r.Tag.Flag == tagType); - - return FromQuery(q); - } - - public IEnumerable GetTags(string[] names, TagType tagType) - { - if (names == null) throw new ArgumentNullException("names"); - - var q = Query(FilesDbContext.Tag) - .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) - .Where(r => r.Link.TenantId == r.Tag.TenantId) - .Where(r => r.Tag.Owner == Guid.Empty) - .Where(r => names.Contains(r.Tag.Name)) - .Where(r => r.Tag.Flag == tagType); - - return FromQuery(q); - } - - public IEnumerable GetTags(string name, TagType tagType) - { - if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name"); - - return GetTags(new[] { name }, tagType); - } - - public IEnumerable GetTags(Guid owner, TagType tagType) - { - var q = - Query(FilesDbContext.Tag) - .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) - .Where(r => r.Link.TenantId == r.Tag.TenantId) - .Where(r => r.Tag.Flag == tagType); - - if (owner != Guid.Empty) - { - q = q.Where(r => r.Tag.Owner == owner); + + public IEnumerable GetTags(T entryID, FileEntryType entryType, TagType tagType) + { + var q = Query(FilesDbContext.Tag) + .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => r.Link.EntryType == entryType) + .Where(r => r.Link.EntryId == MappingID(entryID).ToString()) + .Where(r => r.Tag.Flag == tagType); + + return FromQuery(q); + } + + public IEnumerable GetTags(string[] names, TagType tagType) + { + if (names == null) throw new ArgumentNullException("names"); + + var q = Query(FilesDbContext.Tag) + .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => r.Tag.Owner == Guid.Empty) + .Where(r => names.Contains(r.Tag.Name)) + .Where(r => r.Tag.Flag == tagType); + + return FromQuery(q); + } + + public IEnumerable GetTags(string name, TagType tagType) + { + if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name"); + + return GetTags(new[] { name }, tagType); + } + + public IEnumerable GetTags(Guid owner, TagType tagType) + { + var q = + Query(FilesDbContext.Tag) + .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => r.Tag.Flag == tagType); + + if (owner != Guid.Empty) + { + q = q.Where(r => r.Tag.Owner == owner); } - + q = q.OrderByDescending(r => r.Link.CreateOn); - - return FromQuery(q); - } - - public IEnumerable SaveTags(IEnumerable tags) - { - var result = new List(); - - if (tags == null) return result; - - tags = tags.Where(x => x != null && !x.EntryId.Equals(null) && !x.EntryId.Equals(0)).ToArray(); - - if (!tags.Any()) return result; - - lock (syncRoot) - { - using var tx = FilesDbContext.Database.BeginTransaction(); - DeleteTagsBeforeSave(); - - var createOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()); - var cacheTagId = new Dictionary(); - - result.AddRange(tags.Select(t => SaveTag(t, cacheTagId, createOn))); - - tx.Commit(); - } - - return result; - } - - public IEnumerable SaveTags(Tag tag) - { - var result = new List(); - - if (tag == null) return result; - - if (tag.EntryId.Equals(null) || tag.EntryId.Equals(0)) return result; - - lock (syncRoot) - { - using var tx = FilesDbContext.Database.BeginTransaction(); - DeleteTagsBeforeSave(); - - var createOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()); - var cacheTagId = new Dictionary(); - - result.Add(SaveTag(tag, cacheTagId, createOn)); - - tx.Commit(); - } - - return result; - } - - private void DeleteTagsBeforeSave() - { - var mustBeDeleted = - Query(FilesDbContext.Tag) - .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) - .Where(r => r.Link.TenantId == r.Tag.TenantId) + + return FromQuery(q); + } + + public IEnumerable SaveTags(IEnumerable tags) + { + var result = new List(); + + if (tags == null) return result; + + tags = tags.Where(x => x != null && !x.EntryId.Equals(null) && !x.EntryId.Equals(0)).ToArray(); + + if (!tags.Any()) return result; + + lock (syncRoot) + { + using var tx = FilesDbContext.Database.BeginTransaction(); + DeleteTagsBeforeSave(); + + var createOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()); + var cacheTagId = new Dictionary(); + + result.AddRange(tags.Select(t => SaveTag(t, cacheTagId, createOn))); + + tx.Commit(); + } + + return result; + } + + public IEnumerable SaveTags(Tag tag) + { + var result = new List(); + + if (tag == null) return result; + + if (tag.EntryId.Equals(null) || tag.EntryId.Equals(0)) return result; + + lock (syncRoot) + { + using var tx = FilesDbContext.Database.BeginTransaction(); + DeleteTagsBeforeSave(); + + var createOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()); + var cacheTagId = new Dictionary(); + + result.Add(SaveTag(tag, cacheTagId, createOn)); + + tx.Commit(); + } + + return result; + } + + private void DeleteTagsBeforeSave() + { + var mustBeDeleted = + Query(FilesDbContext.Tag) + .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) .Where(r => (r.Tag.Flag == TagType.New || r.Tag.Flag == TagType.Recent) && r.Link.CreateOn <= TenantUtil.DateTimeNow().AddMonths(-1)) - .ToList(); - - foreach (var row in mustBeDeleted) - { - var linksToRemove = Query(FilesDbContext.TagLink) - .Where(r => r.TagId == row.Link.TagId) - .Where(r => r.EntryId == row.Link.EntryId) + .ToList(); + + foreach (var row in mustBeDeleted) + { + var linksToRemove = Query(FilesDbContext.TagLink) + .Where(r => r.TagId == row.Link.TagId) + .Where(r => r.EntryId == row.Link.EntryId) .Where(r => r.EntryType == row.Link.EntryType) - .ToList(); - FilesDbContext.TagLink.RemoveRange(linksToRemove); - } - - FilesDbContext.SaveChanges(); - - var tagsToRemove = Query(FilesDbContext.Tag) - .Where(r => !Query(FilesDbContext.TagLink).Any(a => a.TagId == r.Id)); - - FilesDbContext.Tag.RemoveRange(tagsToRemove); - FilesDbContext.SaveChanges(); - } - - private Tag SaveTag(Tag t, Dictionary cacheTagId, DateTime createOn) - { - var cacheTagIdKey = string.Join("/", new[] { TenantID.ToString(), t.Owner.ToString(), t.TagName, ((int)t.TagType).ToString(CultureInfo.InvariantCulture) }); - - if (!cacheTagId.TryGetValue(cacheTagIdKey, out var id)) - { - id = FilesDbContext.Tag - .Where(r => r.Owner == t.Owner) - .Where(r => r.Name == t.TagName) - .Where(r => r.Flag == t.TagType) - .Select(r => r.Id) - .FirstOrDefault(); - - if (id == 0) - { - var toAdd = new DbFilesTag - { - Id = 0, - Name = t.TagName, - Owner = t.Owner, - Flag = t.TagType, - TenantId = TenantID - }; - + .ToList(); + FilesDbContext.TagLink.RemoveRange(linksToRemove); + } + + FilesDbContext.SaveChanges(); + + var tagsToRemove = Query(FilesDbContext.Tag) + .Where(r => !Query(FilesDbContext.TagLink).Any(a => a.TagId == r.Id)); + + FilesDbContext.Tag.RemoveRange(tagsToRemove); + FilesDbContext.SaveChanges(); + } + + private Tag SaveTag(Tag t, Dictionary cacheTagId, DateTime createOn) + { + var cacheTagIdKey = string.Join("/", new[] { TenantID.ToString(), t.Owner.ToString(), t.TagName, ((int)t.TagType).ToString(CultureInfo.InvariantCulture) }); + + if (!cacheTagId.TryGetValue(cacheTagIdKey, out var id)) + { + id = FilesDbContext.Tag + .Where(r => r.Owner == t.Owner) + .Where(r => r.Name == t.TagName) + .Where(r => r.Flag == t.TagType) + .Select(r => r.Id) + .FirstOrDefault(); + + if (id == 0) + { + var toAdd = new DbFilesTag + { + Id = 0, + Name = t.TagName, + Owner = t.Owner, + Flag = t.TagType, + TenantId = TenantID + }; + toAdd = FilesDbContext.Tag.Add(toAdd).Entity; - FilesDbContext.SaveChanges(); - id = toAdd.Id; - } - - cacheTagId.Add(cacheTagIdKey, id); - } - - t.Id = id; - - var linkToInsert = new DbFilesTagLink - { - TenantId = TenantID, - TagId = id, - EntryId = MappingID(t.EntryId, true).ToString(), - EntryType = t.EntryType, - CreateBy = AuthContext.CurrentAccount.ID, - CreateOn = createOn, - TagCount = t.Count - }; - - FilesDbContext.AddOrUpdate(r => r.TagLink, linkToInsert); - FilesDbContext.SaveChanges(); - - return t; - } - - public void UpdateNewTags(IEnumerable tags) - { - if (tags == null || !tags.Any()) return; - - lock (syncRoot) - { + FilesDbContext.SaveChanges(); + id = toAdd.Id; + } + + cacheTagId.Add(cacheTagIdKey, id); + } + + t.Id = id; + + var linkToInsert = new DbFilesTagLink + { + TenantId = TenantID, + TagId = id, + EntryId = MappingID(t.EntryId, true).ToString(), + EntryType = t.EntryType, + CreateBy = AuthContext.CurrentAccount.ID, + CreateOn = createOn, + TagCount = t.Count + }; + + FilesDbContext.AddOrUpdate(r => r.TagLink, linkToInsert); + FilesDbContext.SaveChanges(); + + return t; + } + + public void UpdateNewTags(IEnumerable tags) + { + if (tags == null || !tags.Any()) return; + + lock (syncRoot) + { using var tx = FilesDbContext.Database.BeginTransaction(); var createOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()); @@ -352,112 +355,112 @@ namespace ASC.Files.Core.Data { UpdateNewTagsInDb(tag, createOn); } - tx.Commit(); - } - } - - public void UpdateNewTags(Tag tag) - { - if (tag == null) return; - - lock (syncRoot) - { - var createOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()); - - UpdateNewTagsInDb(tag, createOn); - } - } - - private void UpdateNewTagsInDb(Tag tag, DateTime createOn) - { - if (tag == null) return; - - var forUpdate = Query(FilesDbContext.TagLink) - .Where(r => r.TagId == tag.Id) - .Where(r => r.EntryType == tag.EntryType) - .Where(r => r.EntryId == MappingID(tag.EntryId).ToString()); - - foreach (var f in forUpdate) - { - f.CreateBy = AuthContext.CurrentAccount.ID; - f.CreateOn = createOn; - f.TagCount = tag.Count; - } - - FilesDbContext.SaveChanges(); - } - - public void RemoveTags(IEnumerable tags) - { - if (tags == null || !tags.Any()) return; - - lock (syncRoot) - { + tx.Commit(); + } + } + + public void UpdateNewTags(Tag tag) + { + if (tag == null) return; + + lock (syncRoot) + { + var createOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()); + + UpdateNewTagsInDb(tag, createOn); + } + } + + private void UpdateNewTagsInDb(Tag tag, DateTime createOn) + { + if (tag == null) return; + + var forUpdate = Query(FilesDbContext.TagLink) + .Where(r => r.TagId == tag.Id) + .Where(r => r.EntryType == tag.EntryType) + .Where(r => r.EntryId == MappingID(tag.EntryId).ToString()); + + foreach (var f in forUpdate) + { + f.CreateBy = AuthContext.CurrentAccount.ID; + f.CreateOn = createOn; + f.TagCount = tag.Count; + } + + FilesDbContext.SaveChanges(); + } + + public void RemoveTags(IEnumerable tags) + { + if (tags == null || !tags.Any()) return; + + lock (syncRoot) + { using var tx = FilesDbContext.Database.BeginTransaction(); foreach (var t in tags) { RemoveTagInDb(t); } - tx.Commit(); - } - } - - public void RemoveTags(Tag tag) - { - if (tag == null) return; - - lock (syncRoot) - { + tx.Commit(); + } + } + + public void RemoveTags(Tag tag) + { + if (tag == null) return; + + lock (syncRoot) + { using var tx = FilesDbContext.Database.BeginTransaction(); RemoveTagInDb(tag); - tx.Commit(); - } - } - - private void RemoveTagInDb(Tag tag) - { - if (tag == null) return; - - var id = Query(FilesDbContext.Tag) + tx.Commit(); + } + } + + private void RemoveTagInDb(Tag tag) + { + if (tag == null) return; + + var id = Query(FilesDbContext.Tag) .Where(r => r.Name == tag.TagName && r.Owner == tag.Owner && - r.Flag == tag.TagType) - .Select(r => r.Id) - .FirstOrDefault(); - - if (id != 0) + r.Flag == tag.TagType) + .Select(r => r.Id) + .FirstOrDefault(); + + if (id != 0) { - var entryId = MappingID(tag.EntryId).ToString(); - var toDelete = Query(FilesDbContext.TagLink) + var entryId = MappingID(tag.EntryId).ToString(); + var toDelete = Query(FilesDbContext.TagLink) .Where(r => r.TagId == id && r.EntryId == entryId && - r.EntryType == tag.EntryType); - - FilesDbContext.TagLink.RemoveRange(toDelete); - FilesDbContext.SaveChanges(); - - var count = Query(FilesDbContext.TagLink).Count(r => r.TagId == id); - if (count == 0) - { - var tagToDelete = Query(FilesDbContext.Tag).Where(r => r.Id == id); - FilesDbContext.Tag.RemoveRange(tagToDelete); - FilesDbContext.SaveChanges(); - } - } - } - - public IEnumerable GetNewTags(Guid subject, FileEntry fileEntry) - { - return GetNewTags(subject, new List>(1) { fileEntry }); - } - - public IEnumerable GetNewTags(Guid subject, IEnumerable> fileEntries) - { + r.EntryType == tag.EntryType); + + FilesDbContext.TagLink.RemoveRange(toDelete); + FilesDbContext.SaveChanges(); + + var count = Query(FilesDbContext.TagLink).Count(r => r.TagId == id); + if (count == 0) + { + var tagToDelete = Query(FilesDbContext.Tag).Where(r => r.Id == id); + FilesDbContext.Tag.RemoveRange(tagToDelete); + FilesDbContext.SaveChanges(); + } + } + } + + public IEnumerable GetNewTags(Guid subject, FileEntry fileEntry) + { + return GetNewTags(subject, new List>(1) { fileEntry }); + } + + public IEnumerable GetNewTags(Guid subject, IEnumerable> fileEntries) + { var result = new List(); var tags = new List(); - var entryIds = new HashSet(); - var entryTypes = new HashSet(); + var entryIds = new HashSet(); + var entryTypes = new HashSet(); foreach (var r in fileEntries) { @@ -492,259 +495,272 @@ namespace ASC.Files.Core.Data result = FromQuery(sqlQuery); } - - return result; - } - - public IEnumerable GetNewTags(Guid subject, Folder parentFolder, bool deepSearch) - { - if (parentFolder == null || EqualityComparer.Default.Equals(parentFolder.ID, default(T))) - throw new ArgumentException("folderId"); - - var result = new List(); - - var monitorFolderIds = new object[] { parentFolder.ID }.AsEnumerable(); - - var getBaseSqlQuery = new Func>(() => - { - var fnResult = Query(FilesDbContext.Tag) - .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) - .Where(r => r.Link.TenantId == r.Tag.TenantId) - .Where(r => r.Tag.Flag == TagType.New) - .Distinct(); - - if (subject != Guid.Empty) - { - fnResult = fnResult.Where(r => r.Tag.Owner == subject); - } - - return fnResult; - }); - - var tempTags = Enumerable.Empty(); - - if (parentFolder.FolderType == FolderType.SHARE) - { - var shareQuery = - new Func>(() => getBaseSqlQuery().Where( - r => FilesDbContext.Security - .Any(a => a.TenantId == TenantID && a.EntryId == r.Link.EntryId && a.EntryType == r.Link.EntryType))); - - var tmpShareFileTags = - shareQuery() - .Join(FilesDbContext.Files, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, f => f.Id, (tagLink, file) => new { tagLink, file }) - .Where(r => r.file.TenantId == TenantID && r.file.CreateBy != subject && r.tagLink.Link.EntryType == FileEntryType.File) - .Select(r => new - { - r.tagLink, - root = FilesDbContext.Folders - .Join(FilesDbContext.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree }) - .Where(x => x.folder.TenantId == TenantID && x.tree.FolderId == r.file.FolderId) - .OrderByDescending(r => r.tree.Level) - .Select(r => r.folder) - .Take(1) - .FirstOrDefault() - }) - .Where(r => r.root.FolderType == FolderType.USER) - .Select(r => r.tagLink) - .Distinct(); - - tempTags = tempTags.Concat(FromQuery(tmpShareFileTags)); - - - var tmpShareFolderTags = - shareQuery() - .Join(FilesDbContext.Folders, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, f => f.Id, (tagLink, folder) => new { tagLink, folder }) - .Where(r => r.folder.TenantId == TenantID && r.folder.CreateBy != subject && r.tagLink.Link.EntryType == FileEntryType.Folder) - .Select(r => new - { - r.tagLink, - root = FilesDbContext.Folders - .Join(FilesDbContext.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree }) - .Where(x => x.folder.TenantId == TenantID) - .Where(x => x.tree.FolderId == r.folder.ParentId) - .OrderByDescending(r => r.tree.Level) - .Select(r => r.folder) - .Take(1) - .FirstOrDefault() - }) - .Where(r => r.root.FolderType == FolderType.USER) - .Select(r => r.tagLink) - .Distinct(); - - tempTags = tempTags.Concat(FromQuery(tmpShareFolderTags)); - - var tmpShareSboxTags = - shareQuery() - .Join(FilesDbContext.ThirdpartyIdMapping, r => r.Link.EntryId, r => r.HashId, (tagLink, mapping) => new { tagLink, mapping }) - .Where(r => r.mapping.TenantId == r.tagLink.Link.TenantId) - .Join(FilesDbContext.ThirdpartyAccount, r => r.mapping.TenantId, r => r.TenantId, (tagLinkMapping, account) => new { tagLinkMapping.tagLink, tagLinkMapping.mapping, account }) - .Where(r => r.account.UserId != subject && - r.account.FolderType == FolderType.USER && - (r.mapping.Id.StartsWith("sbox-" + r.account.Id) || - r.mapping.Id.StartsWith("box-" + r.account.Id) || - r.mapping.Id.StartsWith("dropbox-" + r.account.Id) || - r.mapping.Id.StartsWith("spoint-" + r.account.Id) || - r.mapping.Id.StartsWith("drive-" + r.account.Id) || - r.mapping.Id.StartsWith("onedrive-" + r.account.Id)) - ) - .Select(r => r.tagLink) - .Distinct(); - - tempTags = tempTags.Concat(FromQuery(tmpShareSboxTags)); - } - else if (parentFolder.FolderType == FolderType.Privacy) + + return result; + } + + static Func, IEnumerable> newTagsForFilesQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject, List where) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => subject == Guid.Empty || r.Owner == subject) + .Where(r => r.Flag == TagType.New) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { - var shareQuery = - new Func>(() => getBaseSqlQuery().Where( - r => FilesDbContext.Security - .Any(a => a.TenantId == TenantID && - a.EntryId == r.Link.EntryId && - a.EntryType == r.Link.EntryType))); + Tag = tag, + Link = link + }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Join(ctx.Files, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, r => r.Id, (tagLink, file) => new { tagLink, file }) + .Where(r => r.file.TenantId == r.tagLink.Link.TenantId) + .Where(r => where.Contains(r.file.FolderId.ToString())) + .Where(r => r.tagLink.Link.EntryType == FileEntryType.File) + .Select(r => r.tagLink) + .Distinct() + ); - var tmpShareFileTags = - shareQuery() - .Join(FilesDbContext.Files, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, f => f.Id, (tagLink, file) => new { tagLink, file }) - .Where(r => r.file.TenantId == TenantID && - r.file.CreateBy != subject && - r.tagLink.Link.EntryType == FileEntryType.File) - .Select(r => new - { - r.tagLink, - root = FilesDbContext.Folders - .Join(FilesDbContext.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree }) - .Where(x => x.folder.TenantId == TenantID && x.tree.FolderId == r.file.FolderId) - .OrderByDescending(r => r.tree.Level) + static Func, IEnumerable> newTagsForFoldersQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject, List monitorFolderIdsStrings) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => subject == Guid.Empty || r.Owner == subject) + .Where(r => r.Flag == TagType.New) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData + { + Tag = tag, + Link = link + }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => monitorFolderIdsStrings.Contains(r.Link.EntryId)) + .Where(r => r.Link.EntryType == FileEntryType.Folder) + ); + + static Func> tmpShareFileTagsQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject, FolderType folderType) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => subject == Guid.Empty || r.Owner == subject) + .Where(r => r.Flag == TagType.New) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData + { + Tag = tag, + Link = link + }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => ctx.Security.Any(a => a.TenantId == tenantId && a.EntryId == r.Link.EntryId && a.EntryType == r.Link.EntryType)) + .Join(ctx.Files, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, f => f.Id, (tagLink, file) => new { tagLink, file }) + .Where(r => r.file.TenantId == tenantId && r.file.CreateBy != subject && r.tagLink.Link.EntryType == FileEntryType.File) + .Select(r => new + { + r.tagLink, + root = ctx.Folders + .Join(ctx.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree }) + .Where(x => x.folder.TenantId == tenantId && x.tree.FolderId == r.file.FolderId) + .OrderByDescending(r => r.tree.Level) + .Select(r => r.folder) + .Take(1) + .FirstOrDefault() + }) + .Where(r => r.root.FolderType == folderType) + .Select(r => r.tagLink) + .Distinct() + ); + + static Func> tmpShareFolderTagsQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject, FolderType folderType) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => subject == Guid.Empty || r.Owner == subject) + .Where(r => r.Flag == TagType.New) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData + { + Tag = tag, + Link = link + }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => ctx.Security.Any(a => a.TenantId == tenantId && a.EntryId == r.Link.EntryId && a.EntryType == r.Link.EntryType)) + .Join(ctx.Folders, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, f => f.Id, (tagLink, folder) => new { tagLink, folder }) + .Where(r => r.folder.TenantId == tenantId && r.folder.CreateBy != subject && r.tagLink.Link.EntryType == FileEntryType.Folder) + .Select(r => new + { + r.tagLink, + root = ctx.Folders + .Join(ctx.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree }) + .Where(x => x.folder.TenantId == tenantId) + .Where(x => x.tree.FolderId == r.folder.ParentId) + .OrderByDescending(r => r.tree.Level) .Select(r => r.folder) - .Take(1) - .FirstOrDefault() - }) - .Where(r => r.root.FolderType == FolderType.Privacy) + .Take(1) + .FirstOrDefault() + }) + .Where(r => r.root.FolderType == folderType) .Select(r => r.tagLink) - .Distinct(); + .Distinct() + ); - tempTags = tempTags.Concat(FromQuery(tmpShareFileTags)); + static Func> tmpShareSboxTagsQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => subject == Guid.Empty || r.Owner == subject) + .Where(r => r.Flag == TagType.New) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData + { + Tag = tag, + Link = link + }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => ctx.Security.Any(a => a.TenantId == tenantId && a.EntryId == r.Link.EntryId && a.EntryType == r.Link.EntryType)) + .Join(ctx.ThirdpartyIdMapping, r => r.Link.EntryId, r => r.HashId, (tagLink, mapping) => new { tagLink, mapping }) + .Where(r => r.mapping.TenantId == r.tagLink.Link.TenantId) + .Join(ctx.ThirdpartyAccount, r => r.mapping.TenantId, r => r.TenantId, (tagLinkMapping, account) => new { tagLinkMapping.tagLink, tagLinkMapping.mapping, account }) + .Where(r => r.account.UserId != subject && + r.account.FolderType == FolderType.USER && + (r.mapping.Id.StartsWith("sbox-" + r.account.Id) || + r.mapping.Id.StartsWith("box-" + r.account.Id) || + r.mapping.Id.StartsWith("dropbox-" + r.account.Id) || + r.mapping.Id.StartsWith("spoint-" + r.account.Id) || + r.mapping.Id.StartsWith("drive-" + r.account.Id) || + r.mapping.Id.StartsWith("onedrive-" + r.account.Id)) + ) + .Select(r => r.tagLink) + .Distinct() + ); - - var tmpShareFolderTags = - shareQuery() - .Join(FilesDbContext.Folders, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, f => f.Id, (tagLink, folder) => new { tagLink, folder }) - .Where(r => r.folder.TenantId == TenantID - && r.folder.CreateBy != subject - && r.tagLink.Link.EntryType == FileEntryType.Folder) - .Select(r => new - { - r.tagLink, - root = FilesDbContext.Folders - .Join(FilesDbContext.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree }) - .Where(x => x.folder.TenantId == TenantID && x.tree.FolderId == r.folder.ParentId) - .OrderByDescending(r => r.tree.Level) - .Select(r => r.folder) - .Take(1) - .FirstOrDefault() - }) - .Where(r => r.root.FolderType == FolderType.Privacy) - .Select(r => r.tagLink) - .Distinct(); - - tempTags = tempTags.Concat(FromQuery(tmpShareFolderTags)); - } - else if (parentFolder.FolderType == FolderType.Projects) - { - var q = getBaseSqlQuery() - .Join(FilesDbContext.BunchObjects, r => r.Link.TenantId, r => r.TenantId, (tagLink, bunch) => new { tagLink, bunch }) + static Func> projectsQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => subject == Guid.Empty || r.Owner == subject) + .Where(r => r.Flag == TagType.New) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData + { + Tag = tag, + Link = link + }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Join(ctx.BunchObjects, r => r.Link.TenantId, r => r.TenantId, (tagLink, bunch) => new { tagLink, bunch }) .Where(r => r.bunch.LeftNode == r.tagLink.Link.EntryId && r.tagLink.Link.EntryType == FileEntryType.Folder && - r.bunch.RightNode.StartsWith("projects/project/")) + r.bunch.RightNode.StartsWith("projects/project/")) .Select(r => r.tagLink) - .Distinct(); - tempTags = tempTags.Concat(FromQuery(q)); - } - - if (tempTags.Any()) - { - if (!deepSearch) return tempTags; - - monitorFolderIds = monitorFolderIds.Concat(tempTags.Where(x => x.EntryType == FileEntryType.Folder).Select(x => x.EntryId)); - result.AddRange(tempTags); - } - - var monitorFolderIdsInt = monitorFolderIds.OfType().ToList(); - var subFoldersSqlQuery = - FilesDbContext.Tree - .Where(r => monitorFolderIdsInt.Contains(r.ParentId)); - - if (!deepSearch) - { - subFoldersSqlQuery = subFoldersSqlQuery.Where(r => r.Level == 1); - } - - monitorFolderIds = monitorFolderIds.Concat(subFoldersSqlQuery.Select(r => r.FolderId).ToList().ConvertAll(r => (object)r)); - - var monitorFolderIdsStrings = monitorFolderIds.Select(r => r.ToString()).ToList(); - - var newTagsForFolders = getBaseSqlQuery() - .Where(r => monitorFolderIdsStrings.Contains(r.Link.EntryId)) - .Where(r => r.Link.EntryType == FileEntryType.Folder); - - result.AddRange(FromQuery(newTagsForFolders)); - - var where = (deepSearch ? monitorFolderIds.ToArray() : new object[] { parentFolder.ID }) - .Select(r => r.ToString()) - .ToList(); - - var newTagsForFiles = - getBaseSqlQuery() - .Join(FilesDbContext.Files, r => Regex.IsMatch(r.Link.EntryId, "^[0-9]+$") ? Convert.ToInt32(r.Link.EntryId) : -1, r => r.Id, (tagLink, file) => new { tagLink, file }) - .Where(r => r.file.TenantId == r.tagLink.Link.TenantId) - .Where(r => where.Contains(r.file.FolderId.ToString())) - .Where(r => r.tagLink.Link.EntryType == FileEntryType.File) - .Select(r => r.tagLink) - .Distinct(); - - result.AddRange(FromQuery(newTagsForFiles)); - - if (parentFolder.FolderType == FolderType.USER || parentFolder.FolderType == FolderType.COMMON) - { - var folderType = parentFolder.FolderType; - - var querySelect = FilesDbContext.ThirdpartyAccount - .Where(r => r.TenantId == TenantID) - .Where(r => r.FolderType == folderType); - - if (folderType == FolderType.USER) - { - querySelect = querySelect.Where(r => r.UserId == subject); - } - - var folderIds = querySelect.Select(r => r.Id).ToList(); - var thirdpartyFolderIds = folderIds.ConvertAll(r => "sbox-" + r) - .Concat(folderIds.ConvertAll(r => $"box-{r}")) - .Concat(folderIds.ConvertAll(r => $"dropbox-{r}")) - .Concat(folderIds.ConvertAll(r => $"spoint-{r}")) - .Concat(folderIds.ConvertAll(r => $"drive-{r}")) - .Concat(folderIds.ConvertAll(r => $"onedrive-{r}")); + .Distinct() + ); - if (thirdpartyFolderIds.Any()) + static Func, IEnumerable> newTagsForSBoxQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject, List thirdpartyFolderIds) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => subject == Guid.Empty || r.Owner == subject) + .Where(r => r.Flag == TagType.New) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { - var newTagsForSBox = getBaseSqlQuery() - .Join(FilesDbContext.ThirdpartyIdMapping, r => r.Link.EntryId, r => r.HashId, (tagLink, mapping) => new { tagLink, mapping }) - .Where(r => r.mapping.TenantId == TenantID && + Tag = tag, + Link = link + }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Join(ctx.ThirdpartyIdMapping, r => r.Link.EntryId, r => r.HashId, (tagLink, mapping) => new { tagLink, mapping }) + .Where(r => r.mapping.TenantId == tenantId && thirdpartyFolderIds.Contains(r.mapping.Id) && r.tagLink.Tag.Owner == subject && r.tagLink.Link.EntryType == FileEntryType.Folder) .Select(r => r.tagLink) - .Distinct(); + .Distinct() + ); - result.AddRange(FromQuery(newTagsForSBox)); - } - } - - return result; - } - - protected List FromQuery(IQueryable dbFilesTags) - { + static Func, bool, IEnumerable> getFolderQuery = Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, List monitorFolderIdsInt, bool deepSearch) => + ctx.Tree + .AsNoTracking() + .Where(r => monitorFolderIdsInt.Contains(r.ParentId)) + .Where(r => deepSearch || r.Level == 1) + .Select(r => r.FolderId)); + + static Func> getThirdpartyAccountQuery = Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, FolderType folderType, Guid subject) => + ctx.ThirdpartyAccount + .Where(r => r.TenantId == tenantId) + .Where(r => r.FolderType == folderType) + .Where(r => folderType != FolderType.USER || r.UserId == subject) + .Select(r => r.Id)); + + public IEnumerable GetNewTags(Guid subject, Folder parentFolder, bool deepSearch) + { + if (parentFolder == null || EqualityComparer.Default.Equals(parentFolder.ID, default(T))) + throw new ArgumentException("folderId"); + + var result = new List(); + + var monitorFolderIds = new object[] { parentFolder.ID }.AsEnumerable(); + + var tenantId = TenantID; + + var tempTags = Enumerable.Empty(); + + if (parentFolder.FolderType == FolderType.SHARE) + { + tempTags = tempTags.Concat(FromQuery(tmpShareFileTagsQuery(FilesDbContext, tenantId, subject, FolderType.USER))); + tempTags = tempTags.Concat(FromQuery(tmpShareFolderTagsQuery(FilesDbContext, tenantId, subject, FolderType.USER))); + tempTags = tempTags.Concat(FromQuery(tmpShareSboxTagsQuery(FilesDbContext, tenantId, subject))); + } + else if (parentFolder.FolderType == FolderType.Privacy) + { + tempTags = tempTags.Concat(FromQuery(tmpShareFileTagsQuery(FilesDbContext, tenantId, subject, FolderType.Privacy))); + tempTags = tempTags.Concat(FromQuery(tmpShareFolderTagsQuery(FilesDbContext, tenantId, subject, FolderType.Privacy))); + } + else if (parentFolder.FolderType == FolderType.Projects) + { + tempTags = tempTags.Concat(FromQuery(projectsQuery(FilesDbContext, tenantId, subject))); + } + + if (tempTags.Any()) + { + if (!deepSearch) return tempTags; + + monitorFolderIds = monitorFolderIds.Concat(tempTags.Where(x => x.EntryType == FileEntryType.Folder).Select(x => x.EntryId)); + result.AddRange(tempTags); + } + + var monitorFolderIdsInt = monitorFolderIds.OfType().ToList(); + var subFoldersSqlQuery = getFolderQuery(FilesDbContext, monitorFolderIdsInt, deepSearch); + + monitorFolderIds = monitorFolderIds.Concat(subFoldersSqlQuery.ToList().ConvertAll(r => (object)r)); + + var monitorFolderIdsStrings = monitorFolderIds.Select(r => r.ToString()).ToList(); + + result.AddRange(FromQuery(newTagsForFoldersQuery(FilesDbContext, tenantId, subject, monitorFolderIdsStrings))); + + var where = deepSearch ? monitorFolderIdsStrings : new List() { parentFolder.ID.ToString() }; + + result.AddRange(FromQuery(newTagsForFilesQuery(FilesDbContext, tenantId, subject, where))); + + if (parentFolder.FolderType == FolderType.USER || parentFolder.FolderType == FolderType.COMMON) + { + var folderIds = getThirdpartyAccountQuery(FilesDbContext, tenantId, parentFolder.FolderType, subject).ToList(); + var thirdpartyFolderIds = folderIds.ConvertAll(r => "sbox-" + r) + .Concat(folderIds.ConvertAll(r => $"box-{r}")) + .Concat(folderIds.ConvertAll(r => $"dropbox-{r}")) + .Concat(folderIds.ConvertAll(r => $"spoint-{r}")) + .Concat(folderIds.ConvertAll(r => $"drive-{r}")) + .Concat(folderIds.ConvertAll(r => $"onedrive-{r}")) + .ToList(); + + if (thirdpartyFolderIds.Any()) + { + result.AddRange(FromQuery(newTagsForSBoxQuery(FilesDbContext, tenantId, subject, thirdpartyFolderIds))); + } + } + + return result; + } + + protected List FromQuery(IQueryable dbFilesTags) + { return dbFilesTags .Select(r => new TagLinkData() { @@ -761,29 +777,53 @@ namespace ASC.Files.Core.Data EntryId = r.Link.EntryId, EntryType = r.Link.EntryType } - }) - .AsEnumerable() + }) + .AsEnumerable() .ToList() - .ConvertAll(ToTag); - } - - private Tag ToTag(TagLinkData r) - { - var result = new Tag(r.Tag.Name, r.Tag.Flag, r.Tag.Owner, r.Link.TagCount) - { - EntryId = MappingID(r.Link.EntryId), - EntryType = r.Link.EntryType, - Id = r.Tag.Id, - }; - - return result; - } - } - - public class TagLinkData - { - public DbFilesTag Tag { get; set; } - - public DbFilesTagLink Link { get; set; } - } + .ConvertAll(ToTag); + } + + protected List FromQuery(IEnumerable dbFilesTags) + { + return dbFilesTags + .Select(r => new TagLinkData() + { + Tag = new DbFilesTag + { + Name = r.Tag.Name, + Flag = r.Tag.Flag, + Owner = r.Tag.Owner, + Id = r.Tag.Id + }, + Link = new DbFilesTagLink + { + TagCount = r.Link.TagCount, + EntryId = r.Link.EntryId, + EntryType = r.Link.EntryType + } + }) + .AsEnumerable() + .ToList() + .ConvertAll(ToTag); + } + + private Tag ToTag(TagLinkData r) + { + var result = new Tag(r.Tag.Name, r.Tag.Flag, r.Tag.Owner, r.Link.TagCount) + { + EntryId = MappingID(r.Link.EntryId), + EntryType = r.Link.EntryType, + Id = r.Tag.Id, + }; + + return result; + } + } + + public class TagLinkData + { + public DbFilesTag Tag { get; set; } + + public DbFilesTagLink Link { get; set; } + } } \ No newline at end of file From 04ccfb2caa47814bf2454ff5e2e4bd01290c52c5 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Tue, 14 Dec 2021 15:51:03 +0300 Subject: [PATCH 07/10] Webhooks: fix empty result --- .../Middleware/WebhooksGlobalFilterAttribute.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/common/ASC.Api.Core/Middleware/WebhooksGlobalFilterAttribute.cs b/common/ASC.Api.Core/Middleware/WebhooksGlobalFilterAttribute.cs index f4ebf99128..6ed151b8fa 100644 --- a/common/ASC.Api.Core/Middleware/WebhooksGlobalFilterAttribute.cs +++ b/common/ASC.Api.Core/Middleware/WebhooksGlobalFilterAttribute.cs @@ -46,13 +46,15 @@ namespace ASC.Api.Core.Middleware base.OnResultExecuted(context); return; } - - var result = (ObjectResult)context.Result; - var resultContent = JsonSerializer.Serialize(result.Value, jsonSerializerOptions); - - var eventName = $"method: {method}, route: {routePattern}"; - - WebhookPublisher.Publish(eventName, resultContent); + + if (context.Result is ObjectResult objectResult) + { + var resultContent = JsonSerializer.Serialize(objectResult.Value, jsonSerializerOptions); + + var eventName = $"method: {method}, route: {routePattern}"; + + WebhookPublisher.Publish(eventName, resultContent); + } base.OnResultExecuted(context); } From fb3bfba1bd90b3956bdb90d3acf31708884028ea Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Thu, 16 Dec 2021 15:49:35 +0300 Subject: [PATCH 08/10] Files: optimization --- .../Security/Cryptography/InstanceCrypto.cs | 31 ++++------ common/ASC.Core.Common/Data/DbQuotaService.cs | 8 +-- common/ASC.FederatedLogin/OAuth20Token.cs | 57 +++++-------------- .../Core/Core/Dao/TeamlabDao/AbstractDao.cs | 10 ++-- .../Core/Core/Dao/TeamlabDao/TagDao.cs | 35 ++++++------ .../Core/Thirdparty/ProviderAccountDao.cs | 41 ++++++------- 6 files changed, 70 insertions(+), 112 deletions(-) diff --git a/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs b/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs index 2d2cf242b6..81328610ba 100644 --- a/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs +++ b/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs @@ -36,11 +36,11 @@ namespace ASC.Security.Cryptography [Singletone] public class InstanceCrypto { - private MachinePseudoKeys MachinePseudoKeys { get; } + private byte[] EKey { get; } public InstanceCrypto(MachinePseudoKeys machinePseudoKeys) { - MachinePseudoKeys = machinePseudoKeys; + EKey = machinePseudoKeys.GetMachineConstant(32); } public string Encrypt(string data) @@ -50,8 +50,8 @@ namespace ASC.Security.Cryptography public byte[] Encrypt(byte[] data) { - var hasher = Aes.Create(); - hasher.Key = EKey(); + using var hasher = Aes.Create(); + hasher.Key = EKey; hasher.IV = new byte[hasher.BlockSize >> 3]; using var ms = new MemoryStream(); @@ -70,24 +70,17 @@ namespace ASC.Security.Cryptography public string Decrypt(byte[] data) { - var hasher = Aes.Create(); - hasher.Key = EKey(); + using var hasher = Aes.Create(); + hasher.Key = EKey; hasher.IV = new byte[hasher.BlockSize >> 3]; - using (MemoryStream msDecrypt = new MemoryStream(data)) - using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, hasher.CreateDecryptor(), CryptoStreamMode.Read)) - using (StreamReader srDecrypt = new StreamReader(csDecrypt)) - { + using var msDecrypt = new MemoryStream(data); + using var csDecrypt = new CryptoStream(msDecrypt, hasher.CreateDecryptor(), CryptoStreamMode.Read); + using var srDecrypt = new StreamReader(csDecrypt); - // Read the decrypted bytes from the decrypting stream - // and place them in a string. - return srDecrypt.ReadToEnd(); - } - } - - private byte[] EKey() - { - return MachinePseudoKeys.GetMachineConstant(32); + // Read the decrypted bytes from the decrypting stream + // and place them in a string. + return srDecrypt.ReadToEnd(); } } } \ No newline at end of file diff --git a/common/ASC.Core.Common/Data/DbQuotaService.cs b/common/ASC.Core.Common/Data/DbQuotaService.cs index ef4b0d2e2f..0c271f2242 100644 --- a/common/ASC.Core.Common/Data/DbQuotaService.cs +++ b/common/ASC.Core.Common/Data/DbQuotaService.cs @@ -62,12 +62,12 @@ namespace ASC.Core.Data [Scope] class DbQuotaService : IQuotaService { - private Expression> FromDbQuotaToTenantQuota { get; set; } - private Expression> FromDbQuotaRowToTenantQuotaRow { get; set; } + private static Expression> FromDbQuotaToTenantQuota { get; set; } + private static Expression> FromDbQuotaRowToTenantQuotaRow { get; set; } internal CoreDbContext CoreDbContext { get => LazyCoreDbContext.Value; } internal Lazy LazyCoreDbContext { get; set; } - public DbQuotaService() + static DbQuotaService() { FromDbQuotaToTenantQuota = r => new TenantQuota() { @@ -91,7 +91,7 @@ namespace ASC.Core.Data }; } - public DbQuotaService(DbContextManager dbContextManager) : this() + public DbQuotaService(DbContextManager dbContextManager) { LazyCoreDbContext = new Lazy(() => dbContextManager.Value); } diff --git a/common/ASC.FederatedLogin/OAuth20Token.cs b/common/ASC.FederatedLogin/OAuth20Token.cs index 293241b6fc..974163b429 100644 --- a/common/ASC.FederatedLogin/OAuth20Token.cs +++ b/common/ASC.FederatedLogin/OAuth20Token.cs @@ -26,30 +26,37 @@ using System; using System.Diagnostics; -using System.Globalization; -using System.Text; - -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; namespace ASC.FederatedLogin { [DebuggerDisplay("{AccessToken} (expired: {IsExpired})")] public class OAuth20Token { + [JsonPropertyName("access_token")] public string AccessToken { get; set; } + [JsonPropertyName("refresh_token")] public string RefreshToken { get; set; } + [JsonPropertyName("expires_in")] + [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)] public long ExpiresIn { get; set; } + [JsonPropertyName("client_id")] public string ClientID { get; set; } + [JsonPropertyName("client_secret")] public string ClientSecret { get; set; } + [JsonPropertyName("redirect_uri")] public string RedirectUri { get; set; } + [JsonPropertyName("timestamp")] public DateTime Timestamp { get; set; } + [JsonIgnore] public string OriginJson { get; set; } public OAuth20Token() @@ -92,55 +99,19 @@ namespace ASC.FederatedLogin public static OAuth20Token FromJson(string json) { if (string.IsNullOrEmpty(json)) return null; - var parser = JObject.Parse(json); - if (parser == null) return null; - - var accessToken = parser.Value("access_token"); - - if (string.IsNullOrEmpty(accessToken)) - return null; - - var token = new OAuth20Token - { - AccessToken = accessToken, - RefreshToken = parser.Value("refresh_token"), - ClientID = parser.Value("client_id"), - ClientSecret = parser.Value("client_secret"), - RedirectUri = parser.Value("redirect_uri"), - OriginJson = json, - }; - - if (long.TryParse(parser.Value("expires_in"), out var expiresIn)) - token.ExpiresIn = expiresIn; - try { - token.Timestamp = - !string.IsNullOrEmpty(parser.Value("timestamp")) - ? parser.Value("timestamp") - : DateTime.UtcNow; + return JsonSerializer.Deserialize(json); } catch (Exception) { - token.Timestamp = DateTime.MinValue; + return null; } - - return token; } public string ToJson() { - var sb = new StringBuilder(); - sb.Append("{"); - sb.AppendFormat(" \"access_token\": \"{0}\"", AccessToken); - sb.AppendFormat(", \"refresh_token\": \"{0}\"", RefreshToken); - sb.AppendFormat(", \"expires_in\": \"{0}\"", ExpiresIn); - sb.AppendFormat(", \"client_id\": \"{0}\"", ClientID); - sb.AppendFormat(", \"client_secret\": \"{0}\"", ClientSecret); - sb.AppendFormat(", \"redirect_uri\": \"{0}\"", RedirectUri); - sb.AppendFormat(", \"timestamp\": \"{0}\"", Timestamp.ToString("o", new CultureInfo("en-US"))); - sb.Append("}"); - return sb.ToString(); + return JsonSerializer.Serialize(this); } public override string ToString() diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/AbstractDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/AbstractDao.cs index 2eb766107a..8232d5e40e 100644 --- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/AbstractDao.cs +++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/AbstractDao.cs @@ -82,7 +82,7 @@ namespace ASC.Files.Core.Data CoreConfiguration coreConfiguration, SettingsManager settingsManager, AuthContext authContext, - IServiceProvider serviceProvider, + IServiceProvider serviceProvider, ICache cache) { this.cache = cache; @@ -128,7 +128,7 @@ namespace ASC.Files.Core.Data .Join(FilesDbContext.Tree, a => a.FolderId, b => b.FolderId, (file, tree) => new { file, tree }) .Where(r => r.file.TenantId == f.TenantId) .Where(r => r.tree.ParentId == f.Id) - .Select(r=> r.file.Id) + .Select(r => r.file.Id) .Distinct() .Count(); @@ -191,7 +191,7 @@ namespace ASC.Files.Core.Data internal static IQueryable BuildSearch(IQueryable query, string text, SearhTypeEnum searhTypeEnum) where T : IDbSearch { - var lowerText = text.ToLower().Trim().Replace("%", "\\%").Replace("_", "\\_"); + var lowerText = GetSearchText(text); return searhTypeEnum switch { @@ -200,7 +200,9 @@ namespace ASC.Files.Core.Data SearhTypeEnum.Any => query.Where(r => r.Title.ToLower().Contains(lowerText)), _ => query, }; - } + } + + internal static string GetSearchText(string text) => (text ?? "").ToLower().Trim().Replace("%", "\\%").Replace("_", "\\_"); internal enum SearhTypeEnum { diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs index 2f139e86fe..11c6380d20 100644 --- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs +++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs @@ -116,6 +116,19 @@ namespace ASC.Files.Core.Data return FromQuery(q); } + static Func, HashSet, HashSet, IEnumerable> getTagsQuery = + Microsoft.EntityFrameworkCore.EF.CompileQuery((EF.FilesDbContext ctx, int tenantId, Guid subject, IEnumerable tagType, HashSet filesId, HashSet foldersId) => + ctx.Tag + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => tagType.Contains(r.Flag)) + .Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) + .Where(r => r.Link.TenantId == r.Tag.TenantId) + .Where(r => r.Link.EntryType == FileEntryType.File && filesId.Contains(r.Link.EntryId) + || r.Link.EntryType == FileEntryType.Folder && foldersId.Contains(r.Link.EntryId)) + .Where(r => subject == Guid.Empty || r.Link.CreateBy == subject) + ); + public IDictionary> GetTags(Guid subject, IEnumerable tagType, IEnumerable> fileEntries) { var filesId = new HashSet(); @@ -136,19 +149,7 @@ namespace ASC.Files.Core.Data if (fileEntries.Any()) { - var q = Query(FilesDbContext.Tag) - .Where(r => tagType.Contains(r.Flag)) - .Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link }) - .Where(r => r.Link.TenantId == r.Tag.TenantId) - .Where(r => r.Link.EntryType == FileEntryType.File && filesId.Contains(r.Link.EntryId) - || r.Link.EntryType == FileEntryType.Folder && foldersId.Contains(r.Link.EntryId)); - - if (subject != Guid.Empty) - { - q = q.Where(r => r.Link.CreateBy == subject); - } - - return FromQuery(q) + return FromQuery(getTagsQuery(FilesDbContext, TenantID, subject, tagType, filesId, foldersId)) .GroupBy(r => r.EntryId) .ToDictionary(r => r.Key, r => r.AsEnumerable()); } @@ -779,8 +780,8 @@ namespace ASC.Files.Core.Data } }) .AsEnumerable() - .ToList() - .ConvertAll(ToTag); + .Select(ToTag) + .ToList(); } protected List FromQuery(IEnumerable dbFilesTags) @@ -803,8 +804,8 @@ namespace ASC.Files.Core.Data } }) .AsEnumerable() - .ToList() - .ConvertAll(ToTag); + .Select(ToTag) + .ToList(); } private Tag ToTag(TagLinkData r) diff --git a/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs b/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs index 91015ab9aa..f1cdd5ba5e 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs @@ -53,6 +53,7 @@ using ASC.Security.Cryptography; using ASC.Web.Files.Classes; using ASC.Web.Files.Helpers; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -136,7 +137,7 @@ namespace ASC.Files.Thirdparty return FilesDbContext.ThirdpartyAccount .Where(r => r.TenantId == TenantID) .Where(r => r.UserId == userId) - .ToList() + .AsEnumerable() .Select(ToProviderInfo) .ToList(); } @@ -145,35 +146,25 @@ namespace ASC.Files.Thirdparty Logger.Error(string.Format("GetProvidersInfoInternal: user = {0}", userId), e); return new List(); } - } + } + + static Func> getProvidersInfoQuery = + EF.CompileQuery((FilesDbContext ctx, int tenantId, int linkId, FolderType folderType, Guid userId, string searchText) => + ctx.ThirdpartyAccount + .AsNoTracking() + .Where(r => r.TenantId == tenantId) + .Where(r => !(folderType == FolderType.USER || folderType == FolderType.DEFAULT && linkId == -1) || r.UserId == userId) + .Where(r => linkId == -1 || r.Id == linkId) + .Where(r => folderType == FolderType.DEFAULT || r.FolderType == folderType) + .Where(r => searchText == "" || r.Title.ToLower().Contains(searchText)) + ); private List GetProvidersInfoInternal(int linkId = -1, FolderType folderType = FolderType.DEFAULT, string searchText = null) { - var querySelect = FilesDbContext.ThirdpartyAccount.Where(r => r.TenantId == TenantID); - - if (folderType == FolderType.USER || folderType == FolderType.DEFAULT && linkId == -1) - { - querySelect = querySelect.Where(r => r.UserId == SecurityContext.CurrentAccount.ID); - } - - if (linkId != -1) - { - querySelect = querySelect.Where(r => r.Id == linkId); - } - - if (folderType != FolderType.DEFAULT) - { - querySelect = querySelect.Where(r => r.FolderType == folderType); - } - - if (!string.IsNullOrEmpty(searchText)) - { - querySelect = BuildSearch(querySelect, searchText, SearhTypeEnum.Any); - } - try { - return querySelect.ToList() + return getProvidersInfoQuery(FilesDbContext, TenantID, linkId, folderType, SecurityContext.CurrentAccount.ID, GetSearchText(searchText)) + .AsEnumerable() .Select(ToProviderInfo) .ToList(); } From 44b227ba98a7e5e392a93a02805eb5aa67ebe204 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Thu, 23 Dec 2021 21:49:02 +0300 Subject: [PATCH 09/10] NLog: maxArchiveDays --- config/nlog.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/nlog.config b/config/nlog.config index 6483b10802..a605f21242 100644 --- a/config/nlog.config +++ b/config/nlog.config @@ -10,7 +10,7 @@ - + From 5e088d3ba8296d2d3a60d551aa9d5db25cf6352b Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Thu, 23 Dec 2021 21:54:42 +0300 Subject: [PATCH 10/10] Jenkins: fix build --- build/Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/Jenkinsfile b/build/Jenkinsfile index 3cb7839b19..056928b739 100644 --- a/build/Jenkinsfile +++ b/build/Jenkinsfile @@ -13,7 +13,7 @@ pipeline { } stage('Backend') { steps { - sh 'dotnet build -c Release ASC.Web.sln' + sh 'dotnet build -c Release ASC.Web.slnf' } } } @@ -28,7 +28,7 @@ pipeline { } stage('Backend') { steps { - bat 'dotnet build -c Release ASC.Web.sln' + bat 'dotnet build -c Release ASC.Web.slnf' } } } @@ -62,7 +62,7 @@ pipeline { } stage('Files') { steps { - sh "git submodule update --progress --init -- products/ASC.Files/Server/DocStore && dotnet build ASC.Web.sln && cd ${env.WORKSPACE}/products/ASC.Files/Tests/ && dotnet test ASC.Files.Tests.csproj -r linux-x64 -l \"console;verbosity=detailed\"" + sh "git submodule update --progress --init -- products/ASC.Files/Server/DocStore && dotnet build ASC.Web.slnf && cd ${env.WORKSPACE}/products/ASC.Files/Tests/ && dotnet test ASC.Files.Tests.csproj -r linux-x64 -l \"console;verbosity=detailed\"" } } } @@ -90,7 +90,7 @@ pipeline { } stage('Files') { steps { - bat "git submodule update --progress --init -- products\\ASC.Files\\Server\\DocStore && dotnet build ASC.Web.sln && cd ${env.WORKSPACE}\\products\\ASC.Files\\Tests\\ && dotnet test ASC.Files.Tests.csproj" + bat "git submodule update --progress --init -- products\\ASC.Files\\Server\\DocStore && dotnet build ASC.Web.slnf && cd ${env.WORKSPACE}\\products\\ASC.Files\\Tests\\ && dotnet test ASC.Files.Tests.csproj" } } }