Merge branch 'release/1.0.0' into bugfix/mousewheel-opening-files

This commit is contained in:
Dmitry Sychugov 2021-09-06 16:59:30 +05:00
commit c15c6733d9
141 changed files with 3153 additions and 3025 deletions

View File

@ -1,4 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.202
MinimumVisualStudioVersion = 10.0.40219.1
@ -57,8 +58,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Feed.Aggregator", "comm
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Thumbnails.Svc", "common\services\ASC.Thumbnails.Svc\ASC.Thumbnails.Svc.csproj", "{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Data.Backup", "common\services\ASC.Data.Backup\ASC.Data.Backup.csproj", "{DE3DAF51-FB29-41FC-AF41-A4BA8D91BFB6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Files.Core", "products\ASC.Files\Core\ASC.Files.Core.csproj", "{F0A39728-940D-4DBE-A37A-05D4EB57F342}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Socket.IO.Svc", "common\services\ASC.Socket.IO.Svc\ASC.Socket.IO.Svc.csproj", "{2DADEAD3-0FE9-4199-9817-41A32E6BF450}"
@ -88,12 +87,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Radicale", "common\serv
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.SsoAuth.Svc", "common\services\ASC.SsoAuth.Svc\ASC.SsoAuth.Svc.csproj", "{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASC.Web.HealthChecks.UI", "web\ASC.Web.HealthChecks.UI\ASC.Web.HealthChecks.UI.csproj", "{0C1A387E-0CD0-4BE8-82FC-9FCAD05BF289}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Web.HealthChecks.UI", "web\ASC.Web.HealthChecks.UI\ASC.Web.HealthChecks.UI.csproj", "{0C1A387E-0CD0-4BE8-82FC-9FCAD05BF289}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.ClearEvents", "common\services\ASC.ClearEvents\ASC.ClearEvents.csproj", "{448221A8-EABA-4200-9192-E08BF241A487}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.CRM.BackgroundTasks", "products\ASC.CRM\BackgroundTasks\ASC.CRM.BackgroundTasks.csproj", "{E52C0E35-A05C-437F-8FF2-3E0AC9F81433}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Data.Backup.Core", "common\ASC.Data.Backup.Core\ASC.Data.Backup.Core.csproj", "{F5D9DE01-06CD-4881-9F41-46882E9ED45C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Data.Backup", "common\services\ASC.Data.Backup\ASC.Data.Backup.csproj", "{027EEE53-7491-48F4-B467-6404D68798A7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -204,10 +207,6 @@ Global
{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}.Release|Any CPU.Build.0 = Release|Any CPU
{DE3DAF51-FB29-41FC-AF41-A4BA8D91BFB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE3DAF51-FB29-41FC-AF41-A4BA8D91BFB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE3DAF51-FB29-41FC-AF41-A4BA8D91BFB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE3DAF51-FB29-41FC-AF41-A4BA8D91BFB6}.Release|Any CPU.Build.0 = Release|Any CPU
{F0A39728-940D-4DBE-A37A-05D4EB57F342}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0A39728-940D-4DBE-A37A-05D4EB57F342}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0A39728-940D-4DBE-A37A-05D4EB57F342}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -244,14 +243,14 @@ Global
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Release|Any CPU.Build.0 = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.Build.0 = Release|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74998718-3C9A-4A89-B834-14453762C60F}.Release|Any CPU.Build.0 = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.Build.0 = Release|Any CPU
{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AD828EA-FBA2-4D30-B969-756B3BE78E4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -268,6 +267,14 @@ Global
{E52C0E35-A05C-437F-8FF2-3E0AC9F81433}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E52C0E35-A05C-437F-8FF2-3E0AC9F81433}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E52C0E35-A05C-437F-8FF2-3E0AC9F81433}.Release|Any CPU.Build.0 = Release|Any CPU
{F5D9DE01-06CD-4881-9F41-46882E9ED45C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5D9DE01-06CD-4881-9F41-46882E9ED45C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5D9DE01-06CD-4881-9F41-46882E9ED45C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5D9DE01-06CD-4881-9F41-46882E9ED45C}.Release|Any CPU.Build.0 = Release|Any CPU
{027EEE53-7491-48F4-B467-6404D68798A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{027EEE53-7491-48F4-B467-6404D68798A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{027EEE53-7491-48F4-B467-6404D68798A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{027EEE53-7491-48F4-B467-6404D68798A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

4
build/Jenkinsfile vendored
View File

@ -13,7 +13,7 @@ pipeline {
}
stage('Backend') {
steps {
sh 'dotnet build ASC.Web.sln'
sh 'dotnet build -c Release ASC.Web.sln'
}
}
}
@ -28,7 +28,7 @@ pipeline {
}
stage('Backend') {
steps {
bat 'dotnet build ASC.Web.sln'
bat 'dotnet build -c Release ASC.Web.sln'
}
}
}

View File

@ -79,7 +79,6 @@ namespace ASC.Core.Data
MaxFileSize = GetInBytes(r.MaxFileSize),
MaxTotalSize = GetInBytes(r.MaxTotalSize),
Price = r.Price,
Price2 = r.Price2,
Visible = r.Visible
};
@ -127,7 +126,6 @@ namespace ASC.Core.Data
ActiveUsers = quota.ActiveUsers,
Features = quota.Features,
Price = quota.Price,
Price2 = quota.Price2,
AvangateId = quota.AvangateId,
Visible = quota.Visible
};

View File

@ -14,7 +14,6 @@ namespace ASC.Core.Common.EF
public int ActiveUsers { get; set; }
public string Features { get; set; }
public decimal Price { get; set; }
public decimal Price2 { get; set; }
public string AvangateId { get; set; }
public bool Visible { get; set; }
public override object[] GetKeys()
@ -30,7 +29,7 @@ namespace ASC.Core.Common.EF
.Add(MySqlAddDbQuota, Provider.MySql)
.Add(PgSqlAddDbQuota, Provider.Postgre)
.HasData(
new DbQuota { Tenant = -1, Name = "default", Description = null, MaxFileSize = 102400, MaxTotalSize = 10995116277760, ActiveUsers = 10000, Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", Price = decimal.Parse("0,00"), Price2 = decimal.Parse("0,00"), AvangateId = "0", Visible = false }
new DbQuota { Tenant = -1, Name = "default", Description = null, MaxFileSize = 102400, MaxTotalSize = 10995116277760, ActiveUsers = 10000, Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", Price = decimal.Parse("0,00"), AvangateId = "0", Visible = false }
);
return modelBuilder;
@ -81,10 +80,6 @@ namespace ASC.Core.Common.EF
.HasColumnName("price")
.HasColumnType("decimal(10,2)");
entity.Property(e => e.Price2)
.HasColumnName("price2")
.HasColumnType("decimal(10,2)");
entity.Property(e => e.Visible).HasColumnName("visible");
});
}
@ -131,11 +126,6 @@ namespace ASC.Core.Common.EF
.HasColumnType("numeric(10,2)")
.HasDefaultValueSql("0.00");
entity.Property(e => e.Price2)
.HasColumnName("price2")
.HasColumnType("numeric(10,2)")
.HasDefaultValueSql("0.00");
entity.Property(e => e.Visible).HasColumnName("visible");
});
}

View File

@ -657,10 +657,6 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
.HasColumnType("decimal(10,2)")
.HasColumnName("price");
b.Property<decimal>("Price2")
.HasColumnType("decimal(10,2)")
.HasColumnName("price2");
b.Property<bool>("Visible")
.HasColumnType("tinyint(1)")
.HasColumnName("visible");
@ -681,7 +677,6 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Price2 = 0.00m,
Visible = false
});
});

View File

@ -58,7 +58,6 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
features = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
price = table.Column<decimal>(type: "decimal(10,2)", nullable: false),
price2 = table.Column<decimal>(type: "decimal(10,2)", nullable: false),
avangate_id = table.Column<string>(type: "varchar(128)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
visible = table.Column<bool>(type: "tinyint(1)", nullable: false)
@ -181,8 +180,8 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
migrationBuilder.InsertData(
table: "tenants_quota",
columns: new[] { "tenant", "active_users", "avangate_id", "description", "features", "max_file_size", "max_total_size", "name", "price", "price2", "visible" },
values: new object[] { -1, 10000, "0", null, "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", 102400L, 10995116277760L, "default", 0.00m, 0.00m, false });
columns: new[] { "tenant", "active_users", "avangate_id", "description", "features", "max_file_size", "max_total_size", "name", "price", "visible" },
values: new object[] { -1, 10000, "0", null, "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", 102400L, 10995116277760L, "default", 0.00m, false });
migrationBuilder.CreateIndex(
name: "last_modified",

View File

@ -655,10 +655,6 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
.HasColumnType("decimal(10,2)")
.HasColumnName("price");
b.Property<decimal>("Price2")
.HasColumnType("decimal(10,2)")
.HasColumnName("price2");
b.Property<bool>("Visible")
.HasColumnType("tinyint(1)")
.HasColumnName("visible");
@ -679,7 +675,6 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Price2 = 0.00m,
Visible = false
});
});

View File

@ -652,12 +652,6 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
.HasColumnType("numeric(10,2)")
.HasDefaultValueSql("0.00");
b.Property<decimal>("Price2")
.ValueGeneratedOnAdd()
.HasColumnName("price2")
.HasColumnType("numeric(10,2)")
.HasDefaultValueSql("0.00");
b.Property<bool>("Visible")
.HasColumnName("visible")
.HasColumnType("boolean");

View File

@ -56,7 +56,6 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
active_users = table.Column<int>(nullable: false),
features = table.Column<string>(nullable: true),
price = table.Column<decimal>(type: "numeric(10,2)", nullable: false, defaultValueSql: "0.00"),
price2 = table.Column<decimal>(type: "numeric(10,2)", nullable: false, defaultValueSql: "0.00"),
avangate_id = table.Column<string>(maxLength: 128, nullable: true, defaultValueSql: "NULL"),
visible = table.Column<bool>(nullable: false)
},

View File

@ -650,12 +650,6 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
.HasColumnType("numeric(10,2)")
.HasDefaultValueSql("0.00");
b.Property<decimal>("Price2")
.ValueGeneratedOnAdd()
.HasColumnName("price2")
.HasColumnType("numeric(10,2)")
.HasDefaultValueSql("0.00");
b.Property<bool>("Visible")
.HasColumnName("visible")
.HasColumnType("boolean");
@ -676,7 +670,6 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Price2 = 0.00m,
Visible = false
});
});

View File

@ -55,8 +55,6 @@ namespace ASC.Core.Tenants
public decimal Price { get; set; }
public decimal Price2 { get; set; }
public string AvangateId { get; set; }
public bool Visible { get; set; }

View File

@ -0,0 +1,55 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<OutputType>Library</OutputType>
<NoWarn>NU1701</NoWarn>
</PropertyGroup>
<ItemGroup>
<None Remove="protos\BackupProgress.proto" />
<None Remove="protos\DeleteSchedule.proto" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
<PackageReference Include="Google.Protobuf" Version="3.13.0" />
<PackageReference Include="Grpc" Version="2.32.0">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Grpc.Tools" Version="2.32.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="MySql.Data" Version="8.0.23" />
<PackageReference Include="SharpZipLib" Version="1.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\products\ASC.Files\Core\ASC.Files.Core.csproj" />
<ProjectReference Include="..\ASC.Data.Storage\ASC.Data.Storage.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\BackupProgress.proto" />
<Protobuf Include="protos\DeleteSchedule.proto" />
</ItemGroup>
<ItemGroup>
<Compile Update="BackupResource.Designer.cs">
<DependentUpon>BackupResource.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="BackupResource.resx">
<LastGenOutput>BackupResource.Designer.cs</LastGenOutput>
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -32,7 +32,7 @@ namespace ASC.Data.Backup
public static class ActionInvoker
{
public static void Try(
Action action,
Action action,
int maxAttempts,
Action<Exception> onFailure = null,
Action<Exception> onAttemptFailure = null,
@ -65,13 +65,13 @@ namespace ASC.Data.Backup
catch (Exception error)
{
if (countAttempts < maxAttempts)
{
{
onAttemptFailure?.Invoke(error);
if (sleepMs > 0)
if (sleepMs > 0)
Thread.Sleep(isSleepExponential ? sleepMs * countAttempts : sleepMs);
}
else
else
{
onFailure?.Invoke(error);
}

View File

@ -1,24 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Api.Utils;
using System.Linq;
using ASC.Api.Utils;
using ASC.Common;
using ASC.Core;
using ASC.Core.Billing;
using ASC.Core.Common.Configuration;
using ASC.Core.Users;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.Service;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.Service;
using ASC.MessagingSystem;
using ASC.Notify.Cron;
using ASC.Web.Core.PublicResources;
using ASC.Web.Studio.Core;
using ASC.Web.Studio.Core.Backup;
using ASC.Web.Studio.Utility;
using ASC.Web.Studio.Core.Backup;
using ASC.Web.Studio.Utility;
namespace ASC.Data.Backup
{
{
[Scope]
public class BackupAjaxHandler
{
@ -30,23 +30,23 @@ namespace ASC.Data.Backup
private SecurityContext SecurityContext { get; }
private UserManager UserManager { get; }
private TenantExtra TenantExtra { get; }
private ConsumerFactory ConsumerFactory { get; }
private BackupFileUploadHandler BackupFileUploadHandler { get; }
private BackupService BackupService { get; }
private ConsumerFactory ConsumerFactory { get; }
private BackupFileUploadHandler BackupFileUploadHandler { get; }
private BackupService BackupService { get; }
#region backup
public BackupAjaxHandler(
BackupService backupService,
TenantManager tenantManager,
MessageService messageService,
CoreBaseSettings coreBaseSettings,
CoreConfiguration coreConfiguration,
PermissionContext permissionContext,
SecurityContext securityContext,
UserManager userManager,
TenantExtra tenantExtra,
ConsumerFactory consumerFactory,
public BackupAjaxHandler(
BackupService backupService,
TenantManager tenantManager,
MessageService messageService,
CoreBaseSettings coreBaseSettings,
CoreConfiguration coreConfiguration,
PermissionContext permissionContext,
SecurityContext securityContext,
UserManager userManager,
TenantExtra tenantExtra,
ConsumerFactory consumerFactory,
BackupFileUploadHandler backupFileUploadHandler)
{
TenantManager = tenantManager;
@ -57,8 +57,8 @@ namespace ASC.Data.Backup
SecurityContext = securityContext;
UserManager = userManager;
TenantExtra = tenantExtra;
ConsumerFactory = consumerFactory;
BackupFileUploadHandler = backupFileUploadHandler;
ConsumerFactory = consumerFactory;
BackupFileUploadHandler = backupFileUploadHandler;
BackupService = backupService;
}
@ -71,7 +71,7 @@ namespace ASC.Data.Backup
TenantId = GetCurrentTenantId(),
UserId = SecurityContext.CurrentAccount.ID,
BackupMail = backupMail,
StorageType = storageType,
StorageType = storageType,
StorageParams = storageParams
};
@ -87,22 +87,22 @@ namespace ASC.Data.Backup
break;
}
MessageService.Send(MessageAction.StartBackupSetting);
MessageService.Send(MessageAction.StartBackupSetting);
BackupService.StartBackup(backupRequest);
}
public BackupProgress GetBackupProgress()
{
DemandPermissionsBackup();
DemandPermissionsBackup();
return BackupService.GetBackupProgress(GetCurrentTenantId());
}
public BackupProgress GetBackupProgress(int tenantId)
{
DemandPermissionsBackup();
DemandPermissionsBackup();
return BackupService.GetBackupProgress(tenantId);
}
@ -141,10 +141,10 @@ namespace ASC.Data.Backup
BackupMail = backupMail,
Cron = cronParams.ToString(),
NumberOfBackupsStored = backupsStored,
StorageType = storageType,
StorageType = storageType,
StorageParams = storageParams
};
};
switch (storageType)
{
case BackupStorageType.ThridpartyDocuments:
@ -206,7 +206,7 @@ namespace ASC.Data.Backup
BackupMail = schedule.BackupMail != null && (bool)schedule.BackupMail,
Cron = schedule.CronParams.ToString(),
NumberOfBackupsStored = schedule.BackupsStored == null ? 0 : (int)schedule.BackupsStored,
StorageType = schedule.StorageType,
StorageType = schedule.StorageType,
StorageParams = schedule.StorageParams
};
@ -248,7 +248,7 @@ namespace ASC.Data.Backup
var restoreRequest = new StartRestoreRequest
{
TenantId = GetCurrentTenantId(),
NotifyAfterCompletion = notify,
NotifyAfterCompletion = notify,
StorageParams = storageParams
};
@ -259,13 +259,13 @@ namespace ASC.Data.Backup
else
{
restoreRequest.StorageType = storageType;
restoreRequest.FilePathOrId = storageParams["filePath"];
if (restoreRequest.StorageType == BackupStorageType.Local && !CoreBaseSettings.Standalone)
{
restoreRequest.FilePathOrId = BackupFileUploadHandler.GetFilePath();
restoreRequest.FilePathOrId = storageParams["filePath"];
if (restoreRequest.StorageType == BackupStorageType.Local && !CoreBaseSettings.Standalone)
{
restoreRequest.FilePathOrId = BackupFileUploadHandler.GetFilePath();
}
}
}
BackupService.StartRestore(restoreRequest);
}
@ -282,9 +282,9 @@ namespace ASC.Data.Backup
private void DemandPermissionsRestore()
{
PermissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
if (!SetupInfo.IsVisibleSettings("Restore") ||
PermissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
if (!SetupInfo.IsVisibleSettings("Restore") ||
(!CoreBaseSettings.Standalone && !TenantManager.GetTenantQuota(TenantManager.GetCurrentTenant().TenantId).Restore))
throw new BillingException(Resource.ErrorNotAllowedOption, "Restore");
}
@ -310,7 +310,7 @@ namespace ASC.Data.Backup
}
public BackupProgress GetTransferProgress()
{
{
return BackupService.GetTransferProgress(GetCurrentTenantId());
}
@ -384,13 +384,13 @@ namespace ASC.Data.Backup
public override string ToString()
{
return Period switch
{
BackupPeriod.EveryDay => string.Format("0 0 {0} ? * *", Hour),
BackupPeriod.EveryMonth => string.Format("0 0 {0} {1} * ?", Hour, Day),
BackupPeriod.EveryWeek => string.Format("0 0 {0} ? * {1}", Hour, Day),
_ => base.ToString(),
};
return Period switch
{
BackupPeriod.EveryDay => string.Format("0 0 {0} ? * *", Hour),
BackupPeriod.EveryMonth => string.Format("0 0 {0} {1} * ?", Hour, Day),
BackupPeriod.EveryWeek => string.Format("0 0 {0} ? * {1}", Hour, Day),
_ => base.ToString(),
};
}
}

View File

@ -1,100 +1,100 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.IO;
using ASC.Common;
using ASC.Core;
using Microsoft.AspNetCore.Http;
namespace ASC.Web.Studio.Core.Backup
{
[Scope]
public class BackupFileUploadHandler
{
private const long MaxBackupFileSize = 1024L * 1024L * 1024L;
private const string BackupTempFolder = "backup";
private const string BackupFileName = "backup.tmp";
private PermissionContext PermissionContext { get; }
private TempPath TempPath { get; }
private TenantManager TenantManager { get; }
public BackupFileUploadHandler(
PermissionContext permissionContext,
TempPath tempPath,
TenantManager tenantManager)
{
PermissionContext = permissionContext;
TempPath = tempPath;
TenantManager = tenantManager;
}
public string ProcessUpload(IFormFile file)
{
if (file == null)
{
return "No files.";
}
if (!PermissionContext.CheckPermissions(SecutiryConstants.EditPortalSettings))
{
return "Access denied.";
}
if (file.Length <= 0 || file.Length > MaxBackupFileSize)
{
return $"File size must be greater than 0 and less than {MaxBackupFileSize} bytes";
}
try
{
var filePath = GetFilePath();
if (File.Exists(filePath))
{
File.Delete(filePath);
}
using (var fileStream = File.Create(filePath))
{
file.CopyTo(fileStream);
}
return string.Empty;
}
catch (Exception error)
{
return error.Message;
}
}
internal string GetFilePath()
{
var folder = Path.Combine(TempPath.GetTempPath(), BackupTempFolder, TenantManager.GetCurrentTenant().TenantId.ToString());
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
return Path.Combine(folder, BackupFileName);
}
}
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.IO;
using ASC.Common;
using ASC.Core;
using Microsoft.AspNetCore.Http;
namespace ASC.Web.Studio.Core.Backup
{
[Scope]
public class BackupFileUploadHandler
{
private const long MaxBackupFileSize = 1024L * 1024L * 1024L;
private const string BackupTempFolder = "backup";
private const string BackupFileName = "backup.tmp";
private PermissionContext PermissionContext { get; }
private TempPath TempPath { get; }
private TenantManager TenantManager { get; }
public BackupFileUploadHandler(
PermissionContext permissionContext,
TempPath tempPath,
TenantManager tenantManager)
{
PermissionContext = permissionContext;
TempPath = tempPath;
TenantManager = tenantManager;
}
public string ProcessUpload(IFormFile file)
{
if (file == null)
{
return "No files.";
}
if (!PermissionContext.CheckPermissions(SecutiryConstants.EditPortalSettings))
{
return "Access denied.";
}
if (file.Length <= 0 || file.Length > MaxBackupFileSize)
{
return $"File size must be greater than 0 and less than {MaxBackupFileSize} bytes";
}
try
{
var filePath = GetFilePath();
if (File.Exists(filePath))
{
File.Delete(filePath);
}
using (var fileStream = File.Create(filePath))
{
file.CopyTo(fileStream);
}
return string.Empty;
}
catch (Exception error)
{
return error.Message;
}
}
internal string GetFilePath()
{
var folder = Path.Combine(TempPath.GetTempPath(), BackupTempFolder, TenantManager.GetCurrentTenant().TenantId.ToString());
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
return Path.Combine(folder, BackupFileName);
}
}
}

View File

@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace ASC.Data.Backup {
namespace ASC.Data.Backup.Core {
using System;
@ -39,7 +39,7 @@ namespace ASC.Data.Backup {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ASC.Data.Backup.BackupResource", typeof(BackupResource).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ASC.Data.Backup.Core.BackupResource", typeof(BackupResource).Assembly);
resourceMan = temp;
}
return resourceMan;

View File

@ -1,67 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.6.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.6.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BackupNotFound" xml:space="preserve">
<value>The backup file is invalid. Please, use a file created in ONLYOFFICE v11.5 or later.</value>
</data>
<data name="ButtonSetPassword" xml:space="preserve">
<value>Set Password</value>
</data>
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.6.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.6.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BackupNotFound" xml:space="preserve">
<value>The backup file is invalid. Please, use a file created in ONLYOFFICE v11.5 or later.</value>
</data>
<data name="ButtonSetPassword" xml:space="preserve">
<value>Set Password</value>
</data>
</root>

View File

@ -23,9 +23,9 @@
*
*/
using System;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace ASC.Data.Backup.Contracts
{
public enum BackupStorageType
@ -41,130 +41,130 @@ namespace ASC.Data.Backup.Contracts
DataStore = 4,
ThirdPartyConsumer = 5
}
}
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; }
}
public class BackupHistoryRecord
{
public Guid Id { get; set; }
public string FileName { get; set; }
public BackupStorageType StorageType { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ExpiresOn { get; set; }
}
public class StartTransferRequest
{
public int TenantId { get; set; }
public string TargetRegion { get; set; }
public bool NotifyUsers { get; set; }
public int TenantId { get; set; }
public Guid UserId { get; set; }
public bool BackupMail { get; set; }
}
public class TransferRegion
{
public string Name { get; set; }
public string BaseDomain { get; set; }
public bool IsCurrentRegion { get; set; }
}
public class StartRestoreRequest
{
public int TenantId { get; set; }
public Guid BackupId { get; set; }
public BackupStorageType StorageType { get; set; }
public string FilePathOrId { get; set; }
public bool NotifyAfterCompletion { get; set; }
public BackupStorageType StorageType { get; set; }
public string StorageBasePath { get; set; }
public Dictionary<string, string> StorageParams { get; set; }
}
}
public class BackupHistoryRecord
{
public Guid Id { get; set; }
public string FileName { get; set; }
public BackupStorageType StorageType { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ExpiresOn { get; set; }
}
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
{
public string Name { get; set; }
public string BaseDomain { get; set; }
public bool IsCurrentRegion { get; set; }
}
public class StartRestoreRequest
{
public int TenantId { get; set; }
public Guid BackupId { get; set; }
public BackupStorageType StorageType { get; set; }
public string FilePathOrId { get; set; }
public bool NotifyAfterCompletion { get; set; }
public Dictionary<string, string> StorageParams { get; set; }
}
public class CreateScheduleRequest : StartBackupRequest
{
public string Cron { get; set; }
{
public string Cron { get; set; }
public int NumberOfBackupsStored { get; set; }
}
}
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; }
{
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; }
public Dictionary<string, string> StorageParams { get; set; }
}
}

View File

@ -31,20 +31,20 @@ using System.Data;
using System.IO;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Utils;
using ASC.Common.Utils;
namespace ASC.Data.Backup
{
{
[Scope]
public class DbBackupProvider : IBackupProvider
{
private readonly List<string> processedTables = new List<string>();
private readonly DbHelper dbHelper;
private readonly TempStream tempStream;
private readonly DbHelper dbHelper;
private readonly TempStream tempStream;
public string Name
{
get { return "databases"; }
@ -52,8 +52,8 @@ namespace ASC.Data.Backup
public DbBackupProvider(DbHelper dbHelper, TempStream tempStream)
{
this.dbHelper = dbHelper;
this.tempStream = tempStream;
this.dbHelper = dbHelper;
this.tempStream = tempStream;
}
public IEnumerable<XElement> GetElements(int tenant, string[] configs, IDataWriteOperator writer)
{
@ -104,13 +104,13 @@ namespace ASC.Data.Backup
{
if (config.Contains(Path.DirectorySeparatorChar) && !Uri.IsWellFormedUriString(config, UriKind.Relative))
{
var map = new ExeConfigurationFileMap
{
ExeConfigFilename = string.Compare(Path.GetExtension(config), ".config", true) == 0 ? config : CrossPlatform.PathCombine(config, "Web.config")
var map = new ExeConfigurationFileMap
{
ExeConfigFilename = string.Compare(Path.GetExtension(config), ".config", true) == 0 ? config : CrossPlatform.PathCombine(config, "Web.config")
};
return ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
}
return ConfigurationManager.OpenExeConfiguration(config);
return ConfigurationManager.OpenExeConfiguration(config);
}
public IEnumerable<ConnectionStringSettings> GetConnectionStrings(string[] configs)
@ -178,12 +178,12 @@ namespace ASC.Data.Backup
foreach (DataColumn c in dataTable.Columns)
{
if (c.DataType == typeof(DateTime)) c.DateTimeMode = DataSetDateTime.Unspecified;
}
using (var file = tempStream.Create())
{
dataTable.WriteXml(file, XmlWriteMode.WriteSchema);
writer.WriteEntry(string.Format("{0}\\{1}\\{2}", Name, connectionString.Name, table).ToLower(), file);
}
using (var file = tempStream.Create())
{
dataTable.WriteXml(file, XmlWriteMode.WriteSchema);
writer.WriteEntry(string.Format("{0}\\{1}\\{2}", Name, connectionString.Name, table).ToLower(), file);
}
processedTables.Add(table);
@ -224,6 +224,6 @@ namespace ASC.Data.Backup
processedTables.Add(table);
}
}
}
}
}
}

View File

@ -11,14 +11,14 @@ using System.Xml.XPath;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Common.Utils;
using ASC.Data.Backup.EF.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup
{
{
[Scope]
public class DbHelper : IDisposable
{

View File

@ -28,25 +28,25 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Data.Storage;
using ASC.Common.Utils;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup
{
{
[Scope]
public class FileBackupProvider : IBackupProvider
{
private readonly IEnumerable<string> allowedModules;
private readonly ILog log;
private StorageFactory StorageFactory { get; set; }
private StorageFactoryConfig StorageFactoryConfig { get; set; }
private StorageFactoryConfig StorageFactoryConfig { get; set; }
public FileBackupProvider(IOptionsMonitor<ILog> options, StorageFactory storageFactory, StorageFactoryConfig storageFactoryConfig)
{
StorageFactory = storageFactory;
@ -90,7 +90,7 @@ namespace ASC.Data.Backup
{
try
{
using var stream = storage.GetReadStream(file.Domain, file.Path);
using var stream = storage.GetReadStream(file.Domain, file.Path);
writer.WriteEntry(backupPath, stream);
break;
}
@ -240,10 +240,10 @@ namespace ASC.Data.Backup
return Equals(other.Module, Module) && Equals(other.Domain, Domain) && Equals(other.Path, Path);
}
public override int GetHashCode()
{
return HashCode.Combine(Module, Domain, Path);
}
public override int GetHashCode()
{
return HashCode.Combine(Module, Domain, Path);
}
}
}
}

View File

@ -37,7 +37,7 @@ namespace ASC.Data.Backup
public interface IDataReadOperator : IDisposable
{
Stream GetEntry(string key);
Stream GetEntry(string key);
IEnumerable<string> GetEntries(string key);
}
}

View File

@ -25,222 +25,223 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Core;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Notify.Model;
using ASC.Notify.Patterns;
using ASC.Notify.Recipients;
using ASC.Web.Core.Users;
using ASC.Web.Core.WhiteLabel;
using ASC.Web.Studio.Core.Notify;
using ASC.Web.Studio.Utility;
using Microsoft.Extensions.DependencyInjection;
using ASC.Core;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Data.Backup.Core;
using ASC.Notify.Model;
using ASC.Notify.Patterns;
using ASC.Notify.Recipients;
using ASC.Web.Core.Users;
using ASC.Web.Core.WhiteLabel;
using ASC.Web.Studio.Core.Notify;
using ASC.Web.Studio.Utility;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Data.Backup
{
{
[Singletone(Additional = typeof(NotifyHelperExtension))]
public class NotifyHelper
{
private IServiceProvider ServiceProvider { get; }
{
private IServiceProvider ServiceProvider { get; }
public NotifyHelper(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
{
ServiceProvider = serviceProvider;
}
public void SendAboutTransferStart(Tenant tenant, string targetRegion, bool notifyUsers)
{
{
MigrationNotify(tenant, Actions.MigrationPortalStart, targetRegion, string.Empty, notifyUsers);
}
public void SendAboutTransferComplete(Tenant tenant, string targetRegion, string targetAddress, bool notifyOnlyOwner, int toTenantId)
{
{
MigrationNotify(tenant, Actions.MigrationPortalSuccessV115, targetRegion, targetAddress, !notifyOnlyOwner, toTenantId);
}
public void SendAboutTransferError(Tenant tenant, string targetRegion, string resultAddress, bool notifyOnlyOwner)
{
{
MigrationNotify(tenant, !string.IsNullOrEmpty(targetRegion) ? Actions.MigrationPortalError : Actions.MigrationPortalServerFailure, targetRegion, resultAddress, !notifyOnlyOwner);
}
public void SendAboutBackupCompleted(Guid userId)
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var (userManager, studioNotifyHelper, studioNotifySource, displayUserSettingsHelper, _) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
client.SendNoticeToAsync(
Actions.BackupCreated,
new[] { studioNotifyHelper.ToRecipient(userId) },
new[] { StudioNotifyService.EMailSenderName },
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var (userManager, studioNotifyHelper, studioNotifySource, displayUserSettingsHelper, _) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
client.SendNoticeToAsync(
Actions.BackupCreated,
new[] { studioNotifyHelper.ToRecipient(userId) },
new[] { StudioNotifyService.EMailSenderName },
new TagValue(Tags.OwnerName, userManager.GetUsers(userId).DisplayUserName(displayUserSettingsHelper)));
}
public void SendAboutRestoreStarted(Tenant tenant, bool notifyAllUsers)
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var (userManager, studioNotifyHelper, studioNotifySource, displayUserSettingsHelper, _) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
var owner = userManager.GetUsers(tenant.OwnerId);
var users =
notifyAllUsers
? studioNotifyHelper.RecipientFromEmail(userManager.GetUsers(EmployeeStatus.Active).Where(r => r.ActivationStatus == EmployeeActivationStatus.Activated).Select(u => u.Email).ToList(), false)
: owner.ActivationStatus == EmployeeActivationStatus.Activated ? studioNotifyHelper.RecipientFromEmail(owner.Email, false) : new IDirectRecipient[0];
client.SendNoticeToAsync(
Actions.RestoreStarted,
users,
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var (userManager, studioNotifyHelper, studioNotifySource, displayUserSettingsHelper, _) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
var owner = userManager.GetUsers(tenant.OwnerId);
var users =
notifyAllUsers
? studioNotifyHelper.RecipientFromEmail(userManager.GetUsers(EmployeeStatus.Active).Where(r => r.ActivationStatus == EmployeeActivationStatus.Activated).Select(u => u.Email).ToList(), false)
: owner.ActivationStatus == EmployeeActivationStatus.Activated ? studioNotifyHelper.RecipientFromEmail(owner.Email, false) : new IDirectRecipient[0];
client.SendNoticeToAsync(
Actions.RestoreStarted,
users,
new[] { StudioNotifyService.EMailSenderName });
}
public void SendAboutRestoreCompleted(Tenant tenant, bool notifyAllUsers)
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
var commonLinkUtility = scope.ServiceProvider.GetService<CommonLinkUtility>();
var (userManager, studioNotifyHelper, studioNotifySource, displayUserSettingsHelper, authManager) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
var owner = userManager.GetUsers(tenant.OwnerId);
var users = notifyAllUsers
? userManager.GetUsers(EmployeeStatus.Active)
: new[] { userManager.GetUsers(tenantManager.GetCurrentTenant().OwnerId) };
foreach (var user in users)
{
var hash = authManager.GetUserPasswordStamp(user.ID).ToString("s");
var confirmationUrl = commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PasswordChange, hash);
Func<string> greenButtonText = () => BackupResource.ButtonSetPassword;
client.SendNoticeToAsync(
Actions.RestoreCompletedV115,
new IRecipient[] { user },
new[] { StudioNotifyService.EMailSenderName },
null,
TagValues.GreenButton(greenButtonText, confirmationUrl));
}
}
private void MigrationNotify(Tenant tenant, INotifyAction action, string region, string url, bool notify, int? toTenantId = null)
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var (userManager, studioNotifyHelper, studioNotifySource, _, authManager) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
var commonLinkUtility = scope.ServiceProvider.GetService<CommonLinkUtility>();
var users = userManager.GetUsers()
.Where(u => notify ? u.ActivationStatus.HasFlag(EmployeeActivationStatus.Activated) : u.IsOwner(tenant))
.ToArray();
if (users.Any())
{
var args = CreateArgs(scope, region, url);
if (action == Actions.MigrationPortalSuccessV115)
{
foreach (var user in users)
{
var currentArgs = new List<ITagValue>(args);
var newTenantId = toTenantId.HasValue ? toTenantId.Value : tenant.TenantId;
var hash = authManager.GetUserPasswordStamp(user.ID).ToString("s");
var confirmationUrl = url + "/" + commonLinkUtility.GetConfirmationUrlRelative(newTenantId, user.Email, ConfirmType.PasswordChange, hash);
Func<string> greenButtonText = () => BackupResource.ButtonSetPassword;
currentArgs.Add(TagValues.GreenButton(greenButtonText, confirmationUrl));
client.SendNoticeToAsync(
action,
null,
new IRecipient[] { user },
new[] { StudioNotifyService.EMailSenderName },
currentArgs.ToArray());
}
}
else
{
client.SendNoticeToAsync(
action,
null,
users.Select(u => studioNotifyHelper.ToRecipient(u.ID)).ToArray(),
new[] { StudioNotifyService.EMailSenderName },
args.ToArray());
}
}
}
private List<ITagValue> CreateArgs(IServiceScope scope,string region, string url)
{
var args = new List<ITagValue>()
{
new TagValue(Tags.RegionName, TransferResourceHelper.GetRegionDescription(region)),
new TagValue(Tags.PortalUrl, url)
};
if (!string.IsNullOrEmpty(url))
{
args.Add(new TagValue(CommonTags.VirtualRootPath, url));
args.Add(new TagValue(CommonTags.ProfileUrl, url + scope.ServiceProvider.GetService<CommonLinkUtility>().GetMyStaff()));
args.Add(new TagValue(CommonTags.LetterLogo, scope.ServiceProvider.GetService<TenantLogoManager>().GetLogoDark(true)));
}
return args;
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
var commonLinkUtility = scope.ServiceProvider.GetService<CommonLinkUtility>();
var (userManager, studioNotifyHelper, studioNotifySource, displayUserSettingsHelper, authManager) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
var owner = userManager.GetUsers(tenant.OwnerId);
var users = notifyAllUsers
? userManager.GetUsers(EmployeeStatus.Active)
: new[] { userManager.GetUsers(tenantManager.GetCurrentTenant().OwnerId) };
foreach (var user in users)
{
var hash = authManager.GetUserPasswordStamp(user.ID).ToString("s");
var confirmationUrl = commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.PasswordChange, hash);
Func<string> greenButtonText = () => BackupResource.ButtonSetPassword;
client.SendNoticeToAsync(
Actions.RestoreCompletedV115,
new IRecipient[] { user },
new[] { StudioNotifyService.EMailSenderName },
null,
TagValues.GreenButton(greenButtonText, confirmationUrl));
}
}
private void MigrationNotify(Tenant tenant, INotifyAction action, string region, string url, bool notify, int? toTenantId = null)
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<NotifyHelperScope>();
var (userManager, studioNotifyHelper, studioNotifySource, _, authManager) = scopeClass;
var client = WorkContext.NotifyContext.NotifyService.RegisterClient(studioNotifySource, scope);
var commonLinkUtility = scope.ServiceProvider.GetService<CommonLinkUtility>();
var users = userManager.GetUsers()
.Where(u => notify ? u.ActivationStatus.HasFlag(EmployeeActivationStatus.Activated) : u.IsOwner(tenant))
.ToArray();
if (users.Any())
{
var args = CreateArgs(scope, region, url);
if (action == Actions.MigrationPortalSuccessV115)
{
foreach (var user in users)
{
var currentArgs = new List<ITagValue>(args);
var newTenantId = toTenantId.HasValue ? toTenantId.Value : tenant.TenantId;
var hash = authManager.GetUserPasswordStamp(user.ID).ToString("s");
var confirmationUrl = url + "/" + commonLinkUtility.GetConfirmationUrlRelative(newTenantId, user.Email, ConfirmType.PasswordChange, hash);
Func<string> greenButtonText = () => BackupResource.ButtonSetPassword;
currentArgs.Add(TagValues.GreenButton(greenButtonText, confirmationUrl));
client.SendNoticeToAsync(
action,
null,
new IRecipient[] { user },
new[] { StudioNotifyService.EMailSenderName },
currentArgs.ToArray());
}
}
else
{
client.SendNoticeToAsync(
action,
null,
users.Select(u => studioNotifyHelper.ToRecipient(u.ID)).ToArray(),
new[] { StudioNotifyService.EMailSenderName },
args.ToArray());
}
}
}
private List<ITagValue> CreateArgs(IServiceScope scope,string region, string url)
{
var args = new List<ITagValue>()
{
new TagValue(Tags.RegionName, TransferResourceHelper.GetRegionDescription(region)),
new TagValue(Tags.PortalUrl, url)
};
if (!string.IsNullOrEmpty(url))
{
args.Add(new TagValue(CommonTags.VirtualRootPath, url));
args.Add(new TagValue(CommonTags.ProfileUrl, url + scope.ServiceProvider.GetService<CommonLinkUtility>().GetMyStaff()));
args.Add(new TagValue(CommonTags.LetterLogo, scope.ServiceProvider.GetService<TenantLogoManager>().GetLogoDark(true)));
}
return args;
}
}
[Scope]
public class NotifyHelperScope
{
private AuthManager AuthManager { get; }
private UserManager UserManager { get; }
private StudioNotifyHelper StudioNotifyHelper { get; }
private StudioNotifySource StudioNotifySource { get; }
private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
public NotifyHelperScope(
UserManager userManager,
StudioNotifyHelper studioNotifyHelper,
StudioNotifySource studioNotifySource,
DisplayUserSettingsHelper displayUserSettingsHelper,
AuthManager authManager)
{
UserManager = userManager;
StudioNotifyHelper = studioNotifyHelper;
StudioNotifySource = studioNotifySource;
DisplayUserSettingsHelper = displayUserSettingsHelper;
AuthManager = authManager;
}
public void Deconstruct(
out UserManager userManager,
out StudioNotifyHelper studioNotifyHelper,
out StudioNotifySource studioNotifySource,
out DisplayUserSettingsHelper displayUserSettingsHelper,
out AuthManager authManager
)
{
userManager = UserManager;
studioNotifyHelper = StudioNotifyHelper;
studioNotifySource = StudioNotifySource;
displayUserSettingsHelper = DisplayUserSettingsHelper;
authManager = AuthManager;
}
public class NotifyHelperScope
{
private AuthManager AuthManager { get; }
private UserManager UserManager { get; }
private StudioNotifyHelper StudioNotifyHelper { get; }
private StudioNotifySource StudioNotifySource { get; }
private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
public NotifyHelperScope(
UserManager userManager,
StudioNotifyHelper studioNotifyHelper,
StudioNotifySource studioNotifySource,
DisplayUserSettingsHelper displayUserSettingsHelper,
AuthManager authManager)
{
UserManager = userManager;
StudioNotifyHelper = studioNotifyHelper;
StudioNotifySource = studioNotifySource;
DisplayUserSettingsHelper = displayUserSettingsHelper;
AuthManager = authManager;
}
public void Deconstruct(
out UserManager userManager,
out StudioNotifyHelper studioNotifyHelper,
out StudioNotifySource studioNotifySource,
out DisplayUserSettingsHelper displayUserSettingsHelper,
out AuthManager authManager
)
{
userManager = UserManager;
studioNotifyHelper = StudioNotifyHelper;
studioNotifySource = StudioNotifySource;
displayUserSettingsHelper = DisplayUserSettingsHelper;
authManager = AuthManager;
}
}
public class NotifyHelperExtension
{
public static void Register(DIHelper services)
{
{
services.TryAdd<NotifyHelperScope>();
}
}

View File

@ -11,7 +11,7 @@ using ASC.Notify.Cron;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup
{
{
[Scope]
public class Schedule
{

View File

@ -26,29 +26,29 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using ASC.Common;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using System.Text;
using ASC.Common;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
namespace ASC.Data.Backup
{
{
public class ZipWriteOperator : IDataWriteOperator
{
private readonly GZipOutputStream gZipOutputStream;
private readonly TarOutputStream tarOutputStream;
private readonly Stream file;
private readonly Stream file;
private TempStream TempStream { get; }
public ZipWriteOperator(TempStream tempStream, string targetFile)
{
file = new FileStream(targetFile, FileMode.Create);
gZipOutputStream = new GZipOutputStream(file);
tarOutputStream = new TarOutputStream(gZipOutputStream, Encoding.UTF8);
TempStream = tempStream;
tarOutputStream = new TarOutputStream(gZipOutputStream, Encoding.UTF8);
TempStream = tempStream;
}
public void WriteEntry(string key, Stream stream)

View File

@ -17,8 +17,8 @@ namespace ASC.Data.Backup.EF.Model
[Column("is_scheduled")]
public bool IsScheduled { get; set; }
public string Name { get; set; }
public string Name { get; set; }
public string Hash { get; set; }
[Column("storage_type")]

View File

@ -19,13 +19,13 @@ namespace ASC.Data.Backup.EF.Context
public BackupsContext(DbContextOptions<BackupsContext> options)
: base(options)
{
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddDbTenant()
.AddDbTenant()
.AddDbTariff();
}
}

View File

@ -9,7 +9,7 @@ using ASC.Data.Backup.Service;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Data.Backup.Listerners
{
{
[Singletone]
public class BackupListener
{

View File

@ -28,20 +28,20 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.EF.Model;
using ASC.Data.Backup.Storage;
using ASC.Data.Backup.Utils;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using ASC.Data.Backup.Utils;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace ASC.Data.Backup.Service
{
[Scope]
@ -190,34 +190,34 @@ namespace ASC.Data.Backup.Service
}
public List<TransferRegion> GetTransferRegions()
{
var settings = Configuration.GetSetting<BackupSettings>("backup");
return settings.WebConfigs.Elements.Select(configElement =>
{
var config = Utils.ConfigurationProvider.Open(PathHelper.ToRootedConfigPath(configElement.Path));
var baseDomain = config.AppSettings.Settings["core:base-domain"].Value;
return new TransferRegion
{
Name = configElement.Region,
BaseDomain = baseDomain,
IsCurrentRegion = configElement.Region.Equals(settings.WebConfigs.CurrentRegion, StringComparison.InvariantCultureIgnoreCase)
};
})
.ToList();
{
var settings = Configuration.GetSetting<BackupSettings>("backup");
return settings.WebConfigs.Elements.Select(configElement =>
{
var config = Utils.ConfigurationProvider.Open(PathHelper.ToRootedConfigPath(configElement.Path));
var baseDomain = config.AppSettings.Settings["core:base-domain"].Value;
return new TransferRegion
{
Name = configElement.Region,
BaseDomain = baseDomain,
IsCurrentRegion = configElement.Region.Equals(settings.WebConfigs.CurrentRegion, StringComparison.InvariantCultureIgnoreCase)
};
})
.ToList();
}
public void CreateSchedule(CreateScheduleRequest request)
{
BackupRepository.SaveBackupSchedule(
new BackupSchedule()
{
TenantId = request.TenantId,
Cron = request.Cron,
BackupMail = request.BackupMail,
BackupsStored = request.NumberOfBackupsStored,
StorageType = request.StorageType,
StorageBasePath = request.StorageBasePath,
StorageParams = JsonConvert.SerializeObject(request.StorageParams)
new BackupSchedule()
{
TenantId = request.TenantId,
Cron = request.Cron,
BackupMail = request.BackupMail,
BackupsStored = request.NumberOfBackupsStored,
StorageType = request.StorageType,
StorageBasePath = request.StorageBasePath,
StorageParams = JsonConvert.SerializeObject(request.StorageParams)
});
}
@ -229,23 +229,23 @@ namespace ASC.Data.Backup.Service
public ScheduleResponse GetSchedule(int tenantId)
{
var schedule = BackupRepository.GetBackupSchedule(tenantId);
if (schedule != null)
{
var tmp = new ScheduleResponse
{
StorageType = schedule.StorageType,
StorageBasePath = schedule.StorageBasePath,
BackupMail = schedule.BackupMail,
NumberOfBackupsStored = schedule.BackupsStored,
Cron = schedule.Cron,
LastBackupTime = schedule.LastBackupTime,
StorageParams = JsonConvert.DeserializeObject<Dictionary<string, string>>(schedule.StorageParams)
};
return tmp;
}
else
{
return null;
if (schedule != null)
{
var tmp = new ScheduleResponse
{
StorageType = schedule.StorageType,
StorageBasePath = schedule.StorageBasePath,
BackupMail = schedule.BackupMail,
NumberOfBackupsStored = schedule.BackupsStored,
Cron = schedule.Cron,
LastBackupTime = schedule.LastBackupTime,
StorageParams = JsonConvert.DeserializeObject<Dictionary<string, string>>(schedule.StorageParams)
};
return tmp;
}
else
{
return null;
}
}
}

View File

@ -26,18 +26,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Core.Common.EF;
using System.Linq;
using ASC.Common;
using ASC.Core.Common.EF;
using ASC.Core.Tenants;
using ASC.Data.Backup.EF.Context;
using ASC.Data.Backup.EF.Model;
using ASC.Data.Backup.EF.Model;
namespace ASC.Data.Backup.Storage
{
{
[Scope]
public class BackupRepository : IBackupRepository
{
{
private Lazy<BackupsContext> LazyBackupsContext { get; }
private BackupsContext BackupContext { get => LazyBackupsContext.Value; }
@ -49,21 +49,21 @@ namespace ASC.Data.Backup.Storage
public void SaveBackupRecord(BackupRecord backup)
{
BackupContext.AddOrUpdate(r => r.Backups, backup);
BackupContext.SaveChanges();
BackupContext.SaveChanges();
}
public BackupRecord GetBackupRecord(Guid id)
{
return BackupContext.Backups.SingleOrDefault(b => b.Id == id);
}
public BackupRecord GetBackupRecord(string hash, int tenant)
{
return BackupContext.Backups.SingleOrDefault(b => b.Hash == hash && b.TenantId == tenant);
}
{
return BackupContext.Backups.SingleOrDefault(b => b.Id == id);
}
public BackupRecord GetBackupRecord(string hash, int tenant)
{
return BackupContext.Backups.SingleOrDefault(b => b.Hash == hash && b.TenantId == tenant);
}
public List<BackupRecord> GetExpiredBackupRecords()
{
{
return BackupContext.Backups.Where(b => b.ExpiresOn != DateTime.MinValue && b.ExpiresOn <= DateTime.UtcNow).ToList();
}
@ -104,18 +104,18 @@ namespace ASC.Data.Backup.Storage
public List<BackupSchedule> GetBackupSchedules()
{
var query = BackupContext.Schedules.Join(BackupContext.Tenants,
s => s.TenantId,
s => s.TenantId,
t => t.Id,
(s, t) => new { schedule = s, tenant = t })
.Where(q => q.tenant.Status == TenantStatus.Active)
.Select(q => q.schedule);
(s, t) => new { schedule = s, tenant = t })
.Where(q => q.tenant.Status == TenantStatus.Active)
.Select(q => q.schedule);
return query.ToList();
}
public BackupSchedule GetBackupSchedule(int tenantId)
{
return BackupContext.Schedules.SingleOrDefault(s => s.TenantId == tenantId);
}
{
return BackupContext.Schedules.SingleOrDefault(s => s.TenantId == tenantId);
}
}
}

View File

@ -25,92 +25,92 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.EF.Model;
using ASC.Data.Backup.Service;
using ASC.Data.Backup.Utils;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using ASC.Data.Backup.Utils;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace ASC.Data.Backup.Storage
{
{
[Scope]
public class BackupStorageFactory
{
private ConfigurationExtension Configuration { get; }
private DocumentsBackupStorage DocumentsBackupStorage { get; }
private DataStoreBackupStorage DataStoreBackupStorage { get; }
private ILog Log { get; }
private DataStoreBackupStorage DataStoreBackupStorage { get; }
private ILog Log { get; }
private LocalBackupStorage LocalBackupStorage { get; }
private ConsumerBackupStorage ConsumerBackupStorage { get; }
private TenantManager TenantManager { get; }
public BackupStorageFactory(
ConsumerBackupStorage consumerBackupStorage,
LocalBackupStorage localBackupStorage,
ConfigurationExtension configuration,
DocumentsBackupStorage documentsBackupStorage,
TenantManager tenantManager,
DataStoreBackupStorage dataStoreBackupStorage,
public BackupStorageFactory(
ConsumerBackupStorage consumerBackupStorage,
LocalBackupStorage localBackupStorage,
ConfigurationExtension configuration,
DocumentsBackupStorage documentsBackupStorage,
TenantManager tenantManager,
DataStoreBackupStorage dataStoreBackupStorage,
IOptionsMonitor<ILog> options)
{
Configuration = configuration;
DocumentsBackupStorage = documentsBackupStorage;
DataStoreBackupStorage = dataStoreBackupStorage;
Log = options.CurrentValue;
DataStoreBackupStorage = dataStoreBackupStorage;
Log = options.CurrentValue;
LocalBackupStorage = localBackupStorage;
ConsumerBackupStorage = consumerBackupStorage;
TenantManager = tenantManager;
}
}
public IBackupStorage GetBackupStorage(BackupRecord record)
{
try
{
return GetBackupStorage(record.StorageType, record.TenantId, JsonConvert.DeserializeObject<Dictionary<string, string>>(record.StorageParams));
}
catch (Exception error)
{
Log.Error("can't get backup storage for record " + record.Id, error);
return null;
{
try
{
return GetBackupStorage(record.StorageType, record.TenantId, JsonConvert.DeserializeObject<Dictionary<string, string>>(record.StorageParams));
}
}
catch (Exception error)
{
Log.Error("can't get backup storage for record " + record.Id, error);
return null;
}
}
public IBackupStorage GetBackupStorage(BackupStorageType type, int tenantId, Dictionary<string, string> storageParams)
{
var settings = Configuration.GetSetting<BackupSettings>("backup");
var webConfigPath = PathHelper.ToRootedConfigPath(settings.WebConfigs.CurrentPath);
var webConfigPath = PathHelper.ToRootedConfigPath(settings.WebConfigs.CurrentPath);
switch (type)
{
case BackupStorageType.Documents:
case BackupStorageType.ThridpartyDocuments:
{
DocumentsBackupStorage.Init(tenantId, webConfigPath);
return DocumentsBackupStorage;
case BackupStorageType.ThridpartyDocuments:
{
DocumentsBackupStorage.Init(tenantId, webConfigPath);
return DocumentsBackupStorage;
}
case BackupStorageType.DataStore:
{
DataStoreBackupStorage.Init(tenantId, webConfigPath);
return DataStoreBackupStorage;
case BackupStorageType.DataStore:
{
DataStoreBackupStorage.Init(tenantId, webConfigPath);
return DataStoreBackupStorage;
}
case BackupStorageType.Local:
return LocalBackupStorage;
case BackupStorageType.ThirdPartyConsumer:
{
if (storageParams == null) return null;
TenantManager.SetCurrentTenant(tenantId);
ConsumerBackupStorage.Init(storageParams);
return ConsumerBackupStorage;
case BackupStorageType.ThirdPartyConsumer:
{
if (storageParams == null) return null;
TenantManager.SetCurrentTenant(tenantId);
ConsumerBackupStorage.Init(storageParams);
return ConsumerBackupStorage;
}
default:
throw new InvalidOperationException("Unknown storage type.");

View File

@ -34,7 +34,7 @@ using ASC.Data.Storage;
using ASC.Data.Storage.Configuration;
namespace ASC.Data.Backup.Storage
{
{
[Scope]
public class ConsumerBackupStorage : IBackupStorage
{
@ -52,16 +52,16 @@ namespace ASC.Data.Backup.Storage
}
public string Upload(string storageBasePath, string localPath, Guid userId)
{
using var stream = File.OpenRead(localPath);
var storagePath = Path.GetFileName(localPath);
Store.Save(Domain, storagePath, stream, ACL.Private);
using var stream = File.OpenRead(localPath);
var storagePath = Path.GetFileName(localPath);
Store.Save(Domain, storagePath, stream, ACL.Private);
return storagePath;
}
public void Download(string storagePath, string targetLocalPath)
{
using var source = Store.GetReadStream(Domain, storagePath);
using var destination = File.OpenWrite(targetLocalPath);
using var source = Store.GetReadStream(Domain, storagePath);
using var destination = File.OpenWrite(targetLocalPath);
source.CopyTo(destination);
}

View File

@ -31,7 +31,7 @@ using ASC.Common;
using ASC.Data.Storage;
namespace ASC.Data.Backup.Storage
{
{
[Scope]
public class DataStoreBackupStorage : IBackupStorage
{
@ -50,16 +50,16 @@ namespace ASC.Data.Backup.Storage
}
public string Upload(string storageBasePath, string localPath, Guid userId)
{
using var stream = File.OpenRead(localPath);
var storagePath = Path.GetFileName(localPath);
GetDataStore().Save("", storagePath, stream);
using var stream = File.OpenRead(localPath);
var storagePath = Path.GetFileName(localPath);
GetDataStore().Save("", storagePath, stream);
return storagePath;
}
public void Download(string storagePath, string targetLocalPath)
{
using var source = GetDataStore().GetReadStream("", storagePath);
using var destination = File.OpenWrite(targetLocalPath);
using var source = GetDataStore().GetReadStream("", storagePath);
using var destination = File.OpenWrite(targetLocalPath);
source.CopyTo(destination);
}
@ -68,7 +68,7 @@ namespace ASC.Data.Backup.Storage
var dataStore = GetDataStore();
if (dataStore.IsFile("", storagePath))
{
dataStore.Delete("", storagePath);
dataStore.Delete("", storagePath);
}
}

View File

@ -25,198 +25,198 @@
using System;
using System.IO;
using ASC.Common;
using System.IO;
using ASC.Common;
using ASC.Core;
using ASC.Data.Storage;
using ASC.Files.Core;
using ASC.Web.Studio.Core;
//using File = ASC.Files.Core.File;
using Microsoft.Extensions.DependencyInjection;
using ASC.Files.Core;
using ASC.Web.Studio.Core;
//using File = ASC.Files.Core.File;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Data.Backup.Storage
{
{
[Scope]
public class DocumentsBackupStorage : IBackupStorage
{
private int TenantId { get; set; }
private string WebConfigPath { get; set; }
private SetupInfo SetupInfo { get; }
private string WebConfigPath { get; set; }
private SetupInfo SetupInfo { get; }
private TenantManager TenantManager { get; set; }
private SecurityContext SecurityContext { get; set; }
private IDaoFactory DaoFactory { get; set; }
private StorageFactory StorageFactory { get; set; }
private IServiceProvider ServiceProvider { get; }
public DocumentsBackupStorage(
SetupInfo setupInfo,
TenantManager tenantManager,
SecurityContext securityContext,
IDaoFactory daoFactory,
StorageFactory storageFactory,
private StorageFactory StorageFactory { get; set; }
private IServiceProvider ServiceProvider { get; }
public DocumentsBackupStorage(
SetupInfo setupInfo,
TenantManager tenantManager,
SecurityContext securityContext,
IDaoFactory daoFactory,
StorageFactory storageFactory,
IServiceProvider serviceProvider)
{
SetupInfo = setupInfo;
{
SetupInfo = setupInfo;
TenantManager = tenantManager;
SecurityContext = securityContext;
DaoFactory = daoFactory;
StorageFactory = storageFactory;
ServiceProvider = serviceProvider;
StorageFactory = storageFactory;
ServiceProvider = serviceProvider;
}
public void Init(int tenantId, string webConfigPath)
{
public void Init(int tenantId, string webConfigPath)
{
TenantId = tenantId;
WebConfigPath = webConfigPath;
WebConfigPath = webConfigPath;
}
public string Upload(string folderId, string localPath, Guid userId)
{
TenantManager.SetCurrentTenant(TenantId);
if (!userId.Equals(Guid.Empty))
{
SecurityContext.AuthenticateMeWithoutCookie(userId);
}
else
{
var tenant = TenantManager.GetTenant(TenantId);
SecurityContext.AuthenticateMeWithoutCookie(tenant.OwnerId);
}
if (int.TryParse(folderId, out var fId))
{
return Upload(fId, localPath).ToString();
}
{
TenantManager.SetCurrentTenant(TenantId);
if (!userId.Equals(Guid.Empty))
{
SecurityContext.AuthenticateMeWithoutCookie(userId);
}
else
{
var tenant = TenantManager.GetTenant(TenantId);
SecurityContext.AuthenticateMeWithoutCookie(tenant.OwnerId);
}
if (int.TryParse(folderId, out var fId))
{
return Upload(fId, localPath).ToString();
}
return Upload(folderId, localPath);
}
public void Download(string fileId, string targetLocalPath)
{
TenantManager.SetCurrentTenant(TenantId);
if (int.TryParse(fileId, out var fId))
{
DownloadDao(fId, targetLocalPath);
return;
}
DownloadDao(fileId, targetLocalPath);
{
TenantManager.SetCurrentTenant(TenantId);
if (int.TryParse(fileId, out var fId))
{
DownloadDao(fId, targetLocalPath);
return;
}
DownloadDao(fileId, targetLocalPath);
}
public void Delete(string fileId)
{
TenantManager.SetCurrentTenant(TenantId);
if (int.TryParse(fileId, out var fId))
{
DeleteDao(fId);
return;
}
DeleteDao(fileId);
{
TenantManager.SetCurrentTenant(TenantId);
if (int.TryParse(fileId, out var fId))
{
DeleteDao(fId);
return;
}
DeleteDao(fileId);
}
public bool IsExists(string fileId)
{
TenantManager.SetCurrentTenant(TenantId);
if (int.TryParse(fileId, out var fId))
{
return IsExistsDao(fId);
}
{
TenantManager.SetCurrentTenant(TenantId);
if (int.TryParse(fileId, out var fId))
{
return IsExistsDao(fId);
}
return IsExistsDao(fileId);
}
public string GetPublicLink(string fileId)
{
return string.Empty;
}
}
private T Upload<T>(T folderId, string localPath)
{
var folderDao = GetFolderDao<T>();
var fileDao = GetFileDao<T>();
var folder = folderDao.GetFolder(folderId);
if (folder == null)
{
throw new FileNotFoundException("Folder not found.");
}
using var source = File.OpenRead(localPath);
var newFile = ServiceProvider.GetService<File<T>>();
newFile.Title = Path.GetFileName(localPath);
newFile.FolderID = folder.ID;
newFile.ContentLength = source.Length;
File<T> file = null;
var buffer = new byte[SetupInfo.ChunkUploadSize];
var chunkedUploadSession = fileDao.CreateUploadSession(newFile, source.Length);
chunkedUploadSession.CheckQuota = false;
var bytesRead = 0;
while ((bytesRead = source.Read(buffer, 0, (int)SetupInfo.ChunkUploadSize)) > 0)
{
using (var theMemStream = new MemoryStream())
{
theMemStream.Write(buffer, 0, bytesRead);
theMemStream.Position = 0;
file = fileDao.UploadChunk(chunkedUploadSession, theMemStream, bytesRead);
}
}
return file.ID;
}
{
var folderDao = GetFolderDao<T>();
var fileDao = GetFileDao<T>();
var folder = folderDao.GetFolder(folderId);
if (folder == null)
{
throw new FileNotFoundException("Folder not found.");
}
using var source = File.OpenRead(localPath);
var newFile = ServiceProvider.GetService<File<T>>();
newFile.Title = Path.GetFileName(localPath);
newFile.FolderID = folder.ID;
newFile.ContentLength = source.Length;
File<T> file = null;
var buffer = new byte[SetupInfo.ChunkUploadSize];
var chunkedUploadSession = fileDao.CreateUploadSession(newFile, source.Length);
chunkedUploadSession.CheckQuota = false;
var bytesRead = 0;
while ((bytesRead = source.Read(buffer, 0, (int)SetupInfo.ChunkUploadSize)) > 0)
{
using (var theMemStream = new MemoryStream())
{
theMemStream.Write(buffer, 0, bytesRead);
theMemStream.Position = 0;
file = fileDao.UploadChunk(chunkedUploadSession, theMemStream, bytesRead);
}
}
return file.ID;
}
private void DownloadDao<T>(T fileId, string targetLocalPath)
{
TenantManager.SetCurrentTenant(TenantId);
var fileDao = GetFileDao<T>();
var file = fileDao.GetFile(fileId);
if (file == null)
{
throw new FileNotFoundException("File not found.");
}
using var source = fileDao.GetFileStream(file);
using var destination = File.OpenWrite(targetLocalPath);
source.CopyTo(destination);
}
{
TenantManager.SetCurrentTenant(TenantId);
var fileDao = GetFileDao<T>();
var file = fileDao.GetFile(fileId);
if (file == null)
{
throw new FileNotFoundException("File not found.");
}
using var source = fileDao.GetFileStream(file);
using var destination = File.OpenWrite(targetLocalPath);
source.CopyTo(destination);
}
private void DeleteDao<T>(T fileId)
{
var fileDao = GetFileDao<T>();
fileDao.DeleteFile(fileId);
}
{
var fileDao = GetFileDao<T>();
fileDao.DeleteFile(fileId);
}
private bool IsExistsDao<T>(T fileId)
{
var fileDao = GetFileDao<T>();
try
{
var file = fileDao.GetFile(fileId);
return file != null && file.RootFolderType != FolderType.TRASH;
}
catch (Exception)
{
return false;
}
}
private IFolderDao<T> GetFolderDao<T>()
{
return DaoFactory.GetFolderDao<T>();
}
private IFileDao<T> GetFileDao<T>()
{
// hack: create storage using webConfigPath and put it into DataStoreCache
// FileDao will use this storage and will not try to create the new one from service config
StorageFactory.GetStorage(WebConfigPath, TenantId.ToString(), "files");
return DaoFactory.GetFileDao<T>();
}
{
var fileDao = GetFileDao<T>();
try
{
var file = fileDao.GetFile(fileId);
return file != null && file.RootFolderType != FolderType.TRASH;
}
catch (Exception)
{
return false;
}
}
private IFolderDao<T> GetFolderDao<T>()
{
return DaoFactory.GetFolderDao<T>();
}
private IFileDao<T> GetFileDao<T>()
{
// hack: create storage using webConfigPath and put it into DataStoreCache
// FileDao will use this storage and will not try to create the new one from service config
StorageFactory.GetStorage(WebConfigPath, TenantId.ToString(), "files");
return DaoFactory.GetFileDao<T>();
}
}
}

View File

@ -34,7 +34,7 @@ namespace ASC.Data.Backup.Storage
public interface IBackupRepository
{
void SaveBackupRecord(BackupRecord backupRecord);
BackupRecord GetBackupRecord(Guid id);
BackupRecord GetBackupRecord(Guid id);
BackupRecord GetBackupRecord(string hash, int tenant);
List<BackupRecord> GetExpiredBackupRecords();
List<BackupRecord> GetScheduledBackupRecords();

View File

@ -28,10 +28,10 @@ using System;
using System.IO;
using ASC.Common;
using ASC.Common.Utils;
using ASC.Common.Utils;
namespace ASC.Data.Backup.Storage
{
{
[Scope]
public class LocalBackupStorage : IBackupStorage
{

View File

@ -58,7 +58,7 @@ namespace ASC.Data.Backup.Storage
public string Upload(string storageBasePath, string localPath, Guid userId)
{
string key;
string key;
if (string.IsNullOrEmpty(storageBasePath))
key = "backup/" + Path.GetFileName(localPath);

View File

@ -33,10 +33,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Common.EF;
using ASC.Data.Backup.EF.Context;
@ -45,24 +45,24 @@ using ASC.Data.Backup.Extensions;
using ASC.Data.Backup.Tasks.Data;
using ASC.Data.Backup.Tasks.Modules;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace ASC.Data.Backup.Tasks
{
{
[Scope]
public class BackupPortalTask : PortalTaskBase
{
private const int MaxLength = 250;
{
private const int MaxLength = 250;
private const int BatchLimit = 5000;
public string BackupFilePath { get; private set; }
public int Limit { get; private set; }
private bool Dump { get; set; }
private TenantManager TenantManager { get; set; }
private TempStream TempStream { get; }
private TenantManager TenantManager { get; set; }
private TempStream TempStream { get; }
private Lazy<BackupsContext> LazyBackupsContext { get; }
private BackupsContext BackupRecordContext { get => LazyBackupsContext.Value; }
@ -70,10 +70,10 @@ namespace ASC.Data.Backup.Tasks
: base(dbFactory, options, storageFactory, storageFactoryConfig, moduleProvider)
{
Dump = coreBaseSettings.Standalone;
TenantManager = tenantManager;
TempStream = tempStream;
TenantManager = tenantManager;
TempStream = tempStream;
LazyBackupsContext = new Lazy<BackupsContext>(() => dbContextManager.Get(DbFactory.ConnectionStringSettings.ConnectionString));
}
}
public void Init(int tenantId, string fromConfigPath, string toFilePath, int limit)
{
@ -91,14 +91,14 @@ namespace ASC.Data.Backup.Tasks
using (var writer = new ZipWriteOperator(TempStream, BackupFilePath))
{
{
if (Dump)
{
DoDump(writer);
}
else
{
{
var modulesToProcess = GetModulesToProcess().ToList();
var fileGroups = GetFilesGroup();
@ -119,10 +119,10 @@ namespace ASC.Data.Backup.Tasks
}
private void DoDump(IDataWriteOperator writer)
{
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(true.ToString())))
{
writer.WriteEntry(KeyHelper.GetDumpKey(), stream);
{
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(true.ToString())))
{
writer.WriteEntry(KeyHelper.GetDumpKey(), stream);
}
List<string> tables;
@ -132,12 +132,12 @@ namespace ASC.Data.Backup.Tasks
var command = connection.CreateCommand();
command.CommandText = "show tables";
tables = ExecuteList(command).Select(r => Convert.ToString(r[0])).ToList();
}
/* using (var dbManager = new DbManager("default", 100000))
{
tables = dbManager.ExecuteList("show tables;").Select(r => Convert.ToString(r[0])).ToList();
}*/
}
/* using (var dbManager = new DbManager("default", 100000))
{
tables = dbManager.ExecuteList("show tables;").Select(r => Convert.ToString(r[0])).ToList();
}*/
var stepscount = tables.Count * 4; // (schema + data) * (dump + zip)
if (ProcessStorage)
{
@ -208,8 +208,8 @@ namespace ASC.Data.Backup.Tasks
private IEnumerable<BackupFileInfo> GetFiles(int tenantId)
{
var files = GetFilesToProcess(tenantId).ToList();
var exclude = BackupRecordContext.Backups.Where(b => b.TenantId == tenantId && b.StorageType == 0 && b.StoragePath != null).ToList();
files = files.Where(f => !exclude.Any(e => f.Path.Replace('\\', '/').Contains(string.Format("/file_{0}/", e.StoragePath)))).ToList();
var exclude = BackupRecordContext.Backups.Where(b => b.TenantId == tenantId && b.StorageType == 0 && b.StoragePath != null).ToList();
files = files.Where(f => !exclude.Any(e => f.Path.Replace('\\', '/').Contains(string.Format("/file_{0}/", e.StoragePath)))).ToList();
return files;
}
@ -240,8 +240,8 @@ namespace ASC.Data.Backup.Tasks
}
SetStepCompleted();
}
}
Logger.DebugFormat("dump table scheme stop {0}", t);
}
catch (Exception e)
@ -256,13 +256,13 @@ namespace ASC.Data.Backup.Tasks
{
try
{
using var connection = DbFactory.OpenConnection();
using var analyzeCommand = connection.CreateCommand();
analyzeCommand.CommandText = $"analyze table {t}";
analyzeCommand.ExecuteNonQuery();
using var command = connection.CreateCommand();
command.CommandText = $"select TABLE_ROWS from INFORMATION_SCHEMA.TABLES where TABLE_NAME = '{t}' and TABLE_SCHEMA = '{connection.Database}'";
return int.Parse(command.ExecuteScalar().ToString());
using var connection = DbFactory.OpenConnection();
using var analyzeCommand = connection.CreateCommand();
analyzeCommand.CommandText = $"analyze table {t}";
analyzeCommand.ExecuteNonQuery();
using var command = connection.CreateCommand();
command.CommandText = $"select TABLE_ROWS from INFORMATION_SCHEMA.TABLES where TABLE_NAME = '{t}' and TABLE_SCHEMA = '{connection.Database}'";
return int.Parse(command.ExecuteScalar().ToString());
}
catch (Exception e)
{
@ -318,47 +318,47 @@ namespace ASC.Data.Backup.Tasks
if (searchWithPrimary)
{
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
command.CommandText = string.Format("select max({1}), min({1}) from {0}", t, primaryIndex);
var minMax = ExecuteList(command).ConvertAll(r => new Tuple<int, int>(Convert.ToInt32(r[0]), Convert.ToInt32(r[1]))).FirstOrDefault();
primaryIndexStart = minMax.Item2;
primaryIndexStep = (minMax.Item1 - minMax.Item2) / count;
if (primaryIndexStep < Limit)
{
primaryIndexStep = Limit;
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
command.CommandText = string.Format("select max({1}), min({1}) from {0}", t, primaryIndex);
var minMax = ExecuteList(command).ConvertAll(r => new Tuple<int, int>(Convert.ToInt32(r[0]), Convert.ToInt32(r[1]))).FirstOrDefault();
primaryIndexStart = minMax.Item2;
primaryIndexStep = (minMax.Item1 - minMax.Item2) / count;
if (primaryIndexStep < Limit)
{
primaryIndexStep = Limit;
}
}
var path = CrossPlatform.PathCombine(dir, t);
var offset = 0;
do
{
List<object[]> result;
if (searchWithPrimary)
{
result = GetDataWithPrimary(t, columns, primaryIndex, primaryIndexStart, primaryIndexStep);
primaryIndexStart += primaryIndexStep;
}
else
{
result = GetData(t, columns, offset);
}
offset += Limit;
var resultCount = result.Count;
if (resultCount == 0) break;
SaveToFile(path, t, columns, result);
if (resultCount < Limit) break;
var path = CrossPlatform.PathCombine(dir, t);
var offset = 0;
do
{
List<object[]> result;
if (searchWithPrimary)
{
result = GetDataWithPrimary(t, columns, primaryIndex, primaryIndexStart, primaryIndexStep);
primaryIndexStart += primaryIndexStep;
}
else
{
result = GetData(t, columns, offset);
}
offset += Limit;
var resultCount = result.Count;
if (resultCount == 0) break;
SaveToFile(path, t, columns, result);
if (resultCount < Limit) break;
} while (true);
@ -374,27 +374,27 @@ namespace ASC.Data.Backup.Tasks
private List<object[]> GetData(string t, List<string> columns, int offset)
{
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
var selects = string.Join(',', columns);
command.CommandText = $"select {selects} from {t} LIMIT {offset}, {Limit}";
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
var selects = string.Join(',', columns);
command.CommandText = $"select {selects} from {t} LIMIT {offset}, {Limit}";
return ExecuteList(command);
}
private List<object[]> GetDataWithPrimary(string t, List<string> columns, string primary, int start, int step)
{
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
var selects = string.Join(',', columns);
command.CommandText = $"select {selects} from {t} where {primary} BETWEEN {start} and {start + step} ";
return ExecuteList(command);
}
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
var selects = string.Join(',', columns);
command.CommandText = $"select {selects} from {t} where {primary} BETWEEN {start} and {start + step} ";
return ExecuteList(command);
}
private void SaveToFile(string path, string t, IReadOnlyCollection<string> columns, List<object[]> data)
{
Logger.DebugFormat("save to file {0}", t);
List<object[]> portion;
while ((portion = data.Take(BatchLimit).ToList()).Any())
{
{
using (var sw = new StreamWriter(path, true))
using (var writer = new JsonTextWriter(sw))
{
@ -478,11 +478,11 @@ namespace ASC.Data.Backup.Tasks
var tmpPath = CrossPlatform.PathCombine(subDir, KeyHelper.GetStorageRestoreInfoZipKey());
Directory.CreateDirectory(Path.GetDirectoryName(tmpPath));
using (var tmpFile = new FileStream(tmpPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.DeleteOnClose))
{
restoreInfoXml.WriteTo(tmpFile);
writer.WriteEntry(KeyHelper.GetStorageRestoreInfoZipKey(), tmpFile);
}
using (var tmpFile = new FileStream(tmpPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.DeleteOnClose))
{
restoreInfoXml.WriteTo(tmpFile);
writer.WriteEntry(KeyHelper.GetStorageRestoreInfoZipKey(), tmpFile);
}
SetStepCompleted();
@ -502,12 +502,12 @@ namespace ASC.Data.Backup.Tasks
if (!Directory.Exists(dirName) && !string.IsNullOrEmpty(dirName))
{
Directory.CreateDirectory(dirName);
}
if (!WorkContext.IsMono && filePath.Length > MaxLength)
{
filePath = @"\\?\" + filePath;
}
}
if (!WorkContext.IsMono && filePath.Length > MaxLength)
{
filePath = @"\\?\" + filePath;
}
using (var fileStream = storage.GetReadStream(file.Domain, file.Path))
using (var tmpFile = File.OpenWrite(filePath))
@ -523,14 +523,14 @@ namespace ASC.Data.Backup.Tasks
Logger.DebugFormat("archive dir start {0}", subDir);
foreach (var enumerateFile in Directory.EnumerateFiles(subDir, "*", SearchOption.AllDirectories))
{
var f = enumerateFile;
if (!WorkContext.IsMono && enumerateFile.Length > MaxLength)
{
f = @"\\?\" + f;
}
using (var tmpFile = new FileStream(f, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.DeleteOnClose))
{
writer.WriteEntry(enumerateFile.Substring(subDir.Length), tmpFile);
var f = enumerateFile;
if (!WorkContext.IsMono && enumerateFile.Length > MaxLength)
{
f = @"\\?\" + f;
}
using (var tmpFile = new FileStream(f, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.DeleteOnClose))
{
writer.WriteEntry(enumerateFile.Substring(subDir.Length), tmpFile);
}
SetStepCompleted();
}
@ -593,12 +593,12 @@ namespace ASC.Data.Backup.Tasks
Logger.DebugFormat("begin saving table {0}", table.Name);
using (var file = TempStream.Create())
{
data.WriteXml(file, XmlWriteMode.WriteSchema);
data.Clear();
writer.WriteEntry(KeyHelper.GetTableZipKey(module, data.TableName), file);
using (var file = TempStream.Create())
{
data.WriteXml(file, XmlWriteMode.WriteSchema);
data.Clear();
writer.WriteEntry(KeyHelper.GetTableZipKey(module, data.TableName), file);
}
Logger.DebugFormat("end saving table {0}", table.Name);
@ -626,7 +626,7 @@ namespace ASC.Data.Backup.Tasks
ActionInvoker.Try(state =>
{
var f = (BackupFileInfo)state;
using var fileStream = storage.GetReadStream(f.Domain, f.Path);
using var fileStream = storage.GetReadStream(f.Domain, f.Path);
writer.WriteEntry(file1.GetZipKey(), fileStream);
}, file, 5, error => Logger.WarnFormat("can't backup file ({0}:{1}): {2}", file1.Module, file1.Path, error));
@ -640,10 +640,10 @@ namespace ASC.Data.Backup.Tasks
.SelectMany(group => group.Select(file => (object)file.ToXElement()))
.ToArray());
using (var tmpFile = TempStream.Create())
{
restoreInfoXml.WriteTo(tmpFile);
writer.WriteEntry(KeyHelper.GetStorageRestoreInfoZipKey(), tmpFile);
using (var tmpFile = TempStream.Create())
{
restoreInfoXml.WriteTo(tmpFile);
writer.WriteEntry(KeyHelper.GetStorageRestoreInfoZipKey(), tmpFile);
}
Logger.Debug("end backup storage");

View File

@ -1,4 +1,4 @@
/*
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
@ -103,4 +103,4 @@ namespace ASC.Data.Backup.Tasks.Data
return sb.ToString();
}
}
}
}

View File

@ -1,4 +1,4 @@
/*
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
@ -97,4 +97,4 @@ namespace ASC.Data.Backup.Tasks.Data
return str;
}
}
}
}

View File

@ -1,4 +1,4 @@
/*
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*

View File

@ -1,4 +1,4 @@
/*
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
@ -88,4 +88,4 @@ namespace ASC.Data.Backup.Tasks.Data
return string.Format("{0} {1} [{2} ({3}), {4}]", InsertMethod, Name, IdColumn, IdType, TenantColumn);
}
}
}
}

View File

@ -37,7 +37,7 @@ using Microsoft.Extensions.Configuration;
using MySql.Data.MySqlClient;
namespace ASC.Data.Backup.Tasks
{
{
[Scope]
public class DbFactory
{
@ -45,7 +45,7 @@ namespace ASC.Data.Backup.Tasks
private DbProviderFactory dbProviderFactory;
private IConfiguration Configuration { get; set; }
private IConfiguration Configuration { get; set; }
private ConfigurationExtension ConfigurationExtension { get; set; }
private string ConnectionString { get; set; }
private string Path { get; set; }
@ -82,8 +82,8 @@ namespace ASC.Data.Backup.Tasks
public DbFactory(IConfiguration configuration, ConfigurationExtension configurationExtension)
{
Configuration = configuration;
ConfigurationExtension = configurationExtension;
Configuration = configuration;
ConfigurationExtension = configurationExtension;
}
public DbConnection OpenConnection(string path = "default", string connectionString = DefaultConnectionStringName)//TODO

View File

@ -31,8 +31,8 @@ using ASC.Data.Backup.Exceptions;
using ASC.Data.Backup.Extensions;
using ASC.Data.Backup.Tasks.Data;
using ASC.Data.Backup.Tasks.Modules;
using ASC.Data.Storage;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Tasks

View File

@ -28,9 +28,9 @@ using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using ASC.Data.Backup.Tasks.Data;
using ASC.Data.Backup.Utils;
using ASC.Data.Backup.Utils;
namespace ASC.Data.Backup.Tasks.Modules
{
@ -70,7 +70,7 @@ namespace ASC.Data.Backup.Tasks.Modules
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}}
},
@ -160,7 +160,7 @@ namespace ASC.Data.Backup.Tasks.Modules
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_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"),
@ -171,7 +171,7 @@ namespace ASC.Data.Backup.Tasks.Modules
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_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"),
@ -180,7 +180,7 @@ namespace ASC.Data.Backup.Tasks.Modules
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_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"),
@ -195,7 +195,7 @@ namespace ASC.Data.Backup.Tasks.Modules
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")
new RelationInfo("wiki_comments", "Id", "wiki_comments", "ParentId")
};
public override ModuleName ModuleName

View File

@ -27,8 +27,8 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Linq;
using ASC.Core.Billing;
using ASC.Data.Backup.Tasks.Data;
@ -53,9 +53,9 @@ namespace ASC.Data.Backup.Tasks.Modules
private const string CrmCasesAclObjectStart = "ASC.CRM.Core.Entities.Cases|";
private const string CrmRelationshipEventAclObjectStart = "ASC.CRM.Core.Entities.RelationshipEvent|";
private const string CalendarCalendarAclObjectStart = "ASC.Api.Calendar.BusinessObjects.Calendar|";
private const string CalendarEventAclObjectStart = "ASC.Api.Calendar.BusinessObjects.Event|";
private const string CalendarEventAclObjectStart = "ASC.Api.Calendar.BusinessObjects.Event|";
private readonly TableInfo[] _tables = new[]
{
new TableInfo("core_acl", "tenant") {InsertMethod = InsertMethod.Ignore},
@ -77,7 +77,7 @@ namespace ASC.Data.Backup.Tasks.Modules
new TableInfo("feed_users") {InsertMethod = InsertMethod.None},
new TableInfo("backup_backup", "tenant_id", "id", IdType.Guid),
new TableInfo("backup_schedule", "tenant_id"),
new TableInfo("core_settings", "tenant")
new TableInfo("core_settings", "tenant")
};
private readonly RelationInfo[] _tableRelations;
@ -175,8 +175,8 @@ namespace ASC.Data.Backup.Tasks.Modules
}
protected override string GetSelectCommandConditionText(int tenantId, TableInfo table)
{
{
if (table.Name == "feed_users")
return "inner join core_user t1 on t1.id = t.user_id where t1.tenant = " + tenantId;

View File

@ -28,10 +28,10 @@ using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text.RegularExpressions;
using ASC.Data.Backup.Tasks.Data;
using System.Text.RegularExpressions;
using ASC.Data.Backup.Tasks.Data;
using Newtonsoft.Json.Linq;
namespace ASC.Data.Backup.Tasks.Modules
@ -97,10 +97,10 @@ namespace ASC.Data.Backup.Tasks.Modules
{
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_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("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)),
@ -200,7 +200,7 @@ namespace ASC.Data.Backup.Tasks.Modules
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),
new RelationInfo("mail_mail", "id", "crm_relationship_event", "content", typeof(MailModuleSpecifics), x => Convert.ToInt32(x["category_id"]) == -3),
};
public override string ConnectionStringName
@ -358,24 +358,24 @@ namespace ASC.Data.Backup.Tasks.Modules
if (table.Name == "crm_invoice" && columnName == "json_data")
{
var data = JObject.Parse((string)value);
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));
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));
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));
data["BillingAddressID"] = Convert.ToInt32(columnMapper.GetMapping("crm_contact_info", "id", oldValue));
}
value = data.ToString();

View File

@ -25,17 +25,17 @@
using System;
using System.Linq;
using System.Linq;
using ASC.Common;
using ASC.Core;
using ASC.Security.Cryptography;
using ASC.Security.Cryptography;
using ConfigurationConstants = ASC.Core.Configuration.Constants;
using UserConstants = ASC.Core.Users.Constants;
namespace ASC.Data.Backup.Tasks.Modules
{
{
[Scope]
public class Helpers
{
@ -46,9 +46,9 @@ namespace ASC.Data.Backup.Tasks.Modules
ConfigurationConstants.CoreSystem.ID,
ConfigurationConstants.Guest.ID,
UserConstants.LostUser.ID
};
};
private readonly Guid[] SystemGroups = new[]
{
Guid.Empty,

View File

@ -26,15 +26,15 @@
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Core;
using Microsoft.Extensions.Options;
using ASC.Core;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Tasks.Modules
{
{
[Scope]
public class ModuleProvider
{
@ -62,15 +62,15 @@ namespace ASC.Data.Backup.Tasks.Modules
}
public IModuleSpecifics GetByStorageModule(string storageModuleName, string storageDomainName = null)
{
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,
};
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,
};
}
}
}

View File

@ -254,8 +254,8 @@ namespace ASC.Data.Backup.Tasks.Modules
{
value = mappedValue;
return true;
}
}
return value == null ||
Guid.TryParse(Convert.ToString(value), out _) ||
int.TryParse(Convert.ToString(value), out _);

View File

@ -28,9 +28,9 @@ using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text.RegularExpressions;
using ASC.Data.Backup.Tasks.Data;
using ASC.Data.Backup.Utils;
using ASC.Data.Backup.Utils;
namespace ASC.Data.Backup.Tasks.Modules
{
@ -87,7 +87,7 @@ namespace ASC.Data.Backup.Tasks.Modules
private readonly RelationInfo[] _tableRelations = new[]
{
new RelationInfo("projects_comments", "id", "projects_comments", "parent_id"),
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)),
@ -107,7 +107,7 @@ namespace ASC.Data.Backup.Tasks.Modules
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")
new RelationInfo("projects_milestones", "id", "projects_tasks_order", "task_order")
};
public override ModuleName ModuleName

View File

@ -27,15 +27,15 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text.RegularExpressions;
using System.Text.RegularExpressions;
using ASC.Data.Backup.Tasks.Data;
namespace ASC.Data.Backup.Tasks.Modules
{
public class WebStudioModuleSpecifics : ModuleSpecificsBase
{
public WebStudioModuleSpecifics(Helpers helpers)
public WebStudioModuleSpecifics(Helpers helpers)
: base(helpers)
{ }
private static readonly Guid CrmSettingsId = new Guid("fdf39b9a-ec96-4eb7-aeab-63f2c608eada");

View File

@ -30,25 +30,25 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks;
using ASC.Common.Logging;
using ASC.Data.Backup.Tasks.Modules;
using ASC.Data.Storage;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Tasks
{
public class ProgressChangedEventArgs : EventArgs
{
public int Progress { get; private set; }
public int Progress { get; private set; }
public ProgressChangedEventArgs(int progress)
{
Progress = progress;
Progress = progress;
}
}
@ -144,8 +144,8 @@ namespace ASC.Data.Backup.Tasks
"fckuploaders",
"talk",
"mailaggregator",
"whitelabel",
"customnavigation",
"whitelabel",
"customnavigation",
"userPhotos"
};
@ -281,39 +281,39 @@ namespace ASC.Data.Backup.Tasks
}
protected async Task RunMysqlFile(Stream stream, string delimiter = ";")
{
if (stream == null) return;
using var reader = new StreamReader(stream, Encoding.UTF8);
string commandText;
while ((commandText = await reader.ReadLineAsync()) != null)
{
while (!commandText.EndsWith(delimiter))
{
var newline = await reader.ReadLineAsync();
if (newline == null)
{
break;
}
commandText += newline;
}
try
{
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
command.CommandText = commandText;
await command.ExecuteNonQueryAsync();
// await dbManager.ExecuteNonQueryAsync(commandText, null);
}
catch (Exception e)
{
Logger.Error("Restore", e);
}
}
{
if (stream == null) return;
using var reader = new StreamReader(stream, Encoding.UTF8);
string commandText;
while ((commandText = await reader.ReadLineAsync()) != null)
{
while (!commandText.EndsWith(delimiter))
{
var newline = await reader.ReadLineAsync();
if (newline == null)
{
break;
}
commandText += newline;
}
try
{
using var connection = DbFactory.OpenConnection();
var command = connection.CreateCommand();
command.CommandText = commandText;
await command.ExecuteNonQueryAsync();
// await dbManager.ExecuteNonQueryAsync(commandText, null);
}
catch (Exception e)
{
Logger.Error("Restore", e);
}
}
}
}
}

View File

@ -35,8 +35,8 @@ using ASC.Data.Backup.Exceptions;
using ASC.Data.Backup.Extensions;
using ASC.Data.Backup.Tasks.Data;
using ASC.Data.Backup.Tasks.Modules;
using ASC.Data.Storage;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Tasks
@ -56,7 +56,7 @@ namespace ASC.Data.Backup.Tasks
{
Reader = reader ?? throw new ArgumentNullException("reader");
ColumnMapper = columnMapper ?? throw new ArgumentNullException("columnMapper");
DbFactory = factory ?? throw new ArgumentNullException("factory");
DbFactory = factory ?? throw new ArgumentNullException("factory");
Module = module;
ReplaceDate = replaceDate;
Dump = dump;
@ -95,111 +95,111 @@ namespace ASC.Data.Backup.Tasks
{
SetColumns(connection, tableInfo);
using var stream = Reader.GetEntry(KeyHelper.GetTableZipKey(Module, tableInfo.Name));
var lowImportanceRelations = Module
.TableRelations
.Where(
r =>
string.Equals(r.ParentTable, tableInfo.Name, StringComparison.InvariantCultureIgnoreCase))
.Where(r => r.Importance == RelationImportance.Low && !r.IsSelfRelation())
.Select(r => Tuple.Create(r, Module.Tables.Single(t => t.Name == r.ChildTable)))
.ToList();
foreach (
var rows in
GetRows(tableInfo, stream)
.Skip(transactionsCommited * TransactionLength)
.MakeParts(TransactionLength))
{
using var transaction = connection.BeginTransaction();
var rowsSuccess = 0;
foreach (var row in rows)
{
if (ReplaceDate)
{
foreach (var column in tableInfo.DateColumns)
{
ColumnMapper.SetDateMapping(tableInfo.Name, column, row[column.Key]);
}
}
object oldIdValue = null;
object newIdValue = null;
if (tableInfo.HasIdColumn())
{
oldIdValue = row[tableInfo.IdColumn];
newIdValue = ColumnMapper.GetMapping(tableInfo.Name, tableInfo.IdColumn, oldIdValue);
if (newIdValue == null)
{
if (tableInfo.IdType == IdType.Guid)
{
newIdValue = Guid.NewGuid().ToString("D");
}
else if (tableInfo.IdType == IdType.Integer)
{
var command = connection.CreateCommand();
command.CommandText = string.Format("select max({0}) from {1};", tableInfo.IdColumn, tableInfo.Name);
newIdValue = (int)command.WithTimeout(120).ExecuteScalar() + 1;
}
}
if (newIdValue != null)
{
ColumnMapper.SetMapping(tableInfo.Name, tableInfo.IdColumn, oldIdValue,
newIdValue);
}
}
var insertCommand = Module.CreateInsertCommand(Dump, connection, ColumnMapper, tableInfo,
row);
if (insertCommand == null)
{
Logger.WarnFormat("Can't create command to insert row to {0} with values [{1}]", tableInfo,
row);
ColumnMapper.Rollback();
continue;
}
insertCommand.WithTimeout(120).ExecuteNonQuery();
rowsSuccess++;
if (tableInfo.HasIdColumn() && tableInfo.IdType == IdType.Autoincrement)
{
var lastIdCommand = DbFactory.CreateLastInsertIdCommand();
lastIdCommand.Connection = connection;
newIdValue = Convert.ToInt32(lastIdCommand.ExecuteScalar());
ColumnMapper.SetMapping(tableInfo.Name, tableInfo.IdColumn, oldIdValue, newIdValue);
}
ColumnMapper.Commit();
foreach (var relation in lowImportanceRelations)
{
if (!relation.Item2.HasTenantColumn())
{
Logger.WarnFormat(
"Table {0} does not contain tenant id column. Can't apply low importance relations on such tables.",
relation.Item2.Name);
continue;
}
var oldValue = row[relation.Item1.ParentColumn];
var newValue = ColumnMapper.GetMapping(relation.Item1.ParentTable,
relation.Item1.ParentColumn, oldValue);
var command = connection.CreateCommand();
command.CommandText = string.Format("update {0} set {1} = {2} where {1} = {3} and {4} = {5}",
relation.Item1.ChildTable,
relation.Item1.ChildColumn,
newValue is string ? "'" + newValue + "'" : newValue,
oldValue is string ? "'" + oldValue + "'" : oldValue,
relation.Item2.TenantColumn,
ColumnMapper.GetTenantMapping());
command.WithTimeout(120).ExecuteNonQuery();
}
}
transaction.Commit();
transactionsCommited++;
rowsInserted += rowsSuccess;
using var stream = Reader.GetEntry(KeyHelper.GetTableZipKey(Module, tableInfo.Name));
var lowImportanceRelations = Module
.TableRelations
.Where(
r =>
string.Equals(r.ParentTable, tableInfo.Name, StringComparison.InvariantCultureIgnoreCase))
.Where(r => r.Importance == RelationImportance.Low && !r.IsSelfRelation())
.Select(r => Tuple.Create(r, Module.Tables.Single(t => t.Name == r.ChildTable)))
.ToList();
foreach (
var rows in
GetRows(tableInfo, stream)
.Skip(transactionsCommited * TransactionLength)
.MakeParts(TransactionLength))
{
using var transaction = connection.BeginTransaction();
var rowsSuccess = 0;
foreach (var row in rows)
{
if (ReplaceDate)
{
foreach (var column in tableInfo.DateColumns)
{
ColumnMapper.SetDateMapping(tableInfo.Name, column, row[column.Key]);
}
}
object oldIdValue = null;
object newIdValue = null;
if (tableInfo.HasIdColumn())
{
oldIdValue = row[tableInfo.IdColumn];
newIdValue = ColumnMapper.GetMapping(tableInfo.Name, tableInfo.IdColumn, oldIdValue);
if (newIdValue == null)
{
if (tableInfo.IdType == IdType.Guid)
{
newIdValue = Guid.NewGuid().ToString("D");
}
else if (tableInfo.IdType == IdType.Integer)
{
var command = connection.CreateCommand();
command.CommandText = string.Format("select max({0}) from {1};", tableInfo.IdColumn, tableInfo.Name);
newIdValue = (int)command.WithTimeout(120).ExecuteScalar() + 1;
}
}
if (newIdValue != null)
{
ColumnMapper.SetMapping(tableInfo.Name, tableInfo.IdColumn, oldIdValue,
newIdValue);
}
}
var insertCommand = Module.CreateInsertCommand(Dump, connection, ColumnMapper, tableInfo,
row);
if (insertCommand == null)
{
Logger.WarnFormat("Can't create command to insert row to {0} with values [{1}]", tableInfo,
row);
ColumnMapper.Rollback();
continue;
}
insertCommand.WithTimeout(120).ExecuteNonQuery();
rowsSuccess++;
if (tableInfo.HasIdColumn() && tableInfo.IdType == IdType.Autoincrement)
{
var lastIdCommand = DbFactory.CreateLastInsertIdCommand();
lastIdCommand.Connection = connection;
newIdValue = Convert.ToInt32(lastIdCommand.ExecuteScalar());
ColumnMapper.SetMapping(tableInfo.Name, tableInfo.IdColumn, oldIdValue, newIdValue);
}
ColumnMapper.Commit();
foreach (var relation in lowImportanceRelations)
{
if (!relation.Item2.HasTenantColumn())
{
Logger.WarnFormat(
"Table {0} does not contain tenant id column. Can't apply low importance relations on such tables.",
relation.Item2.Name);
continue;
}
var oldValue = row[relation.Item1.ParentColumn];
var newValue = ColumnMapper.GetMapping(relation.Item1.ParentTable,
relation.Item1.ParentColumn, oldValue);
var command = connection.CreateCommand();
command.CommandText = string.Format("update {0} set {1} = {2} where {1} = {3} and {4} = {5}",
relation.Item1.ChildTable,
relation.Item1.ChildColumn,
newValue is string ? "'" + newValue + "'" : newValue,
oldValue is string ? "'" + oldValue + "'" : oldValue,
relation.Item2.TenantColumn,
ColumnMapper.GetTenantMapping());
command.WithTimeout(120).ExecuteNonQuery();
}
}
transaction.Commit();
transactionsCommited++;
rowsInserted += rowsSuccess;
}
}

View File

@ -34,18 +34,18 @@ using System.Xml.Linq;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Billing;
using ASC.Core.Tenants;
using ASC.Data.Backup.Extensions;
using ASC.Data.Backup.Tasks.Modules;
using ASC.Data.Storage;
using ASC.Data.Storage;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Tasks
{
{
[Scope]
public class RestorePortalTask : PortalTaskBase
{
@ -57,29 +57,29 @@ namespace ASC.Data.Backup.Tasks
public bool ReplaceDate { get; set; }
public bool Dump { get; set; }
private CoreBaseSettings CoreBaseSettings { get; set; }
private LicenseReader LicenseReader { get; set; }
public TenantManager TenantManager { get; }
private LicenseReader LicenseReader { get; set; }
public TenantManager TenantManager { get; }
private AscCacheNotify AscCacheNotify { get; set; }
private IOptionsMonitor<ILog> Options { get; set; }
public RestorePortalTask(
DbFactory dbFactory,
IOptionsMonitor<ILog> options,
StorageFactory storageFactory,
StorageFactoryConfig storageFactoryConfig,
CoreBaseSettings coreBaseSettings,
LicenseReader licenseReader,
TenantManager tenantManager,
AscCacheNotify ascCacheNotify,
public RestorePortalTask(
DbFactory dbFactory,
IOptionsMonitor<ILog> options,
StorageFactory storageFactory,
StorageFactoryConfig storageFactoryConfig,
CoreBaseSettings coreBaseSettings,
LicenseReader licenseReader,
TenantManager tenantManager,
AscCacheNotify ascCacheNotify,
ModuleProvider moduleProvider)
: base(dbFactory, options, storageFactory, storageFactoryConfig, moduleProvider)
{
CoreBaseSettings = coreBaseSettings;
LicenseReader = licenseReader;
TenantManager = tenantManager;
LicenseReader = licenseReader;
TenantManager = tenantManager;
AscCacheNotify = ascCacheNotify;
Options = options;
}
}
public void Init(string toConfigPath, string fromFilePath, int tenantId = -1, ColumnMapper columnMapper = null, string upgradesPath = null)
{
@ -93,7 +93,7 @@ namespace ASC.Data.Backup.Tasks
UpgradesPath = upgradesPath;
ColumnMapper = columnMapper ?? new ColumnMapper();
Init(tenantId, toConfigPath);
}
}
public override void RunJob()
{
@ -132,12 +132,12 @@ namespace ASC.Data.Backup.Tasks
Logger.Debug("end restore data");
if (ProcessStorage)
{
if (CoreBaseSettings.Standalone)
{
Logger.Debug("clear cache");
AscCacheNotify.ClearCache();
}
{
if (CoreBaseSettings.Standalone)
{
Logger.Debug("clear cache");
AscCacheNotify.ClearCache();
}
DoRestoreStorage(dataReader);
}
@ -179,23 +179,23 @@ namespace ASC.Data.Backup.Tasks
var stepscount = keys.Count * 2 + upgrades.Count;
SetStepsCount(ProcessStorage ? stepscount + 1 : stepscount);
if (ProcessStorage)
{
var storageModules = StorageFactoryConfig.GetModuleList(ConfigPath).Where(IsStorageModuleAllowed);
var tenants = TenantManager.GetTenants(false);
stepscount += storageModules.Count() * tenants.Count;
SetStepsCount(stepscount + 1);
DoDeleteStorage(storageModules, tenants);
}
else
{
SetStepsCount(stepscount);
}
SetStepsCount(ProcessStorage ? stepscount + 1 : stepscount);
if (ProcessStorage)
{
var storageModules = StorageFactoryConfig.GetModuleList(ConfigPath).Where(IsStorageModuleAllowed);
var tenants = TenantManager.GetTenants(false);
stepscount += storageModules.Count() * tenants.Count;
SetStepsCount(stepscount + 1);
DoDeleteStorage(storageModules, tenants);
}
else
{
SetStepsCount(stepscount);
}
for (var i = 0; i < keys.Count; i += TasksLimit)
{
@ -289,14 +289,14 @@ namespace ASC.Data.Backup.Tasks
{
key = CrossPlatform.PathCombine(KeyHelper.GetStorage(), key);
}
using var stream = dataReader.GetEntry(key);
try
{
storage.Save(file.Domain, adjustedPath, module != null ? module.PrepareData(key, stream, ColumnMapper) : stream);
}
catch (Exception error)
{
Logger.WarnFormat("can't restore file ({0}:{1}): {2}", file.Module, file.Path, error);
using var stream = dataReader.GetEntry(key);
try
{
storage.Save(file.Domain, adjustedPath, module != null ? module.PrepareData(key, stream, ColumnMapper) : stream);
}
catch (Exception error)
{
Logger.WarnFormat("can't restore file ({0}:{1}): {2}", file.Module, file.Path, error);
}
}
}
@ -317,69 +317,69 @@ namespace ASC.Data.Backup.Tasks
SetStepCompleted();
}
Logger.Debug("end restore storage");
}
private void DoDeleteStorage(IEnumerable<string> storageModules, IEnumerable<Tenant> tenants)
{
Logger.Debug("begin delete storage");
foreach (var tenant in tenants)
{
foreach (var module in storageModules)
{
var storage = StorageFactory.GetStorage(ConfigPath, tenant.TenantId.ToString(), module);
var domains = StorageFactoryConfig.GetDomainList(ConfigPath, module).ToList();
domains.Add(string.Empty); //instead storage.DeleteFiles("\\", "*.*", true);
foreach (var domain in domains)
{
ActionInvoker.Try(
state =>
{
if (storage.IsDirectory((string)state))
{
storage.DeleteFiles((string)state, "\\", "*.*", true);
}
},
domain,
5,
onFailure: error => Logger.WarnFormat("Can't delete files for domain {0}: \r\n{1}", domain, error)
);
}
SetStepCompleted();
}
}
Logger.Debug("end delete storage");
}
private void DoDeleteStorage(IEnumerable<string> storageModules, IEnumerable<Tenant> tenants)
{
Logger.Debug("begin delete storage");
foreach (var tenant in tenants)
{
foreach (var module in storageModules)
{
var storage = StorageFactory.GetStorage(ConfigPath, tenant.TenantId.ToString(), module);
var domains = StorageFactoryConfig.GetDomainList(ConfigPath, module).ToList();
domains.Add(string.Empty); //instead storage.DeleteFiles("\\", "*.*", true);
foreach (var domain in domains)
{
ActionInvoker.Try(
state =>
{
if (storage.IsDirectory((string)state))
{
storage.DeleteFiles((string)state, "\\", "*.*", true);
}
},
domain,
5,
onFailure: error => Logger.WarnFormat("Can't delete files for domain {0}: \r\n{1}", domain, error)
);
}
SetStepCompleted();
}
}
Logger.Debug("end delete storage");
}
private IEnumerable<BackupFileInfo> GetFilesToProcess(IDataReadOperator dataReader)
{
using var stream = dataReader.GetEntry(KeyHelper.GetStorageRestoreInfoZipKey());
if (stream == null)
{
return Enumerable.Empty<BackupFileInfo>();
}
var restoreInfo = XElement.Load(new StreamReader(stream));
using var stream = dataReader.GetEntry(KeyHelper.GetStorageRestoreInfoZipKey());
if (stream == null)
{
return Enumerable.Empty<BackupFileInfo>();
}
var restoreInfo = XElement.Load(new StreamReader(stream));
return restoreInfo.Elements("file").Select(BackupFileInfo.FromXElement).ToList();
}
private void SetTenantActive(int tenantId)
{
using var connection = DbFactory.OpenConnection();
var commandText = string.Format(
"update tenants_tenants " +
"set " +
" status={0}, " +
" last_modified='{1}', " +
" statuschanged='{1}' " +
"where id = '{2}'",
(int)TenantStatus.Active,
DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
tenantId);
using var connection = DbFactory.OpenConnection();
var commandText = string.Format(
"update tenants_tenants " +
"set " +
" status={0}, " +
" last_modified='{1}', " +
" statuschanged='{1}' " +
"where id = '{2}'",
(int)TenantStatus.Active,
DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
tenantId);
connection.CreateCommand().WithTimeout(120).ExecuteNonQuery();
}
}

View File

@ -31,7 +31,7 @@ using System.Linq;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Common.Utils;
using ASC.Core.Tenants;
using ASC.Data.Backup.Extensions;
using ASC.Data.Backup.Tasks.Modules;
@ -41,7 +41,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Tasks
{
{
[Scope]
public class TransferPortalTask : PortalTaskBase
{
@ -53,30 +53,30 @@ namespace ASC.Data.Backup.Tasks
public bool DeleteBackupFileAfterCompletion { get; set; }
public bool BlockOldPortalAfterStart { get; set; }
public bool DeleteOldPortalAfterCompletion { get; set; }
private IOptionsMonitor<ILog> Options { get; set; }
private TempStream TempStream { get; }
private TempPath TempPath { get; }
private IOptionsMonitor<ILog> Options { get; set; }
private TempStream TempStream { get; }
private TempPath TempPath { get; }
private IServiceProvider ServiceProvider { get; set; }
public int ToTenantId { get; private set; }
public int Limit { get; private set; }
public TransferPortalTask(
DbFactory dbFactory,
IServiceProvider serviceProvider,
IOptionsMonitor<ILog> options,
StorageFactory storageFactory,
StorageFactoryConfig storageFactoryConfig,
ModuleProvider moduleProvider,
TempStream tempStream,
public TransferPortalTask(
DbFactory dbFactory,
IServiceProvider serviceProvider,
IOptionsMonitor<ILog> options,
StorageFactory storageFactory,
StorageFactoryConfig storageFactoryConfig,
ModuleProvider moduleProvider,
TempStream tempStream,
TempPath tempPath)
: base(dbFactory, options, storageFactory, storageFactoryConfig, moduleProvider)
{
DeleteBackupFileAfterCompletion = true;
BlockOldPortalAfterStart = true;
DeleteOldPortalAfterCompletion = true;
Options = options;
TempStream = tempStream;
TempPath = tempPath;
Options = options;
TempStream = tempStream;
TempPath = tempPath;
ServiceProvider = serviceProvider;
}
@ -145,8 +145,8 @@ namespace ASC.Data.Backup.Tasks
else if (BlockOldPortalAfterStart)
{
SaveTenant(fromDbFactory, tenantAlias, TenantStatus.Active);
}
}
ToTenantId = columnMapper.GetTenantMapping();
}
catch

View File

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View File

@ -907,16 +907,19 @@ namespace ASC.Data.Storage.S3
return true;
}
catch (AmazonS3Exception ex)
catch (AggregateException agg)
{
if (string.Equals(ex.ErrorCode, "NoSuchBucket"))
if (agg.InnerException is AmazonS3Exception ex)
{
return false;
}
if (string.Equals(ex.ErrorCode, "NoSuchBucket"))
{
return false;
}
if (string.Equals(ex.ErrorCode, "NotFound"))
{
return false;
if (string.Equals(ex.ErrorCode, "NotFound"))
{
return false;
}
}
throw;

View File

@ -35,6 +35,7 @@ using System.Web;
using ASC.Common;
using ASC.Common.Utils;
using ASC.Common.Web;
using ASC.Core;
using ASC.Security.Cryptography;
@ -131,14 +132,14 @@ namespace ASC.Data.Storage.DiscStorage
context.Response.Headers[toCopy] = h.Substring(toCopy.Length + 1);
}
//try
//{
// context.Response.ContentType = MimeMapping.GetMimeMapping(path);
//}
//catch (Exception e)
//{
// var a = 0;
//}
try
{
context.Response.ContentType = MimeMapping.GetMimeMapping(path);
}
catch (Exception)
{
}
if (encoding != null)
context.Response.Headers["Content-Encoding"] = encoding;

View File

@ -5,13 +5,11 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\ASC.Core.Common\ASC.Core.Common.csproj" />
<PackageReference Include="NUnit" Version="3.12.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft\Xamarin\NuGet\nunit\3.12.0\lib\netstandard2.0\nunit.framework.dll</HintPath>
</Reference>
<ProjectReference Include="..\..\ASC.Core.Common\ASC.Core.Common.csproj" />
</ItemGroup>
</Project>

View File

@ -4,15 +4,13 @@
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NUnit" Version="3.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ASC.Core.Common\ASC.Core.Common.csproj" />
<ProjectReference Include="..\..\ASC.Notify.Textile\ASC.Notify.Textile.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft\Xamarin\NuGet\nunit\3.12.0\lib\netstandard2.0\nunit.framework.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -12,47 +12,6 @@
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<None Remove="protos\BackupProgress.proto" />
<None Remove="protos\DeleteSchedule.proto" />
</ItemGroup>
<ItemGroup>
<Compile Update="BackupResource.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>BackupResource.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="BackupResource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>BackupResource.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
<PackageReference Include="Google.Protobuf" Version="3.13.0" />
<PackageReference Include="Grpc" Version="2.32.0">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Grpc.Tools" Version="2.32.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="MySql.Data" Version="8.0.23" />
<PackageReference Include="SharpZipLib" Version="1.3.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\products\ASC.Files\Core\ASC.Files.Core.csproj" />
<ProjectReference Include="..\..\ASC.Data.Storage\ASC.Data.Storage.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\DeleteSchedule.proto" />
<Protobuf Include="protos\BackupProgress.proto" />
</ItemGroup>
<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'MySqlConnector'">
@ -61,5 +20,8 @@
</ItemGroup>
</Target>
<ItemGroup>
<ProjectReference Include="..\..\ASC.Data.Backup.Core\ASC.Data.Backup.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -26,41 +26,41 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Data.Backup.Storage;
using ASC.Files.Core;
using Microsoft.Extensions.DependencyInjection;
using ASC.Data.Backup.Storage;
using ASC.Files.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Service
{
{
[Scope]
internal class BackupCleanerHelperService
{
private readonly ILog log;
private BackupRepository BackupRepository { get; }
private BackupStorageFactory BackupStorageFactory { get; }
public BackupCleanerHelperService(
IOptionsMonitor<ILog> options,
BackupRepository backupRepository,
private readonly ILog log;
private BackupRepository BackupRepository { get; }
private BackupStorageFactory BackupStorageFactory { get; }
public BackupCleanerHelperService(
IOptionsMonitor<ILog> options,
BackupRepository backupRepository,
BackupStorageFactory backupStorageFactory)
{
log = options.CurrentValue;
BackupRepository = backupRepository;
BackupStorageFactory = backupStorageFactory;
log = options.CurrentValue;
BackupRepository = backupRepository;
BackupStorageFactory = backupStorageFactory;
}
internal void DeleteExpiredBackups(BackupCleanerService backupCleanerService)
{
log.Debug("started to clean expired backups");
log.Debug("started to clean expired backups");
var backupsToRemove = BackupRepository.GetExpiredBackupRecords();
log.DebugFormat("found {0} backups which are expired", backupsToRemove.Count);
@ -95,14 +95,14 @@ namespace ASC.Data.Backup.Service
backupStorage.Delete(backupRecord.StoragePath);
BackupRepository.DeleteBackupRecord(backupRecord.Id);
}
catch (ProviderInfoArgumentException error)
{
log.Warn("can't remove backup record " + backupRecord.Id, error);
if (DateTime.UtcNow > backupRecord.CreatedOn.AddMonths(6))
{
BackupRepository.DeleteBackupRecord(backupRecord.Id);
}
}
catch (ProviderInfoArgumentException error)
{
log.Warn("can't remove backup record " + backupRecord.Id, error);
if (DateTime.UtcNow > backupRecord.CreatedOn.AddMonths(6))
{
BackupRepository.DeleteBackupRecord(backupRecord.Id);
}
}
catch (Exception error)
{
@ -110,8 +110,8 @@ namespace ASC.Data.Backup.Service
}
}
}
}
}
[Singletone(Additional = typeof(BackupCleanerServiceExtension))]
public class BackupCleanerService
{
@ -119,14 +119,14 @@ namespace ASC.Data.Backup.Service
private Timer CleanTimer { get; set; }
internal bool IsStarted { get; set; }
private ILog Log { get; set; }
public TimeSpan Period { get; set; }
private IServiceProvider ServiceProvider { get; set; }
public BackupCleanerService(
IOptionsMonitor<ILog> options,
public TimeSpan Period { get; set; }
private IServiceProvider ServiceProvider { get; set; }
public BackupCleanerService(
IOptionsMonitor<ILog> options,
IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
{
ServiceProvider = serviceProvider;
Log = options.CurrentValue;
Period = TimeSpan.FromMinutes(15);
}
@ -164,10 +164,10 @@ namespace ASC.Data.Backup.Service
if (Monitor.TryEnter(cleanerLock))
{
try
{
using var scope = ServiceProvider.CreateScope();
var backupCleanerHelperService = scope.ServiceProvider.GetService<BackupCleanerHelperService>();
{
using var scope = ServiceProvider.CreateScope();
var backupCleanerHelperService = scope.ServiceProvider.GetService<BackupCleanerHelperService>();
backupCleanerHelperService.DeleteExpiredBackups(this);
}
catch (Exception error)
@ -180,13 +180,13 @@ namespace ASC.Data.Backup.Service
}
}
}
}
public class BackupCleanerServiceExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<BackupCleanerHelperService>();
}
}
public class BackupCleanerServiceExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<BackupCleanerHelperService>();
}
}
}

View File

@ -27,44 +27,44 @@
using System;
using System.Linq;
using System.Threading;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Core;
using ASC.Core.Billing;
using ASC.Data.Backup.Storage;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ASC.Data.Backup.Service
{
{
[Scope]
internal class BackupSchedulerServiceHelper
{
private ILog Log { get; }
private PaymentManager PaymentManager { get; }
private BackupWorker BackupWorker { get; }
private BackupRepository BackupRepository { get; }
private Schedule Schedule { get; }
private TenantManager TenantManager { get; }
private CoreBaseSettings CoreBaseSettings { get; }
public BackupSchedulerServiceHelper(
IOptionsMonitor<ILog> options,
PaymentManager paymentManager,
BackupWorker backupWorker,
BackupRepository backupRepository,
Schedule schedule,
TenantManager tenantManager,
private BackupWorker BackupWorker { get; }
private BackupRepository BackupRepository { get; }
private Schedule Schedule { get; }
private TenantManager TenantManager { get; }
private CoreBaseSettings CoreBaseSettings { get; }
public BackupSchedulerServiceHelper(
IOptionsMonitor<ILog> options,
PaymentManager paymentManager,
BackupWorker backupWorker,
BackupRepository backupRepository,
Schedule schedule,
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings)
{
PaymentManager = paymentManager;
BackupWorker = backupWorker;
BackupRepository = backupRepository;
Schedule = schedule;
TenantManager = tenantManager;
CoreBaseSettings = coreBaseSettings;
BackupWorker = backupWorker;
BackupRepository = backupRepository;
Schedule = schedule;
TenantManager = tenantManager;
CoreBaseSettings = coreBaseSettings;
Log = options.CurrentValue;
}
@ -80,25 +80,25 @@ namespace ASC.Data.Backup.Service
return;
}
try
{
if (CoreBaseSettings.Standalone || TenantManager.GetTenantQuota(schedule.TenantId).AutoBackup)
{
var tariff = PaymentManager.GetTariff(schedule.TenantId);
if (tariff.State < TariffState.Delay)
{
schedule.LastBackupTime = DateTime.UtcNow;
BackupRepository.SaveBackupSchedule(schedule);
Log.DebugFormat("Start scheduled backup: {0}, {1}, {2}, {3}", schedule.TenantId, schedule.BackupMail, schedule.StorageType, schedule.StorageBasePath);
BackupWorker.StartScheduledBackup(schedule);
}
else
{
Log.DebugFormat("Skip portal {0} not paid", schedule.TenantId);
}
}
else
{
Log.DebugFormat("Skip portal {0} haven't access", schedule.TenantId);
{
if (CoreBaseSettings.Standalone || TenantManager.GetTenantQuota(schedule.TenantId).AutoBackup)
{
var tariff = PaymentManager.GetTariff(schedule.TenantId);
if (tariff.State < TariffState.Delay)
{
schedule.LastBackupTime = DateTime.UtcNow;
BackupRepository.SaveBackupSchedule(schedule);
Log.DebugFormat("Start scheduled backup: {0}, {1}, {2}, {3}", schedule.TenantId, schedule.BackupMail, schedule.StorageType, schedule.StorageBasePath);
BackupWorker.StartScheduledBackup(schedule);
}
else
{
Log.DebugFormat("Skip portal {0} not paid", schedule.TenantId);
}
}
else
{
Log.DebugFormat("Skip portal {0} haven't access", schedule.TenantId);
}
}
catch (Exception error)
@ -107,27 +107,27 @@ namespace ASC.Data.Backup.Service
}
}
}
}
}
[Singletone(Additional = typeof(BackupSchedulerServiceExtension))]
public class BackupSchedulerService
{
private readonly object schedulerLock = new object();
private Timer SchedulerTimer { get; set; }
internal bool IsStarted { get; set; }
internal bool IsStarted { get; set; }
public TimeSpan Period { get; set; }
private ILog Log { get; }
private IServiceProvider ServiceProvider { get; }
public BackupSchedulerService(
IOptionsMonitor<ILog> options,
private ILog Log { get; }
private IServiceProvider ServiceProvider { get; }
public BackupSchedulerService(
IOptionsMonitor<ILog> options,
IServiceProvider serviceProvider)
{
{
Log = options.CurrentValue;
Period = TimeSpan.FromMinutes(15);
ServiceProvider = serviceProvider;
}
Period = TimeSpan.FromMinutes(15);
ServiceProvider = serviceProvider;
}
public void Start()
{
if (!IsStarted && Period > TimeSpan.Zero)
@ -160,9 +160,9 @@ namespace ASC.Data.Backup.Service
if (Monitor.TryEnter(schedulerLock))
{
try
{
using var scope = ServiceProvider.CreateScope();
var backupSchedulerServiceHelper = scope.ServiceProvider.GetService<BackupSchedulerServiceHelper>();
{
using var scope = ServiceProvider.CreateScope();
var backupSchedulerServiceHelper = scope.ServiceProvider.GetService<BackupSchedulerServiceHelper>();
backupSchedulerServiceHelper.ScheduleBackupTasks(this);
}
catch (Exception error)
@ -175,13 +175,13 @@ namespace ASC.Data.Backup.Service
}
}
}
}
public class BackupSchedulerServiceExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<BackupSchedulerServiceHelper>();
}
}
public class BackupSchedulerServiceExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<BackupSchedulerServiceHelper>();
}
}
}

View File

@ -29,42 +29,42 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Utils;
using ASC.Data.Backup.Listerners;
using ASC.Web.Studio.Core.Notify;
using ASC.Data.Backup.Listerners;
using ASC.Web.Studio.Core.Notify;
using Microsoft.Extensions.Hosting;
namespace ASC.Data.Backup.Service
{
[Singletone]
internal class BackupServiceLauncher : IHostedService
{
{
private BackupCleanerService CleanerService { get; set; }
private BackupSchedulerService SchedulerService { get; set; }
private BackupWorker BackupWorker { get; set; }
private ConfigurationExtension Configuration { get; set; }
private ConfigurationExtension Configuration { get; set; }
private BackupListener BackupListener { get; set; }
public NotifyConfiguration NotifyConfiguration { get; }
public BackupServiceLauncher(
public NotifyConfiguration NotifyConfiguration { get; }
public BackupServiceLauncher(
BackupCleanerService cleanerService,
BackupSchedulerService schedulerService,
BackupWorker backupWorker,
ConfigurationExtension configuration,
BackupListener backupListener,
BackupListener backupListener,
NotifyConfiguration notifyConfiguration)
{
{
CleanerService = cleanerService;
SchedulerService = schedulerService;
BackupWorker = backupWorker;
Configuration = configuration;
Configuration = configuration;
BackupListener = backupListener;
NotifyConfiguration = notifyConfiguration;
NotifyConfiguration = notifyConfiguration;
}
public Task StartAsync(CancellationToken cancellationToken)
{
NotifyConfiguration.Configure();
{
NotifyConfiguration.Configure();
var settings = Configuration.GetSetting<BackupSettings>("backup");

View File

@ -1,271 +1,271 @@

using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Core;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.ModelApi;
using ASC.Data.Backup.Models;
using ASC.Web.Api.Routing;
using ASC.Web.Studio.Utility;
using Microsoft.AspNetCore.Mvc;
using static ASC.Data.Backup.BackupAjaxHandler;
namespace ASC.Data.Backup.Controllers
{
[Scope]
[DefaultRoute]
[ApiController]
public class BackupController
{
private BackupAjaxHandler BackupHandler { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private TenantExtra TenantExtra { get; }
public BackupController(
BackupAjaxHandler backupAjaxHandler,
CoreBaseSettings coreBaseSettings,
TenantExtra tenantExtra)
{
BackupHandler = backupAjaxHandler;
CoreBaseSettings = coreBaseSettings;
TenantExtra = tenantExtra;
}
/// <summary>
/// Returns the backup schedule of the current portal
/// </summary>
/// <category>Backup</category>
/// <returns>Backup Schedule</returns>
[Read("getbackupschedule")]
public BackupAjaxHandler.Schedule GetBackupSchedule()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetSchedule();
}
/// <summary>
/// Create the backup schedule of the current portal
/// </summary>
/// <param name="storageType">Storage type</param>
/// <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>
[Create("createbackupschedule")]
public bool CreateBackupScheduleFromBody([FromBody]BackupSchedule backupSchedule)
{
return CreateBackupSchedule(backupSchedule);
}
[Create("createbackupschedule")]
[Consumes("application/x-www-form-urlencoded")]
public bool CreateBackupScheduleFromForm([FromForm]BackupSchedule backupSchedule)
{
return CreateBackupSchedule(backupSchedule);
}
private bool CreateBackupSchedule(BackupSchedule backupSchedule)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
var storageType = backupSchedule.StorageType == null ? BackupStorageType.Documents : (BackupStorageType)Int32.Parse(backupSchedule.StorageType);
var storageParams = backupSchedule.StorageParams == null ? new Dictionary<string, string>() : backupSchedule.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString());
var backupStored = backupSchedule.BackupsStored == null ? 0 : Int32.Parse(backupSchedule.BackupsStored);
var cron = new CronParams()
{
Period = backupSchedule.CronParams.Period == null ? BackupPeriod.EveryDay : (BackupPeriod)Int32.Parse(backupSchedule.CronParams.Period),
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);
return true;
}
/// <summary>
/// Delete the backup schedule of the current portal
/// </summary>
/// <category>Backup</category>
[Delete("deletebackupschedule")]
public bool DeleteBackupSchedule()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteSchedule();
return true;
}
/// <summary>
/// Start a backup of the current portal
/// </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>
[Create("startbackup")]
public BackupProgress StartBackupFromBody([FromBody]Models.Backup backup)
{
return StartBackup(backup);
}
[Create("startbackup")]
[Consumes("application/x-www-form-urlencoded")]
public BackupProgress StartBackupFromForm([FromForm]Models.Backup backup)
{
return StartBackup(backup);
}
private BackupProgress StartBackup(Models.Backup backup)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
var storageType = backup.StorageType == null ? BackupStorageType.Documents : (BackupStorageType)Int32.Parse(backup.StorageType);
var storageParams = backup.StorageParams == null ? new Dictionary<string, string>() : backup.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString());
BackupHandler.StartBackup(storageType, storageParams, backup.BackupMail);
return BackupHandler.GetBackupProgress();
}
/// <summary>
/// Returns the progress of the started backup
/// </summary>
/// <category>Backup</category>
/// <returns>Backup Progress</returns>
[Read("getbackupprogress")]
public BackupProgress GetBackupProgress()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetBackupProgress();
}
/// <summary>
/// Returns the backup history of the started backup
/// </summary>
/// <category>Backup</category>
/// <returns>Backup History</returns>
[Read("getbackuphistory")]
public List<BackupHistoryRecord> GetBackupHistory()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetBackupHistory();
}
/// <summary>
/// Delete the backup with the specified id
/// </summary>
/// <category>Backup</category>
[Delete("deletebackup/{id}")]
public bool DeleteBackup(Guid id)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteBackup(id);
return true;
}
/// <summary>
/// Delete all backups of the current portal
/// </summary>
/// <category>Backup</category>
/// <returns>Backup History</returns>
[Delete("deletebackuphistory")]
public bool DeleteBackupHistory()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteAllBackups();
return true;
}
/// <summary>
/// Start a data restore of the current portal
/// </summary>
/// <param name="backupId">Backup Id</param>
/// <param name="storageType">Storage Type</param>
/// <param name="storageParams">Storage Params</param>
/// <param name="notify">Notify about backup to users</param>
/// <category>Backup</category>
/// <returns>Restore Progress</returns>
[Create("startrestore")]
public BackupProgress StartBackupRestoreFromBody([FromBody]BackupRestore backupRestore)
{
return StartBackupRestore(backupRestore);
}
[Create("startrestore")]
[Consumes("application/x-www-form-urlencoded")]
public BackupProgress StartBackupRestoreFromForm([FromForm]BackupRestore backupRestore)
{
return StartBackupRestore(backupRestore);
}
private BackupProgress StartBackupRestore(BackupRestore backupRestore)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
var storageParams = backupRestore.StorageParams == null ? new Dictionary<string, string>() : backupRestore.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString());
BackupHandler.StartRestore(backupRestore.BackupId, (BackupStorageType)Int32.Parse(backupRestore.StorageType.ToString()), storageParams, backupRestore.Notify);
return BackupHandler.GetBackupProgress();
}
/// <summary>
/// Returns the progress of the started restore
/// </summary>
/// <category>Backup</category>
/// <returns>Restore Progress</returns>
[Read("getrestoreprogress", true)] //NOTE: this method doesn't check payment!!!
public BackupProgress GetRestoreProgress()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetRestoreProgress();
}
///<visible>false</visible>
[Read("backuptmp")]
public object GetTempPath()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetTmpFolder();
}
}
}

using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Core;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.ModelApi;
using ASC.Data.Backup.Models;
using ASC.Web.Api.Routing;
using ASC.Web.Studio.Utility;
using Microsoft.AspNetCore.Mvc;
using static ASC.Data.Backup.BackupAjaxHandler;
namespace ASC.Data.Backup.Controllers
{
[Scope]
[DefaultRoute]
[ApiController]
public class BackupController
{
private BackupAjaxHandler BackupHandler { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private TenantExtra TenantExtra { get; }
public BackupController(
BackupAjaxHandler backupAjaxHandler,
CoreBaseSettings coreBaseSettings,
TenantExtra tenantExtra)
{
BackupHandler = backupAjaxHandler;
CoreBaseSettings = coreBaseSettings;
TenantExtra = tenantExtra;
}
/// <summary>
/// Returns the backup schedule of the current portal
/// </summary>
/// <category>Backup</category>
/// <returns>Backup Schedule</returns>
[Read("getbackupschedule")]
public BackupAjaxHandler.Schedule GetBackupSchedule()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetSchedule();
}
/// <summary>
/// Create the backup schedule of the current portal
/// </summary>
/// <param name="storageType">Storage type</param>
/// <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>
[Create("createbackupschedule")]
public bool CreateBackupScheduleFromBody([FromBody]BackupSchedule backupSchedule)
{
return CreateBackupSchedule(backupSchedule);
}
[Create("createbackupschedule")]
[Consumes("application/x-www-form-urlencoded")]
public bool CreateBackupScheduleFromForm([FromForm]BackupSchedule backupSchedule)
{
return CreateBackupSchedule(backupSchedule);
}
private bool CreateBackupSchedule(BackupSchedule backupSchedule)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
var storageType = backupSchedule.StorageType == null ? BackupStorageType.Documents : (BackupStorageType)Int32.Parse(backupSchedule.StorageType);
var storageParams = backupSchedule.StorageParams == null ? new Dictionary<string, string>() : backupSchedule.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString());
var backupStored = backupSchedule.BackupsStored == null ? 0 : Int32.Parse(backupSchedule.BackupsStored);
var cron = new CronParams()
{
Period = backupSchedule.CronParams.Period == null ? BackupPeriod.EveryDay : (BackupPeriod)Int32.Parse(backupSchedule.CronParams.Period),
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);
return true;
}
/// <summary>
/// Delete the backup schedule of the current portal
/// </summary>
/// <category>Backup</category>
[Delete("deletebackupschedule")]
public bool DeleteBackupSchedule()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteSchedule();
return true;
}
/// <summary>
/// Start a backup of the current portal
/// </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>
[Create("startbackup")]
public BackupProgress StartBackupFromBody([FromBody]Models.Backup backup)
{
return StartBackup(backup);
}
[Create("startbackup")]
[Consumes("application/x-www-form-urlencoded")]
public BackupProgress StartBackupFromForm([FromForm]Models.Backup backup)
{
return StartBackup(backup);
}
private BackupProgress StartBackup(Models.Backup backup)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
var storageType = backup.StorageType == null ? BackupStorageType.Documents : (BackupStorageType)Int32.Parse(backup.StorageType);
var storageParams = backup.StorageParams == null ? new Dictionary<string, string>() : backup.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString());
BackupHandler.StartBackup(storageType, storageParams, backup.BackupMail);
return BackupHandler.GetBackupProgress();
}
/// <summary>
/// Returns the progress of the started backup
/// </summary>
/// <category>Backup</category>
/// <returns>Backup Progress</returns>
[Read("getbackupprogress")]
public BackupProgress GetBackupProgress()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetBackupProgress();
}
/// <summary>
/// Returns the backup history of the started backup
/// </summary>
/// <category>Backup</category>
/// <returns>Backup History</returns>
[Read("getbackuphistory")]
public List<BackupHistoryRecord> GetBackupHistory()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetBackupHistory();
}
/// <summary>
/// Delete the backup with the specified id
/// </summary>
/// <category>Backup</category>
[Delete("deletebackup/{id}")]
public bool DeleteBackup(Guid id)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteBackup(id);
return true;
}
/// <summary>
/// Delete all backups of the current portal
/// </summary>
/// <category>Backup</category>
/// <returns>Backup History</returns>
[Delete("deletebackuphistory")]
public bool DeleteBackupHistory()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteAllBackups();
return true;
}
/// <summary>
/// Start a data restore of the current portal
/// </summary>
/// <param name="backupId">Backup Id</param>
/// <param name="storageType">Storage Type</param>
/// <param name="storageParams">Storage Params</param>
/// <param name="notify">Notify about backup to users</param>
/// <category>Backup</category>
/// <returns>Restore Progress</returns>
[Create("startrestore")]
public BackupProgress StartBackupRestoreFromBody([FromBody]BackupRestore backupRestore)
{
return StartBackupRestore(backupRestore);
}
[Create("startrestore")]
[Consumes("application/x-www-form-urlencoded")]
public BackupProgress StartBackupRestoreFromForm([FromForm]BackupRestore backupRestore)
{
return StartBackupRestore(backupRestore);
}
private BackupProgress StartBackupRestore(BackupRestore backupRestore)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
var storageParams = backupRestore.StorageParams == null ? new Dictionary<string, string>() : backupRestore.StorageParams.ToDictionary(r => r.Key.ToString(), r => r.Value.ToString());
BackupHandler.StartRestore(backupRestore.BackupId, (BackupStorageType)Int32.Parse(backupRestore.StorageType.ToString()), storageParams, backupRestore.Notify);
return BackupHandler.GetBackupProgress();
}
/// <summary>
/// Returns the progress of the started restore
/// </summary>
/// <category>Backup</category>
/// <returns>Restore Progress</returns>
[Read("getrestoreprogress", true)] //NOTE: this method doesn't check payment!!!
public BackupProgress GetRestoreProgress()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetRestoreProgress();
}
///<visible>false</visible>
[Read("backuptmp")]
public object GetTempPath()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetTmpFolder();
}
}
}

View File

@ -1,56 +1,56 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Api.Core;
using ASC.Common.Utils;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Api.Core;
using ASC.Common.Utils;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace ASC.Data.Backup
{
public class Program
{
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
var builder = webBuilder.UseStartup<Startup>();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
if (!kestrelConfig.Exists()) return;
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
var builder = webBuilder.UseStartup<Startup>();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
if (!kestrelConfig.Exists()) return;
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
})
.ConfigureAppConfiguration((hostContext, config) =>
{
@ -67,17 +67,18 @@ namespace ASC.Data.Backup
.AddJsonFile($"appsettings.{env}.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("notify.json")
.AddJsonFile($"notify.{env}.json", true)
.AddJsonFile("backup.json")
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables()
.AddEnvironmentVariables()
.AddInMemoryCollection(new Dictionary<string, string>
{
{"pathToConf", path }
}
);
})
.ConfigureNLogLogging();
})
.ConfigureNLogLogging();
}
}

View File

@ -21,15 +21,15 @@
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
*/
using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Threading;
using ASC.Common;
using ASC.Common.Threading;
using ASC.Data.Backup.Controllers;
using ASC.Data.Backup.Service;
using ASC.Web.Studio.Core.Notify;
using ASC.Data.Backup.Service;
using ASC.Web.Studio.Core.Notify;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -41,22 +41,22 @@ namespace ASC.Data.Backup
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
{
}
}
public override void ConfigureServices(IServiceCollection services)
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
base.ConfigureServices(services);
DIHelper.AddDistributedTaskQueueService<BaseBackupProgressItem>(1);
DIHelper.TryAdd<BackupProgressItem>();
DIHelper.TryAdd<RestoreProgressItem>();
DIHelper.TryAdd<TransferProgressItem>();
DIHelper.TryAdd<BackupServiceLauncher>();
DIHelper.TryAdd<BackupController>();
NotifyConfigurationExtension.Register(DIHelper);
DIHelper.TryAdd<BackupProgressItem>();
DIHelper.TryAdd<RestoreProgressItem>();
DIHelper.TryAdd<TransferProgressItem>();
DIHelper.TryAdd<BackupServiceLauncher>();
DIHelper.TryAdd<BackupController>();
NotifyConfigurationExtension.Register(DIHelper);
services.AddHostedService<BackupServiceLauncher>();
}
}

View File

@ -95,7 +95,8 @@ namespace ASC.Data.Storage.Encryption
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env}.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("notify.json")
.AddJsonFile("notify.json")
.AddJsonFile($"notify.{env}.json", true)
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables();

View File

@ -49,6 +49,7 @@ namespace ASC.Data.Storage.Migration
.AddJsonFile($"appsettings.services.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("notify.json")
.AddJsonFile($"notify.{env}.json", true)
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables()

View File

@ -100,7 +100,7 @@ namespace ASC.ElasticSearch
SearchSettingsHelper searchSettingsHelper,
FactoryIndexer factoryIndexer,
BaseIndexer<T> baseIndexer,
IServiceProvider serviceProvider,
IServiceProvider serviceProvider,
ICache cache)
{
Cache = cache;
@ -229,7 +229,7 @@ namespace ASC.ElasticSearch
{
Thread.Sleep(60000);
if (retry < 5)
{
{
Index(data, immediately, retry++);
return;
}
@ -558,7 +558,6 @@ namespace ASC.ElasticSearch
private readonly ICache cache;
private IServiceProvider ServiceProvider { get; }
private FactoryIndexerHelper FactoryIndexerHelper { get; }
internal static bool Init { get; set; }
public ILog Log { get; }
private Client Client { get; }
private CoreBaseSettings CoreBaseSettings { get; }
@ -568,7 +567,7 @@ namespace ASC.ElasticSearch
FactoryIndexerHelper factoryIndexerHelper,
Client client,
IOptionsMonitor<ILog> options,
CoreBaseSettings coreBaseSettings,
CoreBaseSettings coreBaseSettings,
ICache cache)
{
this.cache = cache;
@ -589,8 +588,6 @@ namespace ASC.ElasticSearch
public bool CheckState(bool cacheState = true)
{
if (!Init) return false;
const string key = "elasticsearch";
if (cacheState)
@ -633,8 +630,6 @@ namespace ASC.ElasticSearch
public async Task<bool> CheckStateAsync(bool cacheState = true)
{
if (!Init) return false;
const string key = "elasticsearch";
if (cacheState)

View File

@ -51,6 +51,7 @@ namespace ASC.Notify
.AddJsonFile($"appsettings.services.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("notify.json")
.AddJsonFile($"notify.{env}.json", true)
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables()

Some files were not shown because too many files have changed in this diff Show More