Merge branch 'develop' into feature/archived-redesign-empty-screen
This commit is contained in:
commit
ae0eb0a143
@ -1,4 +1,4 @@
|
||||
@echo off
|
||||
|
||||
PUSHD %~dp0..\..
|
||||
set servicepath=%cd%\web\ASC.Web.Api\bin\Debug\ASC.Web.Api.exe urls=http://0.0.0.0:5000 $STORAGE_ROOT=%cd%\Data log:dir=%cd%\Logs log:name=api pathToConf=%cd%\config core:products:folder=%cd%\products
|
||||
set servicepath=%cd%\web\ASC.Web.Api\bin\Debug\ASC.Web.Api.exe urls=http://0.0.0.0:5000 $STORAGE_ROOT=%cd%\Data log:dir=%cd%\Logs log:name=web.api pathToConf=%cd%\config core:products:folder=%cd%\products
|
@ -1,4 +1,4 @@
|
||||
@echo off
|
||||
|
||||
PUSHD %~dp0..\..
|
||||
set servicepath=%cd%\web\ASC.Web.Studio\bin\Debug\ASC.Web.Studio.exe urls=http://0.0.0.0:5003 $STORAGE_ROOT=%cd%\Data log:dir=%cd%\Logs log:name=studio pathToConf=%cd%\config core:products:folder=%cd%\products
|
||||
set servicepath=%cd%\web\ASC.Web.Studio\bin\Debug\ASC.Web.Studio.exe urls=http://0.0.0.0:5003 $STORAGE_ROOT=%cd%\Data log:dir=%cd%\Logs log:name=web.studio pathToConf=%cd%\config core:products:folder=%cd%\products
|
@ -21,7 +21,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.1.0" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.1.4" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="8.0.4" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="8.0.4" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0" />
|
||||
|
@ -273,35 +273,3 @@ public abstract class BaseStartup
|
||||
}
|
||||
}
|
||||
|
||||
public static class LogNLogConfigureExtenstion
|
||||
{
|
||||
private static LoggingConfiguration GetXmlLoggingConfiguration(IHostEnvironment hostEnvironment, IConfiguration configuration)
|
||||
{
|
||||
var loggerConfiguration = new XmlLoggingConfiguration(CrossPlatform.PathCombine(configuration["pathToConf"], "nlog.config"));
|
||||
|
||||
var settings = new ConfigurationExtension(configuration).GetSetting<NLogSettings>("log");
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.Name))
|
||||
{
|
||||
loggerConfiguration.Variables["name"] = settings.Name;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.Dir))
|
||||
{
|
||||
var dir = Path.IsPathRooted(settings.Dir) ? settings.Dir : CrossPlatform.PathCombine(hostEnvironment.ContentRootPath, settings.Dir);
|
||||
loggerConfiguration.Variables["dir"] = dir.TrimEnd('/').TrimEnd('\\') + Path.DirectorySeparatorChar;
|
||||
}
|
||||
|
||||
return loggerConfiguration;
|
||||
}
|
||||
|
||||
public static IHostBuilder ConfigureNLogLogging(this IHostBuilder hostBuilder)
|
||||
{
|
||||
return hostBuilder.ConfigureLogging((hostBuildexContext, r) =>
|
||||
{
|
||||
LogManager.ThrowConfigExceptions = false;
|
||||
|
||||
r.AddNLog(GetXmlLoggingConfiguration(hostBuildexContext.HostingEnvironment, hostBuildexContext.Configuration));
|
||||
});
|
||||
}
|
||||
}
|
@ -47,16 +47,15 @@ public static class ConfigurationManagerExtension
|
||||
{"pathToConf", path }
|
||||
});
|
||||
|
||||
config.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
|
||||
.AddJsonFile("storage.json")
|
||||
.AddJsonFile("kafka.json")
|
||||
.AddJsonFile($"kafka.{env.EnvironmentName}.json", true)
|
||||
.AddJsonFile("rabbitmq.json")
|
||||
.AddJsonFile($"rabbitmq.{env.EnvironmentName}.json", true)
|
||||
.AddJsonFile("redis.json")
|
||||
.AddJsonFile($"redis.{env.EnvironmentName}.json", true);
|
||||
|
||||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile("storage.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("kafka.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile($"kafka.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile("rabbitmq.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile($"rabbitmq.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile("redis.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile($"redis.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
// 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
|
||||
|
||||
using NLog.Web;
|
||||
|
||||
namespace ASC.Api.Core.Extensions;
|
||||
|
||||
public static class HostBuilderExtension
|
||||
@ -33,8 +35,10 @@ public static class HostBuilderExtension
|
||||
hostBuilder.UseSystemd();
|
||||
hostBuilder.UseWindowsService();
|
||||
hostBuilder.UseServiceProviderFactory(new AutofacServiceProviderFactory());
|
||||
hostBuilder.ConfigureNLogLogging();
|
||||
|
||||
hostBuilder.UseNLog();
|
||||
|
||||
return hostBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
69
common/ASC.Api.Core/Extensions/ISetupBuilderExtension.cs
Normal file
69
common/ASC.Api.Core/Extensions/ISetupBuilderExtension.cs
Normal file
@ -0,0 +1,69 @@
|
||||
// (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
|
||||
|
||||
using NLog.AWS.Logger;
|
||||
|
||||
namespace ASC.Api.Core.Extensions;
|
||||
public static class ISetupBuilderExtension
|
||||
{
|
||||
public static ISetupBuilder LoadConfiguration(this ISetupBuilder loggingBuilder, IConfiguration configuration, IHostEnvironment hostEnvironment)
|
||||
{
|
||||
var conf = new XmlLoggingConfiguration(CrossPlatform.PathCombine(configuration["pathToConf"], "nlog.config"));
|
||||
|
||||
var settings = new ConfigurationExtension(configuration).GetSetting<NLogSettings>("log");
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.Name))
|
||||
{
|
||||
conf.Variables["name"] = settings.Name;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.Dir))
|
||||
{
|
||||
var dir = Path.IsPathRooted(settings.Dir) ? settings.Dir : CrossPlatform.PathCombine(hostEnvironment.ContentRootPath, settings.Dir);
|
||||
conf.Variables["dir"] = dir.TrimEnd('/').TrimEnd('\\') + Path.DirectorySeparatorChar;
|
||||
}
|
||||
|
||||
foreach (var targetName in new[] { "aws", "aws_sql" })
|
||||
{
|
||||
var awsTarget = conf.FindTargetByName<AWSTarget>(targetName);
|
||||
|
||||
if (awsTarget == null) continue;
|
||||
|
||||
//hack
|
||||
if (!string.IsNullOrEmpty(settings.Name))
|
||||
{
|
||||
awsTarget.LogGroup = awsTarget.LogGroup.Replace("${var:name}", settings.Name);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.AWSSecretAccessKey))
|
||||
{
|
||||
awsTarget.Credentials = new Amazon.Runtime.BasicAWSCredentials(settings.AWSAccessKeyId, settings.AWSSecretAccessKey);
|
||||
}
|
||||
}
|
||||
|
||||
return loggingBuilder.LoadConfiguration(conf);
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@
|
||||
<PackageReference Include="ARSoft.Tools.NetStandard.DXSdata" Version="1.0.0" />
|
||||
<PackageReference Include="Autofac.Configuration" Version="6.0.0" />
|
||||
<PackageReference Include="AutoMapper" Version="11.0.1" />
|
||||
<PackageReference Include="AWS.Logger.NLog" Version="3.1.0" />
|
||||
<PackageReference Include="Confluent.Kafka" Version="1.9.0" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.21.4" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.47.0">
|
||||
@ -54,7 +55,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference> -->
|
||||
<PackageReference Include="NLog" Version="5.0.1" />
|
||||
<PackageReference Include="NLog" Version="5.0.4" />
|
||||
<PackageReference Include="NVelocity" Version="1.2.0" />
|
||||
<PackageReference Include="protobuf-net" Version="3.1.17" />
|
||||
<PackageReference Include="RabbitMQ.Client" Version="6.4.0" />
|
||||
|
@ -30,5 +30,8 @@ namespace ASC.Common.Logging;
|
||||
public class NLogSettings
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Dir { get; set; }
|
||||
public string Dir { get; set; }
|
||||
public string AWSAccessKeyId { get; set; }
|
||||
public string AWSSecretAccessKey {get; set;}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
// 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
|
||||
|
||||
using ASC.Notify;
|
||||
|
||||
namespace ASC.Core.Common.Hosting;
|
||||
|
||||
[Scope]
|
||||
@ -48,6 +50,10 @@ public class RegisterInstanceDao<T> : IRegisterInstanceDao<T> where T : IHostedS
|
||||
if (inst == null)
|
||||
{
|
||||
await _instanceRegistrationContext.AddAsync(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
_instanceRegistrationContext.Entry(inst).CurrentValues.SetValues(obj);
|
||||
}
|
||||
|
||||
bool saveFailed;
|
||||
|
@ -60,7 +60,7 @@ public class RegisterInstanceManager<T> : IRegisterInstanceManager<T> where T :
|
||||
{
|
||||
var firstAliceInstance = GetFirstAliveInstance(instances);
|
||||
|
||||
if (firstAliceInstance != null && firstAliceInstance.InstanceRegistrationId == instance.InstanceRegistrationId)
|
||||
if (firstAliceInstance == null || firstAliceInstance.InstanceRegistrationId == instance.InstanceRegistrationId)
|
||||
{
|
||||
instance.IsActive = true;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public class BackupAjaxHandler
|
||||
_tempPath = tempPath;
|
||||
}
|
||||
|
||||
public void StartBackup(BackupStorageType storageType, Dictionary<string, string> storageParams, bool backupMail)
|
||||
public void StartBackup(BackupStorageType storageType, Dictionary<string, string> storageParams)
|
||||
{
|
||||
DemandPermissionsBackup();
|
||||
|
||||
@ -80,7 +80,6 @@ public class BackupAjaxHandler
|
||||
{
|
||||
TenantId = GetCurrentTenantId(),
|
||||
UserId = _securityContext.CurrentAccount.ID,
|
||||
BackupMail = backupMail,
|
||||
StorageType = storageType,
|
||||
StorageParams = storageParams
|
||||
};
|
||||
@ -141,7 +140,7 @@ public class BackupAjaxHandler
|
||||
return _backupService.GetBackupHistory(GetCurrentTenantId());
|
||||
}
|
||||
|
||||
public void CreateSchedule(BackupStorageType storageType, Dictionary<string, string> storageParams, int backupsStored, CronParams cronParams, bool backupMail)
|
||||
public void CreateSchedule(BackupStorageType storageType, Dictionary<string, string> storageParams, int backupsStored, CronParams cronParams)
|
||||
{
|
||||
DemandPermissionsBackup();
|
||||
|
||||
@ -155,7 +154,6 @@ public class BackupAjaxHandler
|
||||
var scheduleRequest = new CreateScheduleRequest
|
||||
{
|
||||
TenantId = _tenantManager.GetCurrentTenant().Id,
|
||||
BackupMail = backupMail,
|
||||
Cron = cronParams.ToString(),
|
||||
NumberOfBackupsStored = backupsStored,
|
||||
StorageType = storageType,
|
||||
@ -198,7 +196,6 @@ public class BackupAjaxHandler
|
||||
StorageType = response.StorageType,
|
||||
StorageParams = response.StorageParams.ToDictionary(r => r.Key, r => r.Value) ?? new Dictionary<string, string>(),
|
||||
CronParams = new CronParams(response.Cron),
|
||||
BackupMail = response.BackupMail.NullIfDefault(),
|
||||
BackupsStored = response.NumberOfBackupsStored.NullIfDefault(),
|
||||
LastBackupTime = response.LastBackupTime
|
||||
};
|
||||
@ -224,7 +221,6 @@ public class BackupAjaxHandler
|
||||
var Schedule = new CreateScheduleRequest
|
||||
{
|
||||
TenantId = _tenantManager.GetCurrentTenant().Id,
|
||||
BackupMail = schedule.BackupMail != null && (bool)schedule.BackupMail,
|
||||
Cron = schedule.CronParams.ToString(),
|
||||
NumberOfBackupsStored = schedule.BackupsStored == null ? 0 : (int)schedule.BackupsStored,
|
||||
StorageType = schedule.StorageType,
|
||||
@ -337,7 +333,7 @@ public class BackupAjaxHandler
|
||||
|
||||
#region transfer
|
||||
|
||||
public void StartTransfer(string targetRegion, bool notifyUsers, bool transferMail)
|
||||
public void StartTransfer(string targetRegion, bool notifyUsers)
|
||||
{
|
||||
DemandPermissionsTransfer();
|
||||
|
||||
@ -347,7 +343,6 @@ public class BackupAjaxHandler
|
||||
{
|
||||
TenantId = GetCurrentTenantId(),
|
||||
TargetRegion = targetRegion,
|
||||
BackupMail = transferMail,
|
||||
NotifyUsers = notifyUsers
|
||||
});
|
||||
|
||||
@ -405,7 +400,6 @@ public class BackupAjaxHandler
|
||||
public BackupStorageType StorageType { get; set; }
|
||||
public Dictionary<string, string> StorageParams { get; set; }
|
||||
public CronParams CronParams { get; set; }
|
||||
public bool? BackupMail { get; set; }
|
||||
public int? BackupsStored { get; set; }
|
||||
public DateTime LastBackupTime { get; set; }
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ public class StartBackupRequest
|
||||
{
|
||||
public int TenantId { get; set; }
|
||||
public Guid UserId { get; set; }
|
||||
public bool BackupMail { get; set; }
|
||||
public BackupStorageType StorageType { get; set; }
|
||||
public string StorageBasePath { get; set; }
|
||||
public Dictionary<string, string> StorageParams { get; set; }
|
||||
@ -61,7 +60,6 @@ public class StartTransferRequest
|
||||
public int TenantId { get; set; }
|
||||
public string TargetRegion { get; set; }
|
||||
public bool NotifyUsers { get; set; }
|
||||
public bool BackupMail { get; set; }
|
||||
}
|
||||
|
||||
public class TransferRegion
|
||||
@ -91,7 +89,6 @@ public class ScheduleResponse
|
||||
{
|
||||
public BackupStorageType StorageType { get; set; }
|
||||
public string StorageBasePath { get; set; }
|
||||
public bool BackupMail { get; set; }
|
||||
public int NumberOfBackupsStored { get; set; }
|
||||
public string Cron { get; set; }
|
||||
public DateTime LastBackupTime { get; set; }
|
||||
|
@ -30,8 +30,6 @@ public class BackupSchedule : BaseEntity
|
||||
{
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public bool BackupMail { get; set; }
|
||||
|
||||
public string Cron { get; set; }
|
||||
|
||||
public int BackupsStored { get; set; }
|
||||
@ -76,11 +74,6 @@ public static class BackupScheduleExtension
|
||||
.HasColumnType("int(10)")
|
||||
.ValueGeneratedNever();
|
||||
|
||||
entity.Property(e => e.BackupMail)
|
||||
.HasColumnName("backup_mail")
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasDefaultValueSql("'0'");
|
||||
|
||||
entity.Property(e => e.Cron)
|
||||
.IsRequired()
|
||||
.HasColumnName("cron")
|
||||
@ -132,11 +125,6 @@ public static class BackupScheduleExtension
|
||||
.HasColumnName("tenant_id")
|
||||
.HasMaxLength(10);
|
||||
|
||||
entity.Property(e => e.BackupMail)
|
||||
.HasColumnName("backup_mail")
|
||||
.HasMaxLength(10)
|
||||
.HasDefaultValueSql("'0'");
|
||||
|
||||
entity.Property(e => e.Cron)
|
||||
.IsRequired()
|
||||
.HasColumnName("cron")
|
||||
|
@ -38,14 +38,12 @@ public record BackupRequestIntegrationEvent : IntegrationEvent
|
||||
int tenantId,
|
||||
Guid createBy,
|
||||
Dictionary<string, string> storageParams,
|
||||
bool backupMail,
|
||||
bool isScheduled = false,
|
||||
int backupsStored = 0,
|
||||
string storageBasePath = "") : base(createBy, tenantId)
|
||||
{
|
||||
StorageType = storageType;
|
||||
StorageParams = storageParams;
|
||||
BackupMail = backupMail;
|
||||
IsScheduled = isScheduled;
|
||||
BackupsStored = backupsStored;
|
||||
StorageBasePath = storageBasePath;
|
||||
@ -57,9 +55,6 @@ public record BackupRequestIntegrationEvent : IntegrationEvent
|
||||
[ProtoMember(2)]
|
||||
public Dictionary<string, string> StorageParams { get; private init; }
|
||||
|
||||
[ProtoMember(3)]
|
||||
public bool BackupMail { get; private init; }
|
||||
|
||||
[ProtoMember(4)]
|
||||
public bool IsScheduled { get; private init; }
|
||||
|
||||
|
@ -126,7 +126,7 @@ public class BackupService : IBackupService
|
||||
|
||||
public void StartTransfer(StartTransferRequest request)
|
||||
{
|
||||
var progress = _backupWorker.StartTransfer(request.TenantId, request.TargetRegion, request.BackupMail, request.NotifyUsers);
|
||||
var progress = _backupWorker.StartTransfer(request.TenantId, request.TargetRegion, request.NotifyUsers);
|
||||
if (!string.IsNullOrEmpty(progress.Error))
|
||||
{
|
||||
throw new FaultException();
|
||||
@ -209,7 +209,6 @@ public class BackupService : IBackupService
|
||||
{
|
||||
TenantId = request.TenantId,
|
||||
Cron = request.Cron,
|
||||
BackupMail = request.BackupMail,
|
||||
BackupsStored = request.NumberOfBackupsStored,
|
||||
StorageType = request.StorageType,
|
||||
StorageBasePath = request.StorageBasePath,
|
||||
@ -231,7 +230,6 @@ public class BackupService : IBackupService
|
||||
{
|
||||
StorageType = schedule.StorageType,
|
||||
StorageBasePath = schedule.StorageBasePath,
|
||||
BackupMail = schedule.BackupMail,
|
||||
NumberOfBackupsStored = schedule.BackupsStored,
|
||||
Cron = schedule.Cron,
|
||||
LastBackupTime = schedule.LastBackupTime,
|
||||
|
@ -209,7 +209,7 @@ public class BackupWorker
|
||||
}
|
||||
}
|
||||
|
||||
public BackupProgress StartTransfer(int tenantId, string targetRegion, bool transferMail, bool notify)
|
||||
public BackupProgress StartTransfer(int tenantId, string targetRegion, bool notify)
|
||||
{
|
||||
lock (_synchRoot)
|
||||
{
|
||||
@ -223,7 +223,7 @@ public class BackupWorker
|
||||
if (item == null)
|
||||
{
|
||||
item = _serviceProvider.GetService<TransferProgressItem>();
|
||||
item.Init(targetRegion, transferMail, tenantId, TempFolder, _limit, notify, _currentRegion, _configPaths);
|
||||
item.Init(targetRegion, tenantId, TempFolder, _limit, notify, _currentRegion, _configPaths);
|
||||
|
||||
_progressQueue.EnqueueTask(item);
|
||||
}
|
||||
|
@ -54,7 +54,6 @@ namespace ASC.Data.Backup.Services;
|
||||
[Transient]
|
||||
public class BackupProgressItem : BaseBackupProgressItem
|
||||
{
|
||||
public bool BackupMail { get; set; }
|
||||
public Dictionary<string, string> StorageParams { get; set; }
|
||||
public string TempFolder { get; set; }
|
||||
|
||||
@ -94,7 +93,6 @@ public class BackupProgressItem : BaseBackupProgressItem
|
||||
TenantId = schedule.TenantId;
|
||||
_storageType = schedule.StorageType;
|
||||
_storageBasePath = schedule.StorageBasePath;
|
||||
BackupMail = schedule.BackupMail;
|
||||
StorageParams = JsonConvert.DeserializeObject<Dictionary<string, string>>(schedule.StorageParams);
|
||||
_isScheduled = isScheduled;
|
||||
TempFolder = tempFolder;
|
||||
@ -109,7 +107,6 @@ public class BackupProgressItem : BaseBackupProgressItem
|
||||
TenantId = request.TenantId;
|
||||
_storageType = request.StorageType;
|
||||
_storageBasePath = request.StorageBasePath;
|
||||
BackupMail = request.BackupMail;
|
||||
StorageParams = request.StorageParams.ToDictionary(r => r.Key, r => r.Value);
|
||||
_isScheduled = isScheduled;
|
||||
TempFolder = tempFolder;
|
||||
@ -142,11 +139,7 @@ public class BackupProgressItem : BaseBackupProgressItem
|
||||
{
|
||||
var backupTask = _backupPortalTask;
|
||||
|
||||
backupTask.Init(TenantId, _configPaths[_currentRegion], tempFile, _limit);
|
||||
if (!BackupMail)
|
||||
{
|
||||
backupTask.IgnoreModule(ModuleName.Mail);
|
||||
}
|
||||
backupTask.Init(TenantId, _configPaths[_currentRegion], tempFile, _limit);
|
||||
|
||||
backupTask.ProgressChanged += (sender, args) =>
|
||||
{
|
||||
|
@ -74,7 +74,6 @@ public class TransferProgressItem : BaseBackupProgressItem
|
||||
}
|
||||
|
||||
public string TargetRegion { get; set; }
|
||||
public bool TransferMail { get; set; }
|
||||
public bool Notify { get; set; }
|
||||
public string TempFolder { get; set; }
|
||||
public Dictionary<string, string> ConfigPaths { get; set; }
|
||||
@ -83,7 +82,6 @@ public class TransferProgressItem : BaseBackupProgressItem
|
||||
|
||||
public void Init(
|
||||
string targetRegion,
|
||||
bool transferMail,
|
||||
int tenantId,
|
||||
string tempFolder,
|
||||
int limit,
|
||||
@ -93,7 +91,6 @@ public class TransferProgressItem : BaseBackupProgressItem
|
||||
{
|
||||
TenantId = tenantId;
|
||||
TargetRegion = targetRegion;
|
||||
TransferMail = transferMail;
|
||||
Notify = notify;
|
||||
TempFolder = tempFolder;
|
||||
ConfigPaths = configPaths;
|
||||
@ -122,11 +119,8 @@ public class TransferProgressItem : BaseBackupProgressItem
|
||||
{
|
||||
Percentage = args.Progress;
|
||||
PublishChanges();
|
||||
};
|
||||
if (!TransferMail)
|
||||
{
|
||||
transferProgressItem.IgnoreModule(ModuleName.Mail);
|
||||
}
|
||||
};
|
||||
|
||||
transferProgressItem.RunJob();
|
||||
|
||||
Link = GetLink(alias, false);
|
||||
|
@ -1,101 +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.Data.Backup.Tasks.Modules;
|
||||
|
||||
public class CalendarModuleSpecifics : ModuleSpecificsBase
|
||||
{
|
||||
public override ModuleName ModuleName => ModuleName.Calendar;
|
||||
public override IEnumerable<TableInfo> Tables => _tables;
|
||||
public override IEnumerable<RelationInfo> TableRelations => _tableRelations;
|
||||
|
||||
private readonly RelationInfo[] _tableRelations;
|
||||
private readonly TableInfo[] _tables = new[]
|
||||
{
|
||||
new TableInfo("calendar_calendars", "tenant", "id") {UserIDColumns = new[] {"owner_id"}},
|
||||
new TableInfo("calendar_calendar_item"),
|
||||
new TableInfo("calendar_calendar_user") {UserIDColumns = new[] {"user_id"}},
|
||||
new TableInfo("calendar_events", "tenant", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"owner_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"start_date", true}, {"end_date", true}}
|
||||
},
|
||||
new TableInfo("calendar_event_history", "tenant"),
|
||||
new TableInfo("calendar_event_item"),
|
||||
new TableInfo("calendar_event_user") {UserIDColumns = new[] {"user_id"}},
|
||||
new TableInfo("calendar_notifications", "tenant")
|
||||
{
|
||||
UserIDColumns = new[] {"user_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"notify_date", true}}
|
||||
}
|
||||
};
|
||||
|
||||
public CalendarModuleSpecifics(Helpers helpers)
|
||||
: base(helpers)
|
||||
{
|
||||
_tableRelations = new[]
|
||||
{
|
||||
new RelationInfo("calendar_calendars", "id", "calendar_calendar_item", "calendar_id"),
|
||||
new RelationInfo("calendar_calendars", "id", "calendar_calendar_user", "calendar_id"),
|
||||
new RelationInfo("calendar_calendars", "id", "calendar_events", "calendar_id"),
|
||||
new RelationInfo("calendar_calendars", "id", "calendar_event_history", "calendar_id"),
|
||||
new RelationInfo("calendar_events", "id", "calendar_event_history", "event_id"),
|
||||
new RelationInfo("calendar_events", "id", "calendar_event_item", "event_id"),
|
||||
new RelationInfo("calendar_events", "id", "calendar_event_user", "event_id"),
|
||||
new RelationInfo("calendar_events", "id", "calendar_notifications", "event_id"),
|
||||
new RelationInfo("core_user", "id", "calendar_calendar_item", "item_id", typeof(TenantsModuleSpecifics),
|
||||
x => Convert.ToInt32(x["is_group"]) == 0),
|
||||
new RelationInfo("core_group", "id", "calendar_calendar_item", "item_id", typeof(TenantsModuleSpecifics),
|
||||
x => Convert.ToInt32(x["is_group"]) == 1 && !helpers.IsEmptyOrSystemGroup(Convert.ToString(x["item_id"]))),
|
||||
new RelationInfo("core_user", "id", "calendar_event_item", "item_id", typeof(TenantsModuleSpecifics),
|
||||
x => Convert.ToInt32(x["is_group"]) == 0),
|
||||
new RelationInfo("core_group", "id", "calendar_event_item", "item_id", typeof(TenantsModuleSpecifics),
|
||||
x => Convert.ToInt32(x["is_group"]) == 1 && !helpers.IsEmptyOrSystemGroup(Convert.ToString(x["item_id"])))
|
||||
};
|
||||
}
|
||||
|
||||
protected override string GetSelectCommandConditionText(int tenantId, TableInfo table)
|
||||
{
|
||||
if (table.Name == "calendar_calendar_item" || table.Name == "calendar_calendar_user")
|
||||
{
|
||||
return "inner join calendar_calendars as t1 on t1.id = t.calendar_id where t1.tenant = " + tenantId;
|
||||
}
|
||||
|
||||
if (table.Name == "calendar_event_item" || table.Name == "calendar_event_user")
|
||||
{
|
||||
return "inner join calendar_events as t1 on t1.id = t.event_id where t1.tenant = " + tenantId;
|
||||
}
|
||||
|
||||
if (table.Name == "calendar_event_history")
|
||||
{
|
||||
return string.Format(
|
||||
"inner join calendar_calendars as t1 on t1.id = t.calendar_id and t1.tenant = t.tenant inner join calendar_events as t2 on t2.id = t.event_id where t1.tenant = {0} and t2.tenant = {0}",
|
||||
tenantId);
|
||||
}
|
||||
|
||||
return base.GetSelectCommandConditionText(tenantId, table);
|
||||
}
|
||||
}
|
@ -1,289 +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.Data.Backup.Tasks.Modules;
|
||||
|
||||
public class CommunityModuleSpecifics : ModuleSpecificsBase
|
||||
{
|
||||
public override ModuleName ModuleName => ModuleName.Community;
|
||||
public override IEnumerable<TableInfo> Tables => _tables;
|
||||
public override IEnumerable<RelationInfo> TableRelations => _tableRelations;
|
||||
|
||||
private readonly TableInfo[] _tables = new[]
|
||||
{
|
||||
new TableInfo("bookmarking_bookmark", "Tenant", "ID")
|
||||
{
|
||||
UserIDColumns = new[] {"UserCreatorID"},
|
||||
DateColumns = new Dictionary<string, bool> {{"Date", false}}
|
||||
},
|
||||
new TableInfo("bookmarking_bookmarktag", "tenant"),
|
||||
new TableInfo("bookmarking_comment", "tenant", "ID", IdType.Guid)
|
||||
{
|
||||
UserIDColumns = new[] {"UserID"},
|
||||
DateColumns = new Dictionary<string, bool> {{"Datetime", false}}
|
||||
},
|
||||
new TableInfo("bookmarking_tag", "tenant", "TagID"),
|
||||
new TableInfo("bookmarking_userbookmark", "tenant", "UserBookmarkID")
|
||||
{
|
||||
UserIDColumns = new[] {"UserID"},
|
||||
DateColumns = new Dictionary<string, bool> {{"DateAdded", false}, {"LastModified", false}}
|
||||
},
|
||||
new TableInfo("bookmarking_userbookmarktag", "tenant"),
|
||||
new TableInfo("blogs_comments", "Tenant", "id", IdType.Guid)
|
||||
{
|
||||
UserIDColumns = new[] {"created_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"created_when", false}}
|
||||
},
|
||||
new TableInfo("blogs_posts", "Tenant", "post_id", IdType.Autoincrement)
|
||||
{
|
||||
UserIDColumns = new[] {"created_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"created_when", false}, {"LastModified", false}}
|
||||
},
|
||||
new TableInfo("blogs_reviewposts", "Tenant")
|
||||
{
|
||||
UserIDColumns = new[] {"reviewed_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"timestamp", false}}
|
||||
},
|
||||
new TableInfo("blogs_tags", "Tenant"),
|
||||
new TableInfo("events_comment", "Tenant", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"Creator"},
|
||||
DateColumns = new Dictionary<string, bool> {{"Date", false}}
|
||||
},
|
||||
new TableInfo("events_feed", "Tenant", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"Creator"},
|
||||
DateColumns = new Dictionary<string, bool> {{"Date", false}, {"LastModified", false}}
|
||||
},
|
||||
new TableInfo("events_poll", "Tenant")
|
||||
{
|
||||
DateColumns = new Dictionary<string, bool> {{"StartDate", true}, {"EndDate", true}}
|
||||
},
|
||||
new TableInfo("events_pollanswer", "Tenant") {UserIDColumns = new[] {"User"}}, //todo: check //varchar(64)?
|
||||
new TableInfo("events_pollvariant", "Tenant", "Id"),
|
||||
new TableInfo("events_reader", "Tenant") {UserIDColumns = new[] {"Reader"}}, //todo: check
|
||||
new TableInfo("forum_answer", "TenantID", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"user_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_date", false}}
|
||||
},
|
||||
new TableInfo("forum_answer_variant"),
|
||||
new TableInfo("forum_attachment", "TenantID", "id")
|
||||
{
|
||||
DateColumns = new Dictionary<string, bool> {{"create_date", false}}
|
||||
},
|
||||
new TableInfo("forum_category", "TenantID", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"poster_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_date", false}}
|
||||
},
|
||||
new TableInfo("forum_lastvisit", "tenantid")
|
||||
{
|
||||
UserIDColumns = new[] {"user_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"last_visit", false}}
|
||||
},
|
||||
new TableInfo("forum_post", "TenantID", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"poster_id", "editor_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_date", false}, {"edit_date", false}, {"LastModified", false}}
|
||||
},
|
||||
new TableInfo("forum_question", "TenantID", "id") {DateColumns = new Dictionary<string, bool> {{"create_date", false}}},
|
||||
new TableInfo("forum_tag", "TenantID", "id"),
|
||||
new TableInfo("forum_thread", "TenantID", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"recent_poster_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"recent_post_date", false}}
|
||||
},
|
||||
new TableInfo("forum_topic", "TenantID", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"poster_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_date", false}, {"LastModified", false}}
|
||||
},
|
||||
new TableInfo("forum_topicwatch", "TenantID") {UserIDColumns = new[] {"UserID"}},
|
||||
new TableInfo("forum_topic_tag"),
|
||||
new TableInfo("forum_variant", idColumn: "id"),
|
||||
new TableInfo("wiki_categories", "Tenant"),
|
||||
new TableInfo("wiki_comments", "Tenant", "Id", IdType.Guid)
|
||||
{
|
||||
UserIDColumns = new[] {"UserId"},
|
||||
DateColumns = new Dictionary<string, bool> {{"Date", false}}
|
||||
},
|
||||
new TableInfo("wiki_files", "Tenant")
|
||||
{
|
||||
UserIDColumns = new[] {"UserID"},
|
||||
DateColumns = new Dictionary<string, bool> {{"Date", false}}
|
||||
},
|
||||
new TableInfo("wiki_pages", "tenant", "id", IdType.Autoincrement)
|
||||
{
|
||||
UserIDColumns = new[] {"modified_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"modified_on", false}}
|
||||
},
|
||||
new TableInfo("wiki_pages_history", "Tenant")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}}
|
||||
},
|
||||
};
|
||||
|
||||
private readonly RelationInfo[] _tableRelations = new[]
|
||||
{
|
||||
new RelationInfo("bookmarking_bookmark", "ID", "bookmarking_bookmarktag", "BookmarkID"),
|
||||
new RelationInfo("bookmarking_tag", "TagID", "bookmarking_bookmarktag", "TagID"),
|
||||
new RelationInfo("bookmarking_bookmark", "ID", "bookmarking_comment", "BookmarkID"),
|
||||
new RelationInfo("bookmarking_comment", "ID", "bookmarking_comment", "Parent"),
|
||||
new RelationInfo("bookmarking_bookmark", "ID", "bookmarking_userbookmark", "BookmarkID"),
|
||||
new RelationInfo("bookmarking_tag", "TagID", "bookmarking_userbookmarktag", "TagID"),
|
||||
new RelationInfo("bookmarking_userbookmark", "UserBookmarkID", "bookmarking_userbookmarktag", "UserBookmarkID"),
|
||||
new RelationInfo("blogs_comments", "id", "blogs_comments", "parent_id"),
|
||||
new RelationInfo("blogs_posts", "id", "blogs_comments", "post_id"),
|
||||
new RelationInfo("blogs_comments", "id", "blogs_posts", "LastCommentId", null, null, RelationImportance.Low),
|
||||
new RelationInfo("blogs_posts", "id", "blogs_reviewposts", "post_id"),
|
||||
new RelationInfo("blogs_posts", "id", "blogs_tags", "post_id"),
|
||||
new RelationInfo("events_feed", "Id", "events_comment", "Feed"),
|
||||
new RelationInfo("events_comment", "Id", "events_comment", "Parent"),
|
||||
new RelationInfo("events_feed", "Id", "events_poll", "Id"),
|
||||
new RelationInfo("events_pollvariant", "Id", "events_pollanswer", "Variant"),
|
||||
new RelationInfo("events_feed", "Id", "events_pollvariant", "Poll"),
|
||||
new RelationInfo("events_feed", "Id", "events_reader", "Feed"),
|
||||
new RelationInfo("forum_question", "id", "forum_answer", "question_id"),
|
||||
new RelationInfo("forum_answer", "id", "forum_answer_variant", "answer_id"),
|
||||
new RelationInfo("forum_variant", "id", "forum_answer_variant", "variant_id"),
|
||||
new RelationInfo("forum_post", "id", "forum_attachment", "post_id"),
|
||||
new RelationInfo("forum_category", "id", "forum_attachment", "path"),
|
||||
new RelationInfo("forum_thread", "id", "forum_attachment", "path"),
|
||||
new RelationInfo("forum_thread", "id", "forum_lastvisit", "thread_id"),
|
||||
new RelationInfo("forum_topic", "id", "forum_post", "topic_id"),
|
||||
new RelationInfo("forum_post", "id", "forum_post", "parent_post_id"),
|
||||
new RelationInfo("forum_topic", "id", "forum_question", "topic_id"),
|
||||
new RelationInfo("forum_category", "id", "forum_thread", "category_id"),
|
||||
new RelationInfo("forum_post", "id", "forum_thread", "recent_post_id", null, null, RelationImportance.Low),
|
||||
new RelationInfo("forum_topic", "id", "forum_thread", "recent_topic_id", null, null, RelationImportance.Low),
|
||||
new RelationInfo("forum_thread", "id", "forum_topic", "thread_id"),
|
||||
new RelationInfo("forum_question", "id", "forum_topic", "question_id", null, null, RelationImportance.Low),
|
||||
new RelationInfo("forum_post", "id", "forum_topic", "recent_post_id", null, null, RelationImportance.Low),
|
||||
new RelationInfo("forum_topic", "id", "forum_topicwatch", "TopicID"),
|
||||
new RelationInfo("forum_topic", "id", "forum_topic_tag", "topic_id"),
|
||||
new RelationInfo("forum_tag", "id", "forum_topic_tag", "tag_id"),
|
||||
new RelationInfo("forum_question", "id", "forum_variant", "question_id"),
|
||||
new RelationInfo("wiki_comments", "Id", "wiki_comments", "ParentId")
|
||||
};
|
||||
|
||||
public CommunityModuleSpecifics(Helpers helpers)
|
||||
: base(helpers) { }
|
||||
|
||||
public override bool TryAdjustFilePath(bool dump, ColumnMapper columnMapper, ref string filePath)
|
||||
{
|
||||
filePath = PreparePath(dump, columnMapper, "/", filePath);
|
||||
return filePath != null;
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(bool dump, DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, IEnumerable<RelationInfo> relations, ref object value)
|
||||
{
|
||||
relations = relations.ToList();
|
||||
|
||||
if (relations.All(x => x.ChildTable == "forum_attachment" && x.ChildColumn == "path"))
|
||||
{
|
||||
value = PreparePath(dump, columnMapper, "\\", Convert.ToString(value));
|
||||
return value != null;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(dump, connection, columnMapper, table, columnName, relations, ref value);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, ref object value)
|
||||
{
|
||||
var column = columnName.ToLowerInvariant();
|
||||
if (table.Name == "forum_post" && column == "text" ||
|
||||
table.Name == "events_feed" && column == "text" ||
|
||||
table.Name == "events_comment" && column == "comment" ||
|
||||
table.Name == "blogs_posts" && column == "content" ||
|
||||
table.Name == "blogs_comments" && column == "content" ||
|
||||
table.Name == "bookmarking_comment" && column == "content" ||
|
||||
table.Name == "wiki_comments" && column == "body")
|
||||
{
|
||||
value = FCKEditorPathUtility.CorrectStoragePath(value as string, columnMapper.GetTenantMapping());
|
||||
return true;
|
||||
}
|
||||
return base.TryPrepareValue(connection, columnMapper, table, columnName, ref value);
|
||||
}
|
||||
|
||||
protected override string GetSelectCommandConditionText(int tenantId, TableInfo table)
|
||||
{
|
||||
if (table.Name == "forum_answer_variant")
|
||||
{
|
||||
return "inner join forum_answer as t1 on t1.id = t.answer_id where t1.TenantID = " + tenantId;
|
||||
}
|
||||
|
||||
if (table.Name == "forum_variant")
|
||||
{
|
||||
return "inner join forum_question as t1 on t1.id = t.question_id where t1.TenantID = " + tenantId;
|
||||
}
|
||||
|
||||
if (table.Name == "forum_topic_tag")
|
||||
{
|
||||
return "inner join forum_topic as t1 on t1.id = t.topic_id where t1.TenantID = " + tenantId;
|
||||
}
|
||||
|
||||
return base.GetSelectCommandConditionText(tenantId, table);
|
||||
}
|
||||
|
||||
private static string PreparePath(bool dump, ColumnMapper columnMapper, string partsSeparator, string path)
|
||||
{
|
||||
var parts = path.Split(new[] { partsSeparator }, StringSplitOptions.None);
|
||||
|
||||
if (parts.Length != 4)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var categoryId = columnMapper.GetMapping("forum_category", "id", parts[0]);
|
||||
if (categoryId == null)
|
||||
{
|
||||
if (!dump)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
categoryId = parts[0];
|
||||
}
|
||||
|
||||
var threadId = columnMapper.GetMapping("forum_thread", "id", parts[1]);
|
||||
if (threadId == null)
|
||||
{
|
||||
if (!dump)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
threadId = parts[1];
|
||||
}
|
||||
|
||||
parts[0] = categoryId.ToString();
|
||||
parts[1] = threadId.ToString();
|
||||
|
||||
return string.Join(partsSeparator, parts);
|
||||
}
|
||||
}
|
@ -91,51 +91,6 @@ public class CoreModuleSpecifics : ModuleSpecificsBase
|
||||
new RelationInfo("core_group", "id", "core_usergroup", "groupid", typeof(TenantsModuleSpecifics),
|
||||
x => !helpers.IsEmptyOrSystemGroup(Convert.ToString(x["groupid"]))),
|
||||
|
||||
new RelationInfo("crm_contact", "id", "core_acl", "object", typeof(CrmModuleSpecifics),
|
||||
x => Convert.ToString(x["object"]).StartsWith(CrmCompanyAclObjectStart) || Convert.ToString(x["object"]).StartsWith(CrmPersonAclObjectStart)),
|
||||
|
||||
new RelationInfo("crm_deal", "id", "core_acl", "object", typeof(CrmModuleSpecifics),
|
||||
x => Convert.ToString(x["object"]).StartsWith(CrmDealAclObjectStart)),
|
||||
|
||||
new RelationInfo("crm_case", "id", "core_acl", "object", typeof(CrmModuleSpecifics),
|
||||
x => Convert.ToString(x["object"]).StartsWith(CrmCasesAclObjectStart)),
|
||||
|
||||
new RelationInfo("crm_relationship_event", "id", "core_acl", "object", typeof(CrmModuleSpecifics2),
|
||||
x => Convert.ToString(x["object"]).StartsWith(CrmRelationshipEventAclObjectStart)),
|
||||
|
||||
new RelationInfo("calendar_calendars", "id", "core_acl", "object", typeof(CalendarModuleSpecifics),
|
||||
x => Convert.ToString(x["object"]).StartsWith(CalendarCalendarAclObjectStart)),
|
||||
|
||||
new RelationInfo("calendar_events", "id", "core_acl", "object", typeof(CalendarModuleSpecifics),
|
||||
x => Convert.ToString(x["object"]).StartsWith(CalendarEventAclObjectStart)),
|
||||
|
||||
new RelationInfo("projects_projects", "id", "core_subscription", "object", typeof(ProjectsModuleSpecifics),
|
||||
x => ValidateSource(_projectsSourceID, x)),
|
||||
|
||||
new RelationInfo("projects_tasks", "id", "core_subscription", "object", typeof(ProjectsModuleSpecifics),
|
||||
x => ValidateSource(_projectsSourceID, x) && Convert.ToString(x["object"]).StartsWith("Task_")),
|
||||
|
||||
new RelationInfo("projects_messages", "id", "core_subscription", "object", typeof(ProjectsModuleSpecifics),
|
||||
x => ValidateSource(_projectsSourceID, x) && Convert.ToString(x["object"]).StartsWith("Message_")),
|
||||
|
||||
new RelationInfo("projects_milestones", "id", "core_subscription", "object", typeof(ProjectsModuleSpecifics),
|
||||
x => ValidateSource(_projectsSourceID, x) && Convert.ToString(x["object"]).StartsWith("Milestone_")),
|
||||
|
||||
new RelationInfo("bookmarking_bookmark", "ID", "core_subscription", "object", typeof(CommunityModuleSpecifics),
|
||||
x => ValidateSource(_bookmarksSourceID, x) && !string.IsNullOrEmpty(Convert.ToString(x["object"]))),
|
||||
|
||||
new RelationInfo("forum_topic", "id", "core_subscription", "object", typeof(CommunityModuleSpecifics),
|
||||
x => ValidateSource(_forumsSourceID, x) && Convert.ToString(x["action"]) == ForumsNewPostInTopicActionID && !string.IsNullOrEmpty(Convert.ToString(x["object"]))),
|
||||
|
||||
new RelationInfo("forum_thread", "id", "core_subscription", "object", typeof(CommunityModuleSpecifics),
|
||||
x => ValidateSource(_forumsSourceID, x) && Convert.ToString(x["action"]) == ForumsNewPostInThreadActionID && !string.IsNullOrEmpty(Convert.ToString(x["object"]))),
|
||||
|
||||
new RelationInfo("events_feed", "id", "core_subscription", "object", typeof(CommunityModuleSpecifics),
|
||||
x => ValidateSource(_newsSourceID, x) && Convert.ToString(x["action"]) == NewsNewCommentActionID && !string.IsNullOrEmpty(Convert.ToString(x["object"]))),
|
||||
|
||||
new RelationInfo("blogs_posts", "id", "core_subscription", "object", typeof(CommunityModuleSpecifics),
|
||||
x => ValidateSource(_blogsSourceID, x) && Convert.ToString(x["action"]) == BlogsNewCommentActionID),
|
||||
|
||||
new RelationInfo("core_user", "id", "feed_users", "user_id", typeof(CoreModuleSpecifics)),
|
||||
|
||||
new RelationInfo("files_folder", "id", "backup_backup", "storage_base_path", typeof(FilesModuleSpecifics),
|
||||
|
@ -1,356 +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.Data.Backup.Tasks.Modules;
|
||||
|
||||
public class CrmModuleSpecifics : ModuleSpecificsBase
|
||||
{
|
||||
public override ModuleName ModuleName => ModuleName.Crm;
|
||||
public override IEnumerable<TableInfo> Tables => _tables;
|
||||
public override IEnumerable<RelationInfo> TableRelations => _tableRelations;
|
||||
|
||||
private readonly TableInfo[] _tables = new[]
|
||||
{
|
||||
new TableInfo("crm_case", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modifed_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modifed_on", false}}
|
||||
},
|
||||
new TableInfo("crm_contact", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modifed_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modifed_on", false}}
|
||||
},
|
||||
new TableInfo("crm_contact_info", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"last_modifed_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"last_modifed_on", false}}
|
||||
},
|
||||
new TableInfo("crm_deal", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modifed_by", "responsible_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modifed_on", false}, {"expected_close_date", true}, {"actual_close_date", true}}
|
||||
},
|
||||
new TableInfo("crm_deal_milestone", "tenant_id", "id"),
|
||||
new TableInfo("crm_field_description", "tenant_id", "id"),
|
||||
new TableInfo("crm_list_item", "tenant_id", "id"),
|
||||
new TableInfo("crm_projects", "tenant_id"),
|
||||
new TableInfo("crm_tag", "tenant_id", "id"),
|
||||
new TableInfo("crm_task", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modifed_by", "responsible_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modifed_on", false}, {"deadline", true}}
|
||||
},
|
||||
new TableInfo("crm_task_template", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modifed_by", "responsible_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modifed_on", false}}
|
||||
},
|
||||
new TableInfo("crm_task_template_container", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modifed_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modifed_on", false}}
|
||||
},
|
||||
new TableInfo("crm_task_template_task", "tenant_id"),
|
||||
new TableInfo("crm_currency_rate", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modified_on", false}}
|
||||
}
|
||||
};
|
||||
|
||||
private readonly RelationInfo[] _tableRelations = new[]
|
||||
{
|
||||
new RelationInfo("crm_contact", "id", "crm_contact", "company_id"),
|
||||
new RelationInfo("crm_list_item", "id", "crm_contact", "status_id"),
|
||||
new RelationInfo("crm_list_item", "id", "crm_contact", "contact_type_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_contact_info", "contact_id"),
|
||||
new RelationInfo("crm_deal_milestone", "id", "crm_deal", "deal_milestone_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_deal", "contact_id"),
|
||||
new RelationInfo("projects_projects", "id", "crm_projects", "project_id", typeof(ProjectsModuleSpecifics)),
|
||||
new RelationInfo("crm_contact", "id", "crm_projects", "contact_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_task", "entity_id", x => ResolveRelation(x, 0, 4, 5)),
|
||||
new RelationInfo("crm_deal", "id", "crm_task", "entity_id", x => ResolveRelation(x, 1)),
|
||||
new RelationInfo("crm_task", "id", "crm_task", "entity_id", x => ResolveRelation(x, 3)),
|
||||
new RelationInfo("crm_case", "id", "crm_task", "entity_id", x => ResolveRelation(x, 7)),
|
||||
new RelationInfo("crm_contact", "id", "crm_task", "contact_id"),
|
||||
new RelationInfo("crm_list_item", "id", "crm_task", "category_id"),
|
||||
new RelationInfo("crm_list_item", "id", "crm_task_template", "category_id"),
|
||||
new RelationInfo("crm_task_template_container", "id", "crm_task_template", "container_id"),
|
||||
new RelationInfo("crm_task", "id", "crm_task_template_task", "task_id"),
|
||||
new RelationInfo("crm_task_template", "id", "crm_task_template_task", "task_template_id")
|
||||
};
|
||||
|
||||
public CrmModuleSpecifics(Helpers helpers)
|
||||
: base(helpers) { }
|
||||
|
||||
public override bool TryAdjustFilePath(bool dump, ColumnMapper columnMapper, ref string filePath)
|
||||
{
|
||||
var pathMatch = Regex.Match(filePath, @"^photos/\d+/\d+/\d+/contact_(?'contactId'\d+)(?'sizeExtension'_\d+_\d+\.\w+)$", RegexOptions.Compiled);
|
||||
if (pathMatch.Success)
|
||||
{
|
||||
var contactId = columnMapper.GetMapping("crm_contact", "id", pathMatch.Groups["contactId"].Value);
|
||||
if (contactId == null)
|
||||
{
|
||||
if (!dump)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
contactId = pathMatch.Groups["contactId"].Value;
|
||||
}
|
||||
|
||||
var s = contactId.ToString().PadLeft(6, '0');
|
||||
filePath = string.Format("photos/{0}/{1}/{2}/contact_{3}{4}", s.Substring(0, 2), s.Substring(2, 2), s.Substring(4), contactId, pathMatch.Groups["sizeExtension"].Value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool ResolveRelation(DataRowInfo row, params int[] matchingTypes)
|
||||
{
|
||||
var entityType = Convert.ToInt32(row["entity_type"]);
|
||||
|
||||
return matchingTypes.Contains(entityType);
|
||||
}
|
||||
}
|
||||
|
||||
//todo: hack: in future there be no modules only tables!!!
|
||||
public class CrmModuleSpecifics2 : ModuleSpecificsBase
|
||||
{
|
||||
public override string ConnectionStringName => "crm";
|
||||
public override ModuleName ModuleName => ModuleName.Crm2;
|
||||
public override IEnumerable<TableInfo> Tables => _tables;
|
||||
public override IEnumerable<RelationInfo> TableRelations => _tableRelations;
|
||||
|
||||
private readonly TableInfo[] _tables = new[]
|
||||
{
|
||||
new TableInfo("crm_field_value", "tenant_id", "id", IdType.Autoincrement) {UserIDColumns = new[] {"last_modifed_by"}},
|
||||
new TableInfo("crm_entity_contact"),
|
||||
new TableInfo("crm_entity_tag"),
|
||||
new TableInfo("crm_relationship_event", "tenant_id", "id") {UserIDColumns = new[] {"create_by", "last_modifed_by"}},
|
||||
};
|
||||
|
||||
private readonly RelationInfo[] _tableRelations = new[]
|
||||
{
|
||||
new RelationInfo("crm_contact", "id", "crm_field_value", "entity_id", x => ResolveRelation(x, 0, 4, 5)),
|
||||
new RelationInfo("crm_deal", "id", "crm_field_value", "entity_id", x => ResolveRelation(x, 1)),
|
||||
new RelationInfo("crm_task", "id", "crm_field_value", "entity_id", x => ResolveRelation(x, 3)),
|
||||
new RelationInfo("crm_case", "id", "crm_field_value", "entity_id", x => ResolveRelation(x, 7)),
|
||||
new RelationInfo("crm_field_description", "id", "crm_field_value", "field_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_entity_contact", "entity_id", x => ResolveRelation(x, 0, 4, 5)),
|
||||
new RelationInfo("crm_deal", "id", "crm_entity_contact", "entity_id", x => ResolveRelation(x, 1)),
|
||||
new RelationInfo("crm_task", "id", "crm_entity_contact", "entity_id", x => ResolveRelation(x, 3)),
|
||||
new RelationInfo("crm_case", "id", "crm_entity_contact", "entity_id", x => ResolveRelation(x, 7)),
|
||||
new RelationInfo("crm_contact", "id", "crm_entity_contact", "contact_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_entity_tag", "entity_id", x => ResolveRelation(x, 0, 4, 5)),
|
||||
new RelationInfo("crm_deal", "id", "crm_entity_tag", "entity_id", x => ResolveRelation(x, 1)),
|
||||
new RelationInfo("crm_task", "id", "crm_entity_tag", "entity_id", x => ResolveRelation(x, 3)),
|
||||
new RelationInfo("crm_case", "id", "crm_entity_tag", "entity_id", x => ResolveRelation(x, 7)),
|
||||
new RelationInfo("crm_tag", "id", "crm_entity_tag", "tag_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_relationship_event", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 0, 4, 5)),
|
||||
new RelationInfo("crm_deal", "id", "crm_relationship_event", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 1)),
|
||||
new RelationInfo("crm_relationship_event", "id", "crm_relationship_event", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 2)),
|
||||
new RelationInfo("crm_task", "id", "crm_relationship_event", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 3)),
|
||||
new RelationInfo("crm_case", "id", "crm_relationship_event", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 7)),
|
||||
new RelationInfo("crm_contact", "id", "crm_relationship_event", "contact_id", typeof(CrmModuleSpecifics)),
|
||||
new RelationInfo("crm_list_item", "id", "crm_relationship_event", "category_id", typeof(CrmModuleSpecifics)),
|
||||
new RelationInfo("crm_relationship_event", "id", "crm_field_value", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 2)),
|
||||
new RelationInfo("crm_relationship_event", "id", "crm_entity_tag", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 2)),
|
||||
new RelationInfo("crm_relationship_event", "id", "crm_entity_contact", "entity_id", typeof(CrmModuleSpecifics), x => ResolveRelation(x, 2)),
|
||||
new RelationInfo("mail_mail", "id", "crm_relationship_event", "content", typeof(MailModuleSpecifics), x => Convert.ToInt32(x["category_id"]) == -3),
|
||||
};
|
||||
|
||||
public CrmModuleSpecifics2(Helpers helpers) : base(helpers) { }
|
||||
|
||||
public override bool TryAdjustFilePath(bool dump, ColumnMapper columnMapper, ref string filePath)
|
||||
{
|
||||
var match = Regex.Match(filePath, @"(?<=folder_\d+/message_)\d+(?=\.html)"); //todo:
|
||||
if (match.Success)
|
||||
{
|
||||
var mappedMessageId = Convert.ToString(columnMapper.GetMapping("mail_mail", "id", match.Value));
|
||||
|
||||
if (dump && string.IsNullOrEmpty(mappedMessageId))
|
||||
{
|
||||
mappedMessageId = match.Value;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(mappedMessageId))
|
||||
{
|
||||
filePath = string.Format("folder_{0}/message_{1}.html", (Convert.ToInt32(mappedMessageId) / 1000 + 1) * 1000, mappedMessageId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return base.TryAdjustFilePath(dump, columnMapper, ref filePath);
|
||||
}
|
||||
|
||||
protected override string GetSelectCommandConditionText(int tenantId, TableInfo table)
|
||||
{
|
||||
if (table.Name == "crm_entity_contact")
|
||||
{
|
||||
return "inner join crm_contact as t1 on t1.id = t.contact_id where t1.tenant_id = " + tenantId;
|
||||
}
|
||||
|
||||
if (table.Name == "crm_entity_tag")
|
||||
{
|
||||
return "inner join crm_tag as t1 on t1.id = t.tag_id where t1.tenant_id = " + tenantId;
|
||||
}
|
||||
|
||||
return base.GetSelectCommandConditionText(tenantId, table);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, RelationInfo relation, ref object value)
|
||||
{
|
||||
if (relation.ChildTable == "crm_relationship_event" && relation.ChildColumn == "content")
|
||||
{
|
||||
value = Regex.Replace(
|
||||
Convert.ToString(value),
|
||||
@"(?<=""message_id"":|/Products/CRM/HttpHandlers/filehandler\.ashx\?action=mailmessage&message_id=)\d+",
|
||||
match =>
|
||||
{
|
||||
var mappedMessageId = Convert.ToString(columnMapper.GetMapping(relation.ParentTable, relation.ParentColumn, match.Value));
|
||||
var success = !string.IsNullOrEmpty(mappedMessageId);
|
||||
return success ? mappedMessageId : match.Value;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
return base.TryPrepareValue(connection, columnMapper, relation, ref value);
|
||||
}
|
||||
|
||||
private static bool ResolveRelation(DataRowInfo row, params int[] matchingTypes)
|
||||
{
|
||||
var entityType = Convert.ToInt32(row["entity_type"]);
|
||||
return matchingTypes.Contains(entityType);
|
||||
}
|
||||
}
|
||||
|
||||
public class CrmInvoiceModuleSpecifics : ModuleSpecificsBase
|
||||
{
|
||||
public override ModuleName ModuleName => ModuleName.CrmInvoice;
|
||||
public override string ConnectionStringName => "crm";
|
||||
public override IEnumerable<TableInfo> Tables
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<TableInfo>
|
||||
{
|
||||
new TableInfo("crm_organisation_logo", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}}
|
||||
},
|
||||
new TableInfo("crm_invoice", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modified_on", false}, {"due_date", false}, {"issue_date", false}}
|
||||
},
|
||||
new TableInfo("crm_invoice_item", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modified_on", false}}
|
||||
},
|
||||
new TableInfo("crm_invoice_line", "tenant_id", "id"),
|
||||
new TableInfo("crm_invoice_tax", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modified_on", false}}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<RelationInfo> TableRelations
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<RelationInfo>
|
||||
{
|
||||
new RelationInfo("crm_contact", "id", "crm_invoice", "contact_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_invoice", "consignee_id"),
|
||||
new RelationInfo("crm_contact", "id", "crm_invoice", "entity_id", x => ResolveRelation(x, 0, 4, 5)),
|
||||
new RelationInfo("crm_deal", "id", "crm_invoice", "entity_id", x => ResolveRelation(x, 1)),
|
||||
new RelationInfo("crm_task", "id", "crm_invoice", "entity_id", x => ResolveRelation(x, 3)),
|
||||
new RelationInfo("crm_case", "id", "crm_invoice", "entity_id", x => ResolveRelation(x, 7)),
|
||||
new RelationInfo("files_file", "id", "crm_invoice", "file_id", typeof(FilesModuleSpecifics)),
|
||||
new RelationInfo("crm_invoice_tax", "id", "crm_invoice_item", "invoice_tax1_id"),
|
||||
new RelationInfo("crm_invoice_tax", "id", "crm_invoice_item", "invoice_tax2_id"),
|
||||
new RelationInfo("crm_invoice_tax", "id", "crm_invoice_line", "invoice_tax1_id"),
|
||||
new RelationInfo("crm_invoice_tax", "id", "crm_invoice_line", "invoice_tax2_id"),
|
||||
new RelationInfo("crm_invoice", "id", "crm_invoice_line", "invoice_id"),
|
||||
new RelationInfo("crm_invoice_item", "id", "crm_invoice_line", "invoice_item_id"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public CrmInvoiceModuleSpecifics(Helpers helpers) : base(helpers) { }
|
||||
|
||||
protected override bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, ref object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (table.Name == "crm_invoice" && columnName == "json_data")
|
||||
{
|
||||
var data = JObject.Parse((string)value);
|
||||
|
||||
var oldValue = Convert.ToInt32(data["LogoBase64Id"]);
|
||||
if (oldValue != 0)
|
||||
{
|
||||
data["LogoBase64Id"] = Convert.ToInt32(columnMapper.GetMapping("crm_organisation_logo", "id", oldValue));
|
||||
}
|
||||
|
||||
oldValue = Convert.ToInt32(data["DeliveryAddressID"]);
|
||||
if (oldValue != 0)
|
||||
{
|
||||
data["DeliveryAddressID"] = Convert.ToInt32(columnMapper.GetMapping("crm_contact_info", "id", oldValue));
|
||||
}
|
||||
|
||||
oldValue = Convert.ToInt32(data["BillingAddressID"]);
|
||||
if (oldValue != 0)
|
||||
{
|
||||
data["BillingAddressID"] = Convert.ToInt32(columnMapper.GetMapping("crm_contact_info", "id", oldValue));
|
||||
}
|
||||
|
||||
value = data.ToString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(connection, columnMapper, table, columnName, ref value);
|
||||
}
|
||||
|
||||
private static bool ResolveRelation(DataRowInfo row, params int[] matchingTypes)
|
||||
{
|
||||
var entityType = Convert.ToInt32(row["entity_type"]);
|
||||
|
||||
return matchingTypes.Contains(entityType);
|
||||
}
|
||||
}
|
@ -74,11 +74,6 @@ public class FilesModuleSpecifics : ModuleSpecificsBase
|
||||
}),
|
||||
new RelationInfo("core_user", "id", "files_security", "subject", typeof(TenantsModuleSpecifics)),
|
||||
new RelationInfo("core_group", "id", "files_security", "subject", typeof(TenantsModuleSpecifics)),
|
||||
new RelationInfo("crm_deal", "id", "files_bunch_objects", "right_node", typeof(CrmModuleSpecifics),
|
||||
x => Convert.ToString(x["right_node"]).StartsWith(_bunchRightNodeStartCrmOpportunity)),
|
||||
|
||||
new RelationInfo("projects_projects", "id", "files_bunch_objects", "right_node", typeof(ProjectsModuleSpecifics),
|
||||
x => Convert.ToString(x["right_node"]).StartsWith(_bunchRightNodeStartProject, StringComparison.InvariantCultureIgnoreCase)),
|
||||
|
||||
new RelationInfo("files_folder", "id", "files_bunch_objects", "left_node"),
|
||||
new RelationInfo("files_folder", "id", "files_file", "folder_id"),
|
||||
@ -318,18 +313,6 @@ public class FilesModuleSpecifics2 : ModuleSpecificsBase
|
||||
|
||||
private readonly RelationInfo[] _rels = new[]
|
||||
{
|
||||
new RelationInfo("projects_messages", "id", "files_tag", "name", typeof(ProjectsModuleSpecifics),
|
||||
x => Convert.ToString(x["name"]).StartsWith(_tagStartMessage, StringComparison.InvariantCultureIgnoreCase)),
|
||||
|
||||
new RelationInfo("projects_tasks", "id", "files_tag", "name", typeof(ProjectsModuleSpecifics),
|
||||
x => Convert.ToString(x["name"]).StartsWith(_tagStartTask, StringComparison.InvariantCultureIgnoreCase)),
|
||||
|
||||
new RelationInfo("projects_projects", "id", "files_tag", "name", typeof(ProjectsModuleSpecifics),
|
||||
x => Convert.ToString(x["name"]).StartsWith(_tagStartProject, StringComparison.InvariantCultureIgnoreCase)),
|
||||
|
||||
new RelationInfo("crm_relationship_event", "id", "files_tag", "name", typeof(CrmModuleSpecifics2),
|
||||
x => Convert.ToString(x["name"]).StartsWith(_tagStartRelationshipEvent, StringComparison.InvariantCultureIgnoreCase)),
|
||||
|
||||
new RelationInfo("files_tag", "id", "files_tag_link", "tag_id", typeof(FilesModuleSpecifics)),
|
||||
|
||||
new RelationInfo("files_file", "id", "files_tag_link", "entry_id", typeof(FilesModuleSpecifics),
|
||||
|
@ -29,16 +29,9 @@ namespace ASC.Data.Backup.Tasks.Modules;
|
||||
public enum ModuleName
|
||||
{
|
||||
Audit,
|
||||
Calendar,
|
||||
Community,
|
||||
Core,
|
||||
Crm,
|
||||
Crm2,
|
||||
CrmInvoice,
|
||||
Files,
|
||||
Files2,
|
||||
Mail,
|
||||
Projects,
|
||||
Tenants,
|
||||
WebStudio
|
||||
}
|
||||
|
@ -1,304 +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.Data.Backup.Tasks.Modules;
|
||||
|
||||
internal class MailModuleSpecifics : ModuleSpecificsBase
|
||||
{
|
||||
public override ModuleName ModuleName => ModuleName.Mail;
|
||||
public override IEnumerable<TableInfo> Tables => _tables;
|
||||
public override IEnumerable<RelationInfo> TableRelations => _tableRelations;
|
||||
|
||||
private readonly ILogger<ModuleProvider> _logger;
|
||||
private readonly Helpers _helpers;
|
||||
|
||||
private readonly TableInfo[] _tables = new[]
|
||||
{
|
||||
new TableInfo("mail_attachment", "tenant", "id"),
|
||||
new TableInfo("mail_chain", "tenant") {UserIDColumns = new[] {"id_user"}},
|
||||
new TableInfo("mail_contacts", "tenant", "id") {UserIDColumns = new[] {"id_user"}},
|
||||
new TableInfo("mail_folder_counters", "tenant") {UserIDColumns = new[] {"id_user"}},
|
||||
new TableInfo("mail_mail", "tenant", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"id_user"},
|
||||
DateColumns = new Dictionary<string, bool> {{"date_received", false}, {"date_sent", false}, {"chain_date", false}}
|
||||
},
|
||||
new TableInfo("mail_mailbox", "tenant", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"id_user"},
|
||||
DateColumns = new Dictionary<string, bool> {{"begin_date", false}}
|
||||
},
|
||||
new TableInfo("mail_tag", "tenant", "id") {UserIDColumns = new[] {"id_user"}},
|
||||
new TableInfo("mail_tag_addresses", "tenant"),
|
||||
new TableInfo("mail_tag_mail", "tenant") {UserIDColumns = new[] {"id_user"}},
|
||||
new TableInfo("mail_chain_x_crm_entity", "id_tenant"),
|
||||
new TableInfo("mail_mailbox_signature", "tenant"),
|
||||
new TableInfo("mail_mailbox_autoreply", "tenant"),
|
||||
new TableInfo("mail_mailbox_autoreply_history", "tenant"),
|
||||
new TableInfo("mail_contact_info", "tenant", "id") {UserIDColumns = new[] {"id_user"}},
|
||||
new TableInfo("mail_mailbox_provider", idColumn: "id"),
|
||||
new TableInfo("mail_mailbox_domain", idColumn: "id"),
|
||||
new TableInfo("mail_mailbox_server", idColumn: "id")
|
||||
};
|
||||
|
||||
private readonly RelationInfo[] _tableRelations = new[]
|
||||
{
|
||||
new RelationInfo("mail_mail", "id", "mail_attachment", "id_mail"),
|
||||
new RelationInfo("mail_mailbox", "id", "mail_chain", "id_mailbox"),
|
||||
new RelationInfo("mail_tag", "id", "mail_chain", "tags"),
|
||||
new RelationInfo("crm_tag", "id", "mail_chain", "tags", typeof(CrmModuleSpecifics)),
|
||||
new RelationInfo("mail_mailbox", "id", "mail_mail", "id_mailbox"),
|
||||
new RelationInfo("crm_tag", "id", "mail_tag", "crm_id", typeof(CrmModuleSpecifics)),
|
||||
new RelationInfo("mail_tag", "id", "mail_tag_addresses", "id_tag", x => Convert.ToInt32(x["id_tag"]) > 0),
|
||||
new RelationInfo("crm_tag", "id", "mail_tag_addresses", "id_tag", typeof(CrmModuleSpecifics), x => Convert.ToInt32(x["id_tag"]) < 0),
|
||||
new RelationInfo("mail_mail", "id", "mail_tag_mail", "id_mail"),
|
||||
new RelationInfo("mail_tag", "id", "mail_tag_mail", "id_tag", x => Convert.ToInt32(x["id_tag"]) > 0),
|
||||
new RelationInfo("crm_tag", "id", "mail_tag_mail", "id_tag", typeof(CrmModuleSpecifics), x => Convert.ToInt32(x["id_tag"]) < 0),
|
||||
new RelationInfo("mail_mailbox", "id", "mail_chain_x_crm_entity", "id_mailbox"),
|
||||
new RelationInfo("crm_contact", "id", "mail_chain_x_crm_entity", "entity_id", typeof(CrmModuleSpecifics), x => Convert.ToInt32(x["entity_type"]) == 1),
|
||||
new RelationInfo("crm_case", "id", "mail_chain_x_crm_entity", "entity_id", typeof(CrmModuleSpecifics), x => Convert.ToInt32(x["entity_type"]) == 2),
|
||||
new RelationInfo("crm_deal", "id", "mail_chain_x_crm_entity", "entity_id", typeof(CrmModuleSpecifics), x => Convert.ToInt32(x["entity_type"]) == 3),
|
||||
new RelationInfo("mail_mailbox", "id", "mail_mailbox_signature", "id_mailbox"),
|
||||
new RelationInfo("files_folder", "id", "mail_mailbox", "email_in_folder", typeof(FilesModuleSpecifics)),
|
||||
new RelationInfo("mail_mailbox", "id", "mail_mailbox_autoreply", "id_mailbox"),
|
||||
new RelationInfo("mail_mailbox", "id", "mail_mailbox_autoreply_history", "id_mailbox"),
|
||||
new RelationInfo("mail_contacts", "id", "mail_contact_info", "id_contact"),
|
||||
new RelationInfo("mail_mailbox_provider", "id", "mail_mailbox_domain", "id_provider"),
|
||||
new RelationInfo("mail_mailbox_server", "id", "mail_mailbox", "id_smtp_server"),
|
||||
new RelationInfo("mail_mailbox_server", "id", "mail_mailbox", "id_in_server")
|
||||
};
|
||||
|
||||
public MailModuleSpecifics(ILogger<ModuleProvider> logger, Helpers helpers) : base(helpers)
|
||||
{
|
||||
_logger = logger;
|
||||
_helpers = helpers;
|
||||
}
|
||||
|
||||
public override bool TryAdjustFilePath(bool dump, ColumnMapper columnMapper, ref string filePath)
|
||||
{
|
||||
//todo: hack: will be changed later
|
||||
filePath = Regex.Replace(filePath, @"^[-\w]+(?=/)", match => dump ? match.Value : columnMapper.GetUserMapping(match.Value));
|
||||
return !filePath.StartsWith("/");
|
||||
}
|
||||
|
||||
public override void PrepareData(DataTable data)
|
||||
{
|
||||
if (data.TableName == "mail_mailbox")
|
||||
{
|
||||
var address = data.Columns.Cast<DataColumn>().Single(c => c.ColumnName == "address");
|
||||
var smtp = data.Columns.Cast<DataColumn>().Single(c => c.ColumnName == "smtp_password");
|
||||
var pop3 = data.Columns.Cast<DataColumn>().Single(c => c.ColumnName == "pop3_password");
|
||||
var token = data.Columns.Cast<DataColumn>().Single(c => c.ColumnName == "token");
|
||||
for (var i = 0; i < data.Rows.Count; i++)
|
||||
{
|
||||
var row = data.Rows[i];
|
||||
try
|
||||
{
|
||||
row[smtp] = _helpers.CreateHash2(row[smtp] as string);
|
||||
row[pop3] = _helpers.CreateHash2(row[pop3] as string);
|
||||
row[token] = _helpers.CreateHash2(row[token] as string);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorCanNotPrepareData(row[address] as string, ex);
|
||||
data.Rows.Remove(row);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream PrepareData(string key, Stream stream, ColumnMapper columnMapper)
|
||||
{
|
||||
if (!key.EndsWith("body.html"))
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
using (var streamReader = new StreamReader(stream, Encoding.UTF8, true, 1024, true))
|
||||
{
|
||||
var data = streamReader.ReadToEnd();
|
||||
data = Regex.Replace(data, @"(htmleditorfiles|aggregator)(\/0\/|\/[\d]+\/\d\d\/\d\d\/)([-\w]+(?=/))",
|
||||
match => "/" + TenantPath.CreatePath(columnMapper.GetTenantMapping().ToString()) + "/" + columnMapper.GetUserMapping(match.Groups[3].Value));
|
||||
|
||||
var content = Encoding.UTF8.GetBytes(data);
|
||||
|
||||
stream.Position = 0;
|
||||
stream.Write(content, 0, content.Length);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
protected override string GetSelectCommandConditionText(int tenantId, TableInfo table)
|
||||
{
|
||||
//optimization: 1) do not include "deleted" rows, 2) backup mail only for the last 30 days
|
||||
switch (table.Name)
|
||||
{
|
||||
case "mail_mailbox_provider":
|
||||
return string.Format("where t.id in " +
|
||||
"(select distinct t2.id_provider from mail_mailbox t1 " +
|
||||
"inner join mail_mailbox_server t2 on t2.id in (t1.id_in_server, t1.id_smtp_server) and t2.is_user_data = 1 " +
|
||||
"where t1.tenant = {0} and t1.is_removed = 0)", tenantId);
|
||||
|
||||
// mail_mailbox_domain.id_provider not in index
|
||||
case "mail_mailbox_domain":
|
||||
return string.Format("where t.id_provider in " +
|
||||
"(select distinct t2.id_provider from mail_mailbox t1 " +
|
||||
"inner join mail_mailbox_server t2 on t2.id in (t1.id_in_server, t1.id_smtp_server) and t2.is_user_data = 1 " +
|
||||
"where t1.tenant = {0} and t1.is_removed = 0)", tenantId);
|
||||
|
||||
case "mail_mailbox_server":
|
||||
return string.Format("where t.id in " +
|
||||
"(select distinct t2.id from mail_mailbox t1 " +
|
||||
"inner join mail_mailbox_server t2 on t2.id in (t1.id_in_server, t1.id_smtp_server) and t2.is_user_data = 1 " +
|
||||
"where t1.tenant = {0} and t1.is_removed = 0)", tenantId);
|
||||
|
||||
case "mail_mailbox":
|
||||
return string.Format("where t.is_removed = 0 and t.tenant = {0}", tenantId);
|
||||
|
||||
//condition on chain_date because of Bug 18855 - transfer mail only for the last 30 days
|
||||
case "mail_mail":
|
||||
return string.Format("inner join mail_mailbox t1 on t1.id = t.id_mailbox " +
|
||||
"where t.tenant = {0} and t1.tenant = {0} and t.is_removed = 0 and t1.is_removed = 0 and t.chain_date > '{1}'",
|
||||
tenantId,
|
||||
DateTime.UtcNow.Subtract(TimeSpan.FromDays(30)).ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
case "mail_attachment":
|
||||
case "mail_tag_mail":
|
||||
return string.Format("inner join mail_mail as t1 on t1.id = t.id_mail " +
|
||||
"inner join mail_mailbox as t2 on t2.id = t1.id_mailbox " +
|
||||
"where t1.tenant = {0} and t2.tenant = {0} and t1.is_removed = 0 and t2.is_removed = 0 and t1.chain_date > '{1}'",
|
||||
tenantId,
|
||||
DateTime.UtcNow.Subtract(TimeSpan.FromDays(30)).ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
case "mail_chain":
|
||||
return string.Format("inner join mail_mailbox t1 on t1.id = t.id_mailbox " +
|
||||
"where t.tenant = {0} and t1.is_removed = 0",
|
||||
tenantId);
|
||||
|
||||
default:
|
||||
return base.GetSelectCommandConditionText(tenantId, table);
|
||||
}
|
||||
}
|
||||
|
||||
protected override string GetDeleteCommandConditionText(int tenantId, TableInfo table)
|
||||
{
|
||||
//delete all rows regardless of whether there is is_removed = 1 or not
|
||||
return base.GetSelectCommandConditionText(tenantId, table);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareRow(bool dump, DbConnection connection, ColumnMapper columnMapper, TableInfo table, DataRowInfo row, out Dictionary<string, object> preparedRow)
|
||||
{
|
||||
if (table.Name == "mail_mailbox")
|
||||
{
|
||||
var boxType = row["is_server_mailbox"];
|
||||
if (boxType != null && Convert.ToBoolean(int.Parse(boxType.ToString())))
|
||||
{
|
||||
preparedRow = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return base.TryPrepareRow(dump, connection, columnMapper, table, row, out preparedRow);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(bool dump, DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, IEnumerable<RelationInfo> relations, ref object value)
|
||||
{
|
||||
relations = relations.ToList();
|
||||
if (relations.All(x => x.ChildTable == "mail_chain" && x.ChildColumn == "tags"))
|
||||
{
|
||||
var mappedTags = new List<string>();
|
||||
|
||||
foreach (var tag in value.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => Convert.ToInt32(x)))
|
||||
{
|
||||
object tagId;
|
||||
if (tag > 0)
|
||||
{
|
||||
tagId = columnMapper.GetMapping("mail_tag", "id", tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
tagId = columnMapper.GetMapping("crm_tag", "id", -tag);
|
||||
if (tagId != null)
|
||||
{
|
||||
tagId = -Convert.ToInt32(tagId);
|
||||
}
|
||||
}
|
||||
if (tagId != null)
|
||||
{
|
||||
mappedTags.Add(tagId.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
value = string.Join(",", mappedTags.ToArray());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(dump, connection, columnMapper, table, columnName, relations, ref value);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, RelationInfo relation, ref object value)
|
||||
{
|
||||
if (relation.ParentTable == "crm_tag" && relation.ChildColumn == "id_tag"
|
||||
&& (relation.ChildTable == "mail_tag_mail" || relation.ChildTable == "mail_tag_addresses"))
|
||||
{
|
||||
var crmTagId = columnMapper.GetMapping(relation.ParentTable, relation.ParentColumn, -Convert.ToInt32(value));
|
||||
if (crmTagId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = -Convert.ToInt32(crmTagId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(connection, columnMapper, relation, ref value);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, ref object value)
|
||||
{
|
||||
if (table.Name == "mail_mailbox" && (columnName == "smtp_password" || columnName == "pop3_password") && value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = _helpers.CreateHash(value as string); // save original hash
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
_logger.ErrorCanNotPrepareValue(value, err);
|
||||
value = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(connection, columnMapper, table, columnName, ref value);
|
||||
}
|
||||
}
|
@ -37,15 +37,8 @@ public class ModuleProvider
|
||||
{
|
||||
new TenantsModuleSpecifics(coreSettings,helpers),
|
||||
new AuditModuleSpecifics(helpers),
|
||||
new CommunityModuleSpecifics(helpers),
|
||||
new CalendarModuleSpecifics(helpers),
|
||||
new ProjectsModuleSpecifics(helpers),
|
||||
new CrmModuleSpecifics(helpers),
|
||||
new FilesModuleSpecifics(logger,helpers),
|
||||
new MailModuleSpecifics(logger,helpers),
|
||||
new CrmModuleSpecifics2(helpers),
|
||||
new FilesModuleSpecifics2(helpers),
|
||||
new CrmInvoiceModuleSpecifics(helpers),
|
||||
new WebStudioModuleSpecifics(helpers),
|
||||
new CoreModuleSpecifics(helpers)
|
||||
}
|
||||
@ -56,10 +49,6 @@ public class ModuleProvider
|
||||
return storageModuleName switch
|
||||
{
|
||||
"files" => AllModules.FirstOrDefault(m => m.ModuleName == ModuleName.Files),
|
||||
"projects" => AllModules.FirstOrDefault(m => m.ModuleName == ModuleName.Projects),
|
||||
"crm" => AllModules.FirstOrDefault(m => m.ModuleName == (storageDomainName == "mail_messages" ? ModuleName.Crm2 : ModuleName.Crm)),
|
||||
"forum" => AllModules.FirstOrDefault(m => m.ModuleName == ModuleName.Community),
|
||||
"mailaggregator" => AllModules.FirstOrDefault(m => m.ModuleName == ModuleName.Mail),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
@ -1,204 +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.Data.Backup.Tasks.Modules;
|
||||
|
||||
public class ProjectsModuleSpecifics : ModuleSpecificsBase
|
||||
{
|
||||
public override ModuleName ModuleName => ModuleName.Projects;
|
||||
public override IEnumerable<TableInfo> Tables => _tables;
|
||||
public override IEnumerable<RelationInfo> TableRelations => _tableRelations;
|
||||
|
||||
private readonly TableInfo[] _tables = new[]
|
||||
{
|
||||
new TableInfo("projects_comments", "tenant_id", "comment_id", IdType.Autoincrement) {UserIDColumns = new[] {"create_by"}},
|
||||
new TableInfo("projects_following_project_participant") {UserIDColumns = new[] {"participant_id"}},
|
||||
new TableInfo("projects_messages", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by"},
|
||||
DateColumns = new Dictionary<string, bool> {{"create_on", false}, {"last_modified_on", false}}
|
||||
},
|
||||
new TableInfo("projects_milestones", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by", "responsible_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"deadline", true}, {"status_changed", false}, {"create_on", false}, {"last_modified_on", false}}
|
||||
},
|
||||
new TableInfo("projects_projects", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by", "responsible_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"status_changed", false}, {"create_on", false}, {"last_modified_on", false}}
|
||||
},
|
||||
new TableInfo("projects_project_participant", "tenant") {UserIDColumns = new[] {"participant_id"}},
|
||||
new TableInfo("projects_project_tag"),
|
||||
new TableInfo("projects_report_template", "tenant_id", "id") {UserIDColumns = new[] {"create_by"}},
|
||||
new TableInfo("projects_subtasks", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by", "responsible_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"status_changed", false}, {"create_on", false}, {"last_modified_on", false}}
|
||||
},
|
||||
new TableInfo("projects_tags", "tenant_id", "id"),
|
||||
new TableInfo("projects_tasks", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "last_modified_by", "responsible_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"status_changed", true}, {"deadline", true}, {"create_on", false}, {"last_modified_on", true}, {"start_date", true}}
|
||||
},
|
||||
new TableInfo("projects_tasks_responsible", "tenant_id") {UserIDColumns = new[] {"responsible_id"}},
|
||||
new TableInfo("projects_templates", "tenant_id", "id") {UserIDColumns = new[] {"create_by", "last_modified_by"}},
|
||||
new TableInfo("projects_time_tracking", "tenant_id", "id")
|
||||
{
|
||||
UserIDColumns = new[] {"create_by", "person_id"},
|
||||
DateColumns = new Dictionary<string, bool> {{"date", true}, {"create_on", false}, {"status_changed", true}}
|
||||
},
|
||||
new TableInfo("projects_tasks_links", "tenant_id"),
|
||||
new TableInfo("projects_tasks_order", "tenant_id")
|
||||
};
|
||||
|
||||
private readonly RelationInfo[] _tableRelations = new[]
|
||||
{
|
||||
new RelationInfo("projects_comments", "id", "projects_comments", "parent_id"),
|
||||
new RelationInfo("projects_messages", "id", "projects_comments", "target_uniq_id", x => Convert.ToString(x["target_uniq_id"]).StartsWith("Message_", StringComparison.InvariantCultureIgnoreCase)),
|
||||
new RelationInfo("projects_tasks", "id", "projects_comments", "target_uniq_id", x => Convert.ToString(x["target_uniq_id"]).StartsWith("Task_", StringComparison.InvariantCultureIgnoreCase)),
|
||||
new RelationInfo("projects_milestones", "id", "projects_comments", "target_uniq_id", x => Convert.ToString(x["target_uniq_id"]).StartsWith("Milestone_", StringComparison.InvariantCultureIgnoreCase)),
|
||||
new RelationInfo("projects_projects", "id", "projects_following_project_participant", "project_id"),
|
||||
new RelationInfo("projects_projects", "id", "projects_messages", "project_id"),
|
||||
new RelationInfo("projects_projects", "id", "projects_milestones", "project_id"),
|
||||
new RelationInfo("projects_projects", "id", "projects_project_participant", "project_id"),
|
||||
new RelationInfo("projects_projects", "id", "projects_project_tag", "project_id"),
|
||||
new RelationInfo("projects_tags", "id", "projects_project_tag", "tag_id"),
|
||||
new RelationInfo("projects_tasks", "id", "projects_subtasks", "task_id"),
|
||||
new RelationInfo("projects_projects", "id", "projects_tasks", "project_id"),
|
||||
new RelationInfo("projects_milestones", "id", "projects_tasks", "milestone_id"),
|
||||
new RelationInfo("projects_tasks", "id", "projects_tasks_responsible", "task_id"),
|
||||
new RelationInfo("projects_projects", "id", "projects_time_tracking", "project_id"),
|
||||
new RelationInfo("projects_tasks", "id", "projects_time_tracking", "relative_task_id"),
|
||||
new RelationInfo("projects_tasks", "id", "projects_tasks_links", "task_id"),
|
||||
new RelationInfo("projects_tasks", "id", "projects_tasks_links", "parent_id"),
|
||||
new RelationInfo("projects_projects", "id", "projects_tasks_order", "project_id"),
|
||||
new RelationInfo("projects_tasks", "id", "projects_tasks_order", "task_order"),
|
||||
new RelationInfo("projects_milestones", "id", "projects_tasks_order", "task_order")
|
||||
};
|
||||
|
||||
public ProjectsModuleSpecifics(Helpers helpers) : base(helpers) { }
|
||||
|
||||
public override bool TryAdjustFilePath(bool dump, ColumnMapper columnMapper, ref string filePath)
|
||||
{
|
||||
var match = Regex.Match(filePath, @"^thumbs/\d+/\d+/\d+/(?'fileId'\d+)\.jpg$");
|
||||
if (match.Success)
|
||||
{
|
||||
var fileId = columnMapper.GetMapping("files_file", "id", match.Groups["fileId"].Value);
|
||||
if (fileId == null)
|
||||
{
|
||||
if (!dump)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fileId = match.Groups["fileId"].Value;
|
||||
}
|
||||
|
||||
var s = fileId.ToString().PadRight(6, '0');
|
||||
filePath = string.Format("thumbs/{0}/{1}/{2}/{3}.jpg", s.Substring(0, 2), s.Substring(2, 2), s.Substring(4), fileId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override string GetSelectCommandConditionText(int tenantId, TableInfo table)
|
||||
{
|
||||
if (table.Name == "projects_project_tag" || table.Name == "projects_following_project_participant")
|
||||
{
|
||||
return "inner join projects_projects as t1 on t1.id = t.project_id where t1.tenant_id = " + tenantId;
|
||||
}
|
||||
|
||||
return base.GetSelectCommandConditionText(tenantId, table);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, ref object value)
|
||||
{
|
||||
|
||||
if (table.Name == "projects_comments" && columnName == "content" ||
|
||||
table.Name == "projects_messages" && columnName == "content")
|
||||
{
|
||||
value = FCKEditorPathUtility.CorrectStoragePath(value as string, columnMapper.GetTenantMapping());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(connection, columnMapper, table, columnName, ref value);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(DbConnection connection, ColumnMapper columnMapper, RelationInfo relation, ref object value)
|
||||
{
|
||||
if (relation.ChildTable == "projects_comments" && relation.ChildColumn == "target_uniq_id")
|
||||
{
|
||||
var valParts = value.ToString().Split('_');
|
||||
|
||||
var entityId = columnMapper.GetMapping(relation.ParentTable, relation.ParentColumn, valParts[1]);
|
||||
if (entityId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = string.Format("{0}_{1}", valParts[0], entityId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(connection, columnMapper, relation, ref value);
|
||||
}
|
||||
|
||||
protected override bool TryPrepareValue(bool dump, DbConnection connection, ColumnMapper columnMapper, TableInfo table, string columnName, IEnumerable<RelationInfo> relations, ref object value)
|
||||
{
|
||||
if (table.Name == "projects_tasks_order" && columnName == "task_order")
|
||||
{
|
||||
value = Regex.Replace(
|
||||
Convert.ToString(value),
|
||||
@"(?<=""tasks"":\[(\d+,)*)\d+,?",
|
||||
match =>
|
||||
{
|
||||
var mappedId = Convert.ToString(columnMapper.GetMapping("projects_tasks", "id", match.Value.TrimEnd(',')));
|
||||
return !string.IsNullOrEmpty(mappedId) && match.Value.EndsWith(',') ? mappedId + "," : mappedId;
|
||||
},
|
||||
RegexOptions.Compiled);
|
||||
|
||||
value = Regex.Replace(
|
||||
Convert.ToString(value),
|
||||
@"(?<=""milestones"":\[(\d+,)*)\d+,?",
|
||||
match =>
|
||||
{
|
||||
var mappedId = Convert.ToString(columnMapper.GetMapping("projects_milestones", "id", match.Value.TrimEnd(',')));
|
||||
return !string.IsNullOrEmpty(mappedId) && match.Value.EndsWith(',') ? mappedId + "," : mappedId;
|
||||
},
|
||||
RegexOptions.Compiled);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryPrepareValue(dump, connection, columnMapper, table, columnName, relations, ref value);
|
||||
}
|
||||
}
|
@ -41,11 +41,7 @@ public class WebStudioModuleSpecifics : ModuleSpecificsBase
|
||||
new TableInfo("webstudio_uservisit", "tenantid") {InsertMethod = InsertMethod.None}
|
||||
};
|
||||
|
||||
private readonly RelationInfo[] _relations = new[]
|
||||
{
|
||||
new RelationInfo("crm_organisation_logo", "id", "webstudio_settings", "Data", typeof(CrmInvoiceModuleSpecifics),
|
||||
x => _crmSettingsId == new Guid(Convert.ToString(x["ID"])))
|
||||
};
|
||||
private readonly RelationInfo[] _relations = new RelationInfo[0];
|
||||
|
||||
public WebStudioModuleSpecifics(Helpers helpers) : base(helpers) { }
|
||||
|
||||
|
@ -24,25 +24,32 @@
|
||||
// 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
|
||||
|
||||
using ASC.EventBus.Log;
|
||||
|
||||
namespace ASC.Notify.IntegrationEvents.EventHandling;
|
||||
|
||||
[Scope]
|
||||
public class EncryptionDataStorageRequestedIntegrationEventHandler : IIntegrationEventHandler<EncryptionDataStorageRequestedIntegration>
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly EncryptionWorker _encryptionWorker;
|
||||
|
||||
public EncryptionDataStorageRequestedIntegrationEventHandler(EncryptionWorker encryptionWorker)
|
||||
|
||||
public EncryptionDataStorageRequestedIntegrationEventHandler(EncryptionWorker encryptionWorker,
|
||||
ILogger<EncryptionDataStorageRequestedIntegrationEventHandler> logger)
|
||||
{
|
||||
_encryptionWorker = encryptionWorker;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task Handle(EncryptionDataStorageRequestedIntegration @event)
|
||||
{
|
||||
// using (_logger.BeginScope(new[] { new KeyValuePair<string, object>("integrationEventContext", $"{@event.Id}-{Program.AppName}") }))
|
||||
// {
|
||||
// _logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
// _logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
_encryptionWorker.Start(@event.EncryptionSettings, @event.ServerRootPath);
|
||||
|
||||
_encryptionWorker.Start(@event.EncryptionSettings, @event.ServerRootPath);
|
||||
|
||||
await Task.CompletedTask;
|
||||
await Task.CompletedTask;
|
||||
// }
|
||||
}
|
||||
}
|
@ -24,6 +24,8 @@
|
||||
// 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
|
||||
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
Args = args,
|
||||
@ -32,24 +34,57 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger(typeof(Startup).Namespace);
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
try
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
logger.Info("Configuring web host ({applicationContext})...", Program.AppName);
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var app = builder.Build();
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.Configure(app, app.Environment);
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
startup.Configure(app, app.Environment);
|
||||
|
||||
logger.Info("Starting web host ({applicationContext})...", Program.AppName);
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string Namespace = typeof(Startup).Namespace;
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.') + 1);
|
||||
}
|
@ -24,6 +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.Migration.Core;
|
||||
|
||||
public class Startup : BaseStartup
|
||||
{
|
||||
|
@ -24,6 +24,8 @@
|
||||
// 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
|
||||
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
Args = args,
|
||||
@ -32,19 +34,52 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
builder.Services.AddClearEventsServices();
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger("ASC.ClearEvents");
|
||||
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
|
||||
try
|
||||
{
|
||||
builder.Register(context.Configuration, false, false);
|
||||
});
|
||||
logger.Info("Configuring web host ({applicationContext})...", Program.AppName);
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.Services.AddClearEventsServices();
|
||||
|
||||
var app = builder.Build();
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
|
||||
{
|
||||
builder.Register(context.Configuration, false, false);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
logger.Info("Starting web host ({applicationContext})...", Program.AppName);
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string Namespace = "ASC.ClearEvents";
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
await app.RunWithTasksAsync();
|
@ -32,9 +32,9 @@ public static class ConfigurationManagerExtension
|
||||
this ConfigurationManager config,
|
||||
IHostEnvironment env)
|
||||
{
|
||||
config.AddJsonFile("notify.json")
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", true)
|
||||
.AddJsonFile("backup.json");
|
||||
config.AddJsonFile("notify.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile("backup.json", optional: false, reloadOnChange: true);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
@ -62,5 +62,5 @@ global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
global using Microsoft.Extensions.Hosting.WindowsServices;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
|
||||
global using Newtonsoft.Json;
|
||||
global using ASC.Data.Backup.Extension;
|
||||
|
@ -41,11 +41,14 @@ public class BackupDeleteScheldureRequestedIntegrationEventHandler : IIntegratio
|
||||
}
|
||||
|
||||
public async Task Handle(IntegrationEvent @event)
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
_backupService.DeleteSchedule(@event.TenantId);
|
||||
|
||||
await Task.CompletedTask;
|
||||
{
|
||||
using (_logger.BeginScope(new[] { new KeyValuePair<string, object>("integrationEventContext", $"{@event.Id}-{Program.AppName}") }))
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
_backupService.DeleteSchedule(@event.TenantId);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@ -54,36 +54,38 @@ public class BackupRequestedIntegrationEventHandler : IIntegrationEventHandler<B
|
||||
|
||||
public async Task Handle(BackupRequestIntegrationEvent @event)
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
if (!@event.Redelivered)
|
||||
using (_logger.BeginScope(new[] { new KeyValuePair<string, object>("integrationEventContext", $"{@event.Id}-{Program.AppName}") }))
|
||||
{
|
||||
if (_backupWorker.IsInstanceTooBusy())
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
if (!@event.Redelivered)
|
||||
{
|
||||
throw new IntegrationEventRejectExeption(@event.Id);
|
||||
if (_backupWorker.IsInstanceTooBusy())
|
||||
{
|
||||
throw new IntegrationEventRejectExeption(@event.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_tenantManager.SetCurrentTenant(@event.TenantId);
|
||||
_securityContext.AuthenticateMeWithoutCookie(_authManager.GetAccountByID(@event.TenantId, @event.CreateBy));
|
||||
_tenantManager.SetCurrentTenant(@event.TenantId);
|
||||
_securityContext.AuthenticateMeWithoutCookie(_authManager.GetAccountByID(@event.TenantId, @event.CreateBy));
|
||||
|
||||
if (@event.IsScheduled)
|
||||
{
|
||||
_backupWorker.StartScheduledBackup(new EF.Model.BackupSchedule
|
||||
if (@event.IsScheduled)
|
||||
{
|
||||
BackupMail = @event.BackupMail,
|
||||
BackupsStored = @event.BackupsStored,
|
||||
StorageBasePath = @event.StorageBasePath,
|
||||
StorageParams = JsonConvert.SerializeObject(@event.StorageParams),
|
||||
StorageType = @event.StorageType,
|
||||
TenantId = @event.TenantId
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_backupAjaxHandler.StartBackup(@event.StorageType, @event.StorageParams, @event.BackupMail);
|
||||
}
|
||||
_backupWorker.StartScheduledBackup(new EF.Model.BackupSchedule
|
||||
{
|
||||
BackupsStored = @event.BackupsStored,
|
||||
StorageBasePath = @event.StorageBasePath,
|
||||
StorageParams = JsonConvert.SerializeObject(@event.StorageParams),
|
||||
StorageType = @event.StorageType,
|
||||
TenantId = @event.TenantId
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_backupAjaxHandler.StartBackup(@event.StorageType, @event.StorageParams);
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@ -54,24 +54,27 @@ public class BackupRestoreRequestedIntegrationEventHandler : IIntegrationEventHa
|
||||
|
||||
public async Task Handle(BackupRestoreRequestIntegrationEvent @event)
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
if (!@event.Redelivered)
|
||||
using (_logger.BeginScope(new[] { new KeyValuePair<string, object>("integrationEventContext", $"{@event.Id}-{Program.AppName}") }))
|
||||
{
|
||||
if (_backupWorker.IsInstanceTooBusy())
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
if (!@event.Redelivered)
|
||||
{
|
||||
throw new IntegrationEventRejectExeption(@event.Id);
|
||||
if (_backupWorker.IsInstanceTooBusy())
|
||||
{
|
||||
throw new IntegrationEventRejectExeption(@event.Id);
|
||||
}
|
||||
}
|
||||
|
||||
_tenantManager.SetCurrentTenant(@event.TenantId);
|
||||
_securityContext.AuthenticateMeWithoutCookie(_authManager.GetAccountByID(@event.TenantId, @event.CreateBy));
|
||||
|
||||
_backupAjaxHandler.StartRestore(@event.BackupId,
|
||||
@event.StorageType,
|
||||
@event.StorageParams,
|
||||
@event.Notify);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
_tenantManager.SetCurrentTenant(@event.TenantId);
|
||||
_securityContext.AuthenticateMeWithoutCookie(_authManager.GetAccountByID(@event.TenantId, @event.CreateBy));
|
||||
|
||||
_backupAjaxHandler.StartRestore(@event.BackupId,
|
||||
@event.StorageType,
|
||||
@event.StorageParams,
|
||||
@event.Notify);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
@ -46,8 +46,8 @@ internal static partial class BackupSchedulerServiceLogger
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "{count} backups are to schedule")]
|
||||
public static partial void DebugBackupsSchedule(this ILogger<BackupSchedulerService> logger, int count);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Start scheduled backup: {tenantId}, {backupMail}, {storageType}, {storageBasePath}")]
|
||||
public static partial void DebugStartScheduledBackup(this ILogger<BackupSchedulerService> logger, int tenantId, bool backupMail, BackupStorageType storageType, string storageBasePath);
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Start scheduled backup: {tenantId}, {storageType}, {storageBasePath}")]
|
||||
public static partial void DebugStartScheduledBackup(this ILogger<BackupSchedulerService> logger, int tenantId, BackupStorageType storageType, string storageBasePath);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Skip portal {tenantId} not paid")]
|
||||
public static partial void DebugNotPaid(this ILogger<BackupSchedulerService> logger, int tenantId);
|
||||
|
@ -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
|
||||
|
||||
using ASC.Data.Backup.Extension;
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
@ -34,39 +34,65 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddBackupBackgroundTasksConfiguration(builder.Environment)
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
startup.Configure(app, app.Environment);
|
||||
|
||||
var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IEventBus>();
|
||||
|
||||
eventBus.Subscribe<BackupRequestIntegrationEvent, BackupRequestedIntegrationEventHandler>();
|
||||
eventBus.Subscribe<BackupRestoreRequestIntegrationEvent, BackupRestoreRequestedIntegrationEventHandler>();
|
||||
eventBus.Subscribe<IntegrationEvent, BackupDeleteScheldureRequestedIntegrationEventHandler>();
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger(typeof(Startup).Namespace);
|
||||
|
||||
try
|
||||
{
|
||||
logger.Info("Configuring web host ({applicationContext})...", Program.AppName);
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
startup.Configure(app, app.Environment);
|
||||
|
||||
var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IEventBus>();
|
||||
|
||||
eventBus.Subscribe<BackupRequestIntegrationEvent, BackupRequestedIntegrationEventHandler>();
|
||||
eventBus.Subscribe<BackupRestoreRequestIntegrationEvent, BackupRestoreRequestedIntegrationEventHandler>();
|
||||
eventBus.Subscribe<IntegrationEvent, BackupDeleteScheldureRequestedIntegrationEventHandler>();
|
||||
|
||||
logger.Info("Starting web host ({applicationContext})...", Program.AppName);
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string Namespace = typeof(Startup).Namespace;
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1).Replace(".","");
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
"launchBrowser": false,
|
||||
"environmentVariables": {
|
||||
"$STORAGE_ROOT": "../../../Data",
|
||||
"log__name": "backup",
|
||||
"log__name": "backup.backgoundtasks",
|
||||
"log__dir": "../../../Logs",
|
||||
"core__products__folder": "../../../products",
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
@ -17,7 +17,7 @@
|
||||
"launchBrowser": false,
|
||||
"environmentVariables": {
|
||||
"$STORAGE_ROOT": "../../../Data",
|
||||
"log__name": "backup",
|
||||
"log__name": "backup.backgoundtasks",
|
||||
"log__dir": "../../../Logs",
|
||||
"core__products__folder": "../../../products",
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
|
@ -115,14 +115,13 @@ public sealed class BackupSchedulerService : BackgroundService
|
||||
|
||||
backupRepository.SaveBackupSchedule(schedule);
|
||||
|
||||
_logger.DebugStartScheduledBackup(schedule.TenantId, schedule.BackupMail, schedule.StorageType, schedule.StorageBasePath);
|
||||
_logger.DebugStartScheduledBackup(schedule.TenantId, schedule.StorageType, schedule.StorageBasePath);
|
||||
|
||||
_eventBus.Publish(new BackupRequestIntegrationEvent(
|
||||
tenantId: schedule.TenantId,
|
||||
storageBasePath: schedule.StorageBasePath,
|
||||
storageParams: JsonConvert.DeserializeObject<Dictionary<string, string>>(schedule.StorageParams),
|
||||
storageType: schedule.StorageType,
|
||||
backupMail: schedule.BackupMail,
|
||||
createBy: ASC.Core.Configuration.Constants.CoreSystem.ID,
|
||||
isScheduled: true,
|
||||
backupsStored: schedule.BackupsStored
|
||||
|
@ -76,7 +76,6 @@ public class BackupController : ControllerBase
|
||||
/// <param name="storageParams">Storage parameters</param>
|
||||
/// <param name="backupsStored">Max of the backup's stored copies</param>
|
||||
/// <param name="cronParams">Cron parameters</param>
|
||||
/// <param name="backupMail">Include mail in the backup</param>
|
||||
/// <category>Backup</category>
|
||||
[HttpPost("createbackupschedule")]
|
||||
public bool CreateBackupSchedule(BackupScheduleDto backupSchedule)
|
||||
@ -94,7 +93,7 @@ public class BackupController : ControllerBase
|
||||
Hour = backupSchedule.CronParams.Hour == null ? 0 : Int32.Parse(backupSchedule.CronParams.Hour),
|
||||
Day = backupSchedule.CronParams.Day == null ? 0 : Int32.Parse(backupSchedule.CronParams.Day),
|
||||
};
|
||||
_backupHandler.CreateSchedule(storageType, storageParams, backupStored, cron, backupSchedule.BackupMail);
|
||||
_backupHandler.CreateSchedule(storageType, storageParams, backupStored, cron);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -120,7 +119,6 @@ public class BackupController : ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="storageType">Storage Type</param>
|
||||
/// <param name="storageParams">Storage Params</param>
|
||||
/// <param name="backupMail">Include mail in the backup</param>
|
||||
/// <category>Backup</category>
|
||||
/// <returns>Backup Progress</returns>
|
||||
[HttpPost("startbackup")]
|
||||
@ -137,7 +135,6 @@ public class BackupController : ControllerBase
|
||||
tenantId: _tenantId,
|
||||
storageParams: storageParams,
|
||||
storageType: storageType,
|
||||
backupMail: backup.BackupMail,
|
||||
createBy: _currentUserId
|
||||
));
|
||||
|
||||
|
@ -29,6 +29,5 @@ namespace ASC.Data.Backup.ApiModels;
|
||||
public class BackupDto
|
||||
{
|
||||
public string StorageType { get; set; }
|
||||
public bool BackupMail { get; set; }
|
||||
public IEnumerable<ItemKeyValuePair<object, object>> StorageParams { get; set; }
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ public class BackupScheduleDto
|
||||
public IEnumerable<ItemKeyValuePair<object, object>> StorageParams { get; set; }
|
||||
public string BackupsStored { get; set; }
|
||||
public Cron CronParams { get; set; }
|
||||
public bool BackupMail { get; set; }
|
||||
}
|
||||
|
||||
public class Cron
|
||||
|
@ -32,8 +32,8 @@ public static class ConfigurationManagerExtension
|
||||
this ConfigurationManager config,
|
||||
IHostEnvironment env)
|
||||
{
|
||||
config.AddJsonFile("notify.json")
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", true);
|
||||
config.AddJsonFile("notify.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
@ -58,3 +58,9 @@ global using Microsoft.Extensions.Hosting;
|
||||
global using Microsoft.Extensions.Hosting.WindowsServices;
|
||||
|
||||
global using static ASC.Data.Backup.BackupAjaxHandler;
|
||||
|
||||
global using ASC.Data.Backup.Extension;
|
||||
|
||||
global using NLog.Extensions.Logging;
|
||||
global using NLog.Web;
|
||||
global using NLog.AWS.Logger;
|
@ -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
|
||||
|
||||
using ASC.Data.Backup.Extension;
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
@ -34,26 +34,59 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddBackupConfiguration(builder.Environment)
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger(typeof(Startup).Namespace);
|
||||
try
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
logger.Info("Configuring web host ({applicationContext})...", Program.AppName);
|
||||
|
||||
var app = builder.Build();
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
startup.Configure(app, app.Environment);
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
startup.Configure(app, app.Environment);
|
||||
|
||||
logger.Info("Starting web host ({applicationContext})...", Program.AppName);
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string Namespace = typeof(Startup).Namespace;
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.') + 1);
|
||||
}
|
@ -55,7 +55,7 @@ public class Startup : BaseStartup
|
||||
app.MapWhen(
|
||||
context => context.Request.Path.ToString().EndsWith("backupFileUpload.ashx"),
|
||||
appBranch =>
|
||||
{
|
||||
{
|
||||
appBranch.UseBackupFileUploadHandler();
|
||||
});
|
||||
}
|
||||
|
@ -32,9 +32,9 @@ public static class ConfigurationManagerExtension
|
||||
this ConfigurationManager config,
|
||||
IHostEnvironment env)
|
||||
{
|
||||
config.AddJsonFile($"appsettings.services.json", true)
|
||||
.AddJsonFile("notify.json")
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", true);
|
||||
config.AddJsonFile($"appsettings.services.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("notify.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||
|
||||
|
||||
return config;
|
||||
|
@ -74,11 +74,14 @@ public class NotifyInvokeSendMethodRequestedIntegrationEventHandler : IIntegrati
|
||||
|
||||
|
||||
public async Task Handle(NotifyInvokeSendMethodRequestedIntegrationEvent @event)
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
InvokeSendMethod(@event.NotifyInvoke);
|
||||
|
||||
await Task.CompletedTask;
|
||||
{
|
||||
using (_logger.BeginScope(new[] { new KeyValuePair<string, object>("integrationEventContext", $"{@event.Id}-{Program.AppName}") }))
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
InvokeSendMethod(@event.NotifyInvoke);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@ -54,10 +54,13 @@ public class NotifySendMessageRequestedIntegrationEventHandler : IIntegrationEve
|
||||
|
||||
public async Task Handle(NotifySendMessageRequestedIntegrationEvent @event)
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
using (_logger.BeginScope(new[] { new KeyValuePair<string, object>("integrationEventContext", $"{@event.Id}-{Program.AppName}") }))
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
SendNotifyMessage(@event.NotifyMessage);
|
||||
SendNotifyMessage(@event.NotifyMessage);
|
||||
|
||||
await Task.CompletedTask;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,8 @@
|
||||
// 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
|
||||
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
Args = args,
|
||||
@ -32,33 +34,63 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddNotifyConfiguration(builder.Environment)
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger(typeof(Startup).Namespace);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
|
||||
try
|
||||
{
|
||||
builder.Register(context.Configuration);
|
||||
});
|
||||
logger.Info("Configuring web host ({applicationContext})...", Program.AppName);
|
||||
builder.Host.ConfigureDefault();
|
||||
|
||||
var app = builder.Build();
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.Configure(app);
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IEventBus>();
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
|
||||
{
|
||||
builder.Register(context.Configuration);
|
||||
});
|
||||
|
||||
eventBus.Subscribe<NotifyInvokeSendMethodRequestedIntegrationEvent, NotifyInvokeSendMethodRequestedIntegrationEventHandler>();
|
||||
eventBus.Subscribe<NotifySendMessageRequestedIntegrationEvent, NotifySendMessageRequestedIntegrationEventHandler>();
|
||||
var app = builder.Build();
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
startup.Configure(app);
|
||||
|
||||
var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IEventBus>();
|
||||
|
||||
eventBus.Subscribe<NotifyInvokeSendMethodRequestedIntegrationEvent, NotifyInvokeSendMethodRequestedIntegrationEventHandler>();
|
||||
eventBus.Subscribe<NotifySendMessageRequestedIntegrationEvent, NotifySendMessageRequestedIntegrationEventHandler>();
|
||||
|
||||
logger.Info("Starting web host ({applicationContext})...", Program.AppName);
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
public static string Namespace = typeof(Startup).Namespace;
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.') + 1);
|
||||
}
|
@ -32,9 +32,9 @@ public static class ConfigurationManagerExtension
|
||||
this ConfigurationManager config,
|
||||
IHostEnvironment env)
|
||||
{
|
||||
config.AddJsonFile($"appsettings.services.json", true)
|
||||
.AddJsonFile("notify.json")
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", true);
|
||||
config.AddJsonFile($"appsettings.services.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("notify.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||
|
||||
|
||||
return config;
|
||||
|
@ -25,6 +25,9 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using ASC.Notify.Extension;
|
||||
using ASC.Studio.Notify;
|
||||
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
@ -34,25 +37,58 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddStudioNotifyConfiguration(builder.Environment)
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger(typeof(Startup).Namespace);
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
|
||||
try
|
||||
{
|
||||
builder.Register(context.Configuration);
|
||||
});
|
||||
logger.Info("Configuring web host ({applicationContext})...", Program.AppName);
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var app = builder.Build();
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.Configure(app);
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
|
||||
{
|
||||
builder.Register(context.Configuration);
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
startup.Configure(app);
|
||||
|
||||
logger.Info("Starting web host ({applicationContext})...", Program.AppName);
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string Namespace = typeof(Startup).Namespace;
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1).Replace(".", "");
|
||||
}
|
@ -24,6 +24,8 @@
|
||||
// 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.Studio.Notify;
|
||||
|
||||
public class Startup : BaseWorkerStartup
|
||||
{
|
||||
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment)
|
||||
|
@ -32,8 +32,8 @@ public static class ConfigurationManagerExtension
|
||||
this ConfigurationManager config,
|
||||
IHostEnvironment env)
|
||||
{
|
||||
config.AddJsonFile("notify.json")
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", true);
|
||||
config.AddJsonFile("notify.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile($"notify.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
@ -48,8 +48,11 @@ public class TelegramSendMessageRequestedIntegrationEventHandler : IIntegrationE
|
||||
|
||||
public async Task Handle(NotifySendTelegramMessageRequestedIntegrationEvent @event)
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
using (_logger.BeginScope(new[] { new KeyValuePair<string, object>("integrationEventContext", $"{@event.Id}-{Program.AppName}") }))
|
||||
{
|
||||
_logger.InformationHandlingIntegrationEvent(@event.Id, Program.AppName, @event);
|
||||
|
||||
await _telegramHandler.SendMessage(@event.NotifyMessage);
|
||||
await _telegramHandler.SendMessage(@event.NotifyMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
// 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
|
||||
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
Args = args,
|
||||
@ -32,34 +34,60 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddTelegramConfiguration(builder.Environment)
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger(typeof(Startup).Namespace);
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
try
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var app = builder.Build();
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.Configure(app, app.Environment);
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IEventBus>();
|
||||
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
{
|
||||
startup.ConfigureContainer(containerBuilder);
|
||||
});
|
||||
|
||||
eventBus.Subscribe<ASC.Core.Common.Notify.IntegrationEvents.Events.NotifySendTelegramMessageRequestedIntegrationEvent, TelegramSendMessageRequestedIntegrationEventHandler>();
|
||||
var app = builder.Build();
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
startup.Configure(app, app.Environment);
|
||||
|
||||
var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IEventBus>();
|
||||
|
||||
eventBus.Subscribe<ASC.Core.Common.Notify.IntegrationEvents.Events.NotifySendTelegramMessageRequestedIntegrationEvent, TelegramSendMessageRequestedIntegrationEventHandler>();
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
public static string Namespace = typeof(Startup).Namespace;
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.') + 1);
|
||||
}
|
@ -31,7 +31,7 @@ public static class ConfigurationManagerExtension
|
||||
public static ConfigurationManager AddWebhookConfiguration(
|
||||
this ConfigurationManager config)
|
||||
{
|
||||
config.AddJsonFile($"appsettings.services.json", true);
|
||||
config.AddJsonFile($"appsettings.services.json", optional: false, reloadOnChange: true);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
// 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
|
||||
|
||||
using NLog;
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
Args = args,
|
||||
@ -32,21 +34,54 @@ var options = new WebApplicationOptions
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault();
|
||||
|
||||
builder.Configuration.AddDefaultConfiguration(builder.Environment)
|
||||
.AddWebhookConfiguration()
|
||||
.AddEnvironmentVariables()
|
||||
.AddCommandLine(args);
|
||||
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
startup.Configure(app);
|
||||
|
||||
await app.RunWithTasksAsync();
|
||||
var logger = NLog.LogManager.Setup()
|
||||
.SetupExtensions(s =>
|
||||
{
|
||||
s.RegisterLayoutRenderer("application-context", (logevent) => Program.AppName);
|
||||
})
|
||||
.LoadConfiguration(builder.Configuration, builder.Environment)
|
||||
.GetLogger(typeof(Startup).Namespace);
|
||||
|
||||
try
|
||||
{
|
||||
logger.Info("Configuring web host ({applicationContext})...", Program.AppName);
|
||||
builder.Host.ConfigureDefault();
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
||||
startup.ConfigureServices(builder.Services);
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
startup.Configure(app);
|
||||
|
||||
logger.Info("Starting web host ({applicationContext})...", Program.AppName);
|
||||
await app.RunWithTasksAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (logger != null)
|
||||
{
|
||||
logger.Error(ex, "Program terminated unexpectedly ({applicationContext})!", Program.AppName);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
public static string Namespace = typeof(Startup).Namespace;
|
||||
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.') + 1).Replace(".", "");
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
throwConfigExceptions="false"
|
||||
autoReload="true">
|
||||
<extensions>
|
||||
<add assembly="NLog.Web.AspNetCore"/>
|
||||
<add assembly="NLog.AWS.Logger" />
|
||||
</extensions>
|
||||
|
||||
<extensions>
|
||||
<add assembly="NLog.Web.AspNetCore"/>
|
||||
</extensions>
|
||||
<variable name="dir" value="..\Logs\"/>
|
||||
<variable name="name" value="web"/>
|
||||
<conversionPattern value=""/>
|
||||
|
||||
<variable name="dir" value="..\Logs\"/>
|
||||
<variable name="name" value="web"/>
|
||||
<conversionPattern value=""/>
|
||||
|
||||
<targets async="true">
|
||||
<default-target-parameters type="File" maxArchiveDays="30" archiveNumbering="DateAndSequence" archiveEvery="Day" enableArchiveFileCompression="true" archiveAboveSize="52428800" archiveDateFormat="MM-dd" layout="${date:format=yyyy-MM-dd HH\:mm\:ss,fff} ${level:uppercase=true} [${threadid}] ${logger} - ${message} ${exception:format=ToString}"/>
|
||||
<target name="web" type="File" fileName="${var:dir}${var:name}.log" />
|
||||
<target name="sql" type="File" fileName="${var:dir}${var:name}.sql.log" layout="${date:universalTime=true:format=yyyy-MM-dd HH\:mm\:ss,fff}|${threadid}|${event-properties:item=elapsed}|${replace:inner=${event-properties:item=commandText}:searchFor=\\r\\n|\\s:replaceWith= :regex=true}|${event-properties:item=parameters}"/>
|
||||
<target name="ownFile-web" type="File" fileName="${var:dir}${var:name}.asp.log" layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<logger name="ASC.SQL" minlevel="Debug" writeTo="sql" final ="true" />
|
||||
<logger name="ASC*" minlevel="Debug" writeTo="web" />
|
||||
<logger name="Microsoft.AspNetCore.Hosting.Diagnostics" minlevel="Debug" writeTo="ownFile-web" final="true" />
|
||||
<logger name="Microsoft.*" maxlevel="Off" final="true" />
|
||||
</rules>
|
||||
<targets async="true">
|
||||
<default-target-parameters type="File" maxArchiveDays="30" archiveNumbering="DateAndSequence" archiveEvery="Day" enableArchiveFileCompression="true" archiveAboveSize="52428800" archiveDateFormat="MM-dd" layout="${date:format=yyyy-MM-dd HH\:mm\:ss,fff} ${level:uppercase=true} [${threadid}] ${logger} - ${message} ${exception:format=ToString}"/>
|
||||
<target name="web" type="File" fileName="${var:dir}${var:name}.log" />
|
||||
<target name="sql" type="File" fileName="${var:dir}${var:name}.sql.log" layout="${date:universalTime=true:format=yyyy-MM-dd HH\:mm\:ss,fff}|${threadid}|${event-properties:item=elapsed}|${replace:inner=${event-properties:item=commandText}:searchFor=\\r\\n|\\s:replaceWith= :regex=true}|${event-properties:item=parameters}"/>
|
||||
<target name="ownFile-web" type="File" fileName="${var:dir}${var:name}.asp.log" layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
|
||||
<target type="AWSTarget" name="aws" logGroup="/docspace/${var:name}/instance/instance_id/general" region="us-east-1" LibraryLogFileName="">
|
||||
<layout xsi:type="JsonLayout" includeAllProperties="true">
|
||||
<attribute name="date" layout="${date:format=yyyy-MM-dd HH\:mm\:ss,fff}" />
|
||||
<attribute name="level" layout="${level:upperCase=true}"/>
|
||||
<attribute name="applicationContext" layout="${application-context}"/>
|
||||
<attribute name="sourceContext" layout="${logger}"/>
|
||||
<attribute name="threadId" layout="${threadid}"/>
|
||||
<attribute name="message" layout="${message}" />
|
||||
<attribute name="exception" layout="${exception:format=ToString}" />
|
||||
</layout>
|
||||
</target>
|
||||
<target type="AWSTarget" name="aws_sql" logGroup="/docspace/${var:name}/instance/instance_id/sql" region="us-east-1" LibraryLogFileName="">
|
||||
<layout xsi:type="JsonLayout" includeAllProperties="true">
|
||||
<attribute name="date" layout="${date:universalTime=true:format=yyyy-MM-dd HH\:mm\:ss,fff}" />
|
||||
<attribute name="applicationContext" layout="${application-context}"/>
|
||||
<attribute name="sourceContext" layout="${logger}"/>
|
||||
<attribute name="threadId" layout="${threadid}"/>
|
||||
<attribute name="elapsed" layout="${event-properties:item=elapsed}"/>
|
||||
<attribute name="commandText" layout="${replace:inner=${event-properties:item=commandText}:searchFor=\\r\\n|\\s:replaceWith= :regex=true}" />
|
||||
</layout>
|
||||
</target>
|
||||
</targets>
|
||||
<rules>
|
||||
<logger name="ASC.SQL" minlevel="Debug" writeTo="sql" final="true" />
|
||||
<logger name="ASC*" minlevel="Debug" writeTo="web" />
|
||||
<logger name="Microsoft.AspNetCore.Hosting.Diagnostics" minlevel="Debug" writeTo="ownFile-web" final="true" />
|
||||
<logger name="Microsoft.*" maxlevel="Off" final="true" />
|
||||
</rules>
|
||||
</nlog>
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arxivlər",
|
||||
"BackToParentFolderButton": "Ana qovluğa qayıt",
|
||||
"ByAuthor": "Müəllif",
|
||||
"ByCreationDate": "Yaradıldı",
|
||||
"ByLastModifiedDate": "Dəyişdirilib",
|
||||
"ByCreation": "Yaradıldı",
|
||||
"ByLastModified": "Dəyişdirilib",
|
||||
"ByTitle": "Başlıq",
|
||||
"CommonEmptyContainerDescription": "'Ümumi' bölməsi portal inzibatçısı tərəfindən bütün istifadəçilərlə paylaşılan faylları ehtiva edir. Orada yalnız portal inzibatçıları fayl yarada bilər. İstifadəçilərə bölmə daxilində müəyyən bir qovluğa tam giriş verilə bilər. Bu şəkildə bu qovluqda fayllar yarada/yükləyə biləcəklər.",
|
||||
"ContainsSpecCharacter": "Başlıqda aşağıdakı simvollardan heç biri ola bilməz: *+: \"<>? |/ ",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Архиви",
|
||||
"BackToParentFolderButton": "Обратно към родителската папка",
|
||||
"ByAuthor": "Автор",
|
||||
"ByCreationDate": "Създаден",
|
||||
"ByLastModifiedDate": "Модифициран",
|
||||
"ByCreation": "Създаден",
|
||||
"ByLastModified": "Модифициран",
|
||||
"ByTitle": "Заглавие",
|
||||
"CommonEmptyContainerDescription": "Разделът 'Често срещани' съдържа файлове, които са споделени с всички потребители от администратора на портала. Само администраторите на портала могат да създават файлове там. Потребителите могат да се сдобият с Пълен достъп до определена папка в рамките на раздела. По този начин те ще могат да създават/качват файлове във всяка папка.",
|
||||
"ContainsSpecCharacter": "Заглавието не може да съдържа някой от следните символи: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archivy",
|
||||
"BackToParentFolderButton": "Zpět do nadřazené složky",
|
||||
"ByAuthor": "Autor",
|
||||
"ByCreationDate": "Vytvořeno",
|
||||
"ByLastModifiedDate": "Upraveno",
|
||||
"ByCreation": "Vytvořeno",
|
||||
"ByLastModified": "Upraveno",
|
||||
"ByTitle": "Název",
|
||||
"CommonEmptyContainerDescription": "Sekce 'Sdílené' obsahuje soubory, které správce portálu sdílí se všemi uživateli. Soubory v ní mohou vytvářet pouze správci portálu. Uživatelům lze v rámci sekce udělit plný přístup k určité složce. Tímto způsobem budou moci vytvářet/nahrávat soubory právě v této složce. ",
|
||||
"ContainsSpecCharacter": "Název nesmí obsahovat žádný z následujících znaků: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archive",
|
||||
"BackToParentFolderButton": "Zurück zum übergeordneten Ordner",
|
||||
"ByAuthor": "Verfasser",
|
||||
"ByCreationDate": "Erstellt",
|
||||
"ByLastModifiedDate": "Verändert",
|
||||
"ByCreation": "Erstellt",
|
||||
"ByLastModified": "Verändert",
|
||||
"ByTitle": "Titel",
|
||||
"CommonEmptyContainerDescription": "In gemeinsamen Dokumenten finden Sie Dateien, auf denen alle Benutzer Zugriff haben. Nur Portaladministratoren können dort Dateien erstellen. Benutzern kann der vollständigen Zugriff auf einen bestimmten Ordner innerhalb des Abschnitts erteilt werden. Dann können Sie Dateien in diesem Ordner erstellen / hochladen.",
|
||||
"ContainsSpecCharacter": "Der Titel darf diese Symbole nicht beinhalten: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Αρχειοθετήσεις",
|
||||
"BackToParentFolderButton": "Επιστροφή στον γονικό φάκελο",
|
||||
"ByAuthor": "Δημιουργός",
|
||||
"ByCreationDate": "Δημιουργήθηκε",
|
||||
"ByLastModifiedDate": "Τροποποιήθηκε",
|
||||
"ByCreation": "Δημιουργήθηκε",
|
||||
"ByLastModified": "Τροποποιήθηκε",
|
||||
"ByTitle": "Τίτλος",
|
||||
"CommonEmptyContainerDescription": "Η ενότητα «Κοινά» περιέχει αρχεία που μοιράζονται σε όλους τους χρήστες από τον διαχειριστή της πύλης. Μόνο οι διαχειριστές της πύλης μπορούν να δημιουργήσουν αρχεία εκεί. Οι χρήστες μπορούν να έχουν πλήρη πρόσβαση σε έναν συγκεκριμένο φάκελο εντός της ενότητας. Έτσι, θα μπορούν να δημιουργούν/μεταφορτώνουν αρχεία σε αυτόν τον φάκελο.",
|
||||
"ContainsSpecCharacter": "Ο τίτλος δεν μπορεί να περιέχει τους ακόλουθους χαρακτήρες: *+:\"<>?|/",
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"AdvancedFilter": "Advanced search options",
|
||||
"AdvancedFilter": "Search options",
|
||||
"All": "All",
|
||||
"AllFiles": "All files",
|
||||
"Archives": "Archives",
|
||||
@ -7,8 +7,8 @@
|
||||
"ArchiveEmptyScreenHeader": "No archived rooms here yet",
|
||||
"BackToParentFolderButton": "Back to parent folder",
|
||||
"ByAuthor": "Author",
|
||||
"ByCreationDate": "Created",
|
||||
"ByLastModifiedDate": "Modified",
|
||||
"ByCreation": "Created",
|
||||
"ByLastModified": "Modified",
|
||||
"ByOwner": "Owner",
|
||||
"ByTitle": "Title",
|
||||
"CollaborationRooms": "Collaboration",
|
||||
@ -26,7 +26,9 @@
|
||||
"EmptyFolderHeader": "No files in this folder",
|
||||
"EmptyRecycleBin": "Empty Trash",
|
||||
"EmptyScreenFolder": "No docs here yet",
|
||||
"ExcludeSubfolders": "Exclude subfolders",
|
||||
"FavoritesEmptyContainerDescription": "To mark files as favorites or remove them from this list, use the context menu.",
|
||||
"FileContents": "File contents",
|
||||
"FileRemoved": "File moved to Trash",
|
||||
"FileRenamed": "The document '{{oldTitle}}' is renamed to '{{newTitle}}'",
|
||||
"FillingFormRooms": "Filling form",
|
||||
@ -35,6 +37,7 @@
|
||||
"Folder": "Folder",
|
||||
"FolderRemoved": "Folder moved to Trash",
|
||||
"FolderRenamed": "The folder '{{folderTitle}}' is renamed to '{{newFoldedTitle}}'",
|
||||
"Forms": "Forms",
|
||||
"FromArchive": "Move from archive",
|
||||
"GoToMyButton": "Go to My Documents",
|
||||
"GoToShared": "Go to Shared",
|
||||
@ -43,6 +46,7 @@
|
||||
"MarkAsFavorite": "Mark as favorite",
|
||||
"MarkRead": "Mark as read",
|
||||
"MarkedAsFavorite": "Added to favorites",
|
||||
"FormsTemplates": "Forms templates",
|
||||
"Media": "Media",
|
||||
"MoveItem": "<strong>{{title}}</strong> moved",
|
||||
"MoveItems": "<strong>{{qty}}</strong> elements have been moved",
|
||||
@ -77,6 +81,7 @@
|
||||
"ReviewRooms": "Review",
|
||||
"RoomRemoved": "Room removed",
|
||||
"RoomsRemoved": "Rooms removed",
|
||||
"SearchByContent": "Search by file contents",
|
||||
"SendByEmail": "Send by email",
|
||||
"Share": "Share",
|
||||
"SharedEmptyContainerDescription": "The 'Shared with Me' section shows files shared to you by teammates. If you haven't seen the latest changes, they are marked as new. You can remove the files from the list using the context menu. ",
|
||||
@ -96,5 +101,6 @@
|
||||
"VersionHistory": "Version history",
|
||||
"ViewList": "List",
|
||||
"ViewOnlyRooms": "View-only",
|
||||
"ViewTiles": "Tiles"
|
||||
"ViewTiles": "Tiles",
|
||||
"WithSubfolders": "With subfolders"
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"AdditionalSections": "Additional sections",
|
||||
"Clouds": "Clouds",
|
||||
"CommonSettings": "Common settings",
|
||||
"CommonSettings": "Common",
|
||||
"ConnectAdminDescription": "For successful connection, enter the necessary data on <1>this page</1>.",
|
||||
"ConnectCloud": "Connect cloud",
|
||||
"ConnectDescriptionText": "You haven't connected any third-party clouds yet.",
|
||||
@ -15,8 +16,10 @@
|
||||
"IntermediateVersion": "Keep all saved intermediate versions",
|
||||
"KeepIntermediateVersion": "Keep intermediate versions when editing",
|
||||
"OriginalCopy": "Save the file copy in the original format as well",
|
||||
"StoringFileVersion": "Storing file versions",
|
||||
|
||||
"ThirdPartyAccounts": "Third-party accounts",
|
||||
"ThirdPartyBtn": "Allow users to connect third-party storages",
|
||||
"ThirdPartySettings": "Connected clouds",
|
||||
"UpdateOrCreate": "Update the file version for the existing file with the same name. Otherwise, a copy of the file will be created."
|
||||
"UpdateOrCreate": "Update the file version for the existing file with the same name. Otherwise, a copy of the file will be created.",
|
||||
"StoringFileVersion": "Storing file versions"
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archivos",
|
||||
"BackToParentFolderButton": "Volver a la carpeta principal",
|
||||
"ByAuthor": "Autor",
|
||||
"ByCreationDate": "Creado",
|
||||
"ByLastModifiedDate": "Modificado",
|
||||
"ByCreation": "Creado",
|
||||
"ByLastModified": "Modificado",
|
||||
"ByTitle": "Título",
|
||||
"CommonEmptyContainerDescription": "La sección 'Documentos comunes' contiene archivos compartidos por el administrador del portal con todos los usuarios. Sólo los administradores del portal pueden crear archivos allí. Los usuarios pueden tener acceso completo a una determinada carpeta dentro de la sección. De esta manera podrán crear/subir archivos en esta misma carpeta. ",
|
||||
"ContainsSpecCharacter": "El título no puede contener ninguno de los siguientes caracteres: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arkistot",
|
||||
"BackToParentFolderButton": "Takaisin pääkansioon",
|
||||
"ByAuthor": "Tekijä",
|
||||
"ByCreationDate": "Luotu",
|
||||
"ByLastModifiedDate": "Muokattu",
|
||||
"ByCreation": "Luotu",
|
||||
"ByLastModified": "Muokattu",
|
||||
"ByTitle": "Otsikko",
|
||||
"CommonEmptyContainerDescription": "’Yleinen’ -osio sisältää tiedostoja, jotka portaalin ylläpitäjä on jakanut kaikille käyttäjille. Vain portaalin ylläpitäjät voivat luoda tiedostoja sinne. Käyttäjille voidaan myöntää täysi käyttöoikeus tiettyyn osion kansioon. Tällä tavalla he voivat luoda/ladata tiedostoja juuri tähän kansioon. ",
|
||||
"ContainsSpecCharacter": "Otsikko ei voi sisältää mitään seuraavista merkeistä: *+: \"<>? |/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archives",
|
||||
"BackToParentFolderButton": "Retour vers le dossier précédent",
|
||||
"ByAuthor": "Auteur",
|
||||
"ByCreationDate": "Créé",
|
||||
"ByLastModifiedDate": "Modifié",
|
||||
"ByCreation": "Créé",
|
||||
"ByLastModified": "Modifié",
|
||||
"ByTitle": "Titre",
|
||||
"CommonEmptyContainerDescription": "La section \"Documents Communs\" contient des fichiers partagés par l'administrateur du portail avec tous les utilisateurs. Seuls les administrateurs du portail peuvent y créer des fichiers. Les utilisateurs peuvent obtenir un accès complet à un certain dossier de la section. Ainsi, ils pourront créer/télécharger des fichiers dans ce même dossier. ",
|
||||
"ContainsSpecCharacter": "Le titre ne peut contenir aucun des caractères suivants : *+ :\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Արխիվներ",
|
||||
"BackToParentFolderButton": "Վերադառնալ ծնող պանակ",
|
||||
"ByAuthor": "Հեղինակ",
|
||||
"ByCreationDate": "Ստեղծված",
|
||||
"ByLastModifiedDate": "Փոփոխված",
|
||||
"ByCreation": "Ստեղծված",
|
||||
"ByLastModified": "Փոփոխված",
|
||||
"ByTitle": "Անվանում",
|
||||
"CommonEmptyContainerDescription": "'Ընդհանուր'բաժինը պարունակում է ֆայլեր, որոնք կայքէջի ադմինիստրատորի կողմից համօգտագործվում են բոլոր օգտատերերին: Միայն կայքէջի ադմինիստրատորները կարող են այնտեղ ֆայլեր ստեղծել։ Օգտագործողներին կարող է տրվել ամբողջական մուտք դեպի որոշակի պանակ այս բաժնում: Այս կերպ նրանք կկարողանան ստեղծել/վերբեռնել ֆայլեր հենց այս պանակում:",
|
||||
"ContainsSpecCharacter": "Վերնագիրը չի կարող պարունակել հետևյալ նիշերից որևէ մեկը՝ *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archivi",
|
||||
"BackToParentFolderButton": "Vai alla cartella superiore",
|
||||
"ByAuthor": "Autore",
|
||||
"ByCreationDate": "Creato",
|
||||
"ByLastModifiedDate": "Modificato",
|
||||
"ByCreation": "Creato",
|
||||
"ByLastModified": "Modificato",
|
||||
"ByTitle": "Titolo",
|
||||
"CommonEmptyContainerDescription": "La sezione \"Comune\" contiene i file condivisi con tutti gli utenti di tipo amministratore del portale. Solo gli amministratori del portale possono creare file nel posto \"Comune\". Agli utenti può essere concesso l'accesso completo a una determinata cartella all'interno della sezione. In questo modo potranno creare / caricare file in questa stessa cartella.",
|
||||
"ContainsSpecCharacter": "Il titolo non può contenere nessuno dei seguenti caratteri: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "アーカイブ",
|
||||
"BackToParentFolderButton": "親フォルダに戻る",
|
||||
"ByAuthor": "作成者",
|
||||
"ByCreationDate": "作成",
|
||||
"ByLastModifiedDate": "変更",
|
||||
"ByCreation": "作成",
|
||||
"ByLastModified": "変更",
|
||||
"ByTitle": "タイトル",
|
||||
"CommonEmptyContainerDescription": "「共通」セクションには、ポータル管理者が全ユーザに共有するファイルがあります。ここにファイルを作成できるのは、ポータル管理者のみです。ユーザーは、セクション内の特定のフォルダへのフルアクセスを許可することができます。この場合、ユーザーは、このフォルダにファイルを作成/アップロードすることができます。 ",
|
||||
"ContainsSpecCharacter": "タイトルには以下の文字*+:\"<>?|/は使用できません。",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "아카이브",
|
||||
"BackToParentFolderButton": "상위 폴더로 돌아가기",
|
||||
"ByAuthor": "생성자",
|
||||
"ByCreationDate": "생성일",
|
||||
"ByLastModifiedDate": "수정일",
|
||||
"ByCreation": "생성일",
|
||||
"ByLastModified": "수정일",
|
||||
"ByTitle": "제목",
|
||||
"CommonEmptyContainerDescription": "'공통' 섹션은 포털 관리자에 의해 모든 사용자에게 공유된 파일을 포함합니다. 포털 관리자만 공통 섹션에 파일을 생성할 수 있습니다. 사용자는 해당 섹션 내 특정 폴더에 대한 전체 액세스 권한을 부여 받을 수 있습니다. 그리고 이러한 방식으로 해당 폴더에 파일을 생성/업로드할 수 있습니다.",
|
||||
"ContainsSpecCharacter": "제목에는 다음 문자가 포함될 수 없습니다: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "ຮວບຮວມ",
|
||||
"BackToParentFolderButton": "ກັບໄປທີ່ແຟ້ມຫຼັກ",
|
||||
"ByAuthor": "ຜູ້ຂຽນ",
|
||||
"ByCreationDate": "ສ້າງ",
|
||||
"ByLastModifiedDate": "ແກ້ໄຂ",
|
||||
"ByCreation": "ສ້າງ",
|
||||
"ByLastModified": "ແກ້ໄຂ",
|
||||
"ByTitle": "ຫົວຂໍ້",
|
||||
"CommonEmptyContainerDescription": "ສ່ວນ common 'ມີເອກະສານທີ່ແບ່ງປັນໃຫ້ຜູ້ຊົມໃຊ້ທັງໝົດ ໂດຍ Portal admin. ມີພຽງແຕ່ Portal ເປັນຜູ້ຮັບຮອງເທົ່ານັ້ນທີ່ສາມາດສ້າງເອກະສານຢູ່ບ່ອນນັ້ນ. ຜູ້ໃຊ້ສາມາດໄດ້ຮັບການອະນຸຍາດເຂົ້າເຖິງໂຟນເດີທີ່ແນ່ນອນພາຍໃນພາກສ່ວນໃດໜື່ງ. ວິທີນີ້ພວກເຂົາຈະສາມາດສ້າງ / ອັບໂຫລດເອກະສານໃນໂຟນເດີນັ້ນໄດ້.",
|
||||
"ContainsSpecCharacter": "ຫົວຂໍ້ບໍ່ສາມາດມີຕົວອັກສອນຕໍ່ໄປນີ້: * +: \"<>? | /",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arhīvi",
|
||||
"BackToParentFolderButton": "Atpakaļ uz vecāku mapi",
|
||||
"ByAuthor": "Autors",
|
||||
"ByCreationDate": "Izveidots",
|
||||
"ByLastModifiedDate": "Modificēts",
|
||||
"ByCreation": "Izveidots",
|
||||
"ByLastModified": "Modificēts",
|
||||
"ByTitle": "Nosaukums",
|
||||
"CommonEmptyContainerDescription": "Sadaļā 'Kopējs' ir faili, kurus visiem lietotājiem ir kopīgojis portāla administrators. Failus tur var izveidot tikai portāla administratori. Lietotājiem var piešķirt pilnu piekļuvi noteiktai sadaļas mapei. Tādā veidā viņi varēs izveidot/augšupielādēt failus tieši šajā mapē. ",
|
||||
"ContainsSpecCharacter": "Nosaukumā nedrīkst būt neviena no šīm rakstzīmēm: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archieven",
|
||||
"BackToParentFolderButton": "Terug naar bovenliggende map",
|
||||
"ByAuthor": "Auteur",
|
||||
"ByCreationDate": "Aangemaakt",
|
||||
"ByLastModifiedDate": "Gewijzigd",
|
||||
"ByCreation": "Aangemaakt",
|
||||
"ByLastModified": "Gewijzigd",
|
||||
"ByTitle": "Titel",
|
||||
"CommonEmptyContainerDescription": "'Algemene' sectie bevat bestanden die door de portaal beheerder worden gedeeld met alle gebruikers. Alleen portaal beheerders kunnen daar bestanden aanmaken. Gebruikers kunnen volledige toegang krijgen tot een bepaalde map binnen de sectie. Op deze manier kunnen ze bestanden maken/uploaden in deze map. ",
|
||||
"ContainsSpecCharacter": "De titel mag geen van de volgende tekens bevatten: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archiwa",
|
||||
"BackToParentFolderButton": "Wróć do folderu nadrzędnego",
|
||||
"ByAuthor": "Autor",
|
||||
"ByCreationDate": "Utworzono",
|
||||
"ByLastModifiedDate": "Zmodyfikowano",
|
||||
"ByCreation": "Utworzono",
|
||||
"ByLastModified": "Zmodyfikowano",
|
||||
"ByTitle": "Tytuł",
|
||||
"CommonEmptyContainerDescription": "Sekcja 'Wspólne' zawiera pliki udostępnione wszystkim użytkownikom przez administratora portalu. Tylko on może tworzyć w niej nowe pliki. Użytkownicy mogą uzyskać pełen dostęp do pewnych folderów znajdujących się w tej sekcji. Dzięki temu będą w stanie tworzyć/wgrywać w nich dowolne pliki. ",
|
||||
"ContainsSpecCharacter": "Tytuł nie może zawierać następujących znaków: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arquivos",
|
||||
"BackToParentFolderButton": "Voltar para pasta principal",
|
||||
"ByAuthor": "Autor",
|
||||
"ByCreationDate": "Criado",
|
||||
"ByLastModifiedDate": "Modificado",
|
||||
"ByCreation": "Criado",
|
||||
"ByLastModified": "Modificado",
|
||||
"ByTitle": "Titulo",
|
||||
"CommonEmptyContainerDescription": "A seção 'Comum' contém arquivos compartilhados a todos os usuários pelo administrador do portal. Somente os administradores do portal podem criar arquivos lá. Os usuários podem ter acesso total a uma determinada pasta dentro da seção. Desta forma, eles poderão criar/enviar arquivos nesta mesma pasta.",
|
||||
"ContainsSpecCharacter": "O título não pode conter nenhum dos seguintes caracteres: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arquivos",
|
||||
"BackToParentFolderButton": "Voltar à pasta principal",
|
||||
"ByAuthor": "Autor",
|
||||
"ByCreationDate": "Criado",
|
||||
"ByLastModifiedDate": "Modificado",
|
||||
"ByCreation": "Criado",
|
||||
"ByLastModified": "Modificado",
|
||||
"ByTitle": "Titulo",
|
||||
"CommonEmptyContainerDescription": "A secção 'Comum' contém ficheiro partilhados a todos os utilizadores pelo administrador do portal. Apenas os administradores do portal podem criar lá ficheiros. Os utilizadores podem ter acesso total a uma determinada pasta dentro da secção. Desta forma, eles poderão criar/enviar ficheiros nesta mesma pasta.",
|
||||
"ContainsSpecCharacter": "O título não pode conter nenhum dos seguintes caracteres: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arhive",
|
||||
"BackToParentFolderButton": "Revenire la folderul părinte",
|
||||
"ByAuthor": "Autor",
|
||||
"ByCreationDate": "A fost creat la",
|
||||
"ByLastModifiedDate": "Modificat",
|
||||
"ByCreation": "A fost creat la",
|
||||
"ByLastModified": "Modificat",
|
||||
"ByTitle": "Titlu",
|
||||
"CommonEmptyContainerDescription": "Secțiunea Comune conține fișiere partajate cu alți utilizatori de către administratorul portalului. Numai administratorii portalului pot crea fișiere acolo. Utilizatorii pot primi acces complet la un anumit dosar din secțiunea. În acest mod, utilizatorii pot crea/încărca fișiere în acest dosar.",
|
||||
"ContainsSpecCharacter": "Numele nu poate conține niciun din caractere următoare: *+:\"<>?|/ ",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Архивы",
|
||||
"BackToParentFolderButton": "Вернуться в папку на уровень выше",
|
||||
"ByAuthor": "Автор",
|
||||
"ByCreationDate": "Создан",
|
||||
"ByLastModifiedDate": "Изменен",
|
||||
"ByCreation": "Создан",
|
||||
"ByLastModified": "Изменен",
|
||||
"ByTitle": "Название",
|
||||
"CollaborationRooms": "Совместное редактирование",
|
||||
"CommonEmptyContainerDescription": "В разделе «Общие документы» отображаются все документы, которыми администратор портала предоставил общий доступ. Только администраторы портала могут создавать папки в этом разделе, но с предоставленным доступом пользователи портала также могут загружать свои файлы здесь. Перетащите файлы со своего компьютера сюда, чтобы загрузить их на свой портал еще проще.",
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"AdditionalSections": "Дополнительные разделы",
|
||||
"Clouds": "Облака",
|
||||
"CommonSettings": "Общие настройки",
|
||||
"CommonSettings": "Общие",
|
||||
"ConnectAdminDescription": "Для успешного подключения введите нужные данные на <1>этой странице</1>.",
|
||||
"ConnectCloud": "Подключить облако",
|
||||
"ConnectDescriptionText": "Вы еще не подключили сторонние облачные сервисы.",
|
||||
@ -15,8 +16,9 @@
|
||||
"IntermediateVersion": "Хранить все сохраненные промежуточные версии",
|
||||
"KeepIntermediateVersion": "Хранить промежуточные версии при редактировании",
|
||||
"OriginalCopy": "Сохранять также копию файла в исходном формате",
|
||||
"StoringFileVersion": "Хранение версий файлов",
|
||||
"ThirdPartyAccounts": "Сторонние аккаунты",
|
||||
"ThirdPartyBtn": "Разрешить пользователям подключать сторонние хранилища",
|
||||
"ThirdPartySettings": "Подключенные облака",
|
||||
"UpdateOrCreate": "Обновлять версию файла для существующего файла с таким же именем. В противном случае будет создаваться копия файла."
|
||||
"UpdateOrCreate": "Обновлять версию файла для существующего файла с таким же именем. В противном случае будет создаваться копия файла.",
|
||||
"StoringFileVersion": "Хранение версий файлов"
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Archívy",
|
||||
"BackToParentFolderButton": "Späť do nadradeného priečinka",
|
||||
"ByAuthor": "Autor",
|
||||
"ByCreationDate": "Vytvorené",
|
||||
"ByLastModifiedDate": "Upravené",
|
||||
"ByCreation": "Vytvorené",
|
||||
"ByLastModified": "Upravené",
|
||||
"ByTitle": "Názov",
|
||||
"CommonEmptyContainerDescription": "Sekcia 'Spoločné' obsahuje súbory zdieľané všetkým používateľom správcom portálu. Súbory tam môžu vytvárať iba správcovia portálu. Používateľom môže byť udelený úplný prístup k určitému priečinku v rámci sekcie. Týmto spôsobom budú môcť vytvárať/nahrávať súbory práve do tohto priečinka.",
|
||||
"ContainsSpecCharacter": "Názov nemôže obsahovať žiadne z nasledujúcich znakov: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arhivi",
|
||||
"BackToParentFolderButton": "Nazaj na starševsko mapo",
|
||||
"ByAuthor": "Avtor",
|
||||
"ByCreationDate": "Ustvarjeno",
|
||||
"ByLastModifiedDate": "Popravljeno",
|
||||
"ByCreation": "Ustvarjeno",
|
||||
"ByLastModified": "Popravljeno",
|
||||
"ByTitle": "Naslov",
|
||||
"CommonEmptyContainerDescription": "'Skupen' razdelek vsebuje datoteke, ki jih skrbnik portala deli z vsemi uporabniki. Samo skrbniki portala lahko tam ustvarjajo datoteke. Uporabniki lahko dobijo popoln dostop do določene mape v razdelku. Tako bodo lahko ustvarili/naložili datoteke ravno v tej mapi. ",
|
||||
"ContainsSpecCharacter": "Naslov ne sme vsebovati nobenega od naslednjih znakov: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Arşivler",
|
||||
"BackToParentFolderButton": "Üst klasöre geri dön",
|
||||
"ByAuthor": "Yazar",
|
||||
"ByCreationDate": "Oluşturuldu",
|
||||
"ByLastModifiedDate": "Değiştirilmiş",
|
||||
"ByCreation": "Oluşturuldu",
|
||||
"ByLastModified": "Değiştirilmiş",
|
||||
"ByTitle": "Başlık",
|
||||
"CommonEmptyContainerDescription": "'Ortak' bölüm, portal yöneticisi tarafından tüm kullanıcılarla paylaşılan dosyaları içerir. Burada yalnızca portal yöneticileri dosya oluşturabilir. Bu bölüm içinde kullanıcılara belirli bir klasöre Tam erişim verilebilir. Bu şekilde, bu klasörde dosya oluşturabilecek/yükleyebileceklerdir.",
|
||||
"ContainsSpecCharacter": "Başlık şu karakterlerden herhangi birini içeremez:: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Архіви",
|
||||
"BackToParentFolderButton": "Назад до батьківської папки",
|
||||
"ByAuthor": "Автор",
|
||||
"ByCreationDate": "Створено",
|
||||
"ByLastModifiedDate": "Змінено",
|
||||
"ByCreation": "Створено",
|
||||
"ByLastModified": "Змінено",
|
||||
"ByTitle": "Заголовок",
|
||||
"CommonEmptyContainerDescription": "Розділ \"Загальне\" містить файли, до яких адміністратор порталу надав доступ усім користувачам. Тільки адміністратори порталу можуть створювати тут файли. Користувачам може бути наданий повний доступ до певної папки в розділі. Це дозволить їм створювати файли в цій папці та передавати їх до неї.",
|
||||
"ContainsSpecCharacter": "Заголовок не може містити жодного з цих символів: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "Lưu trữ",
|
||||
"BackToParentFolderButton": "Quay lại thư mục gốc",
|
||||
"ByAuthor": "Tác giả",
|
||||
"ByCreationDate": "Đã tạo",
|
||||
"ByLastModifiedDate": "Đã sửa đổi",
|
||||
"ByCreation": "Đã tạo",
|
||||
"ByLastModified": "Đã sửa đổi",
|
||||
"ByTitle": "Tiêu đề",
|
||||
"CommonEmptyContainerDescription": "Phần Chung chứa các tệp được quản trị viên cổng thông tin chia sẻ cho tất cả người dùng. Chỉ quản trị viên cổng thông tin mới có thể tạo ệp ở đó. Người dùng có thể được cấp toàn quyền truy cập vào một thư mục nhất định trong phần này. Bằng cách này họ sẽ có thể tạo/tải lên các tệp trong chính thư mục này.",
|
||||
"ContainsSpecCharacter": "Tiêu đề không được chứa bất kỳ ký tự nào sau đây: *+:\"<>?|/",
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Archives": "归档",
|
||||
"BackToParentFolderButton": "返回父文件夹",
|
||||
"ByAuthor": "作者",
|
||||
"ByCreationDate": "创建日期",
|
||||
"ByLastModifiedDate": "修改日期",
|
||||
"ByCreation": "创建日期",
|
||||
"ByLastModified": "修改日期",
|
||||
"ByTitle": "标题",
|
||||
"CommonEmptyContainerDescription": "'Common'部分包含由门户管理员分享给所有用户的文件。仅门户管理员可在此处创建文件。用户将被授予该部分中特定文件夹的完整访问权限。这样其就能在该文件夹中创建/上传文件了。",
|
||||
"ContainsSpecCharacter": "标题中不得包含任意以下字符:*+:\"<>?|/",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { Events } from "@docspace/client/src/helpers/filesConstants";
|
||||
import { Events } from "@docspace/common/constants";
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
import throttle from "lodash/throttle";
|
||||
|
||||
|
@ -447,7 +447,7 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
|
||||
"/settings",
|
||||
"/settings/common",
|
||||
"/settings/admin",
|
||||
"/settings/connected-clouds",
|
||||
//"/settings/connected-clouds",
|
||||
]}
|
||||
component={FilesRoute}
|
||||
/>
|
||||
|
@ -13,7 +13,7 @@ import SettingsItem from "./SettingsItem";
|
||||
import AccountsItem from "./AccountsItem";
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import { isDesktop, isTablet, isMobileOnly } from "react-device-detect";
|
||||
import ThirdPartyList from "./ThirdPartyList";
|
||||
//import ThirdPartyList from "./ThirdPartyList";
|
||||
import DownloadAppList from "./DownloadAppList";
|
||||
import Banner from "./Banner";
|
||||
import { showLoader, hideLoader } from "@docspace/common/utils";
|
||||
@ -39,14 +39,16 @@ const ArticleBodyContent = (props) => {
|
||||
firstLoad,
|
||||
showText,
|
||||
isDesktopClient,
|
||||
enableThirdParty,
|
||||
isVisitor,
|
||||
// enableThirdParty,
|
||||
// isVisitor,
|
||||
FirebaseHelper,
|
||||
theme,
|
||||
toggleArticleOpen,
|
||||
categoryType,
|
||||
isAdmin,
|
||||
filesIsLoading,
|
||||
roomsFolderId,
|
||||
archiveFolderId,
|
||||
} = props;
|
||||
|
||||
const campaigns = (localStorage.getItem("campaigns") || "")
|
||||
@ -65,8 +67,6 @@ const ArticleBodyContent = (props) => {
|
||||
|
||||
homepage,
|
||||
history,
|
||||
roomsFolderId,
|
||||
archiveFolderId,
|
||||
} = props;
|
||||
|
||||
if (filesIsLoading) return;
|
||||
@ -144,7 +144,7 @@ const ArticleBodyContent = (props) => {
|
||||
});
|
||||
}
|
||||
},
|
||||
[categoryType]
|
||||
[categoryType, roomsFolderId, archiveFolderId]
|
||||
);
|
||||
|
||||
const onShowNewFilesPanel = React.useCallback((folderId) => {
|
||||
@ -163,7 +163,7 @@ const ArticleBodyContent = (props) => {
|
||||
{!personal && !firstLoad && <SettingsItem />}
|
||||
{!isDesktopClient && showText && !docSpace && (
|
||||
<StyledBlock showText={showText}>
|
||||
{enableThirdParty && !isVisitor && <ThirdPartyList />}
|
||||
{/* {enableThirdParty && !isVisitor && <ThirdPartyList />} */}
|
||||
<DownloadAppList theme={theme} />
|
||||
{(isDesktop || isTablet) &&
|
||||
personal &&
|
||||
|
@ -14,7 +14,7 @@ import MobileView from "./MobileView";
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import config from "PACKAGE_FILE";
|
||||
import withLoader from "../../../HOCs/withLoader";
|
||||
import { Events } from "@docspace/client/src/helpers/filesConstants";
|
||||
import { Events } from "@docspace/common/constants";
|
||||
import { getMainButtonItems } from "SRC_DIR/helpers/plugins";
|
||||
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
|
@ -8,16 +8,19 @@ import Box from "@docspace/components/box";
|
||||
const EmptyFolderContainer = ({
|
||||
t,
|
||||
onCreate,
|
||||
filter,
|
||||
fetchFiles,
|
||||
fetchRooms,
|
||||
setIsLoading,
|
||||
parentId,
|
||||
linkStyles,
|
||||
isRooms,
|
||||
}) => {
|
||||
const onBackToParentFolder = () => {
|
||||
const newFilter = filter.clone();
|
||||
setIsLoading(true);
|
||||
fetchFiles(parentId, newFilter).finally(() => setIsLoading(false));
|
||||
|
||||
isRooms
|
||||
? fetchRooms(parentId).finally(() => setIsLoading(false))
|
||||
: fetchFiles(parentId).finally(() => setIsLoading(false));
|
||||
};
|
||||
|
||||
const buttons = (
|
||||
@ -85,12 +88,21 @@ const EmptyFolderContainer = ({
|
||||
};
|
||||
|
||||
export default inject(({ filesStore, selectedFolderStore }) => {
|
||||
const { filter, fetchFiles } = filesStore;
|
||||
const { fetchFiles, fetchRooms } = filesStore;
|
||||
const { navigationPath, parentId } = selectedFolderStore;
|
||||
|
||||
let isRootRoom, isRoom, id;
|
||||
if (navigationPath && navigationPath.length) {
|
||||
isRootRoom = navigationPath.at(-1).isRootRoom;
|
||||
isRoom = navigationPath.at(-1).isRoom;
|
||||
id = navigationPath.at(-1).id;
|
||||
}
|
||||
|
||||
return {
|
||||
filter,
|
||||
fetchFiles,
|
||||
fetchRooms,
|
||||
setIsLoading: filesStore.setIsLoading,
|
||||
parentId: selectedFolderStore.parentId,
|
||||
parentId: id ?? parentId,
|
||||
isRooms: isRoom || isRootRoom,
|
||||
};
|
||||
})(withTranslation(["Files", "Translations"])(observer(EmptyFolderContainer)));
|
||||
|
@ -5,7 +5,7 @@ import EmptyFilterContainer from "./EmptyFilterContainer";
|
||||
import EmptyFolderContainer from "./EmptyFolderContainer";
|
||||
import { FileAction } from "@docspace/common/constants";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { Events } from "@docspace/client/src/helpers/filesConstants";
|
||||
import { Events } from "@docspace/common/constants";
|
||||
|
||||
const linkStyles = {
|
||||
isHovered: true,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useCallback, memo } from "react";
|
||||
|
||||
import { FileAction } from "@docspace/common/constants";
|
||||
import { Events } from "@docspace/client/src/helpers/filesConstants";
|
||||
import { Events } from "@docspace/common/constants";
|
||||
|
||||
import CreateEvent from "./CreateEvent";
|
||||
import RenameEvent from "./RenameEvent";
|
||||
|
@ -153,6 +153,7 @@ const PureConnectDialogContainer = (props) => {
|
||||
loginValue,
|
||||
passwordValue,
|
||||
oAuthToken,
|
||||
false,
|
||||
customerTitle,
|
||||
provider_key || key,
|
||||
provider_id,
|
||||
|
@ -26,6 +26,7 @@ const FilesListBody = ({
|
||||
page,
|
||||
folderSelection,
|
||||
getIcon,
|
||||
maxHeight = 384,
|
||||
}) => {
|
||||
const { t } = useTranslation(["SelectFile", "Common"]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -177,7 +178,7 @@ const FilesListBody = ({
|
||||
{({ onItemsRendered, ref }) => (
|
||||
<List
|
||||
theme={theme}
|
||||
height={384}
|
||||
height={maxHeight}
|
||||
itemCount={itemCount}
|
||||
itemSize={48}
|
||||
onItemsRendered={onItemsRendered}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user