Merge branch 'release/1.0.0' into bugfix/mousewheel-opening-files
This commit is contained in:
commit
c15c6733d9
Binary file not shown.
BIN
.nuget/packages/WebSocketSharpNetStandart.1.0.3-rc12.nupkg
Normal file
BIN
.nuget/packages/WebSocketSharpNetStandart.1.0.3-rc12.nupkg
Normal file
Binary file not shown.
31
ASC.Web.sln
31
ASC.Web.sln
@ -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
4
build/Jenkinsfile
vendored
@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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");
|
||||
});
|
||||
}
|
||||
|
@ -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
|
||||
});
|
||||
});
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
});
|
||||
});
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
},
|
||||
|
@ -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
|
||||
});
|
||||
});
|
||||
|
@ -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; }
|
||||
|
55
common/ASC.Data.Backup.Core/ASC.Data.Backup.Core.csproj
Normal file
55
common/ASC.Data.Backup.Core/ASC.Data.Backup.Core.csproj
Normal 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>
|
@ -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);
|
||||
}
|
@ -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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
@ -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>
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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>();
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ using ASC.Notify.Cron;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Data.Backup
|
||||
{
|
||||
{
|
||||
[Scope]
|
||||
public class Schedule
|
||||
{
|
@ -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)
|
@ -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")]
|
@ -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();
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ using ASC.Data.Backup.Service;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Data.Backup.Listerners
|
||||
{
|
||||
{
|
||||
[Singletone]
|
||||
public class BackupListener
|
||||
{
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
@ -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
|
||||
{
|
@ -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);
|
@ -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");
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
@ -103,4 +103,4 @@ namespace ASC.Data.Backup.Tasks.Data
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
||||
@ -97,4 +97,4 @@ namespace ASC.Data.Backup.Tasks.Data
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2020
|
||||
*
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
@ -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();
|
@ -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,
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -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 _);
|
@ -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
|
@ -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");
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user