From b6268e36505ece94d2ba5f8b4d2842ce59dedaae Mon Sep 17 00:00:00 2001 From: Jan Skovgaard <1932158+BatJan@users.noreply.github.com> Date: Tue, 14 Sep 2021 07:54:46 +0200 Subject: [PATCH 1/5] Bump version to 8.17.0-rc2 --- src/SolutionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 143df3dc4617..e18eabbfc8f0 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -19,4 +19,4 @@ // these are FYI and changed automatically [assembly: AssemblyFileVersion("8.17.0")] -[assembly: AssemblyInformationalVersion("8.17.0-rc")] +[assembly: AssemblyInformationalVersion("8.17.0-rc2")] From 5c0e42e1cbf60b06214a29afb27eb35baf873b7f Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 10 Sep 2021 10:31:38 -0600 Subject: [PATCH 2/5] Allows replacing MainDom with alternate DB There are some cases where there is a complex hosting strategy and folks want a readonly database and are hosting on Azure. In that case, it is not entirely possible to have a readonly Umbraco database because SqlMainDom is required and part of that requirement is to have read/write access to the umbraco key value table. This PR allows for the default MainDom to be replaced and to allow for an SqlMainDomLock to use an alternate connection string so that a separate read/write database can be used. (cherry picked from commit 9f48a9f940b9fee7a09fe4a2f2062c33f455eeb4) --- src/Umbraco.Core/Runtime/MainDom.cs | 2 +- src/Umbraco.Core/Runtime/SqlMainDomLock.cs | 6 +++--- src/Umbraco.Web/UmbracoApplication.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs index d784560f2c04..b5404c62b2c5 100644 --- a/src/Umbraco.Core/Runtime/MainDom.cs +++ b/src/Umbraco.Core/Runtime/MainDom.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Runtime /// When an AppDomain starts, it tries to acquire the main domain status. /// When an AppDomain stops (eg the application is restarting) it should release the main domain status. /// - internal class MainDom : IMainDom, IRegisteredObject, IDisposable + public class MainDom : IMainDom, IRegisteredObject, IDisposable { #region Vars diff --git a/src/Umbraco.Core/Runtime/SqlMainDomLock.cs b/src/Umbraco.Core/Runtime/SqlMainDomLock.cs index 12359c96d102..8e38fa74c418 100644 --- a/src/Umbraco.Core/Runtime/SqlMainDomLock.cs +++ b/src/Umbraco.Core/Runtime/SqlMainDomLock.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Runtime { - internal class SqlMainDomLock : IMainDomLock + public class SqlMainDomLock : IMainDomLock { private readonly TimeSpan _lockTimeout; private string _lockId; @@ -33,14 +33,14 @@ internal class SqlMainDomLock : IMainDomLock private object _locker = new object(); private bool _hasTable = false; - public SqlMainDomLock(ILogger logger) + public SqlMainDomLock(ILogger logger, string connectionStringName = Constants.System.UmbracoConnectionName) { // unique id for our appdomain, this is more unique than the appdomain id which is just an INT counter to its safer _lockId = Guid.NewGuid().ToString(); _logger = logger; _dbFactory = new UmbracoDatabaseFactory( - Constants.System.UmbracoConnectionName, + connectionStringName, _logger, new Lazy(() => new MapperCollection(Enumerable.Empty()))); diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index c96e21e34870..563d553ac25a 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -76,7 +76,7 @@ protected virtual string GetBootErrorFileName() /// /// Returns a new MainDom /// - protected IMainDom GetMainDom(ILogger logger) + protected virtual IMainDom GetMainDom(ILogger logger) { // Determine if we should use the sql main dom or the default var appSettingMainDomLock = ConfigurationManager.AppSettings[Constants.AppSettings.MainDomLock]; From 97ecb07be768a39946c7bfc24ebaba22d2e7f5dc Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 30 Sep 2021 10:07:05 +0200 Subject: [PATCH 3/5] Fixes #11206 (#11225) --- src/Umbraco.Core/Composing/CompositionExtensions/Services.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs index d252c58730ed..d97845928dcb 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs @@ -52,6 +52,7 @@ public static Composition ComposeServices(this Composition composition) composition.RegisterUnique(); composition.RegisterUnique(); composition.RegisterUnique(); + composition.RegisterUnique(); composition.Register(SourcesFactory); composition.RegisterUnique(factory => new LocalizedTextService( factory.GetInstance>(), From 11ad3fc0827488d42ddb62ca639183cea6005054 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 30 Sep 2021 10:16:33 +0200 Subject: [PATCH 4/5] Bump version to 8.17.0 --- src/SolutionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index e18eabbfc8f0..cc6296de4a37 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -19,4 +19,4 @@ // these are FYI and changed automatically [assembly: AssemblyFileVersion("8.17.0")] -[assembly: AssemblyInformationalVersion("8.17.0-rc2")] +[assembly: AssemblyInformationalVersion("8.17.0")] From 213d8c00aa6655b2b5c1514c337221898b3c2ed9 Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Mon, 4 Oct 2021 09:45:33 +0200 Subject: [PATCH 5/5] Remove inherited property group id/key when local properties are added (#11231) * Remove inherited property group id/key when local properties are added * Rebind saved content type values * Remove inherited from save group (cherry picked from commit 20b9db87d091e7d53f9f25d4d11744afcffa2584) --- .../services/contenttypehelper.service.js | 39 +++++++++++++++++ .../services/umbdataformatter.service.js | 40 +++++++++-------- .../views/documenttypes/edit.controller.js | 32 ++------------ .../src/views/mediatypes/edit.controller.js | 35 ++------------- .../src/views/membertypes/edit.controller.js | 43 +++---------------- 5 files changed, 73 insertions(+), 116 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js index d9157093a7b9..cceb67689fed 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js @@ -439,6 +439,45 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje array.push(placeholder); + }, + + rebindSavedContentType: function (contentType, savedContentType) { + // The saved content type might have updated values (eg. new IDs/keys), so make sure the view model is updated + contentType.ModelState = savedContentType.ModelState; + contentType.id = savedContentType.id; + contentType.groups.forEach(function (group) { + if (!group.alias) return; + + var k = 0; + while (k < savedContentType.groups.length && savedContentType.groups[k].alias != group.alias) + k++; + + if (k == savedContentType.groups.length) { + group.id = 0; + return; + } + + var savedGroup = savedContentType.groups[k]; + group.id = savedGroup.id; + group.key = savedGroup.key; + group.contentTypeId = savedGroup.contentTypeId; + + group.properties.forEach(function (property) { + if (property.id || !property.alias) return; + + k = 0; + while (k < savedGroup.properties.length && savedGroup.properties[k].alias != property.alias) + k++; + + if (k == savedGroup.properties.length) { + property.id = 0; + return; + } + + var savedProperty = savedGroup.properties[k]; + property.id = savedProperty.id; + }); + }); } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js index 226fabeae41d..7270ae5bbf06 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js @@ -37,7 +37,7 @@ return { - formatChangePasswordModel: function(model) { + formatChangePasswordModel: function (model) { if (!model) { return null; } @@ -59,26 +59,23 @@ }, formatContentTypePostData: function (displayModel, action) { - - //create the save model from the display model + // Create the save model from the display model var saveModel = _.pick(displayModel, 'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes', 'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed', 'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'allowSegmentVariant', 'isElement'); - // TODO: Map these saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; }); saveModel.defaultTemplate = displayModel.defaultTemplate ? displayModel.defaultTemplate.alias : null; var realGroups = _.reject(displayModel.groups, function (g) { - //do not include these tabs + // Do not include groups with init state return g.tabState === "init"; }); saveModel.groups = _.map(realGroups, function (g) { - - var saveGroup = _.pick(g, 'inherited', 'id', 'sortOrder', 'name', 'key', 'alias', 'type'); + var saveGroup = _.pick(g, 'id', 'sortOrder', 'name', 'key', 'alias', 'type'); var realProperties = _.reject(g.properties, function (p) { - //do not include these properties + // Do not include properties with init state or inherited from a composition return p.propertyState === "init" || p.inherited === true; }); @@ -89,16 +86,21 @@ saveGroup.properties = saveProperties; - //if this is an inherited group and there are not non-inherited properties on it, then don't send up the data - if (saveGroup.inherited === true && saveProperties.length === 0) { - return null; + if (g.inherited === true) { + if (saveProperties.length === 0) { + // All properties are inherited from the compositions, no need to save this group + return null; + } else if (g.contentTypeId != saveModel.id) { + // We have local properties, but the group id is not local, ensure a new id/key is generated on save + saveGroup = _.omit(saveGroup, 'id', 'key'); + } } return saveGroup; }); - //we don't want any null groups saveModel.groups = _.reject(saveModel.groups, function (g) { + // Do not include empty/null groups return !g; }); @@ -127,17 +129,17 @@ }, /** formats the display model used to display the dictionary to the model used to save the dictionary */ - formatDictionaryPostData : function(dictionary, nameIsDirty) { + formatDictionaryPostData: function (dictionary, nameIsDirty) { var saveModel = { parentId: dictionary.parentId, id: dictionary.id, name: dictionary.name, nameIsDirty: nameIsDirty, translations: [], - key : dictionary.key + key: dictionary.key }; - for(var i = 0; i < dictionary.translations.length; i++) { + for (var i = 0; i < dictionary.translations.length; i++) { saveModel.translations.push({ isoCode: dictionary.translations[i].isoCode, languageId: dictionary.translations[i].languageId, @@ -362,7 +364,7 @@ parentId: displayModel.parentId, //set the action on the save model action: action, - variants: _.map(displayModel.variants, function(v) { + variants: _.map(displayModel.variants, function (v) { return { name: v.name || "", //if its null/empty,we must pass up an empty string else we get json converter errors properties: getContentProperties(v.tabs), @@ -392,7 +394,7 @@ * @param {} displayModel * @returns {} */ - formatContentGetData: function(displayModel) { + formatContentGetData: function (displayModel) { // We need to check for invariant properties among the variant variants, // as the value of an invariant property is shared between different variants. @@ -458,12 +460,12 @@ * Formats the display model used to display the relation type to a model used to save the relation type. * @param {Object} relationType */ - formatRelationTypePostData : function(relationType) { + formatRelationTypePostData: function (relationType) { var saveModel = { id: relationType.id, name: relationType.name, alias: relationType.alias, - key : relationType.key, + key: relationType.key, isBidirectional: relationType.isBidirectional, parentObjectType: relationType.parentObjectType, childObjectType: relationType.childObjectType diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 3672af900c4d..a5e49163f9e5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -324,35 +324,9 @@ scope: $scope, content: vm.contentType, infiniteMode: infiniteMode, - // we need to rebind... the IDs that have been created! - rebindCallback: function (origContentType, savedContentType) { - vm.contentType.ModelState = savedContentType.ModelState; - vm.contentType.id = savedContentType.id; - vm.contentType.groups.forEach(function (group) { - if (!group.name) return; - var k = 0; - while (k < savedContentType.groups.length && savedContentType.groups[k].name != group.name) - k++; - if (k == savedContentType.groups.length) { - group.id = 0; - return; - } - var savedGroup = savedContentType.groups[k]; - if (!group.id) group.id = savedGroup.id; - - group.properties.forEach(function (property) { - if (property.id || !property.alias) return; - k = 0; - while (k < savedGroup.properties.length && savedGroup.properties[k].alias != property.alias) - k++; - if (k == savedGroup.properties.length) { - property.id = 0; - return; - } - var savedProperty = savedGroup.properties[k]; - property.id = savedProperty.id; - }); - }); + rebindCallback: function (_, savedContentType) { + // we need to rebind... the IDs that have been created! + contentTypeHelper.rebindSavedContentType(vm.contentType, savedContentType); } }).then(function (data) { // allow UI to access server validation state diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js index ecf2aec30c0b..32fac36baaee 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js @@ -295,38 +295,9 @@ saveMethod: mediaTypeResource.save, scope: $scope, content: vm.contentType, - // we need to rebind... the IDs that have been created! - rebindCallback: function (origContentType, savedContentType) { - vm.contentType.id = savedContentType.id; - vm.contentType.groups.forEach(function (group) { - if (!group.name) return; - - var k = 0; - while (k < savedContentType.groups.length && savedContentType.groups[k].name != group.name) - k++; - if (k == savedContentType.groups.length) { - group.id = 0; - return; - } - - var savedGroup = savedContentType.groups[k]; - if (!group.id) group.id = savedGroup.id; - - group.properties.forEach(function (property) { - if (property.id || !property.alias) return; - - k = 0; - while (k < savedGroup.properties.length && savedGroup.properties[k].alias != property.alias) - k++; - if (k == savedGroup.properties.length) { - property.id = 0; - return; - } - - var savedProperty = savedGroup.properties[k]; - property.id = savedProperty.id; - }); - }); + rebindCallback: function (_, savedContentType) { + // we need to rebind... the IDs that have been created! + contentTypeHelper.rebindSavedContentType(vm.contentType, savedContentType); } }).then(function (data) { //success diff --git a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js index 53bb4adb9b99..2eddc71924be 100644 --- a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js @@ -175,11 +175,11 @@ //we are creating so get an empty data type item memberTypeResource.getScaffold(memberTypeId) - .then(function (dt) { - init(dt); + .then(function (dt) { + init(dt); - vm.page.loading = false; - }); + vm.page.loading = false; + }); } else { loadMemberType(); @@ -215,38 +215,9 @@ saveMethod: memberTypeResource.save, scope: $scope, content: vm.contentType, - // we need to rebind... the IDs that have been created! - rebindCallback: function (origContentType, savedContentType) { - vm.contentType.id = savedContentType.id; - vm.contentType.groups.forEach(function (group) { - if (!group.name) return; - - var k = 0; - while (k < savedContentType.groups.length && savedContentType.groups[k].name != group.name) - k++; - if (k == savedContentType.groups.length) { - group.id = 0; - return; - } - - var savedGroup = savedContentType.groups[k]; - if (!group.id) group.id = savedGroup.id; - - group.properties.forEach(function (property) { - if (property.id || !property.alias) return; - - k = 0; - while (k < savedGroup.properties.length && savedGroup.properties[k].alias != property.alias) - k++; - if (k == savedGroup.properties.length) { - property.id = 0; - return; - } - - var savedProperty = savedGroup.properties[k]; - property.id = savedProperty.id; - }); - }); + rebindCallback: function (_, savedContentType) { + // we need to rebind... the IDs that have been created! + contentTypeHelper.rebindSavedContentType(vm.contentType, savedContentType); } }).then(function (data) { //success