Port 7.7 - WIP

This commit is contained in:
Stephan
2017-09-08 12:35:34 +02:00
parent 4dedd52e37
commit 00d2ea928d
36 changed files with 1048 additions and 1275 deletions

View File

@@ -2,6 +2,7 @@
using Umbraco.Core.Persistence.Migrations.Syntax.Create;
using Umbraco.Core.Persistence.Migrations.Syntax.Delete;
using Umbraco.Core.Persistence.Migrations.Syntax.Execute;
using Umbraco.Core.Persistence.Migrations.Syntax.Update;
namespace Umbraco.Core.Persistence.Migrations
{
@@ -9,6 +10,7 @@ namespace Umbraco.Core.Persistence.Migrations
{
IExecuteBuilder Execute { get; }
IDeleteBuilder Delete { get; }
IUpdateBuilder Update { get; }
IAlterSyntaxBuilder Alter { get; }
ICreateBuilder Create { get; }
string GetSql();

View File

@@ -49,14 +49,19 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
CreateUmbracoUserData();
}
if (tableName.Equals("umbracoUserType"))
if (tableName.Equals("umbracoUserGroup"))
{
CreateUmbracoUserTypeData();
CreateUmbracoUserGroupData();
}
if (tableName.Equals("umbracoUser2app"))
if (tableName.Equals("umbracoUser2UserGroup"))
{
CreateUmbracoUser2AppData();
CreateUmbracoUser2UserGroupData();
}
if (tableName.Equals("umbracoUserGroup2App"))
{
CreateUmbracoUserGroup2AppData();
}
if (tableName.Equals("cmsPropertyTypeGroup"))
@@ -172,27 +177,34 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
private void CreateUmbracoUserData()
{
_database.Insert("umbracoUser", "id", false, new UserDto { Id = 0, Disabled = false, NoConsole = false, Type = 1, ContentStartId = -1, MediaStartId = -1, UserName = "Administrator", Login = "admin", Password = "default", Email = "", UserLanguage = "en" });
//_database.Update<UserDto>("SET id = @IdAfter WHERE id = @IdBefore AND userLogin = @Login", new { IdAfter = 0, IdBefore = 1, Login = "admin" });
_database.Insert("umbracoUser", "id", false, new UserDto { Id = 0, Disabled = false, NoConsole = false, UserName = "Administrator", Login = "admin", Password = "default", Email = "", UserLanguage = "en", CreateDate = DateTime.Now, UpdateDate = DateTime.Now });
}
private void CreateUmbracoUserTypeData()
private void CreateUmbracoUserGroupData()
{
_database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 1, Alias = "admin", Name = "Administrators", DefaultPermissions = "CADMOSKTPIURZ:5F7" });
_database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 2, Alias = "writer", Name = "Writer", DefaultPermissions = "CAH:F" });
_database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 3, Alias = "editor", Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5F" });
_database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 4, Alias = "translator", Name = "Translator", DefaultPermissions = "AF" });
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 1, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.AdminGroupAlias, Name = "Administrators", DefaultPermissions = "CADMOSKTPIURZ:5F7ï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-medal" });
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 2, StartMediaId = -1, StartContentId = -1, Alias = "writer", Name = "Writers", DefaultPermissions = "CAH:F", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-edit" });
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 3, StartMediaId = -1, StartContentId = -1, Alias = "editor", Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5Fï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-tools" });
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 4, StartMediaId = -1, StartContentId = -1, Alias = "translator", Name = "Translators", DefaultPermissions = "AF", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-globe" });
}
private void CreateUmbracoUser2AppData()
private void CreateUmbracoUser2UserGroupData()
{
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Content });
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Developer });
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Media });
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Members });
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Settings });
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Users });
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Forms });
_database.Insert(new User2UserGroupDto { UserGroupId = 1, UserId = 0 });
}
private void CreateUmbracoUserGroup2AppData()
{
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Content });
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Media });
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Settings });
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Developer });
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Users });
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Members });
_database.Insert(new UserGroup2AppDto { UserGroupId = 2, AppAlias = Constants.Applications.Content });
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Content });
_database.Insert(new UserGroup2AppDto { UserGroupId = 3, AppAlias = Constants.Applications.Media });
_database.Insert(new UserGroup2AppDto { UserGroupId = 4, AppAlias = Constants.Applications.Translation });
_database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Translation });
}

View File

@@ -71,15 +71,15 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{29, typeof (TagRelationshipDto)},
//removed: {30...
{31, typeof (UserTypeDto)},
//removed in 7.6: {31, typeof (UserTypeDto)},
{32, typeof (UserDto)},
{33, typeof (TaskTypeDto)},
{34, typeof (TaskDto)},
{35, typeof (ContentType2ContentTypeDto)},
{36, typeof (ContentTypeAllowedContentTypeDto)},
{37, typeof (User2AppDto)},
//removed in 7.6: {37, typeof (User2AppDto)},
{38, typeof (User2NodeNotifyDto)},
{39, typeof (User2NodePermissionDto)},
//removed in 7.6: {39, typeof (User2NodePermissionDto)},
{40, typeof (ServerRegistrationDto)},
{41, typeof (AccessDto)},
@@ -92,7 +92,12 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{48, typeof (RedirectUrlDto) },
{49, typeof (LockDto) },
{50, typeof (ContentNuDto) }
{50, typeof (UserGroupDto) },
{51, typeof (User2UserGroupDto) },
{52, typeof (UserGroup2NodePermissionDto) },
{53, typeof (UserGroup2AppDto) },
{54, typeof (UserStartNodeDto) },
{55, typeof (ContentNuDto) }
};
#endregion

View File

@@ -150,6 +150,12 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
return new Version(7, 5, 0);
}
//if the error is for umbracoUserGroup it must be the previous version to 7.7 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoUserStartNode"))))
{
return new Version(7, 6, 0);
}
return UmbracoVersion.Current;
}

View File

@@ -5,6 +5,7 @@ using Umbraco.Core.Persistence.Migrations.Syntax.Alter;
using Umbraco.Core.Persistence.Migrations.Syntax.Create;
using Umbraco.Core.Persistence.Migrations.Syntax.Delete;
using Umbraco.Core.Persistence.Migrations.Syntax.Execute;
using Umbraco.Core.Persistence.Migrations.Syntax.Update;
namespace Umbraco.Core.Persistence.Migrations
{
@@ -18,6 +19,8 @@ namespace Umbraco.Core.Persistence.Migrations
public IDeleteBuilder Delete => new DeleteBuilder(this);
public IUpdateBuilder Update => new UpdateBuilder(this);
public IAlterSyntaxBuilder Alter => new AlterSyntaxBuilder(this);
public ICreateBuilder Create => new CreateBuilder(this);

View File

@@ -1,55 +0,0 @@
using System.Data;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero
{
[MigrationAttribute("4.9.0", 0, Constants.System.UmbracoMigrationName)]
public class RemoveUmbracoAppConstraints : MigrationBase
{
public RemoveUmbracoAppConstraints(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
//This will work on mysql and should work on mssql however the old keys were not named consistently with how the keys are
// structured now. So we need to do a check and manually remove them based on their old aliases.
if (DatabaseType.IsMySql())
{
Delete.ForeignKey().FromTable("umbracoUser2app").ForeignColumn("app").ToTable("umbracoApp").PrimaryColumn("appAlias");
Delete.ForeignKey().FromTable("umbracoAppTree").ForeignColumn("appAlias").ToTable("umbracoApp").PrimaryColumn("appAlias");
}
else
{
//These are the old aliases, before removing them, check they exist
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoApp")))
{
Delete.ForeignKey("FK_umbracoUser2app_umbracoApp").OnTable("umbracoUser2app");
//name this migration, this is a hack for DeleteAppTables to ensure it's not executed twice
((MigrationExpressionBase)Context.Expressions.Last()).Name = "FK_umbracoUser2app_umbracoApp";
}
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoUser")))
{
Delete.ForeignKey("FK_umbracoUser2app_umbracoUser").OnTable("umbracoUser2app");
}
}
}
public override void Down()
{
Create.ForeignKey("FK_umbracoUser2app_umbracoApp").FromTable("umbracoUser2app").ForeignColumn("app")
.ToTable("umbracoApp").PrimaryColumn("appAlias").OnDeleteOrUpdate(Rule.None);
Create.ForeignKey("FK_umbracoAppTree_umbracoApp").FromTable("umbracoAppTree").ForeignColumn("appAlias")
.ToTable("umbracoApp").PrimaryColumn("appAlias").OnDeleteOrUpdate(Rule.None);
}
}
}

View File

@@ -1,31 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourOneZero
{
[Migration("4.1.0", 0, Constants.System.UmbracoMigrationName)]
public class AddPreviewXmlTable : MigrationBase
{
public AddPreviewXmlTable(IMigrationContext context)
: base(context)
{
}
public override void Up()
{
var tableName = "cmsPreviewXml";
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains(tableName)) return;
Create.Table(tableName)
.WithColumn("nodeId").AsInt32().NotNullable()
.WithColumn("versionId").AsGuid().NotNullable()
.WithColumn("timestamp").AsDateTime().NotNullable()
.WithColumn("xml").AsString();
}
public override void Down()
{ }
}
}

View File

@@ -1,6 +1,7 @@
using System;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
@@ -14,7 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Up()
{
var exists = Context.Database.FirstOrDefault<RelationTypeDto>("WHERE alias=@alias", new {alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias});
var exists = Context.Database.FirstOrDefault<RelationTypeDtoCapture>("WHERE alias=@alias", new {alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias});
if (exists == null)
{
Insert.IntoTable("umbracoRelationType").Row(new
@@ -26,13 +27,42 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias
});
}
}
public override void Down()
{ }
// need to capture the DTO as it is modified in later migrations
[TableName("umbracoRelationType")]
[PrimaryKey("id")]
[ExplicitColumns]
internal class RelationTypeDtoCapture
{
public const int NodeIdSeed = 3;
[Column("id")]
[PrimaryKeyColumn(IdentitySeed = NodeIdSeed)]
public int Id { get; set; }
[Column("dual")]
public bool Dual { get; set; }
[Column("parentObjectType")]
public Guid ParentObjectType { get; set; }
[Column("childObjectType")]
public Guid ChildObjectType { get; set; }
[Column("name")]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRelationType_name")]
public string Name { get; set; }
[Column("alias")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(100)]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRelationType_alias")]
public string Alias { get; set; }
}
}
}

View File

@@ -1,5 +1,4 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -14,12 +13,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
: base(context)
{ }
public override void Up()
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
var indexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
@@ -28,24 +24,19 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
IsUnique = x.Item4
}).ToArray();
//must be non-nullable
// drop the index if it exists
if (indexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")))
Delete.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode");
// set uniqueID to be non-nullable
// the index *must* be dropped else 'one or more objects access this column' exception
Alter.Table("umbracoNode").AlterColumn("uniqueID").AsGuid().NotNullable();
//make sure it already exists
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")))
{
Delete.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode");
}
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNode_uniqueID")) == false)
{
//must be a uniqe index
Create.Index("IX_umbracoNode_uniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Unique();
}
// create the index
Create.Index("IX_umbracoNode_uniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Unique();
}
public override void Down()
{
}
{ }
}
}

View File

@@ -1,55 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 10, Constants.System.UmbracoMigrationName)]
public class DeleteAppTables : MigrationBase
{
public DeleteAppTables(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Delete.Table("umbracoAppTree");
//NOTE: this is a hack since old umbraco versions might not have had their db's upgraded correctly so they are all quite inconsistent.
// This is actually done in migration: RemoveUmbracoAppConstraints to target 4.9.0 but we've found with some db's that are currently at 4.9.1,
// these upgrades did not run. So, now we not only have to check if these constraints exist, but we also have to check if the RemoveUmbracoAppConstraints
// has executed since we cannot drop the same foreign key twice or we'll get errors.
//Here we'll do a dirty check to see if RemoveUmbracoAppConstraints has executed
if (Context.Expressions.Any(x =>
{
var b = x as MigrationExpressionBase;
if (b == null) return false;
return b.Name == "FK_umbracoUser2app_umbracoApp";
}) == false)
{
//These are the old aliases, before removing them, check they exist
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoApp")))
{
Delete.ForeignKey("FK_umbracoUser2app_umbracoApp").OnTable("umbracoUser2app");
}
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("FK_umbracoUser2app_umbracoUser")))
{
Delete.ForeignKey("FK_umbracoUser2app_umbracoUser").OnTable("umbracoUser2app");
}
}
Delete.Table("umbracoApp");
}
public override void Down()
{
//This cannot be rolled back!!
throw new DataLossException("Cannot rollback migration " + typeof(DeleteAppTables) + " the db tables umbracoAppTree and umbracoApp have been droppped");
}
}
}

View File

@@ -1,32 +0,0 @@
using System;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 9, Constants.System.UmbracoMigrationName)]
public class EnsureAppsTreesUpdated : MigrationBase
{
public EnsureAppsTreesUpdated(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
var e = new UpgradingEventArgs();
if (Upgrading != null)
Upgrading(this, e);
}
public override void Down()
{
}
public static event EventHandler<UpgradingEventArgs> Upgrading;
public class UpgradingEventArgs : EventArgs { }
}
}

View File

@@ -1,36 +0,0 @@
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 5, Constants.System.UmbracoMigrationName)]
public class MoveMasterContentTypeData : MigrationBase
{
public MoveMasterContentTypeData(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
//Reading entries from the cmsContentType table in order to update the parentID on the umbracoNode table.
//NOTE This is primarily done because of a shortcoming in sql ce, which has really bad support for updates (can't use FROM or subqueries with multiple results).
if (base.Context != null && base.Context.Database != null)
{
var list = base.Context.Database.Fetch<dynamic>("SELECT nodeId, masterContentType FROM cmsContentType WHERE not masterContentType is null AND masterContentType != 0");
foreach (var item in list)
{
Update.Table("umbracoNode").Set(new { parentID = item.masterContentType }).Where(new { id = item.nodeId });
}
}
Execute.Sql(
"INSERT INTO cmsContentType2ContentType (parentContentTypeId, childContentTypeId) SELECT masterContentType, nodeId FROM cmsContentType WHERE not masterContentType is null and masterContentType != 0");
}
public override void Down()
{
}
}
}

View File

@@ -1,33 +0,0 @@
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 4, Constants.System.UmbracoMigrationName)]
public class NewCmsContentType2ContentTypeTable : MigrationBase
{
public NewCmsContentType2ContentTypeTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Create.Table("cmsContentType2ContentType")
.WithColumn("parentContentTypeId").AsInt16().NotNullable()
.WithColumn("childContentTypeId").AsInt16().NotNullable();
Create.PrimaryKey("PK_cmsContentType2ContentType")
.OnTable("cmsContentType2ContentType")
.Columns(new[] { "parentContentTypeId", "childContentTypeId" });
}
public override void Down()
{
Delete.PrimaryKey("PK_cmsContentType2ContentType").FromTable("cmsContentType2ContentType");
Delete.Table("cmsContentType2ContentType");
}
}
}

View File

@@ -1,31 +0,0 @@
using NPoco;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 6, Constants.System.UmbracoMigrationName)]
public class RemoveMasterContentTypeColumn : MigrationBase
{
public RemoveMasterContentTypeColumn(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
//NOTE Don't think we can remove this column yet as it seems to be used by some starterkits
IfDatabase(DatabaseType.SQLCe, DatabaseType.SqlServer2008)
.Delete.DefaultConstraint().OnTable("cmsContentType").OnColumn("masterContentType");
Delete.Column("masterContentType").FromTable("cmsContentType");
}
public override void Down()
{
Create.UniqueConstraint("DF_cmsContentType_masterContentType").OnTable("cmsContentType").Column("masterContentType");
Create.Column("masterContentType").OnTable("cmsContentType").AsInt16().Nullable().WithDefaultValue(0);
}
}
}

View File

@@ -1,25 +0,0 @@
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 0, Constants.System.UmbracoMigrationName)]
public class RenameCmsTabTable : MigrationBase
{
public RenameCmsTabTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Rename.Table("cmsTab").To("cmsPropertyTypeGroup");
}
public override void Down()
{
Rename.Table("cmsPropertyTypeGroup").To("cmsTab");
}
}
}

View File

@@ -1,82 +0,0 @@
using System.Data;
using NPoco;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 7, Constants.System.UmbracoMigrationName)]
public class RenameTabIdColumn : MigrationBase
{
public RenameTabIdColumn(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
//Conditional Create-column for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Create.Column("propertyTypeGroupId").OnTable("cmsPropertyType").AsInt16().Nullable();
//Conditional Create-foreign for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Create.ForeignKey("FK_cmsPropertyType_cmsPropertyTypeGroup")
.FromTable("cmsPropertyType").ForeignColumn("propertyTypeGroupId")
.ToTable("cmsPropertyTypeGroup").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
//Conditional Delete-foreignkey for MySql databases
IfDatabase(DatabaseType.MySQL)
.Delete.ForeignKey().FromTable("cmsPropertyType").ForeignColumn("tabId").ToTable("cmsPropertyTypeGroup").PrimaryColumn("id");
Rename.Column("tabId").OnTable("cmsPropertyType").To("propertyTypeGroupId");
//Conditional Create-foreign for MySql databases
IfDatabase(DatabaseType.MySQL)
.Create.ForeignKey("FK_cmsPropertyType_cmsPropertyTypeGroup")
.FromTable("cmsPropertyType").ForeignColumn("propertyTypeGroupId")
.ToTable("cmsPropertyTypeGroup").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
//Conditional Delete-foreignkey for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Delete.ForeignKey("FK_cmsPropertyType_cmsTab").OnTable("cmsPropertyType");
//Conditional Delete-column for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Delete.Column("tabId").FromTable("cmsPropertyType");
}
public override void Down()
{
//Conditional Create-column for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Create.Column("tabId").OnTable("cmsPropertyType").AsInt16().Nullable();
//Conditional Create-foreign for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Create.ForeignKey("FK_cmsPropertyType_cmsTab")
.FromTable("cmsPropertyType").ForeignColumn("tabId")
.ToTable("cmsTab").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
//Conditional Delete-foreignkey for MySql databases
IfDatabase(DatabaseType.MySQL)
.Delete.ForeignKey().FromTable("cmsPropertyType").ForeignColumn("propertyTypeGroupId").ToTable("cmsPropertyTypeGroup").PrimaryColumn("id");
Rename.Column("propertyTypeGroupId").OnTable("cmsPropertyType").To("tabId");
//Conditional Create-foreign for MySql databases
IfDatabase(DatabaseType.MySQL)
.Create.ForeignKey("FK_cmsPropertyType_cmsPropertyTypeGroup")
.FromTable("cmsPropertyType").ForeignColumn("tabId")
.ToTable("cmsPropertyTypeGroup").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
//Conditional Delete-foreignkey for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Delete.ForeignKey("FK_cmsPropertyType_cmsPropertyTypeGroup").OnTable("cmsPropertyType");
//Conditional Delete-column for Sql Ce databases
IfDatabase(DatabaseType.SQLCe)
.Delete.Column("propertyTypeGroupId").FromTable("propertyTypeGroupId");
}
}
}

View File

@@ -1,25 +0,0 @@
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 3, Constants.System.UmbracoMigrationName)]
public class UpdateCmsContentTypeAllowedContentTypeTable : MigrationBase
{
public UpdateCmsContentTypeAllowedContentTypeTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Alter.Table("cmsContentTypeAllowedContentType").AddColumn("sortOrder").AsInt16().NotNullable().WithDefaultValue(1);
}
public override void Down()
{
Delete.Column("sortOrder").FromTable("cmsContentTypeAllowedContentType");
}
}
}

View File

@@ -1,31 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 2, Constants.System.UmbracoMigrationName)]
public class UpdateCmsContentTypeTable : MigrationBase
{
public UpdateCmsContentTypeTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Alter.Table("cmsContentType").AddColumn("isContainer").AsBoolean().NotNullable().WithDefaultValue(0);
Alter.Table("cmsContentType").AddColumn("allowAtRoot").AsBoolean().NotNullable().WithDefaultValue(0);
}
public override void Down()
{
Delete.Column("allowAtRoot").FromTable("cmsContentType");
Delete.Column("isContainer").FromTable("cmsContentType");
}
}
}

View File

@@ -1,25 +0,0 @@
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 8, Constants.System.UmbracoMigrationName)]
public class UpdateCmsContentVersionTable : MigrationBase
{
public UpdateCmsContentVersionTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Alter.Table("cmsContentVersion").AddColumn("LanguageLocale").AsString(10).Nullable();
}
public override void Down()
{
Delete.Column("LanguageLocale").FromTable("cmsContentVersion");
}
}
}

View File

@@ -1,32 +0,0 @@
using System.Data;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSix
{
[Migration("6.0.0", 1, Constants.System.UmbracoMigrationName)]
public class UpdateCmsPropertyTypeGroupTable : MigrationBase
{
public UpdateCmsPropertyTypeGroupTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Alter.Table("cmsPropertyTypeGroup").AddColumn("parentGroupId").AsInt16().Nullable();
Create.ForeignKey("FK_cmsPropertyTypeGroup_cmsPropertyTypeGroup_id")
.FromTable("cmsPropertyTypeGroup").ForeignColumn("parentGroupId")
.ToTable("cmsPropertyTypeGroup").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None);
}
public override void Down()
{
Delete.ForeignKey().FromTable("cmsPropertyTypeGroup").ForeignColumn("parentGroupId").ToTable("cmsPropertyTypeGroup").PrimaryColumn("id");
Delete.Column("parentGroupId").FromTable("cmsPropertyTypeGroup");
}
}
}

View File

@@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixOneZero
{
[Migration("6.1.0", 0, Constants.System.UmbracoMigrationName)]
public class CreateServerRegistryTable : MigrationBase
{
public CreateServerRegistryTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
var schemaHelper = new DatabaseSchemaHelper(Context.Database, Logger);
//NOTE: This isn't the correct way to do this but to manually create this table with the Create syntax is a pain in the arse
schemaHelper.CreateTable<ServerRegistrationDto>();
}
public override void Down()
{
Delete.Table("umbracoServer");
}
}
}

View File

@@ -1,61 +0,0 @@
using System.Linq;
using NPoco;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
[Migration("7.1.0", 3, Constants.System.UmbracoMigrationName)]
[Migration("6.2.0", 3, Constants.System.UmbracoMigrationName)]
public class AddChangeDocumentTypePermission : MigrationBase
{
public AddChangeDocumentTypePermission(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Execute.Code(AddChangeDocumentTypePermissionDo);
}
public override void Down()
{
Execute.Code(UndoChangeDocumentTypePermissionDo);
}
private static string AddChangeDocumentTypePermissionDo(IDatabase database)
{
var adminUserType = database.Fetch<UserTypeDto>("WHERE Id = 1").FirstOrDefault();
if (adminUserType != null)
{
if (adminUserType.DefaultPermissions.Contains("7") == false)
{
adminUserType.DefaultPermissions = adminUserType.DefaultPermissions + "7";
database.Save<UserTypeDto>(adminUserType);
}
}
return string.Empty;
}
private static string UndoChangeDocumentTypePermissionDo(IDatabase database)
{
var adminUserType = database.Fetch<UserTypeDto>("WHERE Id = 1").FirstOrDefault();
if (adminUserType != null)
{
if (adminUserType.DefaultPermissions.Contains("7"))
{
adminUserType.DefaultPermissions = adminUserType.DefaultPermissions.Replace("7", "");
database.Save<UserTypeDto>(adminUserType);
}
}
return string.Empty;
}
}
}

View File

@@ -1,113 +0,0 @@
using System;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Migrations.Initial;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
[Migration("7.1.0", 1, Constants.System.UmbracoMigrationName)]
[Migration("6.2.0", 1, Constants.System.UmbracoMigrationName)]
public class AdditionalIndexesAndKeys : MigrationBase
{
public AdditionalIndexesAndKeys(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
//do not create any indexes if they already exist in the database
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeTrashed")) == false)
{
Create.Index("IX_umbracoNodeTrashed").OnTable("umbracoNode").OnColumn("trashed").Ascending().WithOptions().NonClustered();
}
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContentVersion_ContentId")) == false)
{
Create.Index("IX_cmsContentVersion_ContentId").OnTable("cmsContentVersion").OnColumn("ContentId").Ascending().WithOptions().NonClustered();
}
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDocument_published")) == false)
{
Create.Index("IX_cmsDocument_published").OnTable("cmsDocument").OnColumn("published").Ascending().WithOptions().NonClustered();
}
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDocument_newest")) == false)
{
Create.Index("IX_cmsDocument_newest").OnTable("cmsDocument").OnColumn("newest").Ascending().WithOptions().NonClustered();
}
// drop the umbracoUserLogins_Index index since it is named incorrectly
// and then re-create it so it follows the standard naming convention
var sqlServerSyntax = SqlSyntax as SqlServerSyntaxProvider;
if (sqlServerSyntax != null // if running sql server
&& sqlServerSyntax.ServerVersion.IsAzure // on Azure
&& sqlServerSyntax.ServerVersion.ProductVersion.StartsWith("11.")) // version 11.x
{
// SQL Azure v2 does not support dropping clustered indexes on a table
// see http://issues.umbraco.org/issue/U4-5673
// and so we have to use a special method to do some manual work
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("umbracoUserLogins_Index")))
{
//It's the old version that doesn't support dropping a clustered index on a table, so we need to do some manual work.
ExecuteSqlAzureSqlForChangingIndex();
}
}
else
{
// any other db can delete and recreate
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("umbracoUserLogins_Index")))
{
Delete.Index("umbracoUserLogins_Index").OnTable("umbracoUserLogins");
}
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoUserLogins_Index")) == false)
{
Create.Index("IX_umbracoUserLogins_Index").OnTable("umbracoUserLogins").OnColumn("contextID").Ascending().WithOptions().Clustered();
}
}
}
public override void Down()
{
Delete.Index("IX_umbracoNodeTrashed").OnTable("umbracoNode");
Delete.Index("IX_cmsContentVersion_ContentId").OnTable("cmsContentVersion");
Delete.Index("IX_cmsDocument_published").OnTable("cmsDocument");
Delete.Index("IX_cmsDocument_newest").OnTable("cmsDocument");
}
private void ExecuteSqlAzureSqlForChangingIndex()
{
Context.Database.Execute(@"CREATE TABLE ""umbracoUserLogins_temp""
(
contextID uniqueidentifier NOT NULL,
userID int NOT NULL,
[timeout] bigint NOT NULL
);
CREATE CLUSTERED INDEX ""IX_umbracoUserLogins_Index"" ON ""umbracoUserLogins_temp"" (""contextID"");
INSERT INTO ""umbracoUserLogins_temp"" SELECT * FROM ""umbracoUserLogins""
DROP TABLE ""umbracoUserLogins""
CREATE TABLE ""umbracoUserLogins""
(
contextID uniqueidentifier NOT NULL,
userID int NOT NULL,
[timeout] bigint NOT NULL
);
CREATE CLUSTERED INDEX ""IX_umbracoUserLogins_Index"" ON ""umbracoUserLogins"" (""contextID"");
INSERT INTO ""umbracoUserLogins"" SELECT * FROM ""umbracoUserLogins_temp""
DROP TABLE ""umbracoUserLogins_temp""");
}
}
}

View File

@@ -1,89 +0,0 @@
using System.Linq;
using System.Web.UI;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
//see: http://issues.umbraco.org/issue/U4-4430
[Migration("7.1.0", 0, Constants.System.UmbracoMigrationName)]
[Migration("6.2.0", 0, Constants.System.UmbracoMigrationName)]
public class AssignMissingPrimaryForMySqlKeys : MigrationBase
{
public AssignMissingPrimaryForMySqlKeys(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
if (DatabaseType.IsMySql())
{
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
//This should be 2 because this table has 2 keys
if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentTypeAllowedContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_cmsContentTypeAllowedContentType")
.OnTable("cmsContentTypeAllowedContentType")
.Columns(new[] { "Id", "AllowedId" });
}
//This should be 2 because this table has 2 keys
if (constraints.Count(x => x.Item1.InvariantEquals("cmsDocumentType") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_cmsDocumentType")
.OnTable("cmsDocumentType")
.Columns(new[] { "contentTypeNodeId", "templateNodeId" });
}
//This should be 2 because this table has 2 keys
if (constraints.Count(x => x.Item1.InvariantEquals("cmsMember2MemberGroup") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_cmsMember2MemberGroup")
.OnTable("cmsMember2MemberGroup")
.Columns(new[] { "Member", "MemberGroup" });
}
//This should be 2 because this table has 2 keys
if (constraints.Count(x => x.Item1.InvariantEquals("cmsPreviewXml") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_cmsContentPreviewXml")
.OnTable("cmsPreviewXml")
.Columns(new[] { "nodeId", "versionId" });
}
//This should be 2 because this table has 2 keys
if (constraints.Count(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_user2app")
.OnTable("umbracoUser2app")
.Columns(new[] { "user", "app" });
}
//This should be 2 because this table has 3 keys
if (constraints.Count(x => x.Item1.InvariantEquals("umbracoUser2NodeNotify") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_umbracoUser2NodeNotify")
.OnTable("umbracoUser2NodeNotify")
.Columns(new[] { "userId", "nodeId", "action" });
}
//This should be 2 because this table has 3 keys
if (constraints.Count(x => x.Item1.InvariantEquals("umbracoUser2NodePermission") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_umbracoUser2NodePermission")
.OnTable("umbracoUser2NodePermission")
.Columns(new[] { "userId", "nodeId", "permission" });
}
}
}
public override void Down()
{
//don't do anything, these keys should have always existed!
}
}
}

View File

@@ -1,40 +0,0 @@
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
//We have to target this specifically to ensure this DOES NOT execute if upgrading from a version previous to 6.0,
// this is because when the 6.0.0 migrations are executed, this primary key get's created so if this migration is also executed
// we will get exceptions because it is trying to create the PK two times.
[Migration("6.0.0", "6.2.0", 0, Constants.System.UmbracoMigrationName)]
public class AssignMissingPrimaryForMySqlKeys2 : MigrationBase
{
public AssignMissingPrimaryForMySqlKeys2(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
if (DatabaseType.IsMySql())
{
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
//This should be 2 because this table has 2 keys
if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentType2ContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0)
{
Create.PrimaryKey("PK_cmsContentType2ContentType")
.OnTable("cmsContentType2ContentType")
.Columns(new[] { "parentContentTypeId", "childContentTypeId" });
}
}
}
public override void Down()
{
//don't do anything, these keys should have always existed!
}
}
}

View File

@@ -1,29 +0,0 @@
using System;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
[Migration("7.1.0", 2, Constants.System.UmbracoMigrationName)]
[Migration("6.2.0", 2, Constants.System.UmbracoMigrationName)]
public class ChangePasswordColumn : MigrationBase
{
public ChangePasswordColumn(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
//up to 500 chars
Alter.Table("umbracoUser").AlterColumn("userPassword").AsString(500).NotNullable();
}
public override void Down()
{
//back to 125 chars
Alter.Table("umbracoUser").AlterColumn("userPassword").AsString(125).NotNullable();
}
}
}

View File

@@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using NPoco;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
[Migration("7.1.0", 4, Constants.System.UmbracoMigrationName)]
[Migration("6.2.0", 4, Constants.System.UmbracoMigrationName)]
public class UpdateToNewMemberPropertyAliases : MigrationBase
{
public UpdateToNewMemberPropertyAliases(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Execute.Code(Update);
}
internal string Update(IDatabase database)
{
if (database != null)
{
var aliasMap = new Dictionary<string, string>
{
{"umbracoPasswordRetrievalQuestionPropertyTypeAlias", Constants.Conventions.Member.PasswordQuestion},
{"umbracoPasswordRetrievalAnswerPropertyTypeAlias", Constants.Conventions.Member.PasswordAnswer},
{"umbracoCommentPropertyTypeAlias", Constants.Conventions.Member.Comments},
{"umbracoApprovePropertyTypeAlias", Constants.Conventions.Member.IsApproved},
{"umbracoLockPropertyTypeAlias", Constants.Conventions.Member.IsLockedOut},
{"umbracoLastLoginPropertyTypeAlias", Constants.Conventions.Member.LastLoginDate},
{"umbracoMemberLastPasswordChange", Constants.Conventions.Member.LastPasswordChangeDate},
{"umbracoMemberLastLockout", Constants.Conventions.Member.LastLockoutDate},
{"umbracoFailedPasswordAttemptsPropertyTypeAlias", Constants.Conventions.Member.FailedPasswordAttempts}
};
//This query is structured to work with MySql, SQLCE and SqlServer:
// http://issues.umbraco.org/issue/U4-3876
const string propertyTypeUpdateSql = @"UPDATE cmsPropertyType
SET Alias = @newAlias
WHERE Alias = @oldAlias AND contentTypeId IN (
SELECT nodeId FROM (SELECT DISTINCT cmsContentType.nodeId FROM cmsPropertyType
INNER JOIN cmsContentType ON cmsPropertyType.contentTypeId = cmsContentType.nodeId
INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id
WHERE umbracoNode.nodeObjectType = @objectType) x)";
const string xmlSelectSql = @"SELECT cmsContentXml.* FROM cmsContentXml
INNER JOIN umbracoNode ON cmsContentXml.nodeId = umbracoNode.id
WHERE umbracoNode.nodeObjectType = @objectType";
using (var trans = database.GetTransaction())
{
try
{
//Upate all of the property type aliases
foreach (var map in aliasMap)
{
database.Execute(propertyTypeUpdateSql, new { newAlias = map.Value, oldAlias = map.Key, objectType = Constants.ObjectTypes.MemberType });
}
//Update all of the XML
var items = database.Fetch<ContentXmlDto>(xmlSelectSql, new { objectType = Constants.ObjectTypes.Member });
foreach (var item in items)
{
foreach (var map in aliasMap)
{
item.Xml = item.Xml.Replace("<" + map.Key + ">", "<" + map.Value + ">");
item.Xml = item.Xml.Replace("</" + map.Key + ">", "</" + map.Value + ">");
}
database.Update(item);
}
trans.Complete();
}
catch (Exception ex)
{
Logger.Error<UpdateToNewMemberPropertyAliases>("Exception was thrown when trying to upgrade old member aliases to the new ones", ex);
throw;
}
}
}
return string.Empty;
}
public override void Down()
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,97 +0,0 @@
using System;
using System.Linq;
using NPoco;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne
{
[Migration("6.0.2", 0, Constants.System.UmbracoMigrationName)]
public class UpdatePropertyTypesAndGroups : MigrationBase
{
public UpdatePropertyTypesAndGroups(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Execute.Code(UpdatePropertyTypesAndGroupsDo);
}
public override void Down()
{
}
public static string UpdatePropertyTypesAndGroupsDo(IDatabase database)
{
if (database != null)
{
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
//NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns
// won't exist yet
var propertyTypes = database.Fetch<dynamic>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
// need to use dynamic, as PropertyTypeGroupDto has new properties
var propertyGroups = database.Fetch<dynamic>("SELECT * FROM cmsPropertyTypeGroup WHERE id > 0");
foreach (var propertyType in propertyTypes)
{
// get the PropertyTypeGroup of the current PropertyType, skip if not found
var propertyTypeGroup = propertyGroups.FirstOrDefault(x => x.id == propertyType.propertyTypeGroupId);
if (propertyTypeGroup == null) continue;
// if the PropretyTypeGroup belongs to the same content type as the PropertyType, then fine
if (propertyTypeGroup.contenttypeNodeId == propertyType.contentTypeId) continue;
// else we want to assign the PropertyType to a proper PropertyTypeGroup
// ie one that does belong to the same content - look for it
var okPropertyTypeGroup = propertyGroups.FirstOrDefault(x =>
x.text == propertyTypeGroup.text && // same name
x.contenttypeNodeId == propertyType.contentTypeId); // but for proper content type
if (okPropertyTypeGroup == null)
{
// does not exist, create a new PropertyTypeGroup
// cannot use a PropertyTypeGroupDto because of the new (not-yet-existing) uniqueID property
// cannot use a dynamic because database.Insert fails to set the value of property
var propertyGroup = new PropertyTypeGroupDtoTemp
{
id = 0,
contenttypeNodeId = propertyType.contentTypeId,
text = propertyTypeGroup.text,
sortorder = propertyTypeGroup.sortorder
};
// save + add to list of groups
int id = Convert.ToInt16(database.Insert("cmsPropertyTypeGroup", "id", propertyGroup));
propertyGroup.id = id;
propertyGroups.Add(propertyGroup);
// update the PropertyType to use the new PropertyTypeGroup
propertyType.propertyTypeGroupId = id;
}
else
{
// exists, update PropertyType to use the PropertyTypeGroup
propertyType.propertyTypeGroupId = okPropertyTypeGroup.id;
}
database.Update("cmsPropertyType", "id", propertyType);
}
}
return string.Empty;
}
private class PropertyTypeGroupDtoTemp
{
public int id { get; set; }
public int contenttypeNodeId { get; set; }
public string text { get; set; }
public int sortorder { get; set; }
}
}
}

View File

@@ -0,0 +1,53 @@
using System.Linq;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.Temp8
{
[Migration("7.7.0", 5, Constants.System.UmbracoMigrationName)]
public class AddIndexToDictionaryKeyColumn : MigrationBase
{
public AddIndexToDictionaryKeyColumn(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Execute.Code(database =>
{
//Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long
var colLen = (SqlSyntax is MySqlSyntaxProvider)
? database.ExecuteScalar<int?>(string.Format("select max(LENGTH({0})) from cmsDictionary", SqlSyntax.GetQuotedColumnName("key")))
: database.ExecuteScalar<int?>(string.Format("select max(datalength({0})) from cmsDictionary", SqlSyntax.GetQuotedColumnName("key")));
if (colLen < 900 == false && colLen != null)
{
return null;
}
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDictionary_key")) == false)
{
var local = Context.GetLocalMigration();
//we can apply the index
local.Create.Index("IX_cmsDictionary_key").OnTable("cmsDictionary")
.OnColumn("key")
.Ascending()
.WithOptions()
.NonClustered();
return local.GetSql();
}
return null;
});
}
public override void Down()
{
Delete.Index("IX_cmsDictionary_key").OnTable("cmsDictionary");
}
}
}

View File

@@ -0,0 +1,174 @@
using System;
using System.Linq;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.Temp8
{
[Migration("8.0.0", 1, Constants.System.UmbracoMigrationName)]
public class AddUserGroupTables : MigrationBase
{
public AddUserGroupTables(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
var constraints = SqlSyntax.GetConstraintsPerColumn(Context.Database).Distinct().ToArray();
if (AddNewTables(tables))
{
MigrateUserPermissions();
MigrateUserTypesToGroups();
DeleteOldTables(tables, constraints);
SetDefaultIcons();
}
}
private void SetDefaultIcons()
{
Execute.Sql($"UPDATE umbracoUserGroup SET icon = \'\' WHERE userGroupAlias = \'{Constants.Security.AdminGroupAlias}\'");
Execute.Sql("UPDATE umbracoUserGroup SET icon = \'icon-edit\' WHERE userGroupAlias = \'writer\'");
Execute.Sql("UPDATE umbracoUserGroup SET icon = \'icon-tools\' WHERE userGroupAlias = \'editor\'");
Execute.Sql("UPDATE umbracoUserGroup SET icon = \'icon-globe\' WHERE userGroupAlias = \'translator\'");
}
private bool AddNewTables(string[] tables)
{
var updated = false;
if (tables.InvariantContains("umbracoUserGroup") == false)
{
Create.Table<UserGroupDto>();
updated = true;
}
if (tables.InvariantContains("umbracoUser2UserGroup") == false)
{
Create.Table<User2UserGroupDto>();
updated = true;
}
if (tables.InvariantContains("umbracoUserGroup2App") == false)
{
Create.Table<UserGroup2AppDto>();
updated = true;
}
if (tables.InvariantContains("umbracoUserGroup2NodePermission") == false)
{
Create.Table<UserGroup2NodePermissionDto>();
updated = true;
}
return updated;
}
private void MigrateUserTypesToGroups()
{
// Create a user group for each user type
Execute.Sql(@"INSERT INTO umbracoUserGroup (userGroupAlias, userGroupName, userGroupDefaultPermissions)
SELECT userTypeAlias, userTypeName, userTypeDefaultPermissions
FROM umbracoUserType");
// Add each user to the group created from their type
Execute.Sql(@"INSERT INTO umbracoUser2UserGroup (userId, userGroupId)
SELECT u.id, ug.id
FROM umbracoUser u
INNER JOIN umbracoUserType ut ON ut.id = u.userType
INNER JOIN umbracoUserGroup ug ON ug.userGroupAlias = ut.userTypeAlias");
// Add the built-in administrator account to all apps
Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId,app)
SELECT ug.id, app
FROM umbracoUserGroup ug
INNER JOIN umbracoUser2UserGroup u2ug ON u2ug.userGroupId = ug.id
INNER JOIN umbracoUser u ON u.id = u2ug.userId
INNER JOIN umbracoUser2app u2a ON u2a." + SqlSyntax.GetQuotedColumnName("user") + @" = u.id
WHERE u.id = 0");
// 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'");
//Ensure all built in groups have a start node of -1
Execute.Sql("UPDATE umbracoUserGroup SET startContentId = -1 WHERE userGroupAlias = 'editor'");
Execute.Sql("UPDATE umbracoUserGroup SET startMediaId = -1 WHERE userGroupAlias = 'editor'");
Execute.Sql("UPDATE umbracoUserGroup SET startContentId = -1 WHERE userGroupAlias = 'writer'");
Execute.Sql("UPDATE umbracoUserGroup SET startMediaId = -1 WHERE userGroupAlias = 'writer'");
Execute.Sql("UPDATE umbracoUserGroup SET startContentId = -1 WHERE userGroupAlias = 'translator'");
Execute.Sql("UPDATE umbracoUserGroup SET startMediaId = -1 WHERE userGroupAlias = 'translator'");
Execute.Sql("UPDATE umbracoUserGroup SET startContentId = -1 WHERE userGroupAlias = 'admin'");
Execute.Sql("UPDATE umbracoUserGroup SET startMediaId = -1 WHERE userGroupAlias = 'admin'");
}
private void MigrateUserPermissions()
{
// 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
FROM umbracoUser
WHERE (id IN (
SELECT " + SqlSyntax.GetQuotedColumnName("user") + @"
FROM umbracoUser2app
) OR id IN (
SELECT userid
FROM umbracoUser2NodePermission
))
AND id > 0");
// Associate those groups with the users
Execute.Sql(@"INSERT INTO umbracoUser2UserGroup (userId, userGroupId)
SELECT u.id, ug.id
FROM umbracoUser u
INNER JOIN umbracoUserGroup ug ON ug.userGroupAlias = userName + 'Group'");
// Create node permissions on the groups
Execute.Sql(@"INSERT INTO umbracoUserGroup2NodePermission (userGroupId,nodeId,permission)
SELECT ug.id, nodeId, permission
FROM umbracoUserGroup ug
INNER JOIN umbracoUser2UserGroup u2ug ON u2ug.userGroupId = ug.id
INNER JOIN umbracoUser u ON u.id = u2ug.userId
INNER JOIN umbracoUser2NodePermission u2np ON u2np.userId = u.id
WHERE ug.userGroupAlias NOT IN (
SELECT userTypeAlias
FROM umbracoUserType
)");
// Create app permissions on the groups
Execute.Sql(@"INSERT INTO umbracoUserGroup2app (userGroupId,app)
SELECT ug.id, app
FROM umbracoUserGroup ug
INNER JOIN umbracoUser2UserGroup u2ug ON u2ug.userGroupId = ug.id
INNER JOIN umbracoUser u ON u.id = u2ug.userId
INNER JOIN umbracoUser2app u2a ON u2a." + SqlSyntax.GetQuotedColumnName("user") + @" = u.id
WHERE ug.userGroupAlias NOT IN (
SELECT userTypeAlias
FROM umbracoUserType
)");
}
private void DeleteOldTables(string[] tables, Tuple<string, string, string>[] constraints)
{
if (tables.InvariantContains("umbracoUser2App"))
{
Delete.Table("umbracoUser2App");
}
if (tables.InvariantContains("umbracoUser2NodePermission"))
{
Delete.Table("umbracoUser2NodePermission");
}
if (tables.InvariantContains("umbracoUserType") && tables.InvariantContains("umbracoUser"))
{
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_umbracoUser_umbracoUserType_id")))
{
Delete.ForeignKey("FK_umbracoUser_umbracoUserType_id").OnTable("umbracoUser");
}
Delete.Column("userType").FromTable("umbracoUser");
Delete.Table("umbracoUserType");
}
}
}
}

View File

@@ -0,0 +1,42 @@
using System.Linq;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.Temp8
{
[Migration("8.0.0", 2, Constants.System.UmbracoMigrationName)]
public class AddUserStartNodeTable : MigrationBase
{
public AddUserStartNodeTable(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains("umbracoUserStartNode")) return;
Create.Table<UserStartNodeDto>();
MigrateUserStartNodes();
//now remove the old columns
Delete.Column("startStructureID").FromTable("umbracoUser");
Delete.Column("startMediaID").FromTable("umbracoUser");
}
private void MigrateUserStartNodes()
{
Execute.Sql(@"INSERT INTO umbracoUserStartNode (userId, startNode, startNodeType)
SELECT id, startStructureID, 1
FROM umbracoUser
WHERE startStructureID IS NOT NULL AND startStructureID > 0 AND startStructureID IN (SELECT id FROM umbracoNode WHERE nodeObjectType='" + Constants.ObjectTypes.Document + "')");
Execute.Sql(@"INSERT INTO umbracoUserStartNode (userId, startNode, startNodeType)
SELECT id, startMediaID, 2
FROM umbracoUser
WHERE startMediaID IS NOT NULL AND startMediaID > 0 AND startMediaID IN (SELECT id FROM umbracoNode WHERE nodeObjectType='" + Constants.ObjectTypes.Media + "')");
}
}
}

View File

@@ -0,0 +1,42 @@
using System.Linq;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.Temp8
{
/// <summary>
/// Ensures the built-in user groups have the blueprint permission by default on upgrade
/// </summary>
[Migration("8.0.0", 6, Constants.System.UmbracoMigrationName)]
public class EnsureContentTemplatePermissions : MigrationBase
{
public EnsureContentTemplatePermissions(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
Execute.Code(database =>
{
var userGroups = database.Fetch<UserGroupDto>(
Context.Sql().Select("*")
.From<UserGroupDto>()
.Where<UserGroupDto>(x => x.Alias == "admin" || x.Alias == "editor"));
var local = Context.GetLocalMigration();
foreach (var userGroup in userGroups)
{
if (userGroup.DefaultPermissions.Contains('ï') == false)
{
userGroup.DefaultPermissions += "ï";
local.Update.Table("umbracoUserGroup")
.Set(new { userGroupDefaultPermissions = userGroup.DefaultPermissions })
.Where(new { id = userGroup.Id });
}
}
return local.GetSql();
});
}
}
}

View File

@@ -0,0 +1,45 @@
using System.Linq;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.Temp8
{
[Migration("8.0.0", 4, Constants.System.UmbracoMigrationName)]
public class ReduceDictionaryKeyColumnsSize : MigrationBase
{
public ReduceDictionaryKeyColumnsSize(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
//Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long
Execute.Code(database =>
{
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database);
var colLen = SqlSyntax is MySqlSyntaxProvider
? database.ExecuteScalar<int?>(string.Format("select max(LENGTH({0})) from cmsDictionary", SqlSyntax.GetQuotedColumnName("key")))
: database.ExecuteScalar<int?>(string.Format("select max(datalength({0})) from cmsDictionary", SqlSyntax.GetQuotedColumnName("key")));
if (colLen < 900 == false) return null;
var local = Context.GetLocalMigration();
//if it exists we need to drop it first
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDictionary_key")))
{
local.Delete.Index("IX_cmsDictionary_key").OnTable("cmsDictionary");
}
//we can apply the col length change
local.Alter.Table("cmsDictionary")
.AlterColumn("key")
.AsString(450)
.NotNullable();
return local.GetSql();
});
}
}
}

View File

@@ -0,0 +1,46 @@
using System.Linq;
using System.Web.Security;
using Newtonsoft.Json;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Security;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.Temp8
{
[Migration("8.0.0", 0, Constants.System.UmbracoMigrationName)]
public class UpdateUserTables : MigrationBase
{
public UpdateUserTables(IMigrationContext context)
: base(context)
{ }
public override void Up()
{
//Don't exeucte if the column is already there
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("createDate")) == false)
Create.Column("createDate").OnTable("umbracoUser").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentDateTime);
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("updateDate")) == false)
Create.Column("updateDate").OnTable("umbracoUser").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentDateTime);
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("emailConfirmedDate")) == false)
Create.Column("emailConfirmedDate").OnTable("umbracoUser").AsDateTime().Nullable();
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("invitedDate")) == false)
Create.Column("invitedDate").OnTable("umbracoUser").AsDateTime().Nullable();
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("passwordConfig")) == false)
{
Create.Column("passwordConfig").OnTable("umbracoUser").AsString(500).Nullable();
//Check if we have a known config, we only want to store config for hashing
var membershipProvider = MembershipProviderExtensions.GetUsersMembershipProvider();
if (membershipProvider.PasswordFormat == MembershipPasswordFormat.Hashed)
{
var json = JsonConvert.SerializeObject(new { hashAlgorithm = Membership.HashAlgorithmType });
Execute.Sql("UPDATE umbracoUser SET passwordConfig = '" + json + "'");
}
}
}
}
}

View File

@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web.Security;
using Newtonsoft.Json;
using NPoco;
using Umbraco.Core;
using Umbraco.Core.Cache;
@@ -12,7 +15,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Querying;
@@ -20,6 +23,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Security;
#error the entire clads needs to be refactored for proper NPoco usage
namespace Umbraco.Core.Persistence.Repositories
{
/// <summary>
@@ -27,20 +31,26 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal class UserRepository : NPocoRepositoryBase<int, IUser>, IUserRepository
{
private readonly IUserTypeRepository _userTypeRepository;
private readonly CacheHelper _cacheHelper;
private readonly IMapperCollection _mapperCollection;
private readonly IDictionary<string, string> _passwordConfig;
private PermissionRepository<IContent> _permissionRepository;
public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IUserTypeRepository userTypeRepository, IMapperCollection mapperCollection, IDictionary<string, string> passwordConfig = null)
/// <summary>
/// Constructor
/// </summary>
/// <param name="work"></param>
/// <param name="cacheHelper"></param>
/// <param name="logger"></param>
/// <param name="passwordConfig">
/// A dictionary specifying the configuration for user passwords. If this is null then no password configuration will be persisted or read.
/// </param>
#error password config, change: null will ???
public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IMapperCollection mapperCollection, IDictionary<string, string> passwordConfig = null)
: base(work, cacheHelper, logger)
{
_userTypeRepository = userTypeRepository;
_mapperCollection = mapperCollection;
_cacheHelper = cacheHelper;
if (passwordConfig == null)
if (passwordConfig == null) // fixme this is bad bc we may want it to remain null?!
{
var userMembershipProvider = MembershipProviderExtensions.GetUsersMembershipProvider();
passwordConfig = userMembershipProvider == null || userMembershipProvider.PasswordFormat != MembershipPasswordFormat.Hashed
@@ -58,49 +68,193 @@ namespace Umbraco.Core.Persistence.Repositories
protected override IUser PerformGet(int id)
{
var sql = GetBaseQuery(false);
var sql = GetQueryWithGroups();
sql.Where(GetBaseWhereClause(), new { Id = id });
sql //must be included for relator to work
.OrderBy<UserDto>(d => d.Id, SqlSyntax)
.OrderBy<UserGroupDto>(d => d.Id, SqlSyntax)
.OrderBy<UserStartNodeDto>(d => d.Id, SqlSyntax);
var dto = Database
.FetchOneToMany<UserDto>(x => x.User2AppDtos, sql)
var dto = Database.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(new UserGroupRelator().Map, sql)
.FirstOrDefault();
if (dto == null)
return null;
var userType = _userTypeRepository.Get(dto.Type);
var userFactory = new UserFactory(userType);
var user = userFactory.BuildEntity(dto);
var user = UserFactory.BuildEntity(dto);
return user;
}
/// <summary>
/// Returns a user by username
/// </summary>
/// <param name="username"></param>
/// <param name="includeSecurityData">
/// Can be used for slightly faster user lookups if the result doesn't require security data (i.e. groups, apps & start nodes).
/// This is really only used for a shim in order to upgrade to 7.6.
/// </param>
/// <returns>
/// A non cached <see cref="IUser"/> instance
/// </returns>
public IUser GetByUsername(string username, bool includeSecurityData)
{
UserDto dto;
if (includeSecurityData)
{
var sql = GetQueryWithGroups();
sql.Where<UserDto>(userDto => userDto.Login == username, SqlSyntax);
sql //must be included for relator to work
.OrderBy<UserDto>(d => d.Id, SqlSyntax)
.OrderBy<UserGroupDto>(d => d.Id, SqlSyntax)
.OrderBy<UserStartNodeDto>(d => d.Id, SqlSyntax);
dto = Database
.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(
new UserGroupRelator().Map, sql)
.FirstOrDefault();
}
else
{
var sql = GetBaseQuery("umbracoUser.*");
sql.Where<UserDto>(userDto => userDto.Login == username, SqlSyntax);
dto = Database.FirstOrDefault<UserDto>(sql);
}
if (dto == null)
return null;
var user = UserFactory.BuildEntity(dto);
return user;
}
/// <summary>
/// Returns a user by id
/// </summary>
/// <param name="id"></param>
/// <param name="includeSecurityData">
/// This is really only used for a shim in order to upgrade to 7.6 but could be used
/// for slightly faster user lookups if the result doesn't require security data (i.e. groups, apps & start nodes)
/// </param>
/// <returns>
/// A non cached <see cref="IUser"/> instance
/// </returns>
public IUser Get(int id, bool includeSecurityData)
{
UserDto dto;
if (includeSecurityData)
{
var sql = GetQueryWithGroups();
sql.Where(GetBaseWhereClause(), new { Id = id });
sql //must be included for relator to work
.OrderBy<UserDto>(d => d.Id, SqlSyntax)
.OrderBy<UserGroupDto>(d => d.Id, SqlSyntax)
.OrderBy<UserStartNodeDto>(d => d.Id, SqlSyntax);
dto = Database
.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(
new UserGroupRelator().Map, sql)
.FirstOrDefault();
}
else
{
var sql = GetBaseQuery("umbracoUser.*");
sql.Where(GetBaseWhereClause(), new { Id = id });
dto = Database.FirstOrDefault<UserDto>(sql);
}
if (dto == null)
return null;
var user = UserFactory.BuildEntity(dto);
return user;
}
public IProfile GetProfile(string username)
{
var sql = GetBaseQuery(false).Where<UserDto>(userDto => userDto.UserName == username, SqlSyntax);
var dto = Database.Fetch<UserDto>(sql)
.FirstOrDefault();
if (dto == null)
return null;
return new UserProfile(dto.Id, dto.UserName);
}
public IProfile GetProfile(int id)
{
var sql = GetBaseQuery(false).Where<UserDto>(userDto => userDto.Id == id, SqlSyntax);
var dto = Database.Fetch<UserDto>(sql)
.FirstOrDefault();
if (dto == null)
return null;
return new UserProfile(dto.Id, dto.UserName);
}
public IDictionary<UserState, int> GetUserStates()
{
var sql = @"SELECT '1CountOfAll' AS colName, COUNT(id) AS num FROM umbracoUser
UNION
SELECT '2CountOfActive' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL
UNION
SELECT '3CountOfDisabled' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 1
UNION
SELECT '4CountOfLockedOut' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userNoConsole = 1
UNION
SELECT '5CountOfInvited' AS colName, COUNT(id) AS num FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL
ORDER BY colName";
var result = Database.Fetch<dynamic>(sql);
return new Dictionary<UserState, int>
{
{UserState.All, result[0].num},
{UserState.Active, result[1].num},
{UserState.Disabled, result[2].num},
{UserState.LockedOut, result[3].num},
{UserState.Invited, result[4].num}
};
}
protected override IEnumerable<IUser> PerformGetAll(params int[] ids)
{
var sql = GetBaseQuery(false);
var sql = GetQueryWithGroups();
if (ids.Any())
{
sql.Where("umbracoUser.id in (@ids)", new {ids = ids});
sql.Where("umbracoUser.id in (@ids)", new { ids = ids });
}
#error refactor with FetchOneToMany
sql //must be included for relator to work
.OrderBy<UserDto>(d => d.Id, SqlSyntax)
.OrderBy<UserGroupDto>(d => d.Id, SqlSyntax)
.OrderBy<UserStartNodeDto>(d => d.Id, SqlSyntax);
var dtos = Database
.FetchOneToMany<UserDto>(x => x.User2AppDtos, sql);
var users = ConvertFromDtos(Database.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(new UserGroupRelator().Map, sql))
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
return ConvertFromDtos(dtos).ToArray(); // do it now and do it once, else can end up with nulls in cache
return users;
}
protected override IEnumerable<IUser> PerformGetByQuery(IQuery<IUser> query)
{
var sqlClause = GetBaseQuery(false);
var sqlClause = GetQueryWithGroups();
var translator = new SqlTranslator<IUser>(sqlClause, query);
var sql = translator.Translate();
#error obviously refactor with FetchOneToMany!
sql //must be included for relator to work
.OrderBy<UserDto>(d => d.Id, SqlSyntax)
.OrderBy<UserGroupDto>(d => d.Id, SqlSyntax)
.OrderBy<UserStartNodeDto>(d => d.Id, SqlSyntax);
var dtos = Database
.FetchOneToMany<UserDto>(x => x.User2AppDtos, sql)
var dtos = Database.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(new UserGroupRelator().Map, sql)
.DistinctBy(x => x.Id);
return ConvertFromDtos(dtos).ToArray(); // do it now and do it once, else can end up with nulls in cache
var users = ConvertFromDtos(dtos)
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
return users;
}
#endregion
@@ -119,16 +273,39 @@ namespace Umbraco.Core.Persistence.Repositories
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
}
#error prob needs to be refactored entirely
/// <summary>
/// A query to return a user with it's groups and with it's groups sections
/// </summary>
/// <returns></returns>
private Sql GetQueryWithGroups()
{
//base query includes user groups
var sql = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
AddGroupLeftJoin(sql);
return sql;
}
private static void AddGroupLeftJoin(Sql<SqlContext> sql)
{
sql
.LeftJoin<User2UserGroupDto>()
.On<User2UserGroupDto, UserDto>(left => left.UserId, right => right.Id)
.LeftJoin<UserGroupDto>()
.On<UserGroupDto, User2UserGroupDto>(left => left.Id, right => right.UserGroupId)
.LeftJoin<UserGroup2AppDto>()
.On<UserGroup2AppDto, UserGroupDto>(left => left.UserGroupId, right => right.Id)
.LeftJoin<UserStartNodeDto>()
.On<UserStartNodeDto, UserDto>(left => left.UserId, right => right.Id);
}
private Sql<SqlContext> GetBaseQuery(string columns)
{
return Sql()
.Select(columns)
.From<UserDto>()
.LeftJoin<User2AppDto>()
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
.From<UserDto>();
}
protected override string GetBaseWhereClause()
{
return "umbracoUser.id = @Id";
@@ -137,43 +314,66 @@ namespace Umbraco.Core.Persistence.Repositories
protected override IEnumerable<string> GetDeleteClauses()
{
var list = new List<string>
{
"DELETE FROM cmsTask WHERE userId = @Id",
"DELETE FROM cmsTask WHERE parentUserId = @Id",
"DELETE FROM umbracoUser2NodePermission WHERE userId = @Id",
"DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id",
"DELETE FROM umbracoUser2app WHERE " + SqlSyntax.GetQuotedColumnName("user") + "=@Id",
"DELETE FROM umbracoUser WHERE id = @Id",
"DELETE FROM umbracoExternalLogin WHERE id = @Id"
};
{
"DELETE FROM cmsTask WHERE userId = @Id",
"DELETE FROM cmsTask WHERE parentUserId = @Id",
"DELETE FROM umbracoUser2UserGroup WHERE userId = @Id",
"DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id",
"DELETE FROM umbracoUser WHERE id = @Id",
"DELETE FROM umbracoExternalLogin WHERE id = @Id"
};
return list;
}
protected override Guid NodeObjectTypeId
{
get { throw new NotImplementedException(); }
}
protected override Guid NodeObjectTypeId => throw new NotImplementedException();
protected override void PersistNewItem(IUser entity)
{
var userFactory = new UserFactory(entity.UserType);
((User) entity).AddingEntity();
//ensure security stamp if non
// ensure security stamp if missing
if (entity.SecurityStamp.IsNullOrWhiteSpace())
{
entity.SecurityStamp = Guid.NewGuid().ToString();
}
var userDto = userFactory.BuildDto(entity);
var userDto = UserFactory.BuildDto(entity);
// check if we have a known config, we only want to store config for hashing
//TODO: This logic will need to be updated when we do http://issues.umbraco.org/issue/U4-10089
if (_passwordConfig != null && _passwordConfig.Count > 0)
{
var json = JsonConvert.SerializeObject(_passwordConfig);
userDto.PasswordConfig = json;
}
var id = Convert.ToInt32(Database.Insert(userDto));
entity.Id = id;
foreach (var sectionDto in userDto.User2AppDtos)
if (entity.IsPropertyDirty("StartContentIds"))
{
//need to set the id explicitly here
sectionDto.UserId = id;
Database.Insert(sectionDto);
AddingOrUpdateStartNodes(entity, Enumerable.Empty<UserStartNodeDto>(), UserStartNodeDto.StartNodeTypeValue.Content, entity.StartContentIds);
}
if (entity.IsPropertyDirty("StartMediaIds"))
{
AddingOrUpdateStartNodes(entity, Enumerable.Empty<UserStartNodeDto>(), UserStartNodeDto.StartNodeTypeValue.Media, entity.StartMediaIds);
}
if (entity.IsPropertyDirty("Groups"))
{
// lookup all assigned
var assigned = entity.Groups == null || entity.Groups.Any() == false
? new List<UserGroupDto>()
: Database.Fetch<UserGroupDto>("SELECT * FROM umbracoUserGroup WHERE userGroupAlias IN (@aliases)", new { aliases = entity.Groups.Select(x => x.Alias) });
foreach (var groupDto in assigned)
{
var dto = new User2UserGroupDto
{
UserGroupId = groupDto.Id,
UserId = entity.Id
};
Database.Insert(dto);
}
}
entity.ResetDirtyProperties();
@@ -181,25 +381,21 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistUpdatedItem(IUser entity)
{
var userFactory = new UserFactory(entity.UserType);
// updates Modified date
((User) entity).UpdatingEntity();
//ensure security stamp if non
// ensure security stamp if missing
if (entity.SecurityStamp.IsNullOrWhiteSpace())
{
entity.SecurityStamp = Guid.NewGuid().ToString();
}
var userDto = userFactory.BuildDto(entity);
var userDto = UserFactory.BuildDto(entity);
var dirtyEntity = (ICanBeDirty)entity;
//build list of columns to check for saving - we don't want to save the password if it hasn't changed!
//List the columns to save, NOTE: would be nice to not have hard coded strings here but no real good way around that
var colsToSave = new Dictionary<string, string>()
// build list of columns to check for saving - we don't want to save the password if it hasn't changed!
// list the columns to save, NOTE: would be nice to not have hard coded strings here but no real good way around that
var colsToSave = new Dictionary<string, string>
{
{"userDisabled", "IsApproved"},
{"userNoConsole", "IsLockedOut"},
{"userType", "UserType"},
{"startStructureID", "StartContentId"},
{"startMediaID", "StartMediaId"},
{"userName", "Name"},
@@ -211,27 +407,42 @@ namespace Umbraco.Core.Persistence.Repositories
{"lastPasswordChangeDate", "LastPasswordChangeDate"},
{"lastLoginDate", "LastLoginDate"},
{"failedLoginAttempts", "FailedPasswordAttempts"},
{"createDate", "CreateDate"},
{"updateDate", "UpdateDate"},
{"avatar", "Avatar"},
{"emailConfirmedDate", "EmailConfirmedDate"},
{"invitedDate", "InvitedDate"}
};
//create list of properties that have changed
// create list of properties that have changed
var changedCols = colsToSave
.Where(col => dirtyEntity.IsPropertyDirty(col.Value))
.Where(col => entity.IsPropertyDirty(col.Value))
.Select(col => col.Key)
.ToList();
// DO NOT update the password if it has not changed or if it is null or empty
if (dirtyEntity.IsPropertyDirty("RawPasswordValue") && entity.RawPasswordValue.IsNullOrWhiteSpace() == false)
if (entity.IsPropertyDirty("RawPasswordValue") && entity.RawPasswordValue.IsNullOrWhiteSpace() == false)
{
changedCols.Add("userPassword");
//special case - when using ASP.Net identity the user manager will take care of updating the security stamp, however
// special case - when using ASP.Net identity the user manager will take care of updating the security stamp, however
// when not using ASP.Net identity (i.e. old membership providers), we'll need to take care of updating this manually
// so we can just detect if that property is dirty, if it's not we'll set it manually
if (dirtyEntity.IsPropertyDirty("SecurityStamp") == false)
if (entity.IsPropertyDirty("SecurityStamp") == false)
{
userDto.SecurityStampToken = entity.SecurityStamp = Guid.NewGuid().ToString();
changedCols.Add("securityStampToken");
}
// check if we have a known config, we only want to store config for hashing
//TODO: This logic will need to be updated when we do http://issues.umbraco.org/issue/U4-10089
if (_passwordConfig != null && _passwordConfig.Count > 0)
{
var json = JsonConvert.SerializeObject(_passwordConfig);
userDto.PasswordConfig = json;
changedCols.Add("passwordConfig");
}
}
//only update the changed cols
@@ -240,42 +451,66 @@ namespace Umbraco.Core.Persistence.Repositories
Database.Update(userDto, changedCols);
}
//update the sections if they've changed
var user = (User)entity;
if (user.IsPropertyDirty("AllowedSections"))
if (entity.IsPropertyDirty("StartContentIds") || entity.IsPropertyDirty("StartMediaIds"))
{
//now we need to delete any applications that have been removed
foreach (var section in user.RemovedSections)
var assignedStartNodes = Database.Fetch<UserStartNodeDto>("SELECT * FROM umbracoUserStartNode WHERE userId = @userId", new { userId = entity.Id });
if (entity.IsPropertyDirty("StartContentIds"))
{
//we need to manually delete thsi record because it has a composite key
Database.Delete<User2AppDto>("WHERE app=@Section AND " + SqlSyntax.GetQuotedColumnName("user") + "=@UserId",
new { Section = section, UserId = (int)user.Id });
AddingOrUpdateStartNodes(entity, assignedStartNodes, UserStartNodeDto.StartNodeTypeValue.Content, entity.StartContentIds);
}
//for any that exist on the object, we need to determine if we need to update or insert
//NOTE: the User2AppDtos collection wil always be equal to the User.AllowedSections
foreach (var sectionDto in userDto.User2AppDtos)
if (entity.IsPropertyDirty("StartMediaIds"))
{
//if something has been added then insert it
if (user.AddedSections.Contains(sectionDto.AppAlias))
{
//we need to insert since this was added
Database.Insert(sectionDto);
}
else
{
//we need to manually update this record because it has a composite key
Database.Update<User2AppDto>("SET app=@Section WHERE app=@Section AND " + SqlSyntax.GetQuotedColumnName("user") + "=@UserId",
new { Section = sectionDto.AppAlias, UserId = sectionDto.UserId });
}
AddingOrUpdateStartNodes(entity, assignedStartNodes, UserStartNodeDto.StartNodeTypeValue.Media, entity.StartMediaIds);
}
}
if (entity.IsPropertyDirty("Groups"))
{
//lookup all assigned
var assigned = entity.Groups == null || entity.Groups.Any() == false
? new List<UserGroupDto>()
: Database.Fetch<UserGroupDto>("SELECT * FROM umbracoUserGroup WHERE userGroupAlias IN (@aliases)", new { aliases = entity.Groups.Select(x => x.Alias) });
//first delete all
//TODO: We could do this a nicer way instead of "Nuke and Pave"
Database.Delete<User2UserGroupDto>("WHERE UserId = @UserId", new { UserId = entity.Id });
foreach (var groupDto in assigned)
{
var dto = new User2UserGroupDto
{
UserGroupId = groupDto.Id,
UserId = entity.Id
};
Database.Insert(dto);
}
}
entity.ResetDirtyProperties();
}
private void AddingOrUpdateStartNodes(IEntity entity, IEnumerable<UserStartNodeDto> current, UserStartNodeDto.StartNodeTypeValue startNodeType, int[] entityStartIds)
{
var assignedIds = current.Where(x => x.StartNodeType == (int)startNodeType).Select(x => x.StartNode).ToArray();
//remove the ones not assigned to the entity
var toDelete = assignedIds.Except(entityStartIds).ToArray();
if (toDelete.Length > 0)
Database.Delete<UserStartNodeDto>("WHERE UserId = @UserId AND startNode IN (@startNodes)", new { UserId = entity.Id, startNodes = toDelete });
//add the ones not currently in the db
var toAdd = entityStartIds.Except(assignedIds).ToArray();
foreach (var i in toAdd)
{
var dto = new UserStartNodeDto
{
StartNode = i,
StartNodeType = (int)startNodeType,
UserId = entity.Id
};
Database.Insert(dto);
}
}
#endregion
#region Implementation of IUserRepository
@@ -302,47 +537,81 @@ namespace Umbraco.Core.Persistence.Repositories
return Database.ExecuteScalar<int>(sql) > 0;
}
public IEnumerable<IUser> GetUsersAssignedToSection(string sectionAlias)
/// <summary>
/// Gets a list of <see cref="IUser"/> objects associated with a given group
/// </summary>
/// <param name="groupId">Id of group</param>
public IEnumerable<IUser> GetAllInGroup(int groupId)
{
//Here we're building up a query that looks like this, a sub query is required because the resulting structure
// needs to still contain all of the section rows per user.
return GetAllInOrNotInGroup(groupId, true);
}
//SELECT *
//FROM [umbracoUser]
//LEFT JOIN [umbracoUser2app]
//ON [umbracoUser].[id] = [umbracoUser2app].[user]
//WHERE umbracoUser.id IN (SELECT umbracoUser.id
// FROM [umbracoUser]
// LEFT JOIN [umbracoUser2app]
// ON [umbracoUser].[id] = [umbracoUser2app].[user]
// WHERE umbracoUser2app.app = 'content')
/// <summary>
/// Gets a list of <see cref="IUser"/> objects not associated with a given group
/// </summary>
/// <param name="groupId">Id of group</param>
public IEnumerable<IUser> GetAllNotInGroup(int groupId)
{
return GetAllInOrNotInGroup(groupId, false);
}
var sql = GetBaseQuery(false);
var innerSql = GetBaseQuery("umbracoUser.id");
innerSql.Where("umbracoUser2app.app = " + SqlSyntax.GetQuotedValue(sectionAlias));
sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL));
private IEnumerable<IUser> GetAllInOrNotInGroup(int groupId, bool include)
{
#error this needs to be rewritten
var sql = new Sql();
sql.Select("*")
.From<UserDto>();
var dtos = Database
.FetchOneToMany<UserDto>(x => x.User2AppDtos, sql);
var innerSql = new Sql();
innerSql.Select("umbracoUser.id")
.From<UserDto>()
.LeftJoin<User2UserGroupDto>()
.On<UserDto, User2UserGroupDto>(left => left.Id, right => right.UserId)
.Where("umbracoUser2UserGroup.userGroupId = " + groupId);
return ConvertFromDtos(dtos);
sql.Where(string.Format("umbracoUser.id {0} ({1})",
include ? "IN" : "NOT IN",
innerSql.SQL));
return ConvertFromDtos(Database.Fetch<UserDto>(sql));
}
[Obsolete("Use the overload with long operators instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IUser, string>> orderBy)
{
if (orderBy == null) throw new ArgumentNullException("orderBy");
// get the referenced column name and find the corresp mapped column name
var expressionMember = ExpressionHelper.GetMemberInfo(orderBy);
var mapper = MappingResolver.Current.ResolveMapperByType(typeof(IUser));
var mappedField = mapper.Map(expressionMember.Name);
if (mappedField.IsNullOrWhiteSpace())
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
long tr;
var results = GetPagedResultsByQuery(query, Convert.ToInt64(pageIndex), pageSize, out tr, mappedField, Direction.Ascending);
totalRecords = Convert.ToInt32(tr);
return results;
}
/// <summary>
/// Gets paged user results
/// </summary>
/// <param name="query">
/// The where clause, if this is null all records are queried
/// </param>
/// <param name="query"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="userGroups">Optional parameter to filter by specified user groups</param>
/// <param name="userState">Optional parameter to filter by specfied user state</param>
/// <param name="filter"></param>
/// <returns></returns>
/// <remarks>
/// The query supplied will ONLY work with data specifically on the umbracoUser table because we are using NPoco paging (SQL paging)
/// </remarks>
public IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, Expression<Func<IUser, string>> orderBy)
public IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, Expression<Func<IUser, object>> orderBy, Direction orderDirection, string[] userGroups = null, UserState[] userState = null, IQuery<IUser> filter = null)
{
if (orderBy == null) throw new ArgumentNullException(nameof(orderBy));
@@ -354,29 +623,180 @@ namespace Umbraco.Core.Persistence.Repositories
if (mappedField.IsNullOrWhiteSpace())
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
var sql = Sql()
.Select("umbracoUser.Id")
.From<UserDto>();
return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, mappedField, orderDirection, userGroups, userState, filter);
}
var idsQuery = query == null ? sql : new SqlTranslator<IUser>(sql, query).Translate();
// need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177
idsQuery.OrderBy("(" + mappedField + ")");
var page = Database.Page<int>(pageIndex + 1, pageSize, idsQuery);
totalRecords = Convert.ToInt32(page.TotalItems);
if (totalRecords == 0)
return Enumerable.Empty<IUser>();
private IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection,
string[] userGroups = null,
UserState[] userState = null,
IQuery<IUser> filter = null)
{
if (string.IsNullOrWhiteSpace(orderBy)) throw new ArgumentException("Value cannot be null or whitespace.", "orderBy");
// now get the actual users and ensure they are ordered properly (same clause)
var ids = page.Items.ToArray();
return ids.Length == 0 ? Enumerable.Empty<IUser>() : GetAll(ids).OrderBy(orderBy.Compile());
Sql filterSql = null;
if (filter != null || (userGroups != null && userGroups.Length > 0) || (userState != null && userState.Length > 0 && userState.Contains(UserState.All) == false))
filterSql = new Sql();
if (filter != null)
{
foreach (var filterClause in filter.GetWhereClauses())
{
filterSql.Append(string.Format("AND ({0})", filterClause.Item1), filterClause.Item2);
}
}
if (userGroups != null && userGroups.Length > 0)
{
var subQuery = @"AND (umbracoUser.id IN (SELECT DISTINCT umbracoUser.id
FROM umbracoUser
INNER JOIN umbracoUser2UserGroup ON umbracoUser2UserGroup.userId = umbracoUser.id
INNER JOIN umbracoUserGroup ON umbracoUserGroup.id = umbracoUser2UserGroup.userGroupId
WHERE umbracoUserGroup.userGroupAlias IN (@userGroups)))";
filterSql.Append(subQuery, new { userGroups = userGroups });
}
if (userState != null && userState.Length > 0)
{
//the "ALL" state doesn't require any filtering so we ignore that, if it exists in the list we don't do any filtering
if (userState.Contains(UserState.All) == false)
{
var sb = new StringBuilder("(");
var appended = false;
if (userState.Contains(UserState.Active))
{
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL)");
appended = true;
}
if (userState.Contains(UserState.Disabled))
{
if (appended) sb.Append(" OR ");
sb.Append("(userDisabled = 1)");
}
if (userState.Contains(UserState.LockedOut))
{
if (appended) sb.Append(" OR ");
sb.Append("(userNoConsole = 1)");
}
if (userState.Contains(UserState.Invited))
{
if (appended) sb.Append(" OR ");
sb.Append("(lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL)");
}
sb.Append(")");
filterSql.Append("AND " + sb);
}
}
// Get base query for returning IDs
var sqlBaseIds = GetBaseQuery("id");
if (query == null) query = new Query<IUser>();
var translatorIds = new SqlTranslator<IUser>(sqlBaseIds, query);
var sqlQueryIds = translatorIds.Translate();
//get sorted and filtered sql
var sqlNodeIdsWithSort = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(sqlQueryIds, filterSql),
orderDirection, orderBy);
// Get page of results and total count
var pagedResult = Database.Page<UserDto>(pageIndex + 1, pageSize, sqlNodeIdsWithSort);
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
//NOTE: We need to check the actual items returned, not the 'totalRecords', that is because if you request a page number
// that doesn't actually have any data on it, the totalRecords will still indicate there are records but there are none in
// the pageResult.
if (pagedResult.Items.Any())
{
//Create the inner paged query that was used above to get the paged result, we'll use that as the inner sub query
var args = sqlNodeIdsWithSort.Arguments;
string sqlStringCount, sqlStringPage;
Database.BuildPageQueries<UserDto>(pageIndex * pageSize, pageSize, sqlNodeIdsWithSort.SQL, ref args, out sqlStringCount, out sqlStringPage);
var sqlQueryFull = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
var fullQueryWithPagedInnerJoin = sqlQueryFull
.Append("INNER JOIN (")
//join the paged query with the paged query arguments
.Append(sqlStringPage, args)
.Append(") temp ")
.Append("ON umbracoUser.id = temp.id");
AddGroupLeftJoin(fullQueryWithPagedInnerJoin);
//get sorted and filtered sql
var fullQuery = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(fullQueryWithPagedInnerJoin, filterSql),
orderDirection, orderBy);
var users = ConvertFromDtos(Database.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(new UserGroupRelator().Map, fullQuery))
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
return users;
}
return Enumerable.Empty<IUser>();
}
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql)
{
Sql filteredSql;
// Apply filter
if (filterSql != null)
{
var sqlFilter = " WHERE " + filterSql.SQL.TrimStart("AND ");
//NOTE: this is certainly strange - NPoco handles this much better but we need to re-create the sql
// instance a couple of times to get the parameter order correct, for some reason the first
// time the arguments don't show up correctly but the SQL argument parameter names are actually updated
// accordingly - so we re-create it again. In v8 we don't need to do this and it's already taken care of.
filteredSql = new Sql(sql.SQL, sql.Arguments);
var args = filteredSql.Arguments.Concat(filterSql.Arguments).ToArray();
filteredSql = new Sql(
string.Format("{0} {1}", filteredSql.SQL, sqlFilter),
args);
filteredSql = new Sql(filteredSql.SQL, args);
}
else
{
//copy to var so that the original isn't changed
filteredSql = new Sql(sql.SQL, sql.Arguments);
}
return filteredSql;
}
private Sql GetSortedSqlForPagedResults(Sql sql, Direction orderDirection, string orderBy)
{
//copy to var so that the original isn't changed
var sortedSql = new Sql(sql.SQL, sql.Arguments);
// Apply order according to parameters
if (string.IsNullOrEmpty(orderBy) == false)
{
//each order by param needs to be in a bracket! see: https://github.com/toptensoftware/PetaPoco/issues/177
var orderByParams = new[] { string.Format("({0})", orderBy) };
if (orderDirection == Direction.Ascending)
{
sortedSql.OrderBy(orderByParams);
}
else
{
sortedSql.OrderByDescending(orderByParams);
}
}
return sortedSql;
}
internal IEnumerable<IUser> GetNextUsers(int id, int count)
{
var idsQuery = Sql()
.Select("umbracoUser.Id")
.Select("umbracoUser.id")
.From<UserDto>()
.Where<UserDto>(x => x.Id >= id)
.OrderBy<UserDto>(x => x.Id);
@@ -388,54 +808,11 @@ namespace Umbraco.Core.Persistence.Repositories
return ids.Length == 0 ? Enumerable.Empty<IUser>() : GetAll(ids).OrderBy(x => x.Id);
}
/// <summary>
/// Returns permissions for a given user for any number of nodes
/// </summary>
/// <param name="userId"></param>
/// <param name="entityIds"></param>
/// <returns></returns>
public IEnumerable<EntityPermission> GetUserPermissionsForEntities(int userId, params int[] entityIds)
{
return PermissionRepository.GetUserPermissionsForEntities(userId, entityIds);
}
/// <summary>
/// Replaces the same permission set for a single user to any number of entities
/// </summary>
/// <param name="userId"></param>
/// <param name="permissions"></param>
/// <param name="entityIds"></param>
public void ReplaceUserPermissions(int userId, IEnumerable<char> permissions, params int[] entityIds)
{
PermissionRepository.ReplaceUserPermissions(userId, permissions, entityIds);
}
/// <summary>
/// Assigns the same permission set for a single user to any number of entities
/// </summary>
/// <param name="userId"></param>
/// <param name="permission"></param>
/// <param name="entityIds"></param>
public void AssignUserPermission(int userId, char permission, params int[] entityIds)
{
PermissionRepository.AssignUserPermission(userId, permission, entityIds);
}
#endregion
private IEnumerable<IUser> ConvertFromDtos(IEnumerable<UserDto> dtos)
{
var userTypeIds = dtos.Select(x => Convert.ToInt32(x.Type)).ToArray();
var allUserTypes = userTypeIds.Length == 0 ? Enumerable.Empty<IUserType>() : _userTypeRepository.GetAll(userTypeIds);
return dtos.Select(dto =>
{
var userType = allUserTypes.Single(x => x.Id == dto.Type);
var userFactory = new UserFactory(userType);
return userFactory.BuildEntity(dto);
});
return dtos.Select(UserFactory.BuildEntity);
}
}
}

View File

@@ -1146,8 +1146,8 @@
<Compile Include="Persistence\Repositories\Interfaces\ITaskRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\ITaskTypeRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\ITemplateRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IUserGroupRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IUserRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IUserTypeRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IXsltFileRepository.cs" />
<Compile Include="Persistence\Repositories\LanguageRepository.cs" />
<Compile Include="Persistence\Repositories\MacroRepository.cs" />
@@ -1181,8 +1181,8 @@
<Compile Include="Persistence\Repositories\TaskTypeRepository.cs" />
<Compile Include="Persistence\Repositories\TemplateRepository.cs" />
<Compile Include="Persistence\Repositories\TupleExtensions.cs" />
<Compile Include="Persistence\Repositories\UserGroupRepository.cs" />
<Compile Include="Persistence\Repositories\UserRepository.cs" />
<Compile Include="Persistence\Repositories\UserTypeRepository.cs" />
<Compile Include="Persistence\Repositories\VersionableRepositoryBase.cs" />
<Compile Include="Persistence\Repositories\VersionableRepositoryBaseAliasRegex.cs" />
<Compile Include="Persistence\Repositories\XsltFileRepository.cs" />