* Add new BackOfficeApi project * Add swagger * Add and route new install controller * Add new install steps * Add Setup endpoint * Add missing RequiresExecution methods * Fix nullability of databasemodel * Move user information to separate model * Remove ping method * Add view models install data * Move mapping folder * Move ViewModels * Add settings endpoint * Remove unused binderprovider * Postfix RequiresExecution with async * Update NewDatabaseUpgradeStep to not depend on install step * Add installstep collection * Move registration into backoffice project * Add InstallService * Use service in controller * Add upgrade to install service and use in controller * Correctly check is database is configured * Reorganize * Reorganize into new core and infrastructure * Rename steps * Rename BackofficeApi to MangementApi * Make install step an interface instead of abstract class * Rename InstallStep to create CreateUserStep * Move restart runtime and sign in user into install steps * Move install service into new core project * Map controllers in composer * Restrict access to installcontroller based on runtime level * Use FireAndForget when logging install * Use actionresult instead of iactionresult * Set new projects as not packable * Link to backoffice in 201 response when installed * Register installations * Add custom backoffice routing template token * Move umbraco path trimming out of application convention * Make it easier to route to backoffice api * Make swagger version aware and move behind backoffice path * Obsolete old install classes * Move maps into single file This is all mappint to/from viewmodels in some manner * Remove usage of InstallSetupResult * Move new projects to the src folder * Remove InstallationType from IInstallStep This upgrade steps should implement their own IUpgradeStep interface * Remove upgrade from service and controller This should be its own service and controller * Add xml docs * Remove internals visible to * Disable package validation for new projects Quite the gotcha here, if the projects are brand new, there is no nuget packages to compare with, this causes the build to fail. * Add ValidateDatabase endpoint * Remove project references to new backoffice We don't actually want to depend on this yet, it's just needed for testing/development * Obsolete installationtype * Add DatabaseSettingsFactory tests * Add InstallServiceTests * Fix InstallServiceTests * Test RequireRuntimeLevelAttribute * Implement new backoffice upgrader (#12818) * Add UpgradeSettingsModel and viewmodel * Add upgrade/settings endpoint * Implement upgrade steps * Add upgrade step collection * Add UpgradeService * Add authorize endpoint to UpgradeController * Fix interface * Add upgrade service tests * Remove runtime check in databaseinstallstep * Move RequireRuntimeLevel to controller * Add a readme to the new backoffice part * BackOffice not Backoffice * Add conditional project references * Fixes based on review * Fix up * Move running of steps into its own method in UpgradeService * Make services transient * More fixup * Log exceptions when running steps
158 lines
5.5 KiB
C#
158 lines
5.5 KiB
C#
using Umbraco.Cms.Core.Collections;
|
|
using Umbraco.Cms.Core.Hosting;
|
|
using Umbraco.Cms.Core.Install.Models;
|
|
using Umbraco.Cms.Core.Serialization;
|
|
using Umbraco.Extensions;
|
|
|
|
namespace Umbraco.Cms.Core.Install;
|
|
|
|
/// <summary>
|
|
/// An internal in-memory status tracker for the current installation
|
|
/// </summary>
|
|
[Obsolete("This will no longer be used with the new backoffice APi, instead all steps run in one go")]
|
|
public class InstallStatusTracker
|
|
{
|
|
private static ConcurrentHashSet<InstallTrackingItem> _steps = new();
|
|
private readonly IHostingEnvironment _hostingEnvironment;
|
|
private readonly IJsonSerializer _jsonSerializer;
|
|
|
|
public InstallStatusTracker(IHostingEnvironment hostingEnvironment, IJsonSerializer jsonSerializer)
|
|
{
|
|
_hostingEnvironment = hostingEnvironment;
|
|
_jsonSerializer = jsonSerializer;
|
|
}
|
|
|
|
public static IEnumerable<InstallTrackingItem> GetStatus() =>
|
|
new List<InstallTrackingItem>(_steps).OrderBy(x => x.ServerOrder);
|
|
|
|
public void Reset()
|
|
{
|
|
_steps = new ConcurrentHashSet<InstallTrackingItem>();
|
|
ClearFiles();
|
|
}
|
|
|
|
private string GetFile(Guid installId)
|
|
{
|
|
var file = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempData.EnsureEndsWith('/') +
|
|
"Install/"
|
|
+ "install_"
|
|
+ installId.ToString("N")
|
|
+ ".txt");
|
|
return file;
|
|
}
|
|
|
|
public void ClearFiles()
|
|
{
|
|
var dir = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempData.EnsureEndsWith('/') +
|
|
"Install/");
|
|
if (Directory.Exists(dir))
|
|
{
|
|
var files = Directory.GetFiles(dir);
|
|
foreach (var f in files)
|
|
{
|
|
File.Delete(f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Directory.CreateDirectory(dir);
|
|
}
|
|
}
|
|
|
|
public IEnumerable<InstallTrackingItem> InitializeFromFile(Guid installId)
|
|
{
|
|
// check if we have our persisted file and read it
|
|
var file = GetFile(installId);
|
|
if (File.Exists(file))
|
|
{
|
|
IEnumerable<InstallTrackingItem>? deserialized =
|
|
_jsonSerializer.Deserialize<IEnumerable<InstallTrackingItem>>(
|
|
File.ReadAllText(file));
|
|
if (deserialized is not null)
|
|
{
|
|
foreach (InstallTrackingItem item in deserialized)
|
|
{
|
|
_steps.Add(item);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Cannot initialize from file, the installation file with id " +
|
|
installId + " does not exist");
|
|
}
|
|
|
|
return new List<InstallTrackingItem>(_steps);
|
|
}
|
|
|
|
public IEnumerable<InstallTrackingItem> Initialize(Guid installId, IEnumerable<InstallSetupStep> steps)
|
|
{
|
|
// if there are no steps in memory
|
|
if (_steps.Count == 0)
|
|
{
|
|
// check if we have our persisted file and read it
|
|
var file = GetFile(installId);
|
|
if (File.Exists(file))
|
|
{
|
|
IEnumerable<InstallTrackingItem>? deserialized =
|
|
_jsonSerializer.Deserialize<IEnumerable<InstallTrackingItem>>(
|
|
File.ReadAllText(file));
|
|
if (deserialized is not null)
|
|
{
|
|
foreach (InstallTrackingItem item in deserialized)
|
|
{
|
|
_steps.Add(item);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClearFiles();
|
|
|
|
// otherwise just create the steps in memory (brand new install)
|
|
foreach (InstallSetupStep step in steps.OrderBy(x => x.ServerOrder))
|
|
{
|
|
_steps.Add(new InstallTrackingItem(step.Name, step.ServerOrder));
|
|
}
|
|
|
|
// save the file
|
|
var serialized = _jsonSerializer.Serialize(new List<InstallTrackingItem>(_steps));
|
|
Directory.CreateDirectory(Path.GetDirectoryName(file)!);
|
|
File.WriteAllText(file, serialized);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ensure that the file exists with the current install id
|
|
var file = GetFile(installId);
|
|
if (File.Exists(file) == false)
|
|
{
|
|
ClearFiles();
|
|
|
|
// save the correct file
|
|
var serialized = _jsonSerializer.Serialize(new List<InstallTrackingItem>(_steps));
|
|
Directory.CreateDirectory(Path.GetDirectoryName(file)!);
|
|
File.WriteAllText(file, serialized);
|
|
}
|
|
}
|
|
|
|
return new List<InstallTrackingItem>(_steps);
|
|
}
|
|
|
|
public void SetComplete(Guid installId, string name, IDictionary<string, object>? additionalData = null)
|
|
{
|
|
InstallTrackingItem trackingItem = _steps.Single(x => x.Name == name);
|
|
if (additionalData != null)
|
|
{
|
|
trackingItem.AdditionalData = additionalData;
|
|
}
|
|
|
|
trackingItem.IsComplete = true;
|
|
|
|
// save the file
|
|
var file = GetFile(installId);
|
|
var serialized = _jsonSerializer.Serialize(new List<InstallTrackingItem>(_steps));
|
|
File.WriteAllText(file, serialized);
|
|
}
|
|
}
|