From f453ee2623db8b2369df6b64808ee4ccea748ef8 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 7 Aug 2017 17:21:35 +1000 Subject: [PATCH 1/2] U4-10244 Umbraco 7.7-beta - Migration fails when upgrading users --- .../TargetVersionSevenSevenZero/AddUserGroupTables.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs index d1cf0a40d9..fe10ecd3c5 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs @@ -112,7 +112,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe { // Create user group records for all non-admin users that have specific permissions set Execute.Sql(@"INSERT INTO umbracoUserGroup(userGroupAlias, userGroupName) - SELECT userName + 'Group', 'Group for ' + userName + SELECT userLogin + 'Group', 'Group for ' + userLogin FROM umbracoUser WHERE (id IN ( SELECT " + SqlSyntax.GetQuotedColumnName("user") + @" @@ -127,7 +127,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe Execute.Sql(@"INSERT INTO umbracoUser2UserGroup (userId, userGroupId) SELECT u.id, ug.id FROM umbracoUser u - INNER JOIN umbracoUserGroup ug ON ug.userGroupAlias = userName + 'Group'"); + INNER JOIN umbracoUserGroup ug ON ug.userGroupAlias = userLogin + 'Group'"); // Create node permissions on the groups Execute.Sql(@"INSERT INTO umbracoUserGroup2NodePermission (userGroupId,nodeId,permission) From 121b184941ce81a173644a62f0ac2295f598a074 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 8 Aug 2017 11:01:45 +1000 Subject: [PATCH 2/2] U4-10244 Umbraco 7.7-beta - Migration fails when upgrading users --- .../AddUserGroupTables.cs | 93 ++++++++++++++++++- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs index fe10ecd3c5..05eef52e37 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddUserGroupTables.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Data; using System.Linq; using Umbraco.Core.Configuration; @@ -85,6 +86,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe INNER JOIN umbracoUserGroup ug ON ug.userGroupAlias = ut.userTypeAlias"); // Add the built-in administrator account to all apps + // this will lookup all of the apps that the admin currently has access to in order to assign the sections + // instead of use statically assigning since there could be extra sections we don't know about. Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId,app) SELECT ug.id, app FROM umbracoUserGroup ug @@ -93,6 +96,89 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe INNER JOIN umbracoUser2app u2a ON u2a." + SqlSyntax.GetQuotedColumnName("user") + @" = u.id WHERE u.id = 0"); + // Add the default section access to the other built-in accounts + // writer: + Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId, app) + SELECT ug.id, 'content' as app + FROM umbracoUserGroup ug + WHERE ug.userGroupAlias = 'writer'"); + // editor + Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId, app) + SELECT ug.id, 'content' as app + FROM umbracoUserGroup ug + WHERE ug.userGroupAlias = 'editor'"); + Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId, app) + SELECT ug.id, 'media' as app + FROM umbracoUserGroup ug + WHERE ug.userGroupAlias = 'editor'"); + // translator + Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId, app) + SELECT ug.id, 'translation' as app + FROM umbracoUserGroup ug + WHERE ug.userGroupAlias = 'translator'"); + + //We need to lookup all distinct combinations of section access and create a group for each distinct collection + //and assign groups accordingly. We'll perform the lookup 'now' to then create the queued SQL migrations. + var userAppsData = Context.Database.Query(@"SELECT u.id, u2a.app FROM umbracoUser u + INNER JOIN umbracoUser2app u2a ON u2a." + SqlSyntax.GetQuotedColumnName("user") + @" = u.id + ORDER BY u.id, u2a.app"); + var usersWithApps = new Dictionary>(); + foreach (var userApps in userAppsData) + { + List apps; + if (usersWithApps.TryGetValue(userApps.id, out apps) == false) + { + apps = new List {userApps.app}; + usersWithApps.Add(userApps.id, apps); + } + else + { + apps.Add(userApps.app); + } + } + //At this stage we have a dictionary of users with a collection of their apps which are sorted + //and we need to determine the unique/distinct app collections for each user to create groups with. + //We can do this by creating a hash value of all of the app values and since they are already sorted we can get a distinct + //collection by this hash. + var distinctApps = usersWithApps + .Select(x => new {appCollection = x.Value, appsHash = string.Join("", x.Value).GenerateHash()}) + .DistinctBy(x => x.appsHash) + .ToArray(); + //Now we need to create user groups for each of these distinct app collections, and then assign the corresponding users to those groups + for (var i = 0; i < distinctApps.Length; i++) + { + //create the group + var alias = "MigratedSectionAccessGroup_" + (i + 1); + Insert.IntoTable("umbracoUserGroup").Row(new + { + userGroupAlias = "MigratedSectionAccessGroup_" + (i + 1), + userGroupName = "Migrated Section Access Group " + (i + 1) + }); + //now assign the apps + var distinctApp = distinctApps[i]; + foreach (var app in distinctApp.appCollection) + { + Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId, app) + SELECT ug.id, '" + app + @"' as app + FROM umbracoUserGroup ug + WHERE ug.userGroupAlias = '" + alias + "'"); + } + //now assign the corresponding users to this group + foreach (var userWithApps in usersWithApps) + { + //check if this user's groups hash matches the current groups hash + var hash = string.Join("", userWithApps.Value).GenerateHash(); + if (hash == distinctApp.appsHash) + { + //it matches so assign the user to this group + Execute.Sql(@"INSERT INTO umbracoUser2UserGroup (userId, userGroupId) + SELECT " + userWithApps.Key + @", ug.id + FROM umbracoUserGroup ug + WHERE ug.userGroupAlias = '" + alias + "'"); + } + } + } + // Rename some groups for consistency (plural form) Execute.Sql("UPDATE umbracoUserGroup SET userGroupName = 'Writers' WHERE userGroupAlias = 'writer'"); Execute.Sql("UPDATE umbracoUserGroup SET userGroupName = 'Translators' WHERE userGroupAlias = 'translator'"); @@ -112,12 +198,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe { // Create user group records for all non-admin users that have specific permissions set Execute.Sql(@"INSERT INTO umbracoUserGroup(userGroupAlias, userGroupName) - SELECT userLogin + 'Group', 'Group for ' + userLogin + SELECT 'permissionGroupFor' + userLogin, 'Migrated Permission Group for ' + userLogin FROM umbracoUser WHERE (id IN ( - SELECT " + SqlSyntax.GetQuotedColumnName("user") + @" - FROM umbracoUser2app - ) OR id IN ( SELECT userid FROM umbracoUser2NodePermission )) @@ -127,7 +210,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe Execute.Sql(@"INSERT INTO umbracoUser2UserGroup (userId, userGroupId) SELECT u.id, ug.id FROM umbracoUser u - INNER JOIN umbracoUserGroup ug ON ug.userGroupAlias = userLogin + 'Group'"); + INNER JOIN umbracoUserGroup ug ON ug.userGroupAlias = 'permissionGroupFor' + userLogin"); // Create node permissions on the groups Execute.Sql(@"INSERT INTO umbracoUserGroup2NodePermission (userGroupId,nodeId,permission)