Merge branch 'feature/open-location' of github.com:ONLYOFFICE/AppServer into feature/open-location
This commit is contained in:
commit
9bdc7cc49d
@ -43,7 +43,7 @@
|
||||
DOCUMENT_SERVER_URL_INTERNAL=http://${DOCUMENT_SERVER_HOST}/
|
||||
|
||||
MYSQL_ROOT_PASSWORD=my-secret-pw
|
||||
MYSQL_DATABASE=${PRODUCT}
|
||||
MYSQL_DATABASE=docspace
|
||||
MYSQL_USER=${PRODUCT}_user
|
||||
MYSQL_PASSWORD=${PRODUCT}_pass
|
||||
MYSQL_HOST=${CONTAINER_PREFIX}mysql-server
|
||||
|
@ -57,13 +57,13 @@ public class LdapNotifyService : BackgroundService
|
||||
{
|
||||
var tId = t.Id;
|
||||
|
||||
var ldapSettings = settingsManager.LoadForTenant<LdapSettings>(tId);
|
||||
var ldapSettings = settingsManager.Load<LdapSettings>(tId);
|
||||
if (!ldapSettings.EnableLdapAuthentication)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var cronSettings = settingsManager.LoadForTenant<LdapCronSettings>(tId);
|
||||
var cronSettings = settingsManager.Load<LdapCronSettings>(tId);
|
||||
if (string.IsNullOrEmpty(cronSettings.Cron))
|
||||
{
|
||||
continue;
|
||||
@ -103,13 +103,13 @@ public class LdapNotifyService : BackgroundService
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var settingsManager = scope.ServiceProvider.GetRequiredService<SettingsManager>();
|
||||
var ldapSettings = settingsManager.LoadForTenant<LdapSettings>(tenant.Id);
|
||||
var ldapSettings = settingsManager.Load<LdapSettings>(tenant.Id);
|
||||
|
||||
if (!ldapSettings.EnableLdapAuthentication)
|
||||
{
|
||||
var cronSettings = settingsManager.LoadForTenant<LdapCronSettings>(tenant.Id);
|
||||
var cronSettings = settingsManager.Load<LdapCronSettings>(tenant.Id);
|
||||
cronSettings.Cron = "";
|
||||
settingsManager.SaveForTenant(cronSettings, tenant.Id);
|
||||
settingsManager.Save(cronSettings, tenant.Id);
|
||||
UnregisterAutoSync(tenant);
|
||||
return;
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ public class LdapUserManager
|
||||
var quotaSettings = _settingsManager.Load<TenantUserQuotaSettings>();
|
||||
if (quotaSettings.EnableUserQuota)
|
||||
{
|
||||
_settingsManager.SaveForUser(new UserQuotaSettings { UserQuota = ldapUserInfo.LdapQouta }, ldapUserInfo.Id);
|
||||
_settingsManager.Save(new UserQuotaSettings { UserQuota = ldapUserInfo.LdapQouta }, ldapUserInfo.Id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -205,7 +205,7 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
|
||||
if (quotaSettings.EnableUserQuota)
|
||||
{
|
||||
result.UsedSpace = Math.Max(0, _quotaService.FindUserQuotaRows(_context.Tenant.Id, userInfo.Id).Where(r => !string.IsNullOrEmpty(r.Tag)).Sum(r => r.Counter));
|
||||
var userQuotaSettings = _settingsManager.LoadForUser<UserQuotaSettings>(userInfo);
|
||||
var userQuotaSettings = _settingsManager.Load<UserQuotaSettings>(userInfo);
|
||||
result.QuotaLimit = userQuotaSettings != null ? userQuotaSettings.UserQuota : quotaSettings.DefaultUserQuota;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Core.Data;
|
||||
namespace ASC.Core.Common.Settings;
|
||||
|
||||
[Singletone]
|
||||
public class DbSettingsManagerCache
|
||||
@ -46,11 +46,11 @@ public class DbSettingsManagerCache
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class DbSettingsManager
|
||||
public class SettingsManager
|
||||
{
|
||||
private readonly TimeSpan _expirationTimeout = TimeSpan.FromMinutes(5);
|
||||
|
||||
private readonly ILogger<DbSettingsManager> _logger;
|
||||
private readonly ILogger<SettingsManager> _logger;
|
||||
private readonly ICache _cache;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly DbSettingsManagerCache _dbSettingsManagerCache;
|
||||
@ -58,10 +58,10 @@ public class DbSettingsManager
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly IDbContextFactory<WebstudioDbContext> _dbContextFactory;
|
||||
|
||||
public DbSettingsManager(
|
||||
public SettingsManager(
|
||||
IServiceProvider serviceProvider,
|
||||
DbSettingsManagerCache dbSettingsManagerCache,
|
||||
ILogger<DbSettingsManager> logger,
|
||||
ILogger<SettingsManager> logger,
|
||||
AuthContext authContext,
|
||||
TenantManager tenantManager,
|
||||
IDbContextFactory<WebstudioDbContext> dbContextFactory)
|
||||
@ -100,96 +100,93 @@ public class DbSettingsManager
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveSettings<T>(T settings, int tenantId) where T : class, ISettings<T>
|
||||
public void ClearCache<T>() where T : class, ISettings<T>
|
||||
{
|
||||
return SaveSettingsFor(settings, tenantId, Guid.Empty);
|
||||
}
|
||||
|
||||
public T LoadSettings<T>(int tenantId) where T : class, ISettings<T>
|
||||
{
|
||||
return LoadSettingsFor<T>(tenantId, Guid.Empty);
|
||||
ClearCache<T>(TenantID);
|
||||
}
|
||||
|
||||
public void ClearCache<T>(int tenantId) where T : class, ISettings<T>
|
||||
{
|
||||
var settings = LoadSettings<T>(tenantId);
|
||||
var settings = Load<T>(tenantId, Guid.Empty);
|
||||
var key = settings.ID.ToString() + tenantId + Guid.Empty;
|
||||
|
||||
_dbSettingsManagerCache.Remove(key);
|
||||
}
|
||||
|
||||
|
||||
public bool SaveSettingsFor<T>(T settings, int tenantId, Guid userId) where T : class, ISettings<T>
|
||||
public T GetDefault<T>() where T : class, ISettings<T>
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(settings);
|
||||
|
||||
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
|
||||
|
||||
try
|
||||
{
|
||||
var key = settings.ID.ToString() + tenantId + userId;
|
||||
var data = Serialize(settings);
|
||||
var def = GetDefault<T>();
|
||||
|
||||
var defaultData = Serialize(def);
|
||||
|
||||
if (data.SequenceEqual(defaultData))
|
||||
{
|
||||
var strategy = webstudioDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tr = webstudioDbContext.Database.BeginTransaction();
|
||||
// remove default settings
|
||||
var s = webstudioDbContext.WebstudioSettings
|
||||
.Where(r => r.Id == settings.ID)
|
||||
.Where(r => r.TenantId == tenantId)
|
||||
.Where(r => r.UserId == userId)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (s != null)
|
||||
{
|
||||
webstudioDbContext.WebstudioSettings.Remove(s);
|
||||
}
|
||||
|
||||
webstudioDbContext.SaveChanges();
|
||||
|
||||
tr.Commit();
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var s = new DbWebstudioSettings
|
||||
{
|
||||
Id = settings.ID,
|
||||
UserId = userId,
|
||||
TenantId = tenantId,
|
||||
Data = data
|
||||
};
|
||||
|
||||
webstudioDbContext.AddOrUpdate(webstudioDbContext.WebstudioSettings, s);
|
||||
|
||||
webstudioDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
_dbSettingsManagerCache.Remove(key);
|
||||
|
||||
_cache.Insert(key, settings, _expirationTimeout);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorSaveSettingsFor(ex);
|
||||
|
||||
return false;
|
||||
}
|
||||
var settingsInstance = ActivatorUtilities.CreateInstance<T>(_serviceProvider);
|
||||
return settingsInstance.GetDefault();
|
||||
}
|
||||
|
||||
internal T LoadSettingsFor<T>(int tenantId, Guid userId) where T : class, ISettings<T>
|
||||
public T Load<T>() where T : class, ISettings<T>
|
||||
{
|
||||
return Load<T>(TenantID, Guid.Empty);
|
||||
}
|
||||
|
||||
public T Load<T>(Guid userId) where T : class, ISettings<T>
|
||||
{
|
||||
return Load<T>(TenantID, userId);
|
||||
}
|
||||
|
||||
public T Load<T>(UserInfo user) where T : class, ISettings<T>
|
||||
{
|
||||
return Load<T>(TenantID, user.Id);
|
||||
}
|
||||
|
||||
public T Load<T>(int tenantId) where T : class, ISettings<T>
|
||||
{
|
||||
return Load<T>(tenantId, Guid.Empty);
|
||||
}
|
||||
|
||||
public T LoadForDefaultTenant<T>() where T : class, ISettings<T>
|
||||
{
|
||||
return Load<T>(Tenant.DefaultTenant);
|
||||
}
|
||||
|
||||
public T LoadForCurrentUser<T>() where T : class, ISettings<T>
|
||||
{
|
||||
return Load<T>(CurrentUserID);
|
||||
}
|
||||
|
||||
public bool Save<T>(T data) where T : class, ISettings<T>
|
||||
{
|
||||
return Save(data, TenantID, Guid.Empty);
|
||||
}
|
||||
|
||||
public bool Save<T>(T data, Guid userId) where T : class, ISettings<T>
|
||||
{
|
||||
return Save(data, TenantID, userId);
|
||||
}
|
||||
|
||||
public bool Save<T>(T data, UserInfo user) where T : class, ISettings<T>
|
||||
{
|
||||
return Save(data, TenantID, user.Id);
|
||||
}
|
||||
|
||||
public bool Save<T>(T data, int tenantId) where T : class, ISettings<T>
|
||||
{
|
||||
return Save(data, tenantId, Guid.Empty);
|
||||
}
|
||||
|
||||
public bool SaveForDefaultTenant<T>(T data) where T : class, ISettings<T>
|
||||
{
|
||||
return Save(data, Tenant.DefaultTenant);
|
||||
}
|
||||
|
||||
public bool SaveForCurrentUser<T>(T data) where T : class, ISettings<T>
|
||||
{
|
||||
return Save(data, CurrentUserID);
|
||||
}
|
||||
|
||||
public bool Manage<T>(Action<T> action) where T : class, ISettings<T>
|
||||
{
|
||||
var settings = Load<T>();
|
||||
action(settings);
|
||||
return Save(settings);
|
||||
}
|
||||
|
||||
internal T Load<T>(int tenantId, Guid userId) where T : class, ISettings<T>
|
||||
{
|
||||
var def = GetDefault<T>();
|
||||
var key = def.ID.ToString() + tenantId + userId;
|
||||
@ -231,75 +228,71 @@ public class DbSettingsManager
|
||||
return def;
|
||||
}
|
||||
|
||||
public T GetDefault<T>() where T : class, ISettings<T>
|
||||
private bool Save<T>(T settings, int tenantId, Guid userId) where T : class, ISettings<T>
|
||||
{
|
||||
var settingsInstance = ActivatorUtilities.CreateInstance<T>(_serviceProvider);
|
||||
return settingsInstance.GetDefault();
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(settings);
|
||||
|
||||
public T Load<T>() where T : class, ISettings<T>
|
||||
{
|
||||
return LoadSettings<T>(TenantID);
|
||||
}
|
||||
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
|
||||
|
||||
public T LoadForCurrentUser<T>() where T : class, ISettings<T>
|
||||
{
|
||||
return LoadForUser<T>(CurrentUserID);
|
||||
}
|
||||
try
|
||||
{
|
||||
var key = settings.ID.ToString() + tenantId + userId;
|
||||
var data = Serialize(settings);
|
||||
var def = GetDefault<T>();
|
||||
|
||||
public T LoadForUser<T>(Guid userId) where T : class, ISettings<T>
|
||||
{
|
||||
return LoadSettingsFor<T>(TenantID, userId);
|
||||
}
|
||||
var defaultData = Serialize(def);
|
||||
|
||||
public T LoadForUser<T>(UserInfo user) where T : class, ISettings<T>
|
||||
{
|
||||
return LoadSettingsFor<T>(TenantID, user.Id);
|
||||
}
|
||||
if (data.SequenceEqual(defaultData))
|
||||
{
|
||||
var strategy = webstudioDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
public T LoadForDefaultTenant<T>() where T : class, ISettings<T>
|
||||
{
|
||||
return LoadForTenant<T>(Tenant.DefaultTenant);
|
||||
}
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tr = webstudioDbContext.Database.BeginTransaction();
|
||||
// remove default settings
|
||||
var s = webstudioDbContext.WebstudioSettings
|
||||
.Where(r => r.Id == settings.ID)
|
||||
.Where(r => r.TenantId == tenantId)
|
||||
.Where(r => r.UserId == userId)
|
||||
.FirstOrDefault();
|
||||
|
||||
public T LoadForTenant<T>(int tenantId) where T : class, ISettings<T>
|
||||
{
|
||||
return LoadSettings<T>(tenantId);
|
||||
}
|
||||
if (s != null)
|
||||
{
|
||||
webstudioDbContext.WebstudioSettings.Remove(s);
|
||||
}
|
||||
|
||||
public virtual bool Save<T>(T data) where T : class, ISettings<T>
|
||||
{
|
||||
return SaveSettings(data, TenantID);
|
||||
}
|
||||
webstudioDbContext.SaveChanges();
|
||||
|
||||
public bool SaveForCurrentUser<T>(T data) where T : class, ISettings<T>
|
||||
{
|
||||
return SaveForUser(data, CurrentUserID);
|
||||
}
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var s = new DbWebstudioSettings
|
||||
{
|
||||
Id = settings.ID,
|
||||
UserId = userId,
|
||||
TenantId = tenantId,
|
||||
Data = data
|
||||
};
|
||||
|
||||
public bool SaveForUser<T>(T data, Guid userId) where T : class, ISettings<T>
|
||||
{
|
||||
return SaveSettingsFor(data, TenantID, userId);
|
||||
}
|
||||
webstudioDbContext.AddOrUpdate(webstudioDbContext.WebstudioSettings, s);
|
||||
|
||||
public bool SaveForUser<T>(T data, UserInfo user) where T : class, ISettings<T>
|
||||
{
|
||||
return SaveSettingsFor(data, TenantID, user.Id);
|
||||
}
|
||||
webstudioDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public bool SaveForDefaultTenant<T>(T data) where T : class, ISettings<T>
|
||||
{
|
||||
return SaveForTenant(data, Tenant.DefaultTenant);
|
||||
}
|
||||
_dbSettingsManagerCache.Remove(key);
|
||||
|
||||
public bool SaveForTenant<T>(T data, int tenantId) where T : class, ISettings<T>
|
||||
{
|
||||
return SaveSettings(data, tenantId);
|
||||
}
|
||||
_cache.Insert(key, settings, _expirationTimeout);
|
||||
|
||||
public void ClearCache<T>() where T : class, ISettings<T>
|
||||
{
|
||||
ClearCache<T>(TenantID);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorSaveSettingsFor(ex);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private T Deserialize<T>(string data)
|
||||
|
@ -39,7 +39,7 @@ public class HostedSolution
|
||||
internal UserFormatter UserFormatter { get; set; }
|
||||
internal TenantManager ClientTenantManager { get; set; }
|
||||
internal TenantUtil TenantUtil { get; set; }
|
||||
internal DbSettingsManager SettingsManager { get; set; }
|
||||
internal SettingsManager SettingsManager { get; set; }
|
||||
internal CoreSettings CoreSettings { get; set; }
|
||||
|
||||
public string Region { get; private set; }
|
||||
@ -51,7 +51,7 @@ public class HostedSolution
|
||||
UserFormatter userFormatter,
|
||||
TenantManager clientTenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbSettingsManager settingsManager,
|
||||
SettingsManager settingsManager,
|
||||
CoreSettings coreSettings)
|
||||
{
|
||||
TenantService = tenantService;
|
||||
@ -196,9 +196,9 @@ public class HostedSolution
|
||||
return null;
|
||||
}
|
||||
|
||||
var tenantSettings = SettingsManager.LoadSettingsFor<TenantCookieSettings>(tenantId, Guid.Empty);
|
||||
var tenantSettings = SettingsManager.Load<TenantCookieSettings>(tenantId, Guid.Empty);
|
||||
var expires = tenantSettings.IsDefault() ? DateTime.UtcNow.AddYears(1) : DateTime.UtcNow.AddMinutes(tenantSettings.LifeTime);
|
||||
var userSettings = SettingsManager.LoadSettingsFor<TenantCookieSettings>(tenantId, user.Id);
|
||||
var userSettings = SettingsManager.Load<TenantCookieSettings>(tenantId, user.Id);
|
||||
|
||||
return cookieStorage.EncryptCookie(tenantId, user.Id, tenantSettings.Index, expires, userSettings.Index, 0);
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ namespace ASC.Core.Common.Log;
|
||||
internal static partial class DbSettingsManagerLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "SaveSettingsFor")]
|
||||
public static partial void ErrorSaveSettingsFor(this ILogger<DbSettingsManager> logger, Exception exception);
|
||||
public static partial void ErrorSaveSettingsFor(this ILogger<SettingsManager> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "LoadSettingsFor")]
|
||||
public static partial void ErrorLoadSettingsFor(this ILogger<DbSettingsManager> logger, Exception exception);
|
||||
public static partial void ErrorLoadSettingsFor(this ILogger<SettingsManager> logger, Exception exception);
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Core.Common.Settings;
|
||||
|
||||
[Scope]
|
||||
public class SettingsManager : DbSettingsManager
|
||||
{
|
||||
public SettingsManager(
|
||||
IServiceProvider serviceProvider,
|
||||
DbSettingsManagerCache dbSettingsManagerCache,
|
||||
ILogger<DbSettingsManager> option,
|
||||
AuthContext authContext,
|
||||
TenantManager tenantManager,
|
||||
IDbContextFactory<WebstudioDbContext> dbContextManager)
|
||||
: base(serviceProvider, dbSettingsManagerCache, option, authContext, tenantManager, dbContextManager)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -72,7 +72,7 @@ public class TenantCookieSettingsHelper
|
||||
public TenantCookieSettings GetForTenant(int tenantId)
|
||||
{
|
||||
return IsVisibleSettings
|
||||
? _settingsManager.LoadForTenant<TenantCookieSettings>(tenantId)
|
||||
? _settingsManager.Load<TenantCookieSettings>(tenantId)
|
||||
: TenantCookieSettings.GetInstance();
|
||||
}
|
||||
|
||||
@ -83,20 +83,20 @@ public class TenantCookieSettingsHelper
|
||||
return;
|
||||
}
|
||||
|
||||
_settingsManager.SaveForTenant(settings ?? TenantCookieSettings.GetInstance(), tenantId);
|
||||
_settingsManager.Save(settings ?? TenantCookieSettings.GetInstance(), tenantId);
|
||||
}
|
||||
|
||||
public TenantCookieSettings GetForUser(Guid userId)
|
||||
{
|
||||
return IsVisibleSettings
|
||||
? _settingsManager.LoadForUser<TenantCookieSettings>(userId)
|
||||
? _settingsManager.Load<TenantCookieSettings>(userId)
|
||||
: TenantCookieSettings.GetInstance();
|
||||
}
|
||||
|
||||
public TenantCookieSettings GetForUser(int tenantId, Guid userId)
|
||||
{
|
||||
return IsVisibleSettings
|
||||
? _settingsManager.LoadSettingsFor<TenantCookieSettings>(tenantId, userId)
|
||||
? _settingsManager.Load<TenantCookieSettings>(tenantId, userId)
|
||||
: TenantCookieSettings.GetInstance();
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ public class TenantCookieSettingsHelper
|
||||
return;
|
||||
}
|
||||
|
||||
_settingsManager.SaveForUser(settings ?? TenantCookieSettings.GetInstance(), userId);
|
||||
_settingsManager.Save(settings ?? TenantCookieSettings.GetInstance(), userId);
|
||||
}
|
||||
|
||||
public DateTime GetExpiresTime(int tenantId)
|
||||
|
@ -63,13 +63,13 @@ public class BaseStorageSettingsListener
|
||||
|
||||
var scopeClass = scope.ServiceProvider.GetService<BaseStorageSettingsListenerScope>();
|
||||
var (storageSettingsHelper, settingsManager) = scopeClass;
|
||||
var settings = settingsManager.LoadForTenant<StorageSettings>(i.TenantId);
|
||||
var settings = settingsManager.Load<StorageSettings>(i.TenantId);
|
||||
if (i.Name == settings.Module)
|
||||
{
|
||||
storageSettingsHelper.Clear(settings);
|
||||
}
|
||||
|
||||
var cdnSettings = settingsManager.LoadForTenant<CdnStorageSettings>(i.TenantId);
|
||||
var cdnSettings = settingsManager.Load<CdnStorageSettings>(i.TenantId);
|
||||
if (i.Name == cdnSettings.Module)
|
||||
{
|
||||
storageSettingsHelper.Clear(cdnSettings);
|
||||
|
@ -56,6 +56,7 @@ public class S3Storage : BaseStorage
|
||||
|
||||
private EncryptionMethod _encryptionMethod = EncryptionMethod.None;
|
||||
private string _encryptionKey;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public S3Storage(
|
||||
TempStream tempStream,
|
||||
@ -65,9 +66,11 @@ public class S3Storage : BaseStorage
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILoggerProvider factory,
|
||||
ILogger<S3Storage> options,
|
||||
IHttpClientFactory clientFactory)
|
||||
IHttpClientFactory clientFactory,
|
||||
IConfiguration configuration)
|
||||
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, factory, options, clientFactory)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public Uri GetUriInternal(string path)
|
||||
@ -1225,7 +1228,7 @@ public class S3Storage : BaseStorage
|
||||
|
||||
var uploadId = initResponse.UploadId;
|
||||
|
||||
var partSize = 5 * (long)Math.Pow(2, 20); // Part size is 5 MB.
|
||||
var partSize = GetChunkSize();
|
||||
|
||||
long bytePosition = 0;
|
||||
for (var i = 1; bytePosition < objectSize; i++)
|
||||
@ -1463,7 +1466,19 @@ public class S3Storage : BaseStorage
|
||||
|
||||
return el.ETag;
|
||||
}
|
||||
|
||||
|
||||
private long GetChunkSize()
|
||||
{
|
||||
var configSetting = _configuration["files:uploader:chunk-size"];
|
||||
if (!string.IsNullOrEmpty(configSetting))
|
||||
{
|
||||
configSetting = configSetting.Trim();
|
||||
return long.Parse(configSetting);
|
||||
}
|
||||
long defaultValue = 10 * 1024 * 1024;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private enum EncryptionMethod
|
||||
{
|
||||
None,
|
||||
|
@ -155,7 +155,7 @@ public class StorageFactory
|
||||
throw new InvalidOperationException("config section not found");
|
||||
}
|
||||
|
||||
var settings = _settingsManager.LoadForTenant<StorageSettings>(tenant.Value);
|
||||
var settings = _settingsManager.Load<StorageSettings>(tenant.Value);
|
||||
//TODO:GetStoreAndCache
|
||||
return GetDataStore(tenantPath, module, _storageSettingsHelper.DataStoreConsumer(settings), controller, region);
|
||||
}
|
||||
|
@ -5,19 +5,19 @@
|
||||
{
|
||||
"Provider": "MySql",
|
||||
"ProviderFullName": "MySql.Data.MySqlClient",
|
||||
"ConnectionString": "Server=localhost;Database=onlyoffice;User ID=root;Password=root"
|
||||
"ConnectionString": "Server=localhost;Database=docspace;User ID=root;Password=root"
|
||||
},
|
||||
{
|
||||
"Provider": "PostgreSql",
|
||||
"ProviderFullName": "Npgsql",
|
||||
"ConnectionString": "Host=localhost;Port=5432;Database=onlyoffice;Username=postgres;Password=dev;"
|
||||
"ConnectionString": "Host=localhost;Port=5432;Database=docspace;Username=postgres;Password=dev;"
|
||||
}
|
||||
],
|
||||
"TeamlabsiteProviders": [
|
||||
{
|
||||
"Provider": "MySql",
|
||||
"ProviderFullName": "MySql.Data.MySqlClient",
|
||||
"ConnectionString": "Server=localhost;Database=teamlabsite;User ID=root;Password=root"
|
||||
"ConnectionString": "Server=localhost;Database=docspacesite;User ID=root;Password=root"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
{
|
||||
"Provider": "MySql",
|
||||
"ProviderFullName": "MySql.Data.MySqlClient",
|
||||
"ConnectionString": "Server=localhost;Database=onlyoffice;User ID=root;Password=root"
|
||||
"ConnectionString": "Server=localhost;Database=docspace;User ID=root;Password=root"
|
||||
}
|
||||
],
|
||||
"TeamlabsiteProviders": [
|
||||
|
@ -158,7 +158,7 @@ public class SearchSettingsHelper
|
||||
return true;
|
||||
}
|
||||
|
||||
var settings = _settingsManager.LoadForTenant<SearchSettings>(tenantId);
|
||||
var settings = _settingsManager.Load<SearchSettings>(tenantId);
|
||||
|
||||
return settings.IsEnabled(((ISearchItemDocument)_serviceProvider.GetService(t)).IndexName);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=onlyoffice-mysql-server;Port=3306;Database=onlyoffice;User ID=onlyoffice_user;Password=onlyoffice_pass;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;ConnectionReset=false",
|
||||
"connectionString": "Server=onlyoffice-mysql-server;Port=3306;Database=docspace;User ID=onlyoffice_user;Password=onlyoffice_pass;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
|
@ -39,7 +39,7 @@
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;ConnectionReset=false",
|
||||
"connectionString": "Server=localhost;Database=docspace;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
|
@ -79,8 +79,8 @@
|
||||
"reviewed-docs": [ ".docx", ".docxf" ],
|
||||
"viewed-docs": [ ".pptx", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".gslides", ".xlsx", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".gsheet", ".csv", ".docx", ".docxf", ".oform", ".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".gdoc", ".txt", ".rtf", ".mht", ".html", ".htm", ".epub", ".pdf", ".djvu", ".xps" ],
|
||||
"secret": {
|
||||
"value": "",
|
||||
"header": ""
|
||||
"value": "secret",
|
||||
"header": "AuthorizationJwt"
|
||||
},
|
||||
"url": {
|
||||
"public": "http://localhost:8085/",
|
||||
@ -93,7 +93,7 @@
|
||||
"exts": [ "avi", "mpeg", "mpg", "wmv" ]
|
||||
},
|
||||
"uploader": {
|
||||
"chunk-size": 10485760,
|
||||
"chunk-size": 20971520,
|
||||
"url": "/"
|
||||
},
|
||||
"viewed-images": [ ".svg", ".bmp", ".gif", ".jpeg", ".jpg", ".png", ".ico", ".tif", ".tiff", ".webp" ],
|
||||
@ -128,22 +128,22 @@
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"connectionString": "Server=localhost;Database=docspace;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
},
|
||||
"postgre": {
|
||||
"name": "postgre",
|
||||
"connectionString": "Host=localhost;Port=5432;Database=onlyoffice;Username=postgres;Password=dev;",
|
||||
"connectionString": "Host=localhost;Port=5432;Database=docspace;Username=postgres;Password=dev;",
|
||||
"providerName": "Npgsql"
|
||||
},
|
||||
"mysql": {
|
||||
"name": "mysql",
|
||||
"connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"connectionString": "Server=localhost;Database=docspace;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
},
|
||||
"teamlabsite": {
|
||||
"name": "teamlabsite",
|
||||
"connectionString": "Server=localhost;Database=teamlabsite;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"name": "docspacesite",
|
||||
"connectionString": "Server=localhost;Database=docspacesite;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
|
@ -9,7 +9,7 @@
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=172.18.0.2;Port=3306;Database=onlyoffice;User ID=onlyoffice_user;Password=onlyoffice_pass;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;ConnectionReset=false",
|
||||
"connectionString": "Server=172.18.0.2;Port=3306;Database=docspace;User ID=onlyoffice_user;Password=onlyoffice_pass;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
|
@ -1,10 +1,14 @@
|
||||
{
|
||||
"EmailErrorMessage": "Email address not valid. You can edit the email by clicking on it.",
|
||||
"IndividualInvitation": "Individual invitation",
|
||||
"InviteAccountSearchPlaceholder": "Invite people by email",
|
||||
"InviteRoomSearchPlaceholder": "Invite people by name or email",
|
||||
"InviteUsersToRoom": "Invite users to room",
|
||||
"Invited": "Invited",
|
||||
"LinkCopySuccess": "Link has been copied",
|
||||
"SendInvitation": "Send invitation"
|
||||
"SendInvitation": "Send invitation",
|
||||
"InviteViaLink": "Invite via link",
|
||||
"InviteViaLinkDescriptionRoom": "Create a universal link for self-authorization in the room",
|
||||
"InviteViaLinkDescriptionAccounts": "Create a universal link for self-authorization in DocSpace",
|
||||
"AddManually": "Add manually",
|
||||
"AddManuallyDescriptionRoom": "Add existing DocSpace users to the room using the names or invite new users personally via email",
|
||||
"AddManuallyDescriptionAccounts": "Invite new users to DocSpace personally via email"
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
{
|
||||
"EmailErrorMessage": "Адрес электронной почты недействителен. Вы можете отредактировать адрес, нажав на него.",
|
||||
"IndividualInvitation": "Индивидуальное приглашение",
|
||||
"InviteAccountSearchPlaceholder": "Пригласить людей по электронной почте",
|
||||
"InviteRoomSearchPlaceholder": "Приглашайте людей по имени или электронной почте",
|
||||
"InviteUsersToRoom": "Пригласить пользователей в комнату",
|
||||
"Invited": "Приглашен",
|
||||
"LinkCopySuccess": "Ссылка скопирована",
|
||||
"SendInvitation": "Выслать приглашение"
|
||||
"SendInvitation": "Выслать приглашение",
|
||||
"InviteViaLink": "Пригласить по ссылке",
|
||||
"InviteViaLinkDescriptionRoom": "Создать универсальную ссылку для самостоятельной авторизации в комнате",
|
||||
"InviteViaLinkDescriptionAccounts": "Создать универсальную ссылку для самостоятельной авторизации в DocSpace",
|
||||
"AddManually": "Добавить вручную",
|
||||
"AddManuallyDescriptionRoom": "Добавьте существующих пользователей DocSpace в комнату используя имена или лично пригласите новых пользователей по электронной почте",
|
||||
"AddManuallyDescriptionAccounts": "Приглашайте новых пользователей в DocSpace лично по электронной почте"
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ const StyledSubHeader = styled(Heading)`
|
||||
font-size: 16px;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
margin: 16px 0;
|
||||
margin: 16px 0 8px 0;
|
||||
|
||||
${(props) =>
|
||||
props.inline &&
|
||||
@ -60,6 +60,20 @@ const StyledSubHeader = styled(Heading)`
|
||||
`};
|
||||
`;
|
||||
|
||||
const StyledDescription = styled(Text)`
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
color: ${(props) =>
|
||||
props.theme.createEditRoomDialog.commonParam.descriptionColor};
|
||||
margin-bottom: 16px;
|
||||
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
`;
|
||||
|
||||
StyledDescription.defaultProps = { theme: Base };
|
||||
|
||||
const StyledRow = styled.div`
|
||||
width: calc(100% - 32px) !important;
|
||||
|
||||
@ -252,4 +266,5 @@ export {
|
||||
StyledAccessSelector,
|
||||
StyledToggleButton,
|
||||
StyledText,
|
||||
StyledDescription,
|
||||
};
|
||||
|
@ -199,9 +199,7 @@ const InvitePanel = ({
|
||||
zIndex={310}
|
||||
>
|
||||
<StyledBlock>
|
||||
<StyledHeading>
|
||||
{roomId === -1 ? t("Common:InviteUsers") : t("InviteUsersToRoom")}
|
||||
</StyledHeading>
|
||||
<StyledHeading>{t("Common:InviteUsers")}</StyledHeading>
|
||||
</StyledBlock>
|
||||
|
||||
<ExternalLinks
|
||||
|
@ -20,6 +20,7 @@ import {
|
||||
StyledInviteInput,
|
||||
StyledInviteInputContainer,
|
||||
StyledToggleButton,
|
||||
StyledDescription,
|
||||
} from "../StyledInvitePanel";
|
||||
|
||||
const ExternalLinks = ({
|
||||
@ -156,7 +157,7 @@ const ExternalLinks = ({
|
||||
return (
|
||||
<StyledBlock noPadding ref={inputsRef}>
|
||||
<StyledSubHeader inline>
|
||||
{t("SharingPanel:ExternalLink")}
|
||||
{t("InviteViaLink")}
|
||||
{false && ( //TODO: Change to linksVisible after added link information from backend
|
||||
<div style={{ position: "relative" }}>
|
||||
<IconButton
|
||||
@ -186,6 +187,11 @@ const ExternalLinks = ({
|
||||
)}
|
||||
<StyledToggleButton isChecked={linksVisible} onChange={toggleLinks} />
|
||||
</StyledSubHeader>
|
||||
<StyledDescription>
|
||||
{roomId === -1
|
||||
? t("InviteViaLinkDescriptionAccounts")
|
||||
: t("InviteViaLinkDescriptionRoom")}
|
||||
</StyledDescription>
|
||||
{linksVisible && (
|
||||
<StyledInviteInputContainer key={activeLink.id}>
|
||||
<StyledInviteInput>
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
StyledInviteInputContainer,
|
||||
StyledDropDown,
|
||||
SearchItemText,
|
||||
StyledDescription,
|
||||
} from "../StyledInvitePanel";
|
||||
|
||||
const InviteInput = ({
|
||||
@ -223,7 +224,7 @@ const InviteInput = ({
|
||||
return (
|
||||
<>
|
||||
<StyledSubHeader>
|
||||
{t("IndividualInvitation")}
|
||||
{t("AddManually")}
|
||||
{!hideSelector && (
|
||||
<StyledLink
|
||||
fontWeight="600"
|
||||
@ -235,6 +236,11 @@ const InviteInput = ({
|
||||
</StyledLink>
|
||||
)}
|
||||
</StyledSubHeader>
|
||||
<StyledDescription>
|
||||
{roomId === -1
|
||||
? t("AddManuallyDescriptionAccounts")
|
||||
: t("AddManuallyDescriptionRoom")}
|
||||
</StyledDescription>
|
||||
|
||||
<StyledInviteInputContainer ref={inputsRef}>
|
||||
<StyledInviteInput ref={searchRef}>
|
||||
|
@ -18,8 +18,13 @@ const StyledNoItemContainer = styled.div`
|
||||
}
|
||||
|
||||
.no-thumbnail-img-wrapper {
|
||||
width: 96px;
|
||||
height: 100px;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
|
||||
img {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
}
|
||||
}
|
||||
|
||||
.no-accounts {
|
||||
|
@ -7,6 +7,11 @@ const StyledSeveralItemsContainer = styled.div`
|
||||
justify-content: center;
|
||||
gap: 32px;
|
||||
padding-top: ${(props) => (props.isAccounts ? "80px" : "0")};
|
||||
|
||||
img {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledSeveralItemsContainer };
|
||||
|
@ -31,7 +31,7 @@ const SeveralItems = ({ isAccounts, theme, selectedItems }) => {
|
||||
isAccounts={isAccounts}
|
||||
className="no-thumbnail-img-wrapper"
|
||||
>
|
||||
<img size="96px" src={imgSrc} />
|
||||
<img src={imgSrc} />
|
||||
<Text fontSize="16px" fontWeight={700}>
|
||||
{`${itemsText}: ${selectedItems.length}`}
|
||||
</Text>
|
||||
|
@ -179,12 +179,11 @@ class FilesStore {
|
||||
|
||||
const fileInfo = await api.files.getFileInfo(file.id);
|
||||
|
||||
if (this.files.findIndex((x) => x.id === opt?.id) > -1) return;
|
||||
console.log("[WS] create new file", fileInfo.id, fileInfo.title);
|
||||
|
||||
const newFiles = [fileInfo, ...this.files];
|
||||
|
||||
if (this.files.findIndex((x) => x.id === opt?.id) > -1) return;
|
||||
|
||||
if (newFiles.length > this.filter.pageCount && withPaging) {
|
||||
newFiles.pop(); // Remove last
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ import {
|
||||
isMobile as isMobileUtils,
|
||||
isTablet as isTabletUtils,
|
||||
} from "@docspace/components/utils/device";
|
||||
|
||||
const UPLOAD_LIMIT_AT_ONCE = 5;
|
||||
|
||||
class UploadDataStore {
|
||||
authStore;
|
||||
treeFoldersStore;
|
||||
@ -45,6 +48,7 @@ class UploadDataStore {
|
||||
converted = true;
|
||||
uploadPanelVisible = false;
|
||||
selectedUploadFile = [];
|
||||
tempFiles = [];
|
||||
errors = 0;
|
||||
|
||||
isUploading = false;
|
||||
@ -52,6 +56,11 @@ class UploadDataStore {
|
||||
|
||||
isConvertSingleFile = false;
|
||||
|
||||
currentUploadNumber = 0;
|
||||
uploadedFilesSize = 0;
|
||||
|
||||
isParallel = true;
|
||||
|
||||
constructor(
|
||||
authStore,
|
||||
treeFoldersStore,
|
||||
@ -125,6 +134,7 @@ class UploadDataStore {
|
||||
this.uploaded = true;
|
||||
this.converted = true;
|
||||
this.errors = 0;
|
||||
this.uploadedFilesSize = 0;
|
||||
|
||||
this.isUploadingAndConversion = false;
|
||||
this.isUploading = false;
|
||||
@ -297,6 +307,19 @@ class UploadDataStore {
|
||||
const newPercent =
|
||||
((uploadedSize + totalUploadedSize) / newTotalSize) * 100;
|
||||
|
||||
return newPercent;
|
||||
};
|
||||
|
||||
getFilesPercent = (uploadedSize) => {
|
||||
const newSize = this.uploadedFilesSize + uploadedSize;
|
||||
this.uploadedFilesSize = newSize;
|
||||
|
||||
const newTotalSize = sumBy(this.files, (f) =>
|
||||
f.file && !this.uploaded ? f.file.size : 0
|
||||
);
|
||||
|
||||
const newPercent = (newSize / newTotalSize) * 100;
|
||||
|
||||
/*console.log(
|
||||
`newPercent=${newPercent} (newTotalSize=${newTotalSize} totalUploadedSize=${totalUploadedSize} indexOfFile=${indexOfFile})`
|
||||
);*/
|
||||
@ -468,6 +491,7 @@ class UploadDataStore {
|
||||
file.error = error;
|
||||
file.convertProgress = progress;
|
||||
file.inConversion = false;
|
||||
file.fileInfo = fileInfo;
|
||||
|
||||
if (error.indexOf("password") !== -1) {
|
||||
file.needPassword = true;
|
||||
@ -580,13 +604,36 @@ class UploadDataStore {
|
||||
if (this.uploaded && this.converted) {
|
||||
this.files = [];
|
||||
this.filesToConversion = [];
|
||||
this.uploadedFilesSize = 0;
|
||||
}
|
||||
|
||||
let newFiles = this.files;
|
||||
let filesSize = 0;
|
||||
let convertSize = 0;
|
||||
|
||||
for (let index of Object.keys(uploadFiles)) {
|
||||
const uploadFilesArray = Object.keys(uploadFiles);
|
||||
const hasFolder =
|
||||
uploadFilesArray.findIndex((_, ind) => {
|
||||
const file = uploadFiles[ind];
|
||||
|
||||
const filePath = file.path
|
||||
? file.path
|
||||
: file.webkitRelativePath
|
||||
? file.webkitRelativePath
|
||||
: file.name;
|
||||
|
||||
return file.name !== filePath;
|
||||
}) > -1;
|
||||
|
||||
if (hasFolder) {
|
||||
if (this.uploaded) this.isParallel = false;
|
||||
else {
|
||||
this.tempFiles.push({ uploadFiles, folderId, t });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (let index of uploadFilesArray) {
|
||||
const file = uploadFiles[index];
|
||||
|
||||
const parts = file.name.split(".");
|
||||
@ -647,7 +694,9 @@ class UploadDataStore {
|
||||
converted: !!this.tempConversionFiles.length,
|
||||
};
|
||||
|
||||
if (this.uploaded && countUploadingFiles) {
|
||||
const isParallel = this.isParallel ? true : this.uploaded;
|
||||
|
||||
if (isParallel && countUploadingFiles) {
|
||||
this.setUploadData(newUploadData);
|
||||
this.startUploadFiles(t);
|
||||
}
|
||||
@ -782,15 +831,27 @@ class UploadDataStore {
|
||||
return Promise.reject(res.data.message);
|
||||
}
|
||||
|
||||
const fileId = res.data.data.id;
|
||||
const { uploaded, id: fileId } = res.data.data;
|
||||
|
||||
const { uploaded } = res.data.data;
|
||||
let uploadedSize, newPercent;
|
||||
|
||||
const uploadedSize = uploaded
|
||||
? fileSize
|
||||
: index * this.settingsStore.chunkUploadSize;
|
||||
if (!this.isParallel) {
|
||||
uploadedSize = uploaded
|
||||
? fileSize
|
||||
: index * this.settingsStore.chunkUploadSize;
|
||||
|
||||
const newPercent = this.getNewPercent(uploadedSize, indexOfFile);
|
||||
newPercent = this.getNewPercent(uploadedSize, indexOfFile);
|
||||
} else {
|
||||
if (!uploaded) {
|
||||
uploadedSize =
|
||||
fileSize <= this.settingsStore.chunkUploadSize
|
||||
? fileSize
|
||||
: this.settingsStore.chunkUploadSize;
|
||||
} else {
|
||||
uploadedSize = fileSize - index * this.settingsStore.chunkUploadSize;
|
||||
}
|
||||
newPercent = this.getFilesPercent(uploadedSize);
|
||||
}
|
||||
|
||||
const percentCurrentFile = (index / length) * 100;
|
||||
|
||||
@ -811,6 +872,16 @@ class UploadDataStore {
|
||||
this.files[indexOfFile].fileId = fileId;
|
||||
this.files[indexOfFile].fileInfo = fileInfo;
|
||||
this.percent = newPercent;
|
||||
|
||||
if (this.isParallel) {
|
||||
this.currentUploadNumber -= 1;
|
||||
|
||||
const nextFileIndex = this.files.findIndex((f) => !f.inAction);
|
||||
|
||||
if (nextFileIndex !== -1) {
|
||||
this.startSessionFunc(nextFileIndex, t);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (fileInfo.version > 2) {
|
||||
@ -819,8 +890,6 @@ class UploadDataStore {
|
||||
isFileHasExst: !fileInfo.fileExst,
|
||||
});
|
||||
}
|
||||
|
||||
//setUploadData(uploadData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -867,43 +936,71 @@ class UploadDataStore {
|
||||
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData(progressData);
|
||||
|
||||
let index = 0;
|
||||
let len = files.length;
|
||||
while (index < len) {
|
||||
await this.startSessionFunc(index, t);
|
||||
index++;
|
||||
if (this.isParallel) {
|
||||
// console.log("IS PARALLEL");
|
||||
const notUploadedFiles = this.files.filter((f) => !f.inAction);
|
||||
|
||||
files = this.files;
|
||||
len = files.length;
|
||||
}
|
||||
const countFiles =
|
||||
notUploadedFiles.length >= UPLOAD_LIMIT_AT_ONCE
|
||||
? UPLOAD_LIMIT_AT_ONCE
|
||||
: notUploadedFiles.length;
|
||||
|
||||
if (!this.filesToConversion.length) {
|
||||
this.finishUploadFiles();
|
||||
} else {
|
||||
runInAction(() => (this.uploaded = true));
|
||||
const uploadedFiles = this.files.filter((x) => x.action === "uploaded");
|
||||
const totalErrorsCount = sumBy(uploadedFiles, (f) => (f.error ? 1 : 0));
|
||||
if (totalErrorsCount > 0)
|
||||
console.log("Upload errors: ", totalErrorsCount);
|
||||
|
||||
setTimeout(() => {
|
||||
if (!this.uploadPanelVisible && !totalErrorsCount && this.converted) {
|
||||
this.clearUploadedFiles();
|
||||
for (let i = 0; i < countFiles; i++) {
|
||||
if (this.currentUploadNumber <= UPLOAD_LIMIT_AT_ONCE) {
|
||||
const fileIndex = this.files.findIndex(
|
||||
(f) => f.uniqueId === notUploadedFiles[i].uniqueId
|
||||
);
|
||||
if (fileIndex !== -1) {
|
||||
this.currentUploadNumber += 1;
|
||||
this.startSessionFunc(fileIndex, t);
|
||||
}
|
||||
}
|
||||
}, TIMEOUT);
|
||||
}
|
||||
} else {
|
||||
// console.log("IS NOT PARALLEL");
|
||||
let index = 0;
|
||||
let len = files.length;
|
||||
while (index < len) {
|
||||
await this.startSessionFunc(index, t);
|
||||
index++;
|
||||
|
||||
files = this.files;
|
||||
len = files.length;
|
||||
}
|
||||
|
||||
if (!this.filesToConversion.length) {
|
||||
this.finishUploadFiles();
|
||||
} else {
|
||||
runInAction(() => {
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
});
|
||||
const uploadedFiles = this.files.filter((x) => x.action === "uploaded");
|
||||
const totalErrorsCount = sumBy(uploadedFiles, (f) => (f.error ? 1 : 0));
|
||||
if (totalErrorsCount > 0)
|
||||
console.log("Upload errors: ", totalErrorsCount);
|
||||
|
||||
setTimeout(() => {
|
||||
if (!this.uploadPanelVisible && !totalErrorsCount && this.converted) {
|
||||
this.clearUploadedFiles();
|
||||
}
|
||||
}, TIMEOUT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
startSessionFunc = (indexOfFile, t) => {
|
||||
//console.log("START UPLOAD SESSION FUNC", uploadData);
|
||||
// console.log("START UPLOAD SESSION FUNC");
|
||||
|
||||
if (!this.uploaded && this.files.length === 0) {
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
//setUploadData(uploadData);
|
||||
return;
|
||||
}
|
||||
|
||||
const item = this.files[indexOfFile];
|
||||
this.files[indexOfFile].inAction = true;
|
||||
|
||||
if (!item) {
|
||||
console.error("Empty files");
|
||||
@ -955,15 +1052,17 @@ class UploadDataStore {
|
||||
return { location, requestsDataArray, fileSize, path };
|
||||
})
|
||||
.then(({ location, requestsDataArray, fileSize, path }) => {
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
visible: true,
|
||||
percent: this.percent,
|
||||
loadingFile: {
|
||||
uniqueId: this.files[indexOfFile].uniqueId,
|
||||
percent: chunks < 2 ? 50 : 0,
|
||||
},
|
||||
});
|
||||
if (!this.isParallel) {
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
visible: true,
|
||||
percent: this.percent,
|
||||
loadingFile: {
|
||||
uniqueId: this.files[indexOfFile].uniqueId,
|
||||
percent: chunks < 2 ? 50 : 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return this.uploadFileChunks(
|
||||
location,
|
||||
@ -998,9 +1097,9 @@ class UploadDataStore {
|
||||
|
||||
this.files[indexOfFile].error = errorMessage;
|
||||
|
||||
//dispatch(setUploadData(uploadData));
|
||||
|
||||
const newPercent = this.getNewPercent(fileSize, indexOfFile);
|
||||
const newPercent = this.isParallel
|
||||
? this.getFilesPercent(fileSize)
|
||||
: this.getNewPercent(fileSize, indexOfFile);
|
||||
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
@ -1010,6 +1109,42 @@ class UploadDataStore {
|
||||
});
|
||||
|
||||
return Promise.resolve();
|
||||
})
|
||||
.finally(() => {
|
||||
if (!this.isParallel) return;
|
||||
|
||||
const allFilesIsUploaded =
|
||||
this.files.findIndex((f) => f.action !== "uploaded" && !f.error) ===
|
||||
-1;
|
||||
|
||||
if (allFilesIsUploaded) {
|
||||
if (!this.filesToConversion.length) {
|
||||
this.finishUploadFiles();
|
||||
} else {
|
||||
runInAction(() => {
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
});
|
||||
const uploadedFiles = this.files.filter(
|
||||
(x) => x.action === "uploaded"
|
||||
);
|
||||
const totalErrorsCount = sumBy(uploadedFiles, (f) =>
|
||||
f.error ? 1 : 0
|
||||
);
|
||||
if (totalErrorsCount > 0)
|
||||
console.log("Upload errors: ", totalErrorsCount);
|
||||
|
||||
setTimeout(() => {
|
||||
if (
|
||||
!this.uploadPanelVisible &&
|
||||
!totalErrorsCount &&
|
||||
this.converted
|
||||
) {
|
||||
this.clearUploadedFiles();
|
||||
}
|
||||
}, TIMEOUT);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -1017,6 +1152,21 @@ class UploadDataStore {
|
||||
const { fetchFiles, filter } = this.filesStore;
|
||||
const { withPaging } = this.authStore.settingsStore;
|
||||
|
||||
if (this.tempFiles.length) {
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
this.converted = true;
|
||||
this.uploadedFilesSize = 0;
|
||||
|
||||
for (let item of this.tempFiles) {
|
||||
const { uploadFiles, folderId, t } = item;
|
||||
this.startUpload(uploadFiles, folderId, t);
|
||||
}
|
||||
this.tempFiles = [];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const totalErrorsCount = sumBy(this.files, (f) => {
|
||||
f.error && toastr.error(f.error);
|
||||
return f.error ? 1 : 0;
|
||||
@ -1031,7 +1181,9 @@ class UploadDataStore {
|
||||
}
|
||||
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
this.converted = true;
|
||||
this.uploadedFilesSize = 0;
|
||||
|
||||
const uploadData = {
|
||||
filesSize: 0,
|
||||
|
@ -417,7 +417,7 @@ internal class FileDao : AbstractDao, IFileDao<int>
|
||||
if (quotaSettings.EnableUserQuota)
|
||||
{
|
||||
var user = _userManager.GetUsers(file.Id == default ? _authContext.CurrentAccount.ID : file.CreateBy);
|
||||
var userQuotaSettings = _settingsManager.LoadForUser<UserQuotaSettings>(user);
|
||||
var userQuotaSettings = _settingsManager.Load<UserQuotaSettings>(user);
|
||||
var quotaLimit = userQuotaSettings.UserQuota;
|
||||
|
||||
if (quotaLimit != -1)
|
||||
|
@ -80,7 +80,7 @@ public class FileMarker
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly FilesSettingsHelper _filesSettingsHelper;
|
||||
|
||||
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
|
||||
public FileMarker(
|
||||
TenantManager tenantManager,
|
||||
UserManager userManager,
|
||||
@ -351,30 +351,41 @@ public class FileMarker
|
||||
var tagDao = _daoFactory.GetTagDao<T>();
|
||||
var newTags = new List<Tag>();
|
||||
var updateTags = new List<Tag>();
|
||||
|
||||
foreach (var userID in userEntriesData.Keys)
|
||||
|
||||
try
|
||||
{
|
||||
if (await tagDao.GetNewTagsAsync(userID, obj.FileEntry).AnyAsync())
|
||||
await _semaphore.WaitAsync();
|
||||
|
||||
foreach (var userID in userEntriesData.Keys)
|
||||
{
|
||||
continue;
|
||||
if (await tagDao.GetNewTagsAsync(userID, obj.FileEntry).AnyAsync())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var entries = userEntriesData[userID].Distinct().ToList();
|
||||
|
||||
await GetNewTagsAsync(userID, entries.OfType<FileEntry<int>>().ToList());
|
||||
await GetNewTagsAsync(userID, entries.OfType<FileEntry<string>>().ToList());
|
||||
}
|
||||
|
||||
if (updateTags.Count > 0)
|
||||
{
|
||||
await tagDao.UpdateNewTags(updateTags, obj.CurrentAccountId);
|
||||
}
|
||||
|
||||
if (newTags.Count > 0)
|
||||
{
|
||||
await tagDao.SaveTags(newTags, obj.CurrentAccountId);
|
||||
}
|
||||
|
||||
var entries = userEntriesData[userID].Distinct().ToList();
|
||||
|
||||
await GetNewTagsAsync(userID, entries.OfType<FileEntry<int>>().ToList());
|
||||
await GetNewTagsAsync(userID, entries.OfType<FileEntry<string>>().ToList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (updateTags.Count > 0)
|
||||
catch
|
||||
{
|
||||
await tagDao.UpdateNewTags(updateTags, obj.CurrentAccountId);
|
||||
throw;
|
||||
}
|
||||
|
||||
if (newTags.Count > 0)
|
||||
finally
|
||||
{
|
||||
await tagDao.SaveTags(newTags, obj.CurrentAccountId);
|
||||
_semaphore.Release();
|
||||
}
|
||||
|
||||
await Task.WhenAll(ExecMarkAsNewRequest(updateTags.Concat(newTags), socketManager));
|
||||
|
@ -80,7 +80,7 @@ public class PhotoController : PeopleControllerBase
|
||||
|
||||
var settings = new UserPhotoThumbnailSettings(inDto.X, inDto.Y, inDto.Width, inDto.Height);
|
||||
|
||||
_settingsManager.SaveForUser(settings, user.Id);
|
||||
_settingsManager.Save(settings, user.Id);
|
||||
await _userPhotoManager.RemovePhoto(user.Id);
|
||||
await _userPhotoManager.SaveOrUpdatePhoto(user.Id, data);
|
||||
await _userPhotoManager.RemoveTempPhoto(fileName);
|
||||
|
@ -1172,7 +1172,7 @@ public class UserController : PeopleControllerBase
|
||||
|
||||
var quotaSettings = _settingsManager.Load<TenantUserQuotaSettings>();
|
||||
|
||||
_settingsManager.SaveForUser(new UserQuotaSettings { UserQuota = inDto.Quota }, user);
|
||||
_settingsManager.Save(new UserQuotaSettings { UserQuota = inDto.Quota }, user);
|
||||
|
||||
yield return await _employeeFullDtoHelper.GetFull(user);
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ public class SecurityController : ControllerBase
|
||||
|
||||
DemandAuditPermission();
|
||||
|
||||
var settings = _settingsManager.LoadForTenant<TenantAuditSettings>(_tenantManager.GetCurrentTenant().Id);
|
||||
var settings = _settingsManager.Load<TenantAuditSettings>(_tenantManager.GetCurrentTenant().Id);
|
||||
|
||||
var to = DateTime.UtcNow;
|
||||
var from = to.Subtract(TimeSpan.FromDays(settings.LoginHistoryLifeTime));
|
||||
@ -218,7 +218,7 @@ public class SecurityController : ControllerBase
|
||||
|
||||
var tenantId = _tenantManager.GetCurrentTenant().Id;
|
||||
|
||||
var settings = _settingsManager.LoadForTenant<TenantAuditSettings>(tenantId);
|
||||
var settings = _settingsManager.Load<TenantAuditSettings>(tenantId);
|
||||
|
||||
var to = DateTime.UtcNow;
|
||||
var from = to.Subtract(TimeSpan.FromDays(settings.AuditTrailLifeTime));
|
||||
@ -241,7 +241,7 @@ public class SecurityController : ControllerBase
|
||||
|
||||
DemandBaseAuditPermission();
|
||||
|
||||
return _settingsManager.LoadForTenant<TenantAuditSettings>(_tenantManager.GetCurrentTenant().Id);
|
||||
return _settingsManager.Load<TenantAuditSettings>(_tenantManager.GetCurrentTenant().Id);
|
||||
}
|
||||
|
||||
[HttpPost("audit/settings/lifetime")]
|
||||
@ -261,7 +261,7 @@ public class SecurityController : ControllerBase
|
||||
throw new ArgumentException("AuditTrailLifeTime");
|
||||
}
|
||||
|
||||
_settingsManager.SaveForTenant(wrapper.Settings, _tenantManager.GetCurrentTenant().Id);
|
||||
_settingsManager.Save(wrapper.Settings, _tenantManager.GetCurrentTenant().Id);
|
||||
_messageService.Send(MessageAction.AuditSettingsUpdated);
|
||||
|
||||
return wrapper.Settings;
|
||||
|
@ -147,7 +147,7 @@ public class WhitelabelController : BaseSettingsController
|
||||
}
|
||||
}
|
||||
|
||||
_settingsManager.SaveForTenant(settings, Tenant.Id);
|
||||
_settingsManager.Save(settings, Tenant.Id);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -360,12 +360,11 @@ public class WhitelabelController : BaseSettingsController
|
||||
{
|
||||
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
|
||||
DemandWhiteLabelPermission();
|
||||
|
||||
var settings = _settingsManager.Load<MailWhiteLabelSettings>();
|
||||
|
||||
settings.FooterEnabled = inDto.FooterEnabled;
|
||||
|
||||
_settingsManager.Save(settings);
|
||||
|
||||
_settingsManager.Manage<MailWhiteLabelSettings>(settings =>
|
||||
{
|
||||
settings.FooterEnabled = inDto.FooterEnabled;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -52,26 +52,26 @@ public class TfaAppUserSettings : ISettings<TfaAppUserSettings>
|
||||
|
||||
public static long GetSalt(SettingsManager settingsManager, Guid userId)
|
||||
{
|
||||
var settings = settingsManager.LoadForUser<TfaAppUserSettings>(userId);
|
||||
var settings = settingsManager.Load<TfaAppUserSettings>(userId);
|
||||
var salt = settings.SaltSetting;
|
||||
if (salt == 0)
|
||||
{
|
||||
var from = new DateTime(2018, 07, 07, 0, 0, 0, DateTimeKind.Utc);
|
||||
settings.SaltSetting = salt = (long)(DateTime.UtcNow - from).TotalMilliseconds;
|
||||
|
||||
settingsManager.SaveForUser(settings, userId);
|
||||
settingsManager.Save(settings, userId);
|
||||
}
|
||||
return salt;
|
||||
}
|
||||
|
||||
public static IEnumerable<BackupCode> BackupCodesForUser(SettingsManager settingsManager, Guid userId)
|
||||
{
|
||||
return settingsManager.LoadForUser<TfaAppUserSettings>(userId).CodesSetting;
|
||||
return settingsManager.Load<TfaAppUserSettings>(userId).CodesSetting;
|
||||
}
|
||||
|
||||
public static void DisableCodeForUser(SettingsManager settingsManager, InstanceCrypto instanceCrypto, Signature signature, Guid userId, string code)
|
||||
{
|
||||
var settings = settingsManager.LoadForUser<TfaAppUserSettings>(userId);
|
||||
var settings = settingsManager.Load<TfaAppUserSettings>(userId);
|
||||
var query = settings.CodesSetting.Where(x => x.GetEncryptedCode(instanceCrypto, signature) == code).ToList();
|
||||
|
||||
if (query.Count > 0)
|
||||
@ -79,17 +79,17 @@ public class TfaAppUserSettings : ISettings<TfaAppUserSettings>
|
||||
query.First().IsUsed = true;
|
||||
}
|
||||
|
||||
settingsManager.SaveForUser(settings, userId);
|
||||
settingsManager.Save(settings, userId);
|
||||
}
|
||||
|
||||
public static bool EnableForUser(SettingsManager settingsManager, Guid guid)
|
||||
{
|
||||
return settingsManager.LoadForUser<TfaAppUserSettings>(guid).CodesSetting.Any();
|
||||
return settingsManager.Load<TfaAppUserSettings>(guid).CodesSetting.Any();
|
||||
}
|
||||
|
||||
public static void DisableForUser(SettingsManager settingsManager, Guid guid)
|
||||
{
|
||||
var defaultSettings = settingsManager.GetDefault<TfaAppUserSettings>();
|
||||
settingsManager.SaveForUser(defaultSettings, guid);
|
||||
settingsManager.Save(defaultSettings, guid);
|
||||
}
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ public class UserPhotoManager
|
||||
public void ResetThumbnailSettings(Guid userId)
|
||||
{
|
||||
var thumbSettings = _settingsManager.GetDefault<UserPhotoThumbnailSettings>();
|
||||
_settingsManager.SaveForUser(thumbSettings, userId);
|
||||
_settingsManager.Save(thumbSettings, userId);
|
||||
}
|
||||
|
||||
public async Task<(string, string)> SaveOrUpdatePhoto(Guid userID, byte[] data)
|
||||
@ -583,7 +583,7 @@ public class UserPhotoManager
|
||||
|
||||
private void SetUserPhotoThumbnailSettings(Guid userId, int width, int height)
|
||||
{
|
||||
var settings = _settingsManager.LoadForUser<UserPhotoThumbnailSettings>(userId);
|
||||
var settings = _settingsManager.Load<UserPhotoThumbnailSettings>(userId);
|
||||
|
||||
if (!settings.IsDefault)
|
||||
{
|
||||
@ -599,7 +599,7 @@ public class UserPhotoManager
|
||||
width >= height ? new Point(pos, 0) : new Point(0, pos),
|
||||
new Size(min, min));
|
||||
|
||||
_settingsManager.SaveForUser(settings, userId);
|
||||
_settingsManager.Save(settings, userId);
|
||||
}
|
||||
|
||||
private byte[] TryParseImage(byte[] data, long maxFileSize, Size maxsize, out IImageFormat imgFormat, out int width, out int height)
|
||||
@ -696,7 +696,7 @@ public class UserPhotoManager
|
||||
throw new ImageWeightLimitException();
|
||||
}
|
||||
|
||||
var resizeTask = new ResizeWorkerItem(_tenantManager.GetCurrentTenant().Id, userID, data, maxFileSize, size, GetDataStore(), _settingsManager.LoadForUser<UserPhotoThumbnailSettings>(userID));
|
||||
var resizeTask = new ResizeWorkerItem(_tenantManager.GetCurrentTenant().Id, userID, data, maxFileSize, size, GetDataStore(), _settingsManager.Load<UserPhotoThumbnailSettings>(userID));
|
||||
var key = $"{userID}{size}";
|
||||
resizeTask["key"] = key;
|
||||
|
||||
|
@ -65,7 +65,7 @@ public static class UserPhotoThumbnailManager
|
||||
|
||||
await thumbnailsData.Save(resultBitmaps);
|
||||
|
||||
settingsManager.SaveForUser(thumbnailSettings, userId);
|
||||
settingsManager.Save(thumbnailSettings, userId);
|
||||
|
||||
return await thumbnailsData.ThumbnailList();
|
||||
}
|
||||
|
@ -731,7 +731,7 @@ public class TenantWhiteLabelSettingsHelper
|
||||
|
||||
public void Save(TenantWhiteLabelSettings tenantWhiteLabelSettings, int tenantId, TenantLogoManager tenantLogoManager, bool restore = false)
|
||||
{
|
||||
_settingsManager.SaveForTenant(tenantWhiteLabelSettings, tenantId);
|
||||
_settingsManager.Save(tenantWhiteLabelSettings, tenantId);
|
||||
|
||||
if (tenantId == Tenant.DefaultTenant)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user