diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs
index fc17bd7245..1278ff0e33 100644
--- a/src/Umbraco.Core/Cache/CacheKeys.cs
+++ b/src/Umbraco.Core/Cache/CacheKeys.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace Umbraco.Core.Cache
{
@@ -9,6 +11,7 @@ namespace Umbraco.Core.Cache
public const string ApplicationTreeCacheKey = "ApplicationTreeCache";
public const string ApplicationsCacheKey = "ApplicationCache";
+ [Obsolete("This is no longer used and will be removed from the codebase in the future")]
public const string UserTypeCacheKey = "UserTypeCache";
public const string ContentItemCacheKey = "contentItem";
@@ -24,13 +27,16 @@ namespace Umbraco.Core.Cache
public const string MemberLibraryCacheKey = "UL_GetMember";
public const string MemberBusinessLogicCacheKey = "MemberCacheItem_";
-
+
public const string TemplateFrontEndCacheKey = "template";
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
public const string UserContextCacheKey = "UmbracoUserContext";
public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout";
+
+ [Obsolete("This is no longer used and will be removed from the codebase in the future")]
public const string UserCacheKey = "UmbracoUser";
+
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
public const string ContentTypeCacheKey = "UmbracoContentType";
diff --git a/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs b/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs
index 0536647f55..9f7ec8083c 100644
--- a/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs
+++ b/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs
@@ -28,9 +28,9 @@ namespace Umbraco.Core.Configuration
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
- int oldVersion;
- int.TryParse(versionAttribute.Value, out oldVersion);
- var newVersion = oldVersion + 100;
+ //Set the new version to the hashcode of now
+ var oldVersion = versionAttribute.Value;
+ var newVersion = DateTime.UtcNow.GetHashCode();
versionAttribute.SetValue(newVersion);
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs
index d472150a85..dea05d57af 100644
--- a/src/Umbraco.Core/CoreBootManager.cs
+++ b/src/Umbraco.Core/CoreBootManager.cs
@@ -287,7 +287,7 @@ namespace Umbraco.Core
() => PluginManager.Current.ResolveAssignedMapperTypes());
RepositoryResolver.Current = new RepositoryResolver(
- new RepositoryFactory());
+ new RepositoryFactory(ApplicationCache));
SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver(
new[] { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) })
diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs
index 3fbdeccda8..c18c7c3a43 100644
--- a/src/Umbraco.Core/Models/ContentBase.cs
+++ b/src/Umbraco.Core/Models/ContentBase.cs
@@ -306,10 +306,8 @@ namespace Umbraco.Core.Models
/// Value as a
public virtual TPassType GetValue(string propertyTypeAlias)
{
- if (Properties[propertyTypeAlias].Value is TPassType)
- return (TPassType)Properties[propertyTypeAlias].Value;
-
- return (TPassType)Convert.ChangeType(Properties[propertyTypeAlias].Value, typeof(TPassType));
+ var convertAttempt = Properties[propertyTypeAlias].Value.TryConvertTo();
+ return convertAttempt.Success ? convertAttempt.Result : default(TPassType);
}
///
diff --git a/src/Umbraco.Core/Models/EntityExtensions.cs b/src/Umbraco.Core/Models/EntityExtensions.cs
new file mode 100644
index 0000000000..f461c4007c
--- /dev/null
+++ b/src/Umbraco.Core/Models/EntityExtensions.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Umbraco.Core.Models.EntityBase;
+
+namespace Umbraco.Core.Models
+{
+ public static class EntityExtensions
+ {
+
+ ///
+ /// Returns true if this entity has just been created and persisted to the data store
+ ///
+ ///
+ ///
+ ///
+ /// This is useful when handling events to determine if an entity is a brand new entity or was
+ /// already existing.
+ ///
+ public static bool IsNewEntity(this IEntity entity)
+ {
+ var dirty = (IRememberBeingDirty)entity;
+ return dirty.WasPropertyDirty("Id");
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Models/IMemberGroup.cs b/src/Umbraco.Core/Models/IMemberGroup.cs
new file mode 100644
index 0000000000..5c3741997b
--- /dev/null
+++ b/src/Umbraco.Core/Models/IMemberGroup.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using Umbraco.Core.Models.EntityBase;
+
+namespace Umbraco.Core.Models
+{
+ ///
+ /// Represents a member type
+ ///
+ public interface IMemberGroup : IAggregateRoot
+ {
+ ///
+ /// The name of the member group
+ ///
+ string Name { get; set; }
+
+ ///
+ /// Profile of the user who created this Entity
+ ///
+ int CreatorId { get; set; }
+
+ ///
+ /// Some entities may expose additional data that other's might not, this custom data will be available in this collection
+ ///
+ IDictionary AdditionalData { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/Member.cs b/src/Umbraco.Core/Models/Member.cs
index d43a6a0266..6a54bddc70 100644
--- a/src/Umbraco.Core/Models/Member.cs
+++ b/src/Umbraco.Core/Models/Member.cs
@@ -31,6 +31,7 @@ namespace Umbraco.Core.Models
_contentType = contentType;
}
+ //TODO: Should we just get rid of this one? no reason to have a level set.
internal Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
: base(name, parentId, contentType, new PropertyCollection())
{
@@ -210,14 +211,13 @@ namespace Umbraco.Core.Models
{
get
{
- if (Properties[Constants.Conventions.Member.IsApproved].Value == null)
- return default(bool);
-
- if (Properties[Constants.Conventions.Member.IsApproved].Value is bool)
- return (bool)Properties[Constants.Conventions.Member.IsApproved].Value;
-
+ var tryConvert = Properties[Constants.Conventions.Member.IsApproved].Value.TryConvertTo();
+ if (tryConvert.Success)
+ {
+ return tryConvert.Result;
+ }
+ return default(bool);
//TODO: Use TryConvertTo instead
- return (bool)Convert.ChangeType(Properties[Constants.Conventions.Member.IsApproved].Value, typeof(bool));
}
set
{
@@ -237,14 +237,13 @@ namespace Umbraco.Core.Models
{
get
{
- if (Properties[Constants.Conventions.Member.IsLockedOut].Value == null)
- return default(bool);
-
- if (Properties[Constants.Conventions.Member.IsLockedOut].Value is bool)
- return (bool)Properties[Constants.Conventions.Member.IsLockedOut].Value;
-
+ var tryConvert = Properties[Constants.Conventions.Member.IsLockedOut].Value.TryConvertTo();
+ if (tryConvert.Success)
+ {
+ return tryConvert.Result;
+ }
+ return default(bool);
//TODO: Use TryConvertTo instead
- return (bool)Convert.ChangeType(Properties[Constants.Conventions.Member.IsLockedOut].Value, typeof(bool));
}
set
{
@@ -264,14 +263,13 @@ namespace Umbraco.Core.Models
{
get
{
- if (Properties[Constants.Conventions.Member.LastLoginDate].Value == null)
- return default(DateTime);
-
- if (Properties[Constants.Conventions.Member.LastLoginDate].Value is DateTime)
- return (DateTime)Properties[Constants.Conventions.Member.LastLoginDate].Value;
-
+ var tryConvert = Properties[Constants.Conventions.Member.LastLoginDate].Value.TryConvertTo();
+ if (tryConvert.Success)
+ {
+ return tryConvert.Result;
+ }
+ return default(DateTime);
//TODO: Use TryConvertTo instead
- return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastLoginDate].Value, typeof(DateTime));
}
set
{
@@ -291,14 +289,13 @@ namespace Umbraco.Core.Models
{
get
{
- if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value == null)
- return default(DateTime);
-
- if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value is DateTime)
- return (DateTime)Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value;
-
+ var tryConvert = Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value.TryConvertTo();
+ if (tryConvert.Success)
+ {
+ return tryConvert.Result;
+ }
+ return default(DateTime);
//TODO: Use TryConvertTo instead
- return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value, typeof(DateTime));
}
set
{
@@ -318,14 +315,13 @@ namespace Umbraco.Core.Models
{
get
{
- if (Properties[Constants.Conventions.Member.LastLockoutDate].Value == null)
- return default(DateTime);
-
- if (Properties[Constants.Conventions.Member.LastLockoutDate].Value is DateTime)
- return (DateTime)Properties[Constants.Conventions.Member.LastLockoutDate].Value;
-
+ var tryConvert = Properties[Constants.Conventions.Member.LastLockoutDate].Value.TryConvertTo();
+ if (tryConvert.Success)
+ {
+ return tryConvert.Result;
+ }
+ return default(DateTime);
//TODO: Use TryConvertTo instead
- return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastLockoutDate].Value, typeof(DateTime));
}
set
{
@@ -346,14 +342,13 @@ namespace Umbraco.Core.Models
{
get
{
- if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value == null)
- return default(int);
-
- if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value is int)
- return (int)Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value;
-
+ var tryConvert = Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value.TryConvertTo();
+ if (tryConvert.Success)
+ {
+ return tryConvert.Result;
+ }
+ return default(int);
//TODO: Use TryConvertTo instead
- return (int)Convert.ChangeType(Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value, typeof(int));
}
set
{
diff --git a/src/Umbraco.Core/Models/MemberGroup.cs b/src/Umbraco.Core/Models/MemberGroup.cs
new file mode 100644
index 0000000000..e52448a11d
--- /dev/null
+++ b/src/Umbraco.Core/Models/MemberGroup.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.Serialization;
+using Umbraco.Core.Models.EntityBase;
+
+namespace Umbraco.Core.Models
+{
+ ///
+ /// Represents a member type
+ ///
+ [Serializable]
+ [DataContract(IsReference = true)]
+ public class MemberGroup : Entity, IMemberGroup
+ {
+ public MemberGroup()
+ {
+ AdditionalData = new Dictionary();
+ }
+
+ private string _name;
+ private int _creatorId;
+
+ private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name);
+ private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo(x => x.CreatorId);
+
+ [DataMember]
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ SetPropertyValueAndDetectChanges(o =>
+ {
+ if (_name != value)
+ {
+ //if the name has changed, add the value to the additional data,
+ //this is required purely for event handlers to know the previous name of the group
+ //so we can keep the public access up to date.
+ AdditionalData["previousName"] = _name;
+ }
+
+ _name = value;
+ return _name;
+ }, _name, NameSelector);
+ }
+ }
+
+ public int CreatorId
+ {
+ get { return _creatorId; }
+ set
+ {
+ SetPropertyValueAndDetectChanges(o =>
+ {
+ _creatorId = value;
+ return _creatorId;
+ }, _creatorId, CreatorIdSelector);
+ }
+ }
+
+ public IDictionary AdditionalData { get; private set; }
+
+ ///
+ /// Method to call when Entity is being saved
+ ///
+ /// Created date is set and a Unique key is assigned
+ internal override void AddingEntity()
+ {
+ base.AddingEntity();
+
+ if (Key == Guid.Empty)
+ Key = Guid.NewGuid();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/Membership/IProfile.cs b/src/Umbraco.Core/Models/Membership/IProfile.cs
index fbbff85e7d..749c3371b8 100644
--- a/src/Umbraco.Core/Models/Membership/IProfile.cs
+++ b/src/Umbraco.Core/Models/Membership/IProfile.cs
@@ -3,6 +3,10 @@
///
/// Defines the the Profile interface
///
+ ///
+ /// This interface is pretty useless but has been exposed publicly from 6.x so we're stuck with it. It would make more sense
+ /// if the Id was an int but since it's not people have to cast it to int all of the time!
+ ///
public interface IProfile
{
object Id { get; set; }
diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs
index 3695a84546..46338c8c4a 100644
--- a/src/Umbraco.Core/Models/Membership/IUser.cs
+++ b/src/Umbraco.Core/Models/Membership/IUser.cs
@@ -7,19 +7,18 @@ namespace Umbraco.Core.Models.Membership
/// Defines the interface for a
///
/// Will be left internal until a proper Membership implementation is part of the roadmap
- internal interface IUser : IMembershipUser, IProfile
+ public interface IUser : IMembershipUser
{
- new object Id { get; set; }
-
+ string Name { get; set; }
int SessionTimeout { get; set; }
int StartContentId { get; set; }
int StartMediaId { get; set; }
string Language { get; set; }
- //NOTE: I have removed this because it is obsolete in v7 and we are basically removing live editing for now
- //bool DefaultToLiveEditing { get; set; }
-
- IUserType UserType { get; }
+ ///
+ /// Gets/sets the user type for the user
+ ///
+ IUserType UserType { get; set; }
///
/// The default permission set for the user
@@ -32,5 +31,10 @@ namespace Umbraco.Core.Models.Membership
IEnumerable AllowedSections { get; }
void RemoveAllowedSection(string sectionAlias);
void AddAllowedSection(string sectionAlias);
+
+ ///
+ /// Exposes the basic profile data
+ ///
+ IProfile ProfileData { get; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/Membership/IUserType.cs b/src/Umbraco.Core/Models/Membership/IUserType.cs
index aa2d882e4c..fe678afd2b 100644
--- a/src/Umbraco.Core/Models/Membership/IUserType.cs
+++ b/src/Umbraco.Core/Models/Membership/IUserType.cs
@@ -5,7 +5,7 @@ using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models.Membership
{
- internal interface IUserType : IAggregateRoot
+ public interface IUserType : IAggregateRoot
{
///
/// The user type alias
diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs
index 26e8bf6cc0..8e55ddf1fb 100644
--- a/src/Umbraco.Core/Models/Membership/User.cs
+++ b/src/Umbraco.Core/Models/Membership/User.cs
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
+using Umbraco.Core.Configuration;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;
@@ -19,7 +20,7 @@ namespace Umbraco.Core.Models.Membership
///
[Serializable]
[DataContract(IsReference = true)]
- internal class User : TracksChangesEntityBase, IUser
+ public class User : TracksChangesEntityBase, IUser
{
public User(IUserType userType)
{
@@ -31,6 +32,7 @@ namespace Umbraco.Core.Models.Membership
_sectionCollection = new ObservableCollection();
_addedSections = new List();
_removedSections = new List();
+ _language = GlobalSettings.DefaultUILanguage;
_sectionCollection.CollectionChanged += SectionCollectionChanged;
}
@@ -40,12 +42,12 @@ namespace Umbraco.Core.Models.Membership
_name = name;
_email = email;
_username = username;
- _password = password;
+ _password = password;
}
- private readonly IUserType _userType;
+ private IUserType _userType;
private bool _hasIdentity;
- private object _id;
+ private int _id;
private string _name;
private Type _userTypeKey;
private readonly List _addedSections;
@@ -58,7 +60,6 @@ namespace Umbraco.Core.Models.Membership
private string _username;
private string _email;
private string _password;
- private Guid _key;
private bool _isApproved;
private bool _isLockedOut;
private string _language;
@@ -81,23 +82,43 @@ namespace Umbraco.Core.Models.Membership
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo(x => x.Language);
private static readonly PropertyInfo DefaultPermissionsSelector = ExpressionHelper.GetPropertyInfo>(x => x.DefaultPermissions);
private static readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo(x => x.DefaultToLiveEditing);
+ private static readonly PropertyInfo HasIdentitySelector = ExpressionHelper.GetPropertyInfo(x => x.HasIdentity);
+ private static readonly PropertyInfo UserTypeSelector = ExpressionHelper.GetPropertyInfo(x => x.UserType);
#region Implementation of IEntity
[IgnoreDataMember]
- public bool HasIdentity { get { return Id != null || _hasIdentity; } }
-
- [IgnoreDataMember]
- int IEntity.Id
+ public bool HasIdentity
{
get
{
- return int.Parse(Id.ToString());
+ return _hasIdentity;
+ }
+ protected set
+ {
+ SetPropertyValueAndDetectChanges(o =>
+ {
+ _hasIdentity = value;
+ return _hasIdentity;
+ }, _hasIdentity, HasIdentitySelector);
+ }
+ }
+
+ [DataMember]
+ public int Id
+ {
+ get
+ {
+ return _id;
}
set
{
- Id = value;
- _hasIdentity = true;
+ SetPropertyValueAndDetectChanges(o =>
+ {
+ _id = value;
+ HasIdentity = true; //set the has Identity
+ return _id;
+ }, _id, IdSelector);
}
}
@@ -239,8 +260,8 @@ namespace Umbraco.Core.Models.Membership
public int FailedPasswordAttempts { get; set; }
#endregion
-
- #region Implementation of IProfile
+
+ #region Implementation of IUser
[DataMember]
public string Name
@@ -249,17 +270,13 @@ namespace Umbraco.Core.Models.Membership
set
{
SetPropertyValueAndDetectChanges(o =>
- {
- _name = value;
- return _name;
- }, _name, NameSelector);
+ {
+ _name = value;
+ return _name;
+ }, _name, NameSelector);
}
}
- #endregion
-
- #region Implementation of IUser
-
public IEnumerable AllowedSections
{
get { return _sectionCollection; }
@@ -278,6 +295,11 @@ namespace Umbraco.Core.Models.Membership
}
}
+ public IProfile ProfileData
+ {
+ get { return new UserProfile(this); }
+ }
+
///
/// Used internally to check if we need to add a section in the repository to the db
///
@@ -354,20 +376,6 @@ namespace Umbraco.Core.Models.Membership
}
}
- [DataMember]
- public object Id
- {
- get { return _id; }
- set
- {
- SetPropertyValueAndDetectChanges(o =>
- {
- _id = value;
- return _id;
- }, _id, IdSelector);
- }
- }
-
[DataMember]
public string Language
{
@@ -414,6 +422,19 @@ namespace Umbraco.Core.Models.Membership
public IUserType UserType
{
get { return _userType; }
+ set
+ {
+ if (value.HasIdentity == false)
+ {
+ throw new InvalidOperationException("Cannot assign a User Type that has not been persisted");
+ }
+
+ SetPropertyValueAndDetectChanges(o =>
+ {
+ _userType = value;
+ return _userType;
+ }, _userType, UserTypeSelector);
+ }
}
#endregion
@@ -459,5 +480,30 @@ namespace Umbraco.Core.Models.Membership
_removedSections.Add(e.OldItems.Cast().First());
}
}
+
+ ///
+ /// Internal class used to wrap the user in a profile
+ ///
+ private class UserProfile : IProfile
+ {
+ private readonly IUser _user;
+
+ public UserProfile(IUser user)
+ {
+ _user = user;
+ }
+
+ public object Id
+ {
+ get { return _user.Id; }
+ set { _user.Id = (int)value; }
+ }
+
+ public string Name
+ {
+ get { return _user.Name; }
+ set { _user.Name = value; }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs
index 0b38c19a51..387a345039 100644
--- a/src/Umbraco.Core/Models/Template.cs
+++ b/src/Umbraco.Core/Models/Template.cs
@@ -187,7 +187,7 @@ namespace Umbraco.Core.Models
public void SetMasterTemplate(ITemplate masterTemplate)
{
- MasterTemplateId = new Lazy(() => {return masterTemplate.Id});
+ MasterTemplateId = new Lazy(() => masterTemplate.Id);
}
}
}
diff --git a/src/Umbraco.Core/Models/UmbracoEntity.cs b/src/Umbraco.Core/Models/UmbracoEntity.cs
index b735f385d8..4be916ce7d 100644
--- a/src/Umbraco.Core/Models/UmbracoEntity.cs
+++ b/src/Umbraco.Core/Models/UmbracoEntity.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Reflection;
using Umbraco.Core.Models.EntityBase;
@@ -53,6 +54,12 @@ namespace Umbraco.Core.Models
Trashed = trashed;
}
+ public UmbracoEntity(int trashed)
+ {
+ AdditionalData = new Dictionary();
+ Trashed = trashed == 1;
+ }
+
public int CreatorId
{
get { return _creatorId; }
diff --git a/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs
new file mode 100644
index 0000000000..207eea83b3
--- /dev/null
+++ b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs
@@ -0,0 +1,64 @@
+using System;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.Rdbms;
+
+namespace Umbraco.Core.Persistence.Factories
+{
+ internal class MemberGroupFactory : IEntityFactory
+ {
+
+ private readonly Guid _nodeObjectTypeId;
+
+ public MemberGroupFactory()
+ {
+ _nodeObjectTypeId = new Guid(Constants.ObjectTypes.MemberGroup);
+ }
+
+ #region Implementation of IEntityFactory
+
+ public IMemberGroup BuildEntity(NodeDto dto)
+ {
+ var template = new MemberGroup
+ {
+ CreateDate = dto.CreateDate,
+ Id = dto.NodeId,
+ Key = dto.UniqueId.Value,
+ Name = dto.Text
+ };
+
+ //on initial construction we don't want to have dirty properties tracked
+ // http://issues.umbraco.org/issue/U4-1946
+ template.ResetDirtyProperties(false);
+ return template;
+ }
+
+ public NodeDto BuildDto(IMemberGroup entity)
+ {
+ var dto = new NodeDto
+ {
+ CreateDate = entity.CreateDate,
+ NodeId = entity.Id,
+ Level = 0,
+ NodeObjectType = _nodeObjectTypeId,
+ ParentId = -1,
+ Path = "",
+ SortOrder = 0,
+ Text = entity.Name,
+ Trashed = false,
+ UniqueId = entity.Key,
+ UserId = entity.CreatorId
+ };
+
+ if (entity.HasIdentity)
+ {
+ dto.NodeId = entity.Id;
+ dto.Path = "-1," + entity.Id;
+ }
+
+ return dto;
+ }
+
+ #endregion
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
index d466b3b5ab..2739ede1af 100644
--- a/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
+++ b/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Persistence.Factories
CreateDate = dto.CreateDate,
UpdateDate = dto.UpdateDate,
Name = dto.Text,
- ProviderUserKey = dto.UniqueId.Value,
+ ProviderUserKey = dto.NodeId,
Trashed = dto.Trashed,
Key = dto.UniqueId.Value,
CreatorId = dto.UserId.HasValue ? dto.UserId.Value : 0,
diff --git a/src/Umbraco.Core/Persistence/Mappers/MemberGroupMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MemberGroupMapper.cs
new file mode 100644
index 0000000000..da57738403
--- /dev/null
+++ b/src/Umbraco.Core/Persistence/Mappers/MemberGroupMapper.cs
@@ -0,0 +1,34 @@
+using System.Collections.Concurrent;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.Rdbms;
+
+namespace Umbraco.Core.Persistence.Mappers
+{
+ [MapperFor(typeof (IMemberGroup))]
+ [MapperFor(typeof (MemberGroup))]
+ public sealed class MemberGroupMapper : BaseMapper
+ {
+ private static readonly ConcurrentDictionary PropertyInfoCacheInstance = new ConcurrentDictionary();
+
+ //NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
+ // otherwise that would fail because there is no public constructor.
+ public MemberGroupMapper()
+ {
+ BuildMap();
+ }
+
+ internal override ConcurrentDictionary PropertyInfoCache
+ {
+ get { return PropertyInfoCacheInstance; }
+ }
+
+ internal override void BuildMap()
+ {
+ CacheMap(src => src.Id, dto => dto.NodeId);
+ CacheMap(src => src.CreateDate, dto => dto.CreateDate);
+ CacheMap(src => src.CreatorId, dto => dto.UserId);
+ CacheMap(src => src.Name, dto => dto.Text);
+ CacheMap(src => src.Key, dto => dto.UniqueId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs
index d0d34478a4..361f1f3949 100644
--- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs
+++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs
@@ -79,7 +79,10 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
try
{
- _database.DropTable(tableName);
+ if (_database.TableExist(tableName))
+ {
+ _database.DropTable(tableName);
+ }
}
catch (Exception ex)
{
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
index 228b72b411..583af2d25c 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
@@ -24,8 +24,10 @@ namespace Umbraco.Core.Persistence.Repositories
private readonly IContentTypeRepository _contentTypeRepository;
private readonly ITemplateRepository _templateRepository;
private readonly ITagsRepository _tagRepository;
+ private readonly CacheHelper _cacheHelper;
public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository)
+ public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, CacheHelper cacheHelper)
: base(work)
{
if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository");
@@ -34,11 +36,13 @@ namespace Umbraco.Core.Persistence.Repositories
_contentTypeRepository = contentTypeRepository;
_templateRepository = templateRepository;
_tagRepository = tagRepository;
+ _cacheHelper = cacheHelper;
EnsureUniqueNaming = true;
}
public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository)
+ public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, CacheHelper cacheHelper)
: base(work, cache)
{
if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository");
@@ -47,6 +51,7 @@ namespace Umbraco.Core.Persistence.Repositories
_contentTypeRepository = contentTypeRepository;
_templateRepository = templateRepository;
_tagRepository = tagRepository;
+ _cacheHelper = cacheHelper;
EnsureUniqueNaming = true;
}
@@ -274,7 +279,7 @@ namespace Umbraco.Core.Persistence.Repositories
//Assign the same permissions to it as the parent node
// http://issues.umbraco.org/issue/U4-2161
- var permissionsRepo = new PermissionRepository(UnitOfWork);
+ var permissionsRepo = new PermissionRepository(UnitOfWork, _cacheHelper);
var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray();
//if there are parent permissions then assign them, otherwise leave null and permissions will become the
// user's default permissions.
@@ -557,13 +562,13 @@ namespace Umbraco.Core.Persistence.Repositories
public void AssignEntityPermissions(IContent entity, char permission, IEnumerable