From 72481a220e4be6fd9b375f06f5b97130699c9fa2 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 19 Aug 2024 13:22:26 +0200 Subject: [PATCH] Fix broken Tours migration for V15 (#16912) --- .../Upgrade/V_14_0_0/MigrateTours.cs | 143 +++++++++++++++++- 1 file changed, 140 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_14_0_0/MigrateTours.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_14_0_0/MigrateTours.cs index 302d49e763..17444c33d7 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_14_0_0/MigrateTours.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_14_0_0/MigrateTours.cs @@ -105,13 +105,35 @@ internal class MigrateTours : UnscopedMigrationBase Database.Execute("PRAGMA foreign_keys=off;"); Database.Execute("BEGIN TRANSACTION;"); - List userDtos = Database.Fetch(); + List users = Database.Fetch().Select(x => new NewUserDto + { + Id = x.Id, + Key = x.Id is -1 ? Constants.Security.SuperUserKey : Guid.NewGuid(), + Disabled = x.Disabled, + NoConsole = x.NoConsole, + UserName = x.UserName, + Login = x.Login, + Password = x.Password, + PasswordConfig = x.PasswordConfig, + Email = x.Email, + UserLanguage = x.UserLanguage, + SecurityStampToken = x.SecurityStampToken, + FailedLoginAttempts = x.FailedLoginAttempts, + LastLockoutDate = x.LastLockoutDate, + LastPasswordChangeDate = x.LastPasswordChangeDate, + LastLoginDate = x.LastLoginDate, + EmailConfirmedDate = x.EmailConfirmedDate, + InvitedDate = x.InvitedDate, + CreateDate = x.CreateDate, + UpdateDate = x.UpdateDate, + Avatar = x.Avatar, + }).ToList(); Delete.Table(Constants.DatabaseSchema.Tables.User).Do(); - Create.Table().Do(); + Create.Table().Do(); // We have to insert one at a time to be able to not auto increment the id. - foreach (UserDto user in userDtos) + foreach (NewUserDto user in users) { Database.Insert(Constants.DatabaseSchema.Tables.User, "id", false, user); } @@ -242,6 +264,121 @@ internal class MigrateTours : UnscopedMigrationBase public HashSet UserStartNodeDtos { get; set; } } + [TableName(TableName)] + [PrimaryKey("id", AutoIncrement = true)] + [ExplicitColumns] + public class NewUserDto + { + public const string TableName = Constants.DatabaseSchema.Tables.User; + + public NewUserDto() + { + UserGroupDtos = new List(); + UserStartNodeDtos = new HashSet(); + } + + [Column("id")] + [PrimaryKeyColumn(Name = "PK_user")] + public int Id { get; set; } + + [Column("userDisabled")] + [Constraint(Default = "0")] + public bool Disabled { get; set; } + + [Column("key")] + [NullSetting(NullSetting = NullSettings.NotNull)] + [Constraint(Default = SystemMethods.NewGuid)] + [Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoUser_userKey")] + public Guid Key { get; set; } + + [Column("userNoConsole")] + [Constraint(Default = "0")] + public bool NoConsole { get; set; } + + [Column("userName")] + public string UserName { get; set; } = null!; + + [Column("userLogin")] + [Length(125)] + [Index(IndexTypes.NonClustered)] + public string? Login { get; set; } + + [Column("userPassword")] + [Length(500)] + public string? Password { get; set; } + + /// + /// This will represent a JSON structure of how the password has been created (i.e hash algorithm, iterations) + /// + [Column("passwordConfig")] + [NullSetting(NullSetting = NullSettings.Null)] + [Length(500)] + public string? PasswordConfig { get; set; } + + [Column("userEmail")] + public string Email { get; set; } = null!; + + [Column("userLanguage")] + [NullSetting(NullSetting = NullSettings.Null)] + [Length(10)] + public string? UserLanguage { get; set; } + + [Column("securityStampToken")] + [NullSetting(NullSetting = NullSettings.Null)] + [Length(255)] + public string? SecurityStampToken { get; set; } + + [Column("failedLoginAttempts")] + [NullSetting(NullSetting = NullSettings.Null)] + public int? FailedLoginAttempts { get; set; } + + [Column("lastLockoutDate")] + [NullSetting(NullSetting = NullSettings.Null)] + public DateTime? LastLockoutDate { get; set; } + + [Column("lastPasswordChangeDate")] + [NullSetting(NullSetting = NullSettings.Null)] + public DateTime? LastPasswordChangeDate { get; set; } + + [Column("lastLoginDate")] + [NullSetting(NullSetting = NullSettings.Null)] + public DateTime? LastLoginDate { get; set; } + + [Column("emailConfirmedDate")] + [NullSetting(NullSetting = NullSettings.Null)] + public DateTime? EmailConfirmedDate { get; set; } + + [Column("invitedDate")] + [NullSetting(NullSetting = NullSettings.Null)] + public DateTime? InvitedDate { get; set; } + + [Column("createDate")] + [NullSetting(NullSetting = NullSettings.NotNull)] + [Constraint(Default = SystemMethods.CurrentDateTime)] + public DateTime CreateDate { get; set; } = DateTime.Now; + + [Column("updateDate")] + [NullSetting(NullSetting = NullSettings.NotNull)] + [Constraint(Default = SystemMethods.CurrentDateTime)] + public DateTime UpdateDate { get; set; } = DateTime.Now; + + /// + /// Will hold the media file system relative path of the users custom avatar if they uploaded one + /// + [Column("avatar")] + [NullSetting(NullSetting = NullSettings.Null)] + [Length(500)] + public string? Avatar { get; set; } + + [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "UserId")] + public List UserGroupDtos { get; set; } + + [ResultColumn] + [Reference(ReferenceType.Many, ReferenceMemberName = "UserId")] + public HashSet UserStartNodeDtos { get; set; } + } + public class TourData() { ///