Merge branch '6.2.0' of github.com:umbraco/Umbraco-CMS into 6.2.0

This commit is contained in:
Sebastiaan Janssen
2013-08-26 17:28:31 +02:00
13 changed files with 585 additions and 10 deletions

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;
namespace Umbraco.Core.Models.Membership
@@ -13,11 +15,123 @@ namespace Umbraco.Core.Models.Membership
/// </remarks>
[Serializable]
[DataContract(IsReference = true)]
[DebuggerDisplay("Id: {Id}")]
internal class Member : MemberProfile, IMembershipUser
{
public int Id { get; set; }
private bool _hasIdentity;
private int _id;
private Guid _key;
private DateTime _createDate;
private DateTime _updateDate;
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Member, int>(x => x.Id);
private static readonly PropertyInfo KeySelector = ExpressionHelper.GetPropertyInfo<Member, Guid>(x => x.Key);
private static readonly PropertyInfo CreateDateSelector = ExpressionHelper.GetPropertyInfo<Member, DateTime>(x => x.CreateDate);
private static readonly PropertyInfo UpdateDateSelector = ExpressionHelper.GetPropertyInfo<Member, DateTime>(x => x.UpdateDate);
private static readonly PropertyInfo HasIdentitySelector = ExpressionHelper.GetPropertyInfo<Member, bool>(x => x.HasIdentity);
/// <summary>
/// Integer Id
/// </summary>
[DataMember]
public new int Id
{
get
{
return _id;
}
set
{
SetPropertyValueAndDetectChanges(o =>
{
_id = value;
HasIdentity = true; //set the has Identity
return _id;
}, _id, IdSelector);
}
}
/// <summary>
/// Guid based Id
/// </summary>
/// <remarks>The key is currectly used to store the Unique Id from the
/// umbracoNode table, which many of the entities are based on.</remarks>
[DataMember]
public Guid Key
{
get
{
if (_key == Guid.Empty)
return _id.ToGuid();
return _key;
}
set
{
SetPropertyValueAndDetectChanges(o =>
{
_key = value;
return _key;
}, _key, KeySelector);
}
}
/// <summary>
/// Gets or sets the Created Date
/// </summary>
[DataMember]
public DateTime CreateDate
{
get { return _createDate; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_createDate = value;
return _createDate;
}, _createDate, CreateDateSelector);
}
}
/// <summary>
/// Gets or sets the Modified Date
/// </summary>
[DataMember]
public DateTime UpdateDate
{
get { return _updateDate; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_updateDate = value;
return _updateDate;
}, _updateDate, UpdateDateSelector);
}
}
/// <summary>
/// Indicates whether the current entity has an identity, eg. Id.
/// </summary>
public virtual bool HasIdentity
{
get
{
return _hasIdentity;
}
protected set
{
SetPropertyValueAndDetectChanges(o =>
{
_hasIdentity = value;
return _hasIdentity;
}, _hasIdentity, HasIdentitySelector);
}
}
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string PasswordQuestion { get; set; }
public string PasswordAnswer { get; set; }
@@ -28,11 +142,18 @@ namespace Umbraco.Core.Models.Membership
public DateTime LastLoginDate { get; set; }
public DateTime LastPasswordChangeDate { get; set; }
public DateTime LastLockoutDate { get; set; }
public object ProfileId { get; set; }
public IEnumerable<object> Groups { get; set; }
public Guid Key { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
public bool HasIdentity { get; private set; }
#region Internal methods
internal virtual void ResetIdentity()
{
_hasIdentity = false;
_id = default(int);
}
#endregion
}
}

View File

@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models.Membership
/// <summary>
/// Initializes a new instance of the <see cref="Profile"/> class.
/// </summary>
public Profile()
protected Profile()
{
ProviderUserKeyType = typeof(int);
}
@@ -29,14 +29,16 @@ namespace Umbraco.Core.Models.Membership
private object _id;
private string _name;
private object _providerUserKey;
private Type _userTypeKey;
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Profile, object>(x => x.Id);
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Profile, string>(x => x.Name);
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Profile, object>(x => x.ProviderUserKey);
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Profile, Type>(x => x.ProviderUserKeyType);
[DataMember]
public object Id
public virtual object Id
{
get
{
@@ -53,7 +55,7 @@ namespace Umbraco.Core.Models.Membership
}
[DataMember]
public string Name
public virtual string Name
{
get
{
@@ -72,8 +74,18 @@ namespace Umbraco.Core.Models.Membership
[IgnoreDataMember]
public virtual object ProviderUserKey
{
get { throw new System.NotImplementedException(); }
set { throw new System.NotImplementedException(); }
get
{
return _providerUserKey;
}
set
{
SetPropertyValueAndDetectChanges(o =>
{
_providerUserKey = value;
return _id;
}, _providerUserKey, ProviderUserKeySelector);
}
}
/// <summary>

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Persistence;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoNode")]
[PrimaryKey("id")]
[ExplicitColumns]
public class MemberReadOnlyDto
{
/* from umbracoNode */
[Column("id")]
public int NodeId { get; set; }
[Column("trashed")]
public bool Trashed { get; set; }
[Column("parentID")]
public int ParentId { get; set; }
[Column("nodeUser")]
public int? UserId { get; set; }
[Column("level")]
public short Level { get; set; }
[Column("path")]
public string Path { get; set; }
[Column("sortOrder")]
public int SortOrder { get; set; }
[Column("uniqueID")]
public Guid? UniqueId { get; set; }
[Column("text")]
public string Text { get; set; }
[Column("nodeObjectType")]
public Guid? NodeObjectType { get; set; }
[Column("createDate")]
public DateTime CreateDate { get; set; }
/* from cmsContentType joined with cmsContent */
[Column("ContentTypeAlias")]
public string ContentTypeAlias { get; set; }
/* cmsContentVersion */
[Column("VersionId")]
public Guid VersionId { get; set; }
[Column("VersionDate")]
public DateTime UpdateDate { get; set; }
[Column("LanguageLocale")]
public string Language { get; set; }
/* cmsMember */
[Column("Email")]
public string Email { get; set; }
[Column("LoginName")]
public string LoginName { get; set; }
[Column("Password")]
public string Password { get; set; }
/* Properties */
[ResultColumn]
public List<PropertyDataReadOnlyDto> Properties { get; set; }
}
}

View File

@@ -0,0 +1,65 @@
using System;
using Umbraco.Core.Persistence;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("cmsPropertyData")]
[PrimaryKey("id")]
[ExplicitColumns]
public class PropertyDataReadOnlyDto
{
/* cmsPropertyData */
[Column("id")]
public int Id { get; set; }
[Column("contentNodeId")]
public int NodeId { get; set; }
[Column("VersionId")]
public Guid? VersionId { get; set; }
[Column("propertytypeid")]
public int PropertyTypeId { get; set; }
[Column("dataInt")]
public int? Integer { get; set; }
[Column("dataDate")]
public DateTime? Date { get; set; }
[Column("dataNvarchar")]
public string VarChar { get; set; }
[Column("dataNtext")]
public string Text { get; set; }
/* cmsPropertyType */
[Column("dataTypeId")]
public int DataTypeId { get; set; }
[Column("propertyTypeGroupId")]
public int? PropertyTypeGroupId { get; set; }
[Column("Alias")]
public string Alias { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("helpText")]
public string HelpText { get; set; }
[Column("mandatory")]
public bool Mandatory { get; set; }
[Column("validationRegExp")]
public string ValidationRegExp { get; set; }
[Column("Description")]
public string Description { get; set; }
/* cmsDataType */
[Column("controlId")]
public Guid ControlId { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
using System.Collections.Generic;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Relators
{
internal class PropertyDataRelator
{
internal MemberReadOnlyDto Current;
internal MemberReadOnlyDto Map(MemberReadOnlyDto a, PropertyDataReadOnlyDto p)
{
// Terminating call. Since we can return null from this function
// we need to be ready for PetaPoco to callback later with null
// parameters
if (a == null)
return Current;
// Is this the same MemberReadOnlyDto as the current one we're processing
if (Current != null && Current.UniqueId == a.UniqueId)
{
// Yes, just add this PropertyDataReadOnlyDto to the current MemberReadOnlyDto's collection
Current.Properties.Add(p);
// Return null to indicate we're not done with this MemberReadOnlyDto yet
return null;
}
// This is a different MemberReadOnlyDto to the current one, or this is the
// first time through and we don't have a Tab yet
// Save the current MemberReadOnlyDto
var prev = Current;
// Setup the new current MemberReadOnlyDto
Current = a;
Current.Properties = new List<PropertyDataReadOnlyDto>();
Current.Properties.Add(p);
// Return the now populated previous MemberReadOnlyDto (or null if first time through)
return prev;
}
}
}

View File

@@ -0,0 +1,9 @@
using Umbraco.Core.Models.Membership;
namespace Umbraco.Core.Persistence.Repositories
{
internal interface IMemberRepository : IRepositoryVersionable<int, IMembershipUser>
{
}
}

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Core.Persistence.Repositories
{
public class MemberGroupRepository
{
}
}

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Relators;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
{
internal class MemberRepository : VersionableRepositoryBase<int, IMembershipUser>, IMemberRepository
{
public MemberRepository(IDatabaseUnitOfWork work) : base(work)
{
}
public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache) : base(work, cache)
{
}
/* The following methods might be relevant for this specific repository (in an optimized form)
* GetById - get a member by its integer Id
* GetByKey - get a member by its unique guid Id (which should correspond to a membership provider user's id)
* GetByPropertyValue - get members with a certain property value (supply both property alias and value?)
* GetByMemberTypeAlias - get all members of a certain type
* GetByMemberGroup - get all members in a specific group
* GetAllMembers
*/
#region Overrides of RepositoryBase<int, IMembershipUser>
protected override IMembershipUser PerformGet(int id)
{
var sql = GetBaseQuery(false);
sql.Where(GetBaseWhereClause(), new { Id = id });
sql.OrderByDescending<ContentVersionDto>(x => x.VersionDate);
var dto =
Database.Fetch<MemberReadOnlyDto, PropertyDataReadOnlyDto, MemberReadOnlyDto>(
new PropertyDataRelator().Map, sql);
if (dto == null || dto.Any() == false)
return null;
return new Member();
}
protected override IEnumerable<IMembershipUser> PerformGetAll(params int[] ids)
{
throw new NotImplementedException();
}
protected override IEnumerable<IMembershipUser> PerformGetByQuery(IQuery<IMembershipUser> query)
{
throw new NotImplementedException();
}
#endregion
#region Overrides of PetaPocoRepositoryBase<int,IMembershipUser>
protected override Sql GetBaseQuery(bool isCount)
{
//TODO Count
var sql = new Sql();
sql.Select("umbracoNode.*", "cmsContentType.alias AS ContentTypeAlias", "cmsContentVersion.VersionId",
"cmsContentVersion.VersionDate", "cmsContentVersion.LanguageLocale", "cmsMember.Email",
"cmsMember.LoginName", "cmsMember.Password", "cmsPropertyData.id", "cmsPropertyData.dataDate",
"cmsPropertyData.dataInt", "cmsPropertyData.dataNtext", "cmsPropertyData.dataNvarchar",
"cmsPropertyData.propertytypeid", "cmsPropertyType.Alias", "cmsPropertyType.Description",
"cmsPropertyType.Name", "cmsPropertyType.mandatory", "cmsPropertyType.validationRegExp",
"cmsPropertyType.helpText", "cmsPropertyType.propertyTypeGroupId", "cmsPropertyType.dataTypeId",
"cmsDataType.controlId")
.From<NodeDto>()
.InnerJoin<ContentDto>().On<ContentDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.InnerJoin<ContentTypeDto>().On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId)
.InnerJoin<ContentVersionDto>().On<ContentVersionDto, NodeDto>(left => left.NodeId, right => right.NodeId)
.InnerJoin<MemberDto>().On<MemberDto, ContentDto>(left => left.NodeId, right => right.NodeId)
.LeftJoin<PropertyDataDto>().On<PropertyDataDto, ContentVersionDto>(left => left.VersionId, right => right.VersionId)
.LeftJoin<PropertyTypeDto>().On<PropertyTypeDto, PropertyDataDto>(left => left.Id, right => right.PropertyTypeId)
.LeftJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
return sql;
}
protected override string GetBaseWhereClause()
{
return "umbracoNode.id = @Id";
}
protected override IEnumerable<string> GetDeleteClauses()
{
throw new NotImplementedException();
}
protected override Guid NodeObjectTypeId
{
get { return new Guid(Constants.ObjectTypes.Member); }
}
#endregion
#region Unit of Work Implementation
protected override void PersistNewItem(IMembershipUser entity)
{
throw new NotImplementedException();
}
protected override void PersistUpdatedItem(IMembershipUser entity)
{
throw new NotImplementedException();
}
#endregion
#region Overrides of VersionableRepositoryBase<IMembershipUser>
public override IMembershipUser GetByVersion(Guid versionId)
{
throw new NotImplementedException();
}
protected override void PerformDeleteVersion(int id, Guid versionId)
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Core.Persistence.Repositories
{
public class MemberTypeRepository
{
}
}

View File

@@ -115,6 +115,11 @@ namespace Umbraco.Core.Persistence
CreateUserTypeRepository(uow));
}
internal virtual IMemberRepository CreateMemberRepository(IDatabaseUnitOfWork uow)
{
return new MemberRepository(uow, RuntimeCacheProvider.Current);
}
internal virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
{
return new EntityRepository(uow);

View File

@@ -201,6 +201,8 @@
<Compile Include="Models\IFile.cs" />
<Compile Include="Models\ILanguage.cs" />
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
<Compile Include="Models\Rdbms\MemberReadOnlyDto.cs" />
<Compile Include="Models\Rdbms\PropertyDataReadOnlyDto.cs" />
<Compile Include="Models\ServerRegistration.cs" />
<Compile Include="Models\ITemplate.cs" />
<Compile Include="Models\Language.cs" />
@@ -468,6 +470,7 @@
<Compile Include="Persistence\Querying\Query.cs" />
<Compile Include="Persistence\Querying\SqlTranslator.cs" />
<Compile Include="Persistence\Relators\DictionaryLanguageTextRelator.cs" />
<Compile Include="Persistence\Relators\PropertyDataRelator.cs" />
<Compile Include="Persistence\Relators\UserSectionRelator.cs" />
<Compile Include="Persistence\Repositories\ContentRepository.cs" />
<Compile Include="Persistence\Repositories\ContentTypeBaseRepository.cs" />
@@ -484,6 +487,7 @@
<Compile Include="Persistence\Repositories\Interfaces\ILanguageRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IMediaRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IMediaTypeRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IMemberRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IRelationRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IRelationTypeRepository.cs" />
<Compile Include="Persistence\Repositories\Interfaces\IRepositoryQueryable.cs" />
@@ -498,6 +502,9 @@
<Compile Include="Persistence\Repositories\LanguageRepository.cs" />
<Compile Include="Persistence\Repositories\MediaRepository.cs" />
<Compile Include="Persistence\Repositories\MediaTypeRepository.cs" />
<Compile Include="Persistence\Repositories\MemberGroupRepository.cs" />
<Compile Include="Persistence\Repositories\MemberRepository.cs" />
<Compile Include="Persistence\Repositories\MemberTypeRepository.cs" />
<Compile Include="Persistence\Repositories\PermissionRepository.cs" />
<Compile Include="Persistence\Repositories\PetaPocoRepositoryBase.cs" />
<Compile Include="Persistence\Repositories\RecycleBinRepository.cs" />

View File

@@ -0,0 +1,91 @@
using System;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Persistence.Repositories
{
[TestFixture, NUnit.Framework.Ignore]
public abstract class MemberRepositoryTest : MemberRepositoryBaseTest
{
private Database _database;
#region Overrides of MemberRepositoryBaseTest
[SetUp]
public override void Initialize()
{
base.Initialize();
SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider;
_database = new Database(@"server=.\SQLEXPRESS;database=EmptyForTest;user id=umbraco;password=umbraco",
"System.Data.SqlClient");
}
[TearDown]
public override void TearDown()
{
base.TearDown();
}
public override Database Database
{
get { return _database; }
}
#endregion
}
[TestFixture]
public abstract class MemberRepositoryBaseTest
{
[SetUp]
public virtual void Initialize()
{
TestHelper.SetupLog4NetForTests();
TestHelper.InitializeContentDirectories();
string path = TestHelper.CurrentAssemblyDirectory;
AppDomain.CurrentDomain.SetData("DataDirectory", path);
RepositoryResolver.Current = new RepositoryResolver(
new RepositoryFactory());
ApplicationContext.Current = new ApplicationContext(
//assign the db context
new DatabaseContext(new DefaultDatabaseFactory()),
//assign the service context
new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy()),
//disable cache
false)
{
IsReady = true
};
Resolution.Freeze();
}
[TearDown]
public virtual void TearDown()
{
SqlSyntaxContext.SqlSyntaxProvider = null;
AppDomain.CurrentDomain.SetData("DataDirectory", null);
//reset the app context
ApplicationContext.Current = null;
RepositoryResolver.Reset();
}
public abstract Database Database { get; }
}
}

View File

@@ -188,6 +188,7 @@
<Compile Include="Models\ContentExtensionsTests.cs" />
<Compile Include="Models\DataValueSetterTests.cs" />
<Compile Include="Persistence\PetaPocoExtensionsTest.cs" />
<Compile Include="Persistence\Repositories\MemberRepositoryTest.cs" />
<Compile Include="Persistence\Repositories\UserRepositoryTest.cs" />
<Compile Include="Persistence\Repositories\UserTypeRepositoryTest.cs" />
<Compile Include="Services\PackagingServiceTests.cs" />