diff --git a/src/Umbraco.Abstractions/InstallLog.cs b/src/Umbraco.Abstractions/InstallLog.cs new file mode 100644 index 0000000000..cb14ebd650 --- /dev/null +++ b/src/Umbraco.Abstractions/InstallLog.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Umbraco.Core.Models +{ + public class InstallLog + { + public Guid InstallId { get; } + public bool IsUpgrade { get; set; } + public bool InstallCompleted { get; set; } + public DateTime Timestamp { get; set; } + public int VersionMajor { get; } + public int VersionMinor { get; } + public int VersionPatch { get; } + public string VersionComment { get; } + public string Error { get; } + public string UserAgent { get; } + public string DbProvider { get; set; } + + public InstallLog(Guid installId, bool isUpgrade, bool installCompleted, DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider) + { + InstallId = installId; + IsUpgrade = isUpgrade; + InstallCompleted = installCompleted; + Timestamp = timestamp; + VersionMajor = versionMajor; + VersionMinor = versionMinor; + VersionPatch = versionPatch; + VersionComment = versionComment; + Error = error; + UserAgent = userAgent; + DbProvider = dbProvider; + } + } +} diff --git a/src/Umbraco.Abstractions/Persistence/Repositories/IInstallationRepository.cs b/src/Umbraco.Abstractions/Persistence/Repositories/IInstallationRepository.cs new file mode 100644 index 0000000000..fbc7d2cfbc --- /dev/null +++ b/src/Umbraco.Abstractions/Persistence/Repositories/IInstallationRepository.cs @@ -0,0 +1,11 @@ +using System; +using System.Threading.Tasks; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface IInstallationRepository + { + Task SaveInstallLogAsync(InstallLog installLog); + } +} diff --git a/src/Umbraco.Abstractions/Persistence/Repositories/IUpgradeCheckRepository.cs b/src/Umbraco.Abstractions/Persistence/Repositories/IUpgradeCheckRepository.cs new file mode 100644 index 0000000000..6d56994781 --- /dev/null +++ b/src/Umbraco.Abstractions/Persistence/Repositories/IUpgradeCheckRepository.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Semver; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface IUpgradeCheckRepository + { + Task CheckUpgradeAsync(SemVersion version); + } +} diff --git a/src/Umbraco.Abstractions/Persistence/Repositories/InstallationRepository.cs b/src/Umbraco.Abstractions/Persistence/Repositories/InstallationRepository.cs new file mode 100644 index 0000000000..49fbfe096b --- /dev/null +++ b/src/Umbraco.Abstractions/Persistence/Repositories/InstallationRepository.cs @@ -0,0 +1,28 @@ +using System.Net.Http; +using System.Net.Http.Formatting; +using System.Threading.Tasks; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories.Implement +{ + internal class InstallationRepository : IInstallationRepository + { + private static HttpClient _httpClient; + private const string RestApiInstallUrl = "https://our.umbraco.com/umbraco/api/Installation/Install"; + + + public async Task SaveInstallLogAsync(InstallLog installLog) + { + try + { + if (_httpClient == null) + _httpClient = new HttpClient(); + + await _httpClient.PostAsync(RestApiInstallUrl, installLog, new JsonMediaTypeFormatter()); + } + // this occurs if the server for Our is down or cannot be reached + catch (HttpRequestException) + { } + } + } +} diff --git a/src/Umbraco.Abstractions/Persistence/Repositories/UpgradeCheckRepository.cs b/src/Umbraco.Abstractions/Persistence/Repositories/UpgradeCheckRepository.cs new file mode 100644 index 0000000000..365e8ba481 --- /dev/null +++ b/src/Umbraco.Abstractions/Persistence/Repositories/UpgradeCheckRepository.cs @@ -0,0 +1,49 @@ +using System.Net.Http; +using System.Net.Http.Formatting; +using System.Threading.Tasks; +using Semver; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories.Implement +{ + internal class UpgradeCheckRepository : IUpgradeCheckRepository + { + private static HttpClient _httpClient; + private const string RestApiUpgradeChecklUrl = "https://our.umbraco.com/umbraco/api/UpgradeCheck/CheckUpgrade"; + + + public async Task CheckUpgradeAsync(SemVersion version) + { + try + { + if (_httpClient == null) + _httpClient = new HttpClient(); + + var task = await _httpClient.PostAsync(RestApiUpgradeChecklUrl, new CheckUpgradeDto(version), new JsonMediaTypeFormatter()); + var result = await task.Content.ReadAsAsync(); + + return result ?? new UpgradeResult("None", "", ""); + } + catch (HttpRequestException) + { + // this occurs if the server for Our is down or cannot be reached + return new UpgradeResult("None", "", ""); + } + } + private class CheckUpgradeDto + { + public CheckUpgradeDto(SemVersion version) + { + VersionMajor = version.Major; + VersionMinor = version.Minor; + VersionPatch = version.Patch; + VersionComment = version.Prerelease; + } + + public int VersionMajor { get; } + public int VersionMinor { get; } + public int VersionPatch { get; } + public string VersionComment { get; } + } + } +} diff --git a/src/Umbraco.Abstractions/UpgradeResult.cs b/src/Umbraco.Abstractions/UpgradeResult.cs new file mode 100644 index 0000000000..a27f6bb6a3 --- /dev/null +++ b/src/Umbraco.Abstractions/UpgradeResult.cs @@ -0,0 +1,16 @@ +namespace Umbraco.Core.Models +{ + public class UpgradeResult + { + public string UpgradeType { get; } + public string Comment { get; } + public string UpgradeUrl { get; } + + public UpgradeResult(string upgradeType, string comment, string upgradeUrl) + { + UpgradeType = upgradeType; + Comment = comment; + UpgradeUrl = upgradeUrl; + } + } +} diff --git a/src/Umbraco.Abstractions/UpgradeService.cs b/src/Umbraco.Abstractions/UpgradeService.cs new file mode 100644 index 0000000000..8116c0e738 --- /dev/null +++ b/src/Umbraco.Abstractions/UpgradeService.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Semver; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Services; + +namespace Umbraco.Core +{ + internal class UpgradeService : IUpgradeService + { + private readonly IUpgradeCheckRepository _upgradeCheckRepository; + + public UpgradeService(IUpgradeCheckRepository upgradeCheckRepository) + { + _upgradeCheckRepository = upgradeCheckRepository; + } + + public async Task CheckUpgrade(SemVersion version) + { + return await _upgradeCheckRepository.CheckUpgradeAsync(version); + } + } +} diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs index 0939dd0f71..61ff4ecb6d 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Repositories.cs @@ -47,6 +47,8 @@ namespace Umbraco.Core.Composing.CompositionExtensions composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(); return composition; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index f3db5c5906..2f1b6c5814 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -543,6 +543,16 @@ ORDER BY colName"; } } + // If userlogin or the email has changed then need to reset security stamp + if (changedCols.Contains("userLogin") || changedCols.Contains("userEmail")) + { + userDto.EmailConfirmedDate = null; + userDto.SecurityStampToken = entity.SecurityStamp = Guid.NewGuid().ToString(); + + changedCols.Add("emailConfirmedDate"); + changedCols.Add("securityStampToken"); + } + //only update the changed cols if (changedCols.Count > 0) { diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index e767ce5505..689ee44eb2 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -19,11 +19,13 @@ using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.Scoping; using Umbraco.Core.Serialization; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Web.Models.PublishedContent; using Umbraco.Web.PublishedCache; using Umbraco.Web; +using Umbraco.Web.Migrations.PostMigrations; using Umbraco.Web.PropertyEditors; using Umbraco.Web.Services; using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidator; @@ -143,8 +145,8 @@ namespace Umbraco.Core.Runtime // by default, register a noop factory composition.RegisterUnique(); - // by default, register a noop rebuilder - composition.RegisterUnique(); + // by default + composition.RegisterUnique(); composition.SetCultureDictionaryFactory(); composition.Register(f => f.GetInstance().CreateDictionary(), Lifetime.Singleton); @@ -160,6 +162,10 @@ namespace Umbraco.Core.Runtime // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards composition.Dashboards() .Add(composition.TypeLoader.GetTypes()); + + // will be injected in controllers when needed to invoke rest endpoints on Our + composition.RegisterUnique(); + composition.RegisterUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Services/Implement/IInstallationService.cs b/src/Umbraco.Infrastructure/Services/Implement/IInstallationService.cs new file mode 100644 index 0000000000..334088f8ae --- /dev/null +++ b/src/Umbraco.Infrastructure/Services/Implement/IInstallationService.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Services +{ + public interface IInstallationService + { + Task LogInstall(InstallLog installLog); + } +} diff --git a/src/Umbraco.Infrastructure/Services/Implement/IUpgradeService.cs b/src/Umbraco.Infrastructure/Services/Implement/IUpgradeService.cs new file mode 100644 index 0000000000..70bbb68085 --- /dev/null +++ b/src/Umbraco.Infrastructure/Services/Implement/IUpgradeService.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Semver; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Services +{ + public interface IUpgradeService + { + Task CheckUpgrade(SemVersion version); + } +} diff --git a/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs b/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs new file mode 100644 index 0000000000..a1f74e0862 --- /dev/null +++ b/src/Umbraco.Infrastructure/Services/Implement/Implement/InstallationService.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence.Repositories; + +namespace Umbraco.Core.Services.Implement +{ + public class InstallationService : IInstallationService + { + private readonly IInstallationRepository _installationRepository; + + public InstallationService(IInstallationRepository installationRepository) + { + _installationRepository = installationRepository; + } + + public async Task LogInstall(InstallLog installLog) + { + await _installationRepository.SaveInstallLogAsync(installLog); + } + } +} diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 8b2514eec0..201b84f29a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -423,6 +423,35 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void Can_Invalidate_SecurityStamp_On_Username_Change() + { + // Arrange + var provider = TestObjects.GetScopeProvider(Logger); + using (var scope = provider.CreateScope()) + { + var repository = CreateRepository(provider); + var userGroupRepository = CreateUserGroupRepository(provider); + + var user = CreateAndCommitUserWithGroup(repository, userGroupRepository); + var originalSecurityStamp = user.SecurityStamp; + + // Ensure when user generated a security stamp is present + Assert.That(user.SecurityStamp, Is.Not.Null); + Assert.That(user.SecurityStamp, Is.Not.Empty); + + // Update username + user.Username = user.Username + "UPDATED"; + repository.Save(user); + + // Get the user + var updatedUser = repository.Get(user.Id); + + // Ensure the Security Stamp is invalidated & no longer the same + Assert.AreNotEqual(originalSecurityStamp, updatedUser.SecurityStamp); + } + } + private void AssertPropertyValues(IUser updatedItem, IUser originalUser) { Assert.That(updatedItem.Id, Is.EqualTo(originalUser.Id)); diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 1889e4b032..42a89c5d13 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -1109,9 +1109,9 @@ "integrity": "sha512-kU/fHIGf2a4a3bH7E1tzALTHk+QfoUSCK9fEcMFisd6ZWvNDwPzXWAilItqOC3EDiAXPmGHaNc9/aXiD9xrAxQ==" }, "angular-aria": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/angular-aria/-/angular-aria-1.7.5.tgz", - "integrity": "sha512-X2dGRw+PK7hrV7/X1Ns4e5P3KC/OBFi1l7z//D/v7zbZObsAx48qBoX7unsck+s4+mnO+ikNNkHG5N49VfAyRw==" + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/angular-aria/-/angular-aria-1.7.9.tgz", + "integrity": "sha512-luI3Jemd1AbOQW0krdzfEG3fM0IFtLY0bSSqIDEx3POE0XjKIC1MkrO8Csyq9PPgueLphyAPofzUwZ8YeZ88SA==" }, "angular-chart.js": { "version": "1.1.1", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 508409b4ea..c150af79de 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -13,7 +13,7 @@ "ace-builds": "1.4.2", "angular": "1.7.9", "angular-animate": "1.7.5", - "angular-aria": "1.7.5", + "angular-aria": "1.7.9", "angular-chart.js": "^1.1.1", "angular-cookies": "1.7.5", "angular-dynamic-locale": "0.1.37", diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js index d562b21d52..9a9d6d4a76 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js @@ -71,6 +71,7 @@ templateUrl: 'views/components/forms/umb-checkbox.html', controller: UmbCheckboxController, controllerAs: 'vm', + transclude: true, bindings: { model: "=", inputId: "@", diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js index 7ed84547f1..d79140f947 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js @@ -69,6 +69,7 @@ templateUrl: 'views/components/forms/umb-radiobutton.html', controller: UmbRadiobuttonController, controllerAs: 'vm', + transclude: true, bindings: { model: "=", inputId: "@", diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index 284a7db4d8..d481205657 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -169,6 +169,7 @@ When building a custom infinite editor view you can use the same components as a let editorsKeyboardShorcuts = []; var editors = []; var isEnabled = true; + var lastElementInFocus = null; // events for backdrop @@ -261,6 +262,12 @@ When building a custom infinite editor view you can use the same components as a */ unbindKeyboardShortcuts(); + // if this is the first editor layer, save the currently focused element + // so we can re-apply focus to it once all the editor layers are closed + if (editors.length === 0) { + lastElementInFocus = document.activeElement; + } + // set flag so we know when the editor is open in "infinite mode" editor.infiniteMode = true; @@ -301,6 +308,10 @@ When building a custom infinite editor view you can use the same components as a $timeout(function() { // rebind keyboard shortcuts for the new editor in focus rebindKeyboardShortcuts(); + + if (editors.length === 0 && lastElementInFocus) { + lastElementInFocus.focus(); + } }, 0); } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less index 76a4df0056..b9efd8f7d8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less @@ -3,15 +3,21 @@ .umb-form-check { display: flex; - flex-wrap: wrap; - align-items: center; position: relative; - padding: 0 0 0 26px !important; + padding-left: 0px; margin: 0; min-height: 22px; - line-height: 22px; cursor: pointer !important; + .umb-form-check__symbol { + margin-top: 1px; + margin-right: 10px; + } + .umb-form-check__info { + + } + + &.-small-text{ font-size: 13px; } @@ -22,7 +28,6 @@ &__text { position: relative; - top: 1px; user-select: none; } @@ -90,10 +95,6 @@ &__state { display: flex; height: 18px; - margin-top: 2px; - position: absolute; - top: 0; - left: 0; } &__check { @@ -101,6 +102,7 @@ position: relative; background: @white; border: 1px solid @inputBorder; + border-radius: @baseBorderRadius; width: @checkboxWidth; height: @checkboxHeight; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-search.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-search.less index ac15b3dcf8..68cb9b2e58 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-search.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-search.less @@ -4,16 +4,21 @@ .icon { position: absolute; - padding: 5px 8px; + width: 30px; + height: 30px; + display: flex; + justify-content: center; + align-items: center; + margin: 1px; + padding: 0; pointer-events: none; - top: 2px; color: @ui-action-discreet-type; transition: color .1s linear; } input { width: 0px; - padding-left:24px; + padding-left: 24px; margin-bottom: 0px; background-color: transparent; border-color: @ui-action-discreet-border; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html index 82b21e4c3b..ba5adf199a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html @@ -1,22 +1,28 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html index 9ee50bcae1..a34d548ea6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html @@ -1,16 +1,20 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html b/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html index b5531f477a..cbd1ac3f30 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html @@ -1,4 +1,4 @@ 
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-mini-search/umb-mini-search.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-mini-search/umb-mini-search.html index 20ce87f0eb..93801f14b8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-mini-search/umb-mini-search.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-mini-search/umb-mini-search.html @@ -1,5 +1,5 @@ - + GetCheck() { var updChkCookie = Request.Headers.GetCookies("UMB_UPDCHK").FirstOrDefault(); var updateCheckCookie = updChkCookie != null ? updChkCookie["UMB_UPDCHK"].Value : ""; @@ -31,14 +38,11 @@ namespace Umbraco.Web.Editors { try { - var check = new org.umbraco.update.CheckForUpgrade { Timeout = 2000 }; + var version = new SemVersion(_umbracoVersion.Current.Major, _umbracoVersion.Current.Minor, + _umbracoVersion.Current.Build, _umbracoVersion.Comment); + var result = await _upgradeService.CheckUpgrade(version); - var result = check.CheckUpgrade(_umbracoVersion.Current.Major, - _umbracoVersion.Current.Minor, - _umbracoVersion.Current.Build, - _umbracoVersion.Comment); - - return new UpgradeCheckResponse(result.UpgradeType.ToString(), result.Comment, result.UpgradeUrl, _umbracoVersion); + return new UpgradeCheckResponse(result.UpgradeType, result.Comment, result.UpgradeUrl); } catch (System.Net.WebException) { diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index 0c3e945029..14845f832c 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -2,13 +2,16 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; +using System.Threading.Tasks; using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; +using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Install.Models; @@ -23,11 +26,16 @@ namespace Umbraco.Web.Install private readonly IGlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; private readonly IConnectionStrings _connectionStrings; + private readonly IInstallationService _installationService; private InstallationType? _installationType; public InstallHelper(IHttpContextAccessor httpContextAccessor, DatabaseBuilder databaseBuilder, - ILogger logger, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion, IConnectionStrings connectionStrings) + ILogger logger, + IGlobalSettings globalSettings, + IUmbracoVersion umbracoVersion, + IConnectionStrings connectionStrings, + IInstallationService installationService) { _httpContextAccessor = httpContextAccessor; _logger = logger; @@ -35,6 +43,7 @@ namespace Umbraco.Web.Install _umbracoVersion = umbracoVersion; _databaseBuilder = databaseBuilder; _connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings)); + _installationService = installationService; } public InstallationType GetInstallationType() @@ -42,7 +51,7 @@ namespace Umbraco.Web.Install return _installationType ?? (_installationType = IsBrandNewInstall ? InstallationType.NewInstall : InstallationType.Upgrade).Value; } - internal void InstallStatus(bool isCompleted, string errorMsg) + internal async Task InstallStatus(bool isCompleted, string errorMsg) { try { @@ -61,8 +70,12 @@ namespace Umbraco.Web.Install if (installId == Guid.Empty) installId = Guid.NewGuid(); } + else + { + installId = Guid.NewGuid(); // Guid.TryParse will have reset installId to Guid.Empty + } } - httpContext.Response.Cookies.Set(new HttpCookie(Constants.Web.InstallerCookieName, "1")); + httpContext.Response.Cookies.Set(new HttpCookie(Constants.Web.InstallerCookieName, installId.ToString())); var dbProvider = string.Empty; if (IsBrandNewInstall == false) @@ -72,18 +85,13 @@ namespace Umbraco.Web.Install dbProvider = GetDbProviderString(Current.SqlContext); } - var check = new org.umbraco.update.CheckForUpgrade(); - check.Install(installId, - IsBrandNewInstall == false, - isCompleted, - DateTime.Now, - _umbracoVersion.Current.Major, - _umbracoVersion.Current.Minor, - _umbracoVersion.Current.Build, - _umbracoVersion.Comment, - errorMsg, - userAgent, - dbProvider); + var installLog = new InstallLog(installId: installId, isUpgrade: IsBrandNewInstall == false, + installCompleted: isCompleted, timestamp: DateTime.Now, versionMajor: _umbracoVersion.Current.Major, + versionMinor: _umbracoVersion.Current.Minor, versionPatch: _umbracoVersion.Current.Build, + versionComment: _umbracoVersion.Comment, error: errorMsg, userAgent: userAgent, + dbProvider: dbProvider); + + await _installationService.LogInstall(installLog); } catch (Exception ex) { diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index fa0fe5eda8..de01bdb2fc 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -652,6 +652,8 @@ True Reference.map + + Component @@ -674,22 +676,12 @@ - - - - - - - MSDiscoCodeGenerator - Reference.cs - Designer - Mvc\web.config @@ -698,6 +690,9 @@ Reference.map + + SettingsSingleFileGenerator + Settings.Designer.cs diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.cs b/src/Umbraco.Web/Web References/org.umbraco.update/Reference.cs deleted file mode 100644 index 230594fcbd..0000000000 --- a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.cs +++ /dev/null @@ -1,286 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -// -// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.42000. -// -#pragma warning disable 1591 - -namespace Umbraco.Web.org.umbraco.update { - using System; - using System.Web.Services; - using System.Diagnostics; - using System.Web.Services.Protocols; - using System.Xml.Serialization; - using System.ComponentModel; - - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.7.3062.0")] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Web.Services.WebServiceBindingAttribute(Name="CheckForUpgradeSoap", Namespace="http://update.umbraco.org/")] - public partial class CheckForUpgrade : System.Web.Services.Protocols.SoapHttpClientProtocol { - - private System.Threading.SendOrPostCallback InstallOperationCompleted; - - private System.Threading.SendOrPostCallback CheckUpgradeOperationCompleted; - - private bool useDefaultCredentialsSetExplicitly; - - /// - public CheckForUpgrade() { - this.Url = "http://update.umbraco.org/checkforupgrade.asmx"; - if ((this.IsLocalFileSystemWebService(this.Url) == true)) { - this.UseDefaultCredentials = true; - this.useDefaultCredentialsSetExplicitly = false; - } - else { - this.useDefaultCredentialsSetExplicitly = true; - } - } - - public new string Url { - get { - return base.Url; - } - set { - if ((((this.IsLocalFileSystemWebService(base.Url) == true) - && (this.useDefaultCredentialsSetExplicitly == false)) - && (this.IsLocalFileSystemWebService(value) == false))) { - base.UseDefaultCredentials = false; - } - base.Url = value; - } - } - - public new bool UseDefaultCredentials { - get { - return base.UseDefaultCredentials; - } - set { - base.UseDefaultCredentials = value; - this.useDefaultCredentialsSetExplicitly = true; - } - } - - /// - public event InstallCompletedEventHandler InstallCompleted; - - /// - public event CheckUpgradeCompletedEventHandler CheckUpgradeCompleted; - - /// - [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://update.umbraco.org/Install", RequestNamespace="http://update.umbraco.org/", ResponseNamespace="http://update.umbraco.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public void Install(System.Guid installId, bool isUpgrade, bool installCompleted, System.DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider) { - this.Invoke("Install", new object[] { - installId, - isUpgrade, - installCompleted, - timestamp, - versionMajor, - versionMinor, - versionPatch, - versionComment, - error, - userAgent, - dbProvider}); - } - - /// - public void InstallAsync(System.Guid installId, bool isUpgrade, bool installCompleted, System.DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider) { - this.InstallAsync(installId, isUpgrade, installCompleted, timestamp, versionMajor, versionMinor, versionPatch, versionComment, error, userAgent, dbProvider, null); - } - - /// - public void InstallAsync(System.Guid installId, bool isUpgrade, bool installCompleted, System.DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider, object userState) { - if ((this.InstallOperationCompleted == null)) { - this.InstallOperationCompleted = new System.Threading.SendOrPostCallback(this.OnInstallOperationCompleted); - } - this.InvokeAsync("Install", new object[] { - installId, - isUpgrade, - installCompleted, - timestamp, - versionMajor, - versionMinor, - versionPatch, - versionComment, - error, - userAgent, - dbProvider}, this.InstallOperationCompleted, userState); - } - - private void OnInstallOperationCompleted(object arg) { - if ((this.InstallCompleted != null)) { - System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); - this.InstallCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); - } - } - - /// - [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://update.umbraco.org/CheckUpgrade", RequestNamespace="http://update.umbraco.org/", ResponseNamespace="http://update.umbraco.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] - public UpgradeResult CheckUpgrade(int versionMajor, int versionMinor, int versionPatch, string versionComment) { - object[] results = this.Invoke("CheckUpgrade", new object[] { - versionMajor, - versionMinor, - versionPatch, - versionComment}); - return ((UpgradeResult)(results[0])); - } - - /// - public void CheckUpgradeAsync(int versionMajor, int versionMinor, int versionPatch, string versionComment) { - this.CheckUpgradeAsync(versionMajor, versionMinor, versionPatch, versionComment, null); - } - - /// - public void CheckUpgradeAsync(int versionMajor, int versionMinor, int versionPatch, string versionComment, object userState) { - if ((this.CheckUpgradeOperationCompleted == null)) { - this.CheckUpgradeOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCheckUpgradeOperationCompleted); - } - this.InvokeAsync("CheckUpgrade", new object[] { - versionMajor, - versionMinor, - versionPatch, - versionComment}, this.CheckUpgradeOperationCompleted, userState); - } - - private void OnCheckUpgradeOperationCompleted(object arg) { - if ((this.CheckUpgradeCompleted != null)) { - System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); - this.CheckUpgradeCompleted(this, new CheckUpgradeCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); - } - } - - /// - public new void CancelAsync(object userState) { - base.CancelAsync(userState); - } - - private bool IsLocalFileSystemWebService(string url) { - if (((url == null) - || (url == string.Empty))) { - return false; - } - System.Uri wsUri = new System.Uri(url); - if (((wsUri.Port >= 1024) - && (string.Compare(wsUri.Host, "localHost", System.StringComparison.OrdinalIgnoreCase) == 0))) { - return true; - } - return false; - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.3062.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://update.umbraco.org/")] - public partial class UpgradeResult { - - private string commentField; - - private UpgradeType upgradeTypeField; - - private string upgradeUrlField; - - /// - public string Comment { - get { - return this.commentField; - } - set { - this.commentField = value; - } - } - - /// - public UpgradeType UpgradeType { - get { - return this.upgradeTypeField; - } - set { - this.upgradeTypeField = value; - } - } - - /// - public string UpgradeUrl { - get { - return this.upgradeUrlField; - } - set { - this.upgradeUrlField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.3062.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://update.umbraco.org/")] - public enum UpgradeType { - - /// - None, - - /// - Patch, - - /// - Minor, - - /// - Major, - - /// - Critical, - - /// - Error, - - /// - OutOfSync, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.7.3062.0")] - public delegate void InstallCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.7.3062.0")] - public delegate void CheckUpgradeCompletedEventHandler(object sender, CheckUpgradeCompletedEventArgs e); - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.7.3062.0")] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - public partial class CheckUpgradeCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { - - private object[] results; - - internal CheckUpgradeCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : - base(exception, cancelled, userState) { - this.results = results; - } - - /// - public UpgradeResult Result { - get { - this.RaiseExceptionIfNecessary(); - return ((UpgradeResult)(this.results[0])); - } - } - } -} - -#pragma warning restore 1591 \ No newline at end of file diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.map b/src/Umbraco.Web/Web References/org.umbraco.update/Reference.map deleted file mode 100644 index ded6650264..0000000000 --- a/src/Umbraco.Web/Web References/org.umbraco.update/Reference.map +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/UpgradeResult.datasource b/src/Umbraco.Web/Web References/org.umbraco.update/UpgradeResult.datasource deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/UpgradeResult1.datasource b/src/Umbraco.Web/Web References/org.umbraco.update/UpgradeResult1.datasource deleted file mode 100644 index c42c98b0b7..0000000000 --- a/src/Umbraco.Web/Web References/org.umbraco.update/UpgradeResult1.datasource +++ /dev/null @@ -1,10 +0,0 @@ - - - - umbraco.presentation.org.umbraco.update.UpgradeResult, Web References.org.umbraco.update.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null - \ No newline at end of file diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.disco b/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.disco deleted file mode 100644 index 366f4fdd6e..0000000000 --- a/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.disco +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.wsdl b/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.wsdl deleted file mode 100644 index e2aba65c7c..0000000000 --- a/src/Umbraco.Web/Web References/org.umbraco.update/checkforupgrade.wsdl +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file