diff --git a/src/Umbraco.Core/Models/Membership/IMember.cs b/src/Umbraco.Core/Models/Membership/IMember.cs new file mode 100644 index 0000000000..2cd41c8a5d --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/IMember.cs @@ -0,0 +1,12 @@ +namespace Umbraco.Core.Models.Membership +{ + internal interface IMember : IMembershipUser, IMemberProfile + { + new int Id { get; set; } + } + + internal interface IMemberProfile : IProfile + { + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs index b80faeee10..422b47da22 100644 --- a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs +++ b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Models.Membership { internal interface IMembershipUser : IMembershipUserId, IAggregateRoot { - new object Id { get; set; } + /*new object Id { get; set; }*/ string Username { get; set; } string Email { get; set; } string Password { get; set; } @@ -16,10 +16,6 @@ namespace Umbraco.Core.Models.Membership bool IsApproved { get; set; } bool IsOnline { get; set; } bool IsLockedOut { get; set; } - //Was CreationDate - //DateTime CreateDate { get; set; } - //LastActivityDate - //DateTime UpdateDate { get; set; } DateTime LastLoginDate { get; set; } DateTime LastPasswordChangeDate { get; set; } DateTime LastLockoutDate { get; set; } diff --git a/src/Umbraco.Core/Models/Membership/Member.cs b/src/Umbraco.Core/Models/Membership/Member.cs index 8fb688462a..640c7aa8a9 100644 --- a/src/Umbraco.Core/Models/Membership/Member.cs +++ b/src/Umbraco.Core/Models/Membership/Member.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Diagnostics; using System.Reflection; using System.Runtime.Serialization; @@ -17,27 +16,24 @@ namespace Umbraco.Core.Models.Membership [Serializable] [DataContract(IsReference = true)] [DebuggerDisplay("Id: {Id}")] - internal class Member : MemberProfile, IMembershipUser + internal class Member : MemberProfile, IMember { private bool _hasIdentity; private int _id; private Guid _key; private DateTime _createDate; private DateTime _updateDate; - private PropertyCollection _properties; + private int _contentTypeId; + private string _contentTypeAlias; private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo(x => x.Id); private static readonly PropertyInfo KeySelector = ExpressionHelper.GetPropertyInfo(x => x.Key); private static readonly PropertyInfo CreateDateSelector = ExpressionHelper.GetPropertyInfo(x => x.CreateDate); private static readonly PropertyInfo UpdateDateSelector = ExpressionHelper.GetPropertyInfo(x => x.UpdateDate); private static readonly PropertyInfo HasIdentitySelector = ExpressionHelper.GetPropertyInfo(x => x.HasIdentity); - private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties); - - protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(PropertyCollectionSelector); - } - + private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeId); + private static readonly PropertyInfo DefaultContentTypeAliasSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeAlias); + /// /// Integer Id /// @@ -386,20 +382,49 @@ namespace Umbraco.Core.Models.Membership [IgnoreDataMember] public bool IsOnline { get; set; } - public object ProfileId { get; set; } - public IEnumerable Groups { get; set; } - + /// + /// Guid Id of the curent Version + /// [DataMember] - public PropertyCollection Properties + public Guid Version { get; internal set; } + + /// + /// Integer Id of the default ContentType + /// + [DataMember] + public virtual int ContentTypeId { - get { return _properties; } - set + get { return _contentTypeId; } + internal set { - _properties = value; - _properties.CollectionChanged += PropertiesChanged; + SetPropertyValueAndDetectChanges(o => + { + _contentTypeId = value; + return _contentTypeId; + }, _contentTypeId, DefaultContentTypeIdSelector); } } + /// + /// String alias of the default ContentType + /// + [DataMember] + public virtual string ContentTypeAlias + { + get { return _contentTypeAlias; } + internal set + { + SetPropertyValueAndDetectChanges(o => + { + _contentTypeAlias = value; + return _contentTypeAlias; + }, _contentTypeAlias, DefaultContentTypeAliasSelector); + } + } + + public object ProfileId { get; set; } + public IEnumerable Groups { get; set; } + #region Internal methods internal virtual void ResetIdentity() diff --git a/src/Umbraco.Core/Models/Membership/MemberProfile.cs b/src/Umbraco.Core/Models/Membership/MemberProfile.cs index 6bf7eb33d3..2148cd1ca2 100644 --- a/src/Umbraco.Core/Models/Membership/MemberProfile.cs +++ b/src/Umbraco.Core/Models/Membership/MemberProfile.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Specialized; using System.Reflection; +using System.Runtime.Serialization; using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models.Membership @@ -12,6 +14,7 @@ namespace Umbraco.Core.Models.Membership private string _path; private int _creatorId; private bool _trashed; + private PropertyCollection _properties; private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => ((IUmbracoEntity)x).ParentId); private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => ((IUmbracoEntity)x).SortOrder); @@ -19,6 +22,12 @@ namespace Umbraco.Core.Models.Membership private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => ((IUmbracoEntity)x).Path); private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo(x => ((IUmbracoEntity)x).CreatorId); private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed); + private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties); + + protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) + { + OnPropertyChanged(PropertyCollectionSelector); + } public abstract new int Id { get; set; } public abstract Guid Key { get; set; } @@ -29,6 +38,7 @@ namespace Umbraco.Core.Models.Membership /// /// Profile of the user who created this Content /// + [DataMember] int IUmbracoEntity.CreatorId { get @@ -48,7 +58,8 @@ namespace Umbraco.Core.Models.Membership /// /// Gets or sets the level of the content entity /// - int IUmbracoEntity.Level + [DataMember] + int IUmbracoEntity.Level { get { return _level; } set @@ -63,6 +74,7 @@ namespace Umbraco.Core.Models.Membership /// /// Gets or sets the Id of the Parent entity /// + [DataMember] int IUmbracoEntity.ParentId { get @@ -84,6 +96,7 @@ namespace Umbraco.Core.Models.Membership /// /// Gets or sets the path /// + [DataMember] string IUmbracoEntity.Path { get { return _path; } @@ -100,6 +113,7 @@ namespace Umbraco.Core.Models.Membership /// /// Gets or sets the sort order of the content entity /// + [DataMember] int IUmbracoEntity.SortOrder { get { return _sortOrder; } @@ -117,6 +131,7 @@ namespace Umbraco.Core.Models.Membership /// Boolean indicating whether this Content is Trashed or not. /// If Content is Trashed it will be located in the Recyclebin. /// + [DataMember] public virtual bool Trashed { get { return _trashed; } @@ -129,5 +144,16 @@ namespace Umbraco.Core.Models.Membership }, _trashed, TrashedSelector); } } + + [DataMember] + public PropertyCollection Properties + { + get { return _properties; } + set + { + _properties = value; + _properties.CollectionChanged += PropertiesChanged; + } + } } } \ 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 67c6a29e37..fb8010a28d 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs @@ -8,9 +8,9 @@ using Umbraco.Core.Models.Rdbms; namespace Umbraco.Core.Persistence.Factories { - internal class MemberReadOnlyFactory : IEntityFactory + internal class MemberReadOnlyFactory : IEntityFactory { - public IMembershipUser BuildEntity(MemberReadOnlyDto dto) + public IMember BuildEntity(MemberReadOnlyDto dto) { var member = new Member { @@ -24,7 +24,9 @@ namespace Umbraco.Core.Persistence.Factories ProviderUserKey = dto.UniqueId, Trashed = dto.Trashed, Key = dto.UniqueId.Value, - ProfileId = dto.UniqueId.Value + ProfileId = dto.UniqueId.Value, + ContentTypeId = dto.ContentTypeId, + ContentTypeAlias = dto.ContentTypeAlias }; ((IUmbracoEntity)member).CreatorId = dto.UserId.Value; @@ -55,7 +57,7 @@ namespace Umbraco.Core.Persistence.Factories return member; } - public MemberReadOnlyDto BuildDto(IMembershipUser entity) + public MemberReadOnlyDto BuildDto(IMember entity) { throw new System.NotImplementedException(); } diff --git a/src/Umbraco.Core/Persistence/Mappers/MemberMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MemberMapper.cs new file mode 100644 index 0000000000..cf32d1edd3 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Mappers/MemberMapper.cs @@ -0,0 +1,67 @@ +using System.Collections.Concurrent; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Mappers +{ + /// + /// Represents a to DTO mapper used to translate the properties of the public api + /// implementation to that of the database's DTO as sql: [tableName].[columnName]. + /// + [MapperFor(typeof(IMember))] + [MapperFor(typeof(Member))] + public sealed class MemberMapper : 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 MemberMapper() + { + BuildMap(); + } + + #region Overrides of BaseMapper + + 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 => ((IUmbracoEntity)src).Level, dto => dto.Level); + CacheMap(src => ((IUmbracoEntity)src).ParentId, dto => dto.ParentId); + CacheMap(src => ((IUmbracoEntity)src).Path, dto => dto.Path); + CacheMap(src => ((IUmbracoEntity)src).SortOrder, dto => dto.SortOrder); + CacheMap(src => ((IUmbracoEntity)src).CreatorId, dto => dto.UserId); + CacheMap(src => src.Name, dto => dto.Text); + CacheMap(src => src.Trashed, dto => dto.Trashed); + CacheMap(src => src.Key, dto => dto.UniqueId); + CacheMap(src => src.ProfileId, dto => dto.UniqueId); + CacheMap(src => src.ContentTypeId, dto => dto.ContentTypeId); + CacheMap(src => src.ContentTypeAlias, dto => dto.Alias); + CacheMap(src => src.UpdateDate, dto => dto.VersionDate); + CacheMap(src => src.Version, dto => dto.VersionId); + + CacheMap(src => src.Email, dto => dto.Email); + CacheMap(src => src.Username, dto => dto.LoginName); + CacheMap(src => src.Password, dto => dto.Password); + + CacheMap(src => src.IsApproved, dto => dto.Integer); + CacheMap(src => src.IsLockedOut, dto => dto.Integer); + CacheMap(src => src.Comments, dto => dto.Text); + CacheMap(src => src.PasswordAnswer, dto => dto.VarChar); + CacheMap(src => src.PasswordQuestion, dto => dto.VarChar); + CacheMap(src => src.FailedPasswordAttempts, dto => dto.Integer); + CacheMap(src => src.LastLockoutDate, dto => dto.Date); + CacheMap(src => src.LastLoginDate, dto => dto.Date); + CacheMap(src => src.LastPasswordChangeDate, dto => dto.Date); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs index 9ce6642e3b..616e10286b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs @@ -2,7 +2,7 @@ namespace Umbraco.Core.Persistence.Repositories { - internal interface IMemberRepository : IRepositoryVersionable + internal interface IMemberRepository : IRepositoryVersionable { } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index cb93a00185..d18eb4fb87 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -11,7 +11,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { - internal class MemberRepository : VersionableRepositoryBase, IMemberRepository + internal class MemberRepository : VersionableRepositoryBase, IMemberRepository { public MemberRepository(IDatabaseUnitOfWork work) : base(work) { @@ -33,7 +33,7 @@ namespace Umbraco.Core.Persistence.Repositories #region Overrides of RepositoryBase - protected override IMembershipUser PerformGet(int id) + protected override IMember PerformGet(int id) { var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); @@ -52,12 +52,12 @@ namespace Umbraco.Core.Persistence.Repositories return member; } - protected override IEnumerable PerformGetAll(params int[] ids) + protected override IEnumerable PerformGetAll(params int[] ids) { throw new NotImplementedException(); } - protected override IEnumerable PerformGetByQuery(IQuery query) + protected override IEnumerable PerformGetByQuery(IQuery query) { throw new NotImplementedException(); } @@ -110,12 +110,12 @@ namespace Umbraco.Core.Persistence.Repositories #region Unit of Work Implementation - protected override void PersistNewItem(IMembershipUser entity) + protected override void PersistNewItem(IMember entity) { throw new NotImplementedException(); } - protected override void PersistUpdatedItem(IMembershipUser entity) + protected override void PersistUpdatedItem(IMember entity) { throw new NotImplementedException(); } @@ -124,7 +124,7 @@ namespace Umbraco.Core.Persistence.Repositories #region Overrides of VersionableRepositoryBase - public override IMembershipUser GetByVersion(Guid versionId) + public override IMember GetByVersion(Guid versionId) { throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 32a07f80f8..c20863a8e0 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -200,6 +200,7 @@ + @@ -264,6 +265,7 @@ +