Migration: DI

This commit is contained in:
pavelbannov 2023-08-08 14:09:19 +03:00
parent 6e39c8d104
commit cb3c4cfac7
14 changed files with 93 additions and 124 deletions

View File

@ -24,10 +24,9 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
global using System.Text;
global using ASC.Api.Core; global using ASC.Api.Core;
global using ASC.Api.Core.Extensions; global using ASC.Api.Core.Extensions;
global using ASC.Common.DependencyInjection;
global using ASC.Migration; global using ASC.Migration;
global using Autofac; global using Autofac;

View File

@ -47,18 +47,21 @@ var logger = LogManager.Setup()
try try
{ {
logger.Info("Configuring web host ({applicationContext})...", AppName); logger.Info("Configuring web host ({applicationContext})...", AppName);
builder.Host.ConfigureDefault(); builder.Host.ConfigureDefault();
builder.WebHost.ConfigureDefaultKestrel();
var startup = new Startup(builder.Configuration, builder.Environment); var startup = new Startup(builder.Configuration, builder.Environment);
startup.ConfigureServices(builder.Services); startup.ConfigureServices(builder.Services);
builder.Host.ConfigureContainer<ContainerBuilder>(startup.ConfigureContainer); builder.Host.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.Register(context.Configuration);
});
var app = builder.Build(); var app = builder.Build();
startup.Configure(app, app.Environment); startup.Configure(app);
logger.Info("Starting web host ({applicationContext})...", AppName); logger.Info("Starting web host ({applicationContext})...", AppName);
await app.RunWithTasksAsync(); await app.RunWithTasksAsync();

View File

@ -24,9 +24,11 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using ASC.Migration.Core.Models.Api;
namespace ASC.Migration; namespace ASC.Migration;
public class Startup : BaseStartup public class Startup : BaseWorkerStartup
{ {
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment)
: base(configuration, hostEnvironment) : base(configuration, hostEnvironment)
@ -36,10 +38,8 @@ public class Startup : BaseStartup
public override void ConfigureServices(IServiceCollection services) public override void ConfigureServices(IServiceCollection services)
{ {
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
services.AddMemoryCache();
base.ConfigureServices(services); base.ConfigureServices(services);
MigrationCore.Register(DIHelper);
} }
} }

View File

@ -24,8 +24,9 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Migration.Core; namespace ASC.Migration.Core;
[Scope]
public abstract class AbstractMigration<TMigrationInfo, TUser, TContacts, TCalendar, TFiles, TMail> : IMigration public abstract class AbstractMigration<TMigrationInfo, TUser, TContacts, TCalendar, TFiles, TMail> : IMigration
where TMigrationInfo : IMigrationInfo where TMigrationInfo : IMigrationInfo
{ {
@ -34,8 +35,9 @@ public abstract class AbstractMigration<TMigrationInfo, TUser, TContacts, TCalen
protected TMigrationInfo _migrationInfo; protected TMigrationInfo _migrationInfo;
private double _lastProgressUpdate; private double _lastProgressUpdate;
private string _lastStatusUpdate; private string _lastStatusUpdate;
protected List<Guid> _importedUsers; protected List<Guid> _importedUsers;
public abstract MigratorMeta Meta { get; }
public event Action<double, string> OnProgressUpdate; public event Action<double, string> OnProgressUpdate;
public AbstractMigration(MigrationLogger migrationLogger) public AbstractMigration(MigrationLogger migrationLogger)

View File

@ -26,6 +26,7 @@
namespace ASC.Migration.Core; namespace ASC.Migration.Core;
[Scope]
public interface IMigration : IDisposable public interface IMigration : IDisposable
{ {
event Action<double, string> OnProgressUpdate; event Action<double, string> OnProgressUpdate;
@ -42,5 +43,7 @@ public interface IMigration : IDisposable
Stream GetLogs(); Stream GetLogs();
List<Guid> GetGuidImportedUsers(); List<Guid> GetGuidImportedUsers();
MigratorMeta Meta { get; }
} }

View File

@ -1,47 +0,0 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Migration.Core.Models.Api;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class ApiMigratorAttribute : Attribute
{
public string Name { get; private set; }
public bool RequiresFolder { get; private set; }
public string[] RequiredFileTypes { get; private set; }
public ApiMigratorAttribute(string name, string[] fileTypes)
{
Name = name;
RequiredFileTypes = fileTypes;
}
public ApiMigratorAttribute(string name)
{
Name = name;
}
}

View File

@ -24,44 +24,34 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using ASC.Migration.GoogleWorkspace;
using ASC.Migration.NextcloudWorkspace;
using ASC.Migration.OwnCloud;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Migration.Core.Models.Api; namespace ASC.Migration.Core.Models.Api;
public static class MigrationCore [Scope]
{ public class MigrationCore
{
private readonly System.IServiceProvider _serviceProvider;
public MigrationCore(System.IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
private static Dictionary<string, MigratorMeta> _migrators; public string[] GetAvailableMigrations() => _serviceProvider.GetService<IEnumerable<IMigration>>().Select(r => r.Meta.Name).ToArray();
private static Dictionary<string, MigratorMeta> Migrators
{ public IMigration GetMigrator(string migrator)
get {
{ return _serviceProvider.GetService<IEnumerable<IMigration>>().FirstOrDefault(r => r.Meta.Name == migrator);
if (_migrators != null) }
{
return _migrators;
}
_migrators = new Dictionary<string, MigratorMeta>(StringComparer.OrdinalIgnoreCase); public static void Register(DIHelper services)
{
var migratorTypes = Assembly.GetExecutingAssembly() services.TryAdd<IMigration, GoogleWorkspaceMigration>();
.GetExportedTypes() services.TryAdd<IMigration, NextcloudWorkspaceMigration>();
.Where(t => !t.IsAbstract && !t.IsInterface services.TryAdd<IMigration, OwnCloudMigration>();
&& typeof(IMigration).IsAssignableFrom(t));
foreach (var type in migratorTypes)
{
var attr = type.GetCustomAttribute<ApiMigratorAttribute>();
if (attr == null)
{
continue;
}
_migrators.Add(attr.Name, new MigratorMeta(type));
}
return _migrators;
}
} }
public static string[] GetAvailableMigrations() => Migrators.Keys.ToArray();
public static MigratorMeta GetMigrator(string migrator) => Migrators.TryGetValue(migrator, out var meta) ? meta : null;
} }

View File

@ -28,12 +28,27 @@ namespace ASC.Migration.Core.Models.Api;
public class MigratorMeta public class MigratorMeta
{ {
public Type MigratorType { get; private set; } public string Name { get; private set; }
public int NumberOfSteps { get; }
public bool ArchivesIsMultiple { get; }
public bool RequiresFolder { get; private set; }
public string[] RequiredFileTypes { get; private set; }
public ApiMigratorAttribute MigratorInfo { get => MigratorType.GetCustomAttribute<ApiMigratorAttribute>(); } public MigratorMeta(string name, string[] fileTypes)
public MigratorMeta(Type type)
{ {
MigratorType = type; Name = name;
RequiredFileTypes = fileTypes;
}
public MigratorMeta(string name)
{
Name = name;
}
public MigratorMeta(string name, int numberOfSteps, bool archivesIsMultiple)
{
Name = name;
NumberOfSteps = numberOfSteps;
ArchivesIsMultiple = archivesIsMultiple;
} }
} }

View File

@ -24,23 +24,24 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Migration.GoogleWorkspace namespace ASC.Migration.GoogleWorkspace
{ {
[ApiMigrator("GoogleWorkspace")] [Scope]
public class GoogleWorkspaceMigration : AbstractMigration<GwsMigrationInfo, GwsMigratingUser, GwsMigratingContacts, GwsMigratingCalendar, GwsMigratingFiles, GwsMigratingMail> public class GoogleWorkspaceMigration : AbstractMigration<GwsMigrationInfo, GwsMigratingUser, GwsMigratingContacts, GwsMigratingCalendar, GwsMigratingFiles, GwsMigratingMail>
{ {
private string[] _takeouts; private string[] _takeouts;
private readonly UserManager _userManager; private readonly UserManager _userManager;
private readonly SecurityContext _securityContext; private readonly SecurityContext _securityContext;
private readonly TempPath _tempPath; private readonly TempPath _tempPath;
private readonly MigratorMeta _meta;
public override MigratorMeta Meta => _meta;
public GoogleWorkspaceMigration(MigrationLogger migrationLogger, UserManager userManager, SecurityContext securityContext, TempPath tempPath) : base(migrationLogger) public GoogleWorkspaceMigration(MigrationLogger migrationLogger, UserManager userManager, SecurityContext securityContext, TempPath tempPath) : base(migrationLogger)
{ {
_userManager = userManager; _userManager = userManager;
_securityContext = securityContext; _securityContext = securityContext;
_tempPath = tempPath; _tempPath = tempPath;
_meta = new("GoogleWorkspace", 5, true);
} }
public override void Init(string path, CancellationToken cancellationToken) public override void Init(string path, CancellationToken cancellationToken)

View File

@ -29,8 +29,8 @@ using ASC.Migration.NextcloudWorkspace.Models.Parse;
namespace ASC.Migration.NextcloudWorkspace; namespace ASC.Migration.NextcloudWorkspace;
[ApiMigrator("NextcloudMigrate")] [Scope]
public class NextcloudWorkspaceMigration : AbstractMigration<NCMigrationInfo, NCMigratingUser, NCMigratingContacts, NCMigratingCalendar, NCMigratingFiles, NCMigratingMail> public class NextcloudWorkspaceMigration : AbstractMigration<NCMigrationInfo, NCMigratingUser, NCMigratingContacts, NCMigratingCalendar, NCMigratingFiles, NCMigratingMail>, IMigration
{ {
private string _takeouts; private string _takeouts;
public string[] TempParse; public string[] TempParse;
@ -42,6 +42,8 @@ public class NextcloudWorkspaceMigration : AbstractMigration<NCMigrationInfo, NC
private readonly SecurityContext _securityContext; private readonly SecurityContext _securityContext;
private readonly UserManager _userManager; private readonly UserManager _userManager;
private readonly TenantManager _tenantManager; private readonly TenantManager _tenantManager;
private readonly MigratorMeta _meta;
public override MigratorMeta Meta => _meta;
public NextcloudWorkspaceMigration( public NextcloudWorkspaceMigration(
GlobalFolderHelper globalFolderHelper, GlobalFolderHelper globalFolderHelper,
@ -60,6 +62,7 @@ public class NextcloudWorkspaceMigration : AbstractMigration<NCMigrationInfo, NC
_securityContext = securityContext; _securityContext = securityContext;
_userManager = userManager; _userManager = userManager;
_tenantManager = tenantManager; _tenantManager = tenantManager;
_meta = new("Nextcloud", 6, false);
} }
public override void Init(string path, CancellationToken cancellationToken) public override void Init(string path, CancellationToken cancellationToken)

View File

@ -28,24 +28,24 @@ using ASC.Migration.OwnCloud.Models;
namespace ASC.Migration.OwnCloud; namespace ASC.Migration.OwnCloud;
[ApiMigrator("OwncloudMigrate")] [Scope]
public class OwnCloudMigration : AbstractMigration<OCMigrationInfo, OCMigratingUser, OCMigratingContacts, OCMigratingCalendar, OCMigratingFiles, OCMigratingMail> public class OwnCloudMigration : AbstractMigration<OCMigrationInfo, OCMigratingUser, OCMigratingContacts, OCMigratingCalendar, OCMigratingFiles, OCMigratingMail>, IMigration
{ {
private string _takeouts; private string _takeouts;
public string[] TempParse; public string[] TempParse;
private string _tmpFolder; private string _tmpFolder;
private readonly GlobalFolderHelper _globalFolderHelper; private readonly GlobalFolderHelper _globalFolderHelper;
private readonly IDaoFactory _daoFactory; private readonly IDaoFactory _daoFactory;
private readonly FileSecurity _fileSecurity;
private readonly FileStorageService _fileStorageService; private readonly FileStorageService _fileStorageService;
private readonly SecurityContext _securityContext; private readonly SecurityContext _securityContext;
private readonly TenantManager _tenantManager; private readonly TenantManager _tenantManager;
private readonly UserManager _userManager; private readonly UserManager _userManager;
private readonly MigratorMeta _meta;
public override MigratorMeta Meta => _meta;
public OwnCloudMigration( public OwnCloudMigration(
GlobalFolderHelper globalFolderHelper, GlobalFolderHelper globalFolderHelper,
IDaoFactory daoFactory, IDaoFactory daoFactory,
FileSecurity fileSecurity,
FileStorageService fileStorageService, FileStorageService fileStorageService,
SecurityContext securityContext, SecurityContext securityContext,
TenantManager tenantManager, TenantManager tenantManager,
@ -54,11 +54,11 @@ public class OwnCloudMigration : AbstractMigration<OCMigrationInfo, OCMigratingU
{ {
_globalFolderHelper = globalFolderHelper; _globalFolderHelper = globalFolderHelper;
_daoFactory = daoFactory; _daoFactory = daoFactory;
_fileSecurity = fileSecurity;
_fileStorageService = fileStorageService; _fileStorageService = fileStorageService;
_securityContext = securityContext; _securityContext = securityContext;
_tenantManager = tenantManager; _tenantManager = tenantManager;
_userManager = userManager; _userManager = userManager;
_meta = new MigratorMeta("Owncloud", 6, false);
} }
public override void Init(string path, CancellationToken cancellationToken) public override void Init(string path, CancellationToken cancellationToken)

View File

@ -197,7 +197,7 @@ server {
proxy_pass http://127.0.0.1:5004; proxy_pass http://127.0.0.1:5004;
} }
location ~* /(authentication|modules|portal|security|settings|smtpsettings|capabilities|thirdparty|encryption|feed) { location ~* /(authentication|modules|portal|security|settings|smtpsettings|capabilities|thirdparty|encryption|feed|migration) {
proxy_pass http://127.0.0.1:5000; proxy_pass http://127.0.0.1:5000;
location ~* portal/(.*)(backup|restore)(.*) { location ~* portal/(.*)(backup|restore)(.*) {
@ -220,10 +220,6 @@ server {
location ~* /plugins { location ~* /plugins {
proxy_pass http://127.0.0.1:5014; proxy_pass http://127.0.0.1:5014;
} }
location ~* /migration {
proxy_pass http://127.0.0.1:5034;
}
} }
location /sso { location /sso {

View File

@ -41,6 +41,7 @@ public class MigrationController : ControllerBase
private readonly StudioNotifyService _studioNotifyService; private readonly StudioNotifyService _studioNotifyService;
private readonly ICache _cache; private readonly ICache _cache;
private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpContextAccessor _httpContextAccessor;
private readonly MigrationCore _migrationCore;
public MigrationController( public MigrationController(
CoreBaseSettings coreBaseSettings, CoreBaseSettings coreBaseSettings,
@ -49,7 +50,8 @@ public class MigrationController : ControllerBase
TempPath tempPath, TempPath tempPath,
StudioNotifyService studioNotifyService, StudioNotifyService studioNotifyService,
ICache cache, ICache cache,
IHttpContextAccessor httpContextAccessor) IHttpContextAccessor httpContextAccessor,
MigrationCore migrationCore)
{ {
_coreBaseSettings = coreBaseSettings; _coreBaseSettings = coreBaseSettings;
_userManager = userManager; _userManager = userManager;
@ -58,6 +60,7 @@ public class MigrationController : ControllerBase
_studioNotifyService = studioNotifyService; _studioNotifyService = studioNotifyService;
_cache = cache; _cache = cache;
_httpContextAccessor = httpContextAccessor; _httpContextAccessor = httpContextAccessor;
_migrationCore = migrationCore;
} }
/// <summary> /// <summary>
@ -93,7 +96,7 @@ public class MigrationController : ControllerBase
throw new SecurityException(Resource.ErrorAccessDenied); throw new SecurityException(Resource.ErrorAccessDenied);
} }
return MigrationCore.GetAvailableMigrations(); return _migrationCore.GetAvailableMigrations();
} }
/// <summary> /// <summary>
@ -114,20 +117,20 @@ public class MigrationController : ControllerBase
throw new Exception(MigrationResource.MigrationUploadException); throw new Exception(MigrationResource.MigrationUploadException);
} }
var migratorMeta = MigrationCore.GetMigrator(migratorName); var migrator = _migrationCore.GetMigrator(migratorName);
if (migratorMeta == null) if (migrator == null)
{ {
throw new ItemNotFoundException(MigrationResource.MigrationNotFoundException); throw new ItemNotFoundException(MigrationResource.MigrationNotFoundException);
} }
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var migrator = (IMigration)Activator.CreateInstance(migratorMeta.MigratorType);
try try
{ {
migrator.Init(path, cts.Token); migrator.Init(path, cts.Token);
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception(string.Format(MigrationResource.MigrationUploadException, migratorMeta.MigratorInfo.Name), ex); throw new Exception(string.Format(MigrationResource.MigrationUploadException, migratorName), ex);
} }
var ongoingMigration = new OngoingMigration { Migration = migrator, CancelTokenSource = cts }; var ongoingMigration = new OngoingMigration { Migration = migrator, CancelTokenSource = cts };
@ -156,7 +159,7 @@ public class MigrationController : ControllerBase
if (ongoingMigration.CancelTokenSource.IsCancellationRequested == true) if (ongoingMigration.CancelTokenSource.IsCancellationRequested == true)
{ {
var migratorName = ongoingMigration.Migration.GetType().GetCustomAttribute<ApiMigratorAttribute>().Name; var migratorName = ongoingMigration.Migration.Meta.Name;
return migratorName; return migratorName;
} }

View File

@ -54,6 +54,7 @@ public class Startup : BaseStartup
services.AddScoped<ITenantQuotaFeatureStat<CountRoomFeature, int>, CountRoomCheckerStatistic>(); services.AddScoped<ITenantQuotaFeatureStat<CountRoomFeature, int>, CountRoomCheckerStatistic>();
services.AddScoped<CountRoomCheckerStatistic>(); services.AddScoped<CountRoomCheckerStatistic>();
MigrationCore.Register(DIHelper);
DIHelper.TryAdd<AdditionalWhiteLabelSettingsConverter>(); DIHelper.TryAdd<AdditionalWhiteLabelSettingsConverter>();
} }