Files
Umbraco-CMS/src/Umbraco.Core/Install/InstallStatusTracker.cs
Mole 748fb7d1f7 Implement new backoffice installer (#12790)
* 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
2022-08-29 09:50:48 +02:00

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);
}
}