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
// 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.Extensions;
global using ASC.Common.DependencyInjection;
global using ASC.Migration;
global using Autofac;

View File

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

View File

@ -24,9 +24,11 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using ASC.Migration.Core.Models.Api;
namespace ASC.Migration;
public class Startup : BaseStartup
public class Startup : BaseWorkerStartup
{
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment)
: base(configuration, hostEnvironment)
@ -36,10 +38,8 @@ public class Startup : BaseStartup
public override void ConfigureServices(IServiceCollection services)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
services.AddMemoryCache();
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
// 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
where TMigrationInfo : IMigrationInfo
{
@ -34,8 +35,9 @@ public abstract class AbstractMigration<TMigrationInfo, TUser, TContacts, TCalen
protected TMigrationInfo _migrationInfo;
private double _lastProgressUpdate;
private string _lastStatusUpdate;
protected List<Guid> _importedUsers;
protected List<Guid> _importedUsers;
public abstract MigratorMeta Meta { get; }
public event Action<double, string> OnProgressUpdate;
public AbstractMigration(MigrationLogger migrationLogger)

View File

@ -26,6 +26,7 @@
namespace ASC.Migration.Core;
[Scope]
public interface IMigration : IDisposable
{
event Action<double, string> OnProgressUpdate;
@ -42,5 +43,7 @@ public interface IMigration : IDisposable
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
// 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;
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;
private static Dictionary<string, MigratorMeta> Migrators
{
get
{
if (_migrators != null)
{
return _migrators;
}
public string[] GetAvailableMigrations() => _serviceProvider.GetService<IEnumerable<IMigration>>().Select(r => r.Meta.Name).ToArray();
public IMigration GetMigrator(string migrator)
{
return _serviceProvider.GetService<IEnumerable<IMigration>>().FirstOrDefault(r => r.Meta.Name == migrator);
}
_migrators = new Dictionary<string, MigratorMeta>(StringComparer.OrdinalIgnoreCase);
var migratorTypes = Assembly.GetExecutingAssembly()
.GetExportedTypes()
.Where(t => !t.IsAbstract && !t.IsInterface
&& 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 void Register(DIHelper services)
{
services.TryAdd<IMigration, GoogleWorkspaceMigration>();
services.TryAdd<IMigration, NextcloudWorkspaceMigration>();
services.TryAdd<IMigration, OwnCloudMigration>();
}
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 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(Type type)
public MigratorMeta(string name, string[] fileTypes)
{
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
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Migration.GoogleWorkspace
{
[ApiMigrator("GoogleWorkspace")]
{
[Scope]
public class GoogleWorkspaceMigration : AbstractMigration<GwsMigrationInfo, GwsMigratingUser, GwsMigratingContacts, GwsMigratingCalendar, GwsMigratingFiles, GwsMigratingMail>
{
private string[] _takeouts;
private readonly UserManager _userManager;
private readonly SecurityContext _securityContext;
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)
{
_userManager = userManager;
_securityContext = securityContext;
_tempPath = tempPath;
_meta = new("GoogleWorkspace", 5, true);
}
public override void Init(string path, CancellationToken cancellationToken)

View File

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

View File

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

View File

@ -197,7 +197,7 @@ server {
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;
location ~* portal/(.*)(backup|restore)(.*) {
@ -220,10 +220,6 @@ server {
location ~* /plugins {
proxy_pass http://127.0.0.1:5014;
}
location ~* /migration {
proxy_pass http://127.0.0.1:5034;
}
}
location /sso {

View File

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

View File

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