backports missing logic and tests from 7 that I overlooked.
This commit is contained in:
@@ -236,8 +236,7 @@ namespace Umbraco.Core
|
||||
},
|
||||
{
|
||||
PasswordQuestion,
|
||||
new PropertyType(new Guid(PropertyEditors.Textbox), DataTypeDatabaseType
|
||||
.Nvarchar)
|
||||
new PropertyType(new Guid(PropertyEditors.Textbox), DataTypeDatabaseType.Nvarchar)
|
||||
{
|
||||
Alias = PasswordQuestion,
|
||||
Name = PasswordQuestionLabel
|
||||
|
||||
@@ -20,6 +20,17 @@ namespace Umbraco.Core.Models
|
||||
private object _providerUserKey;
|
||||
private Type _userTypeKey;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for creating a Member object
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the content</param>
|
||||
/// <param name="contentType">ContentType for the current Content object</param>
|
||||
public Member(string name, IMemberType contentType)
|
||||
: base(name, -1, contentType, new PropertyCollection())
|
||||
{
|
||||
_contentType = contentType;
|
||||
}
|
||||
|
||||
internal Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
|
||||
: base(name, parentId, contentType, new PropertyCollection())
|
||||
{
|
||||
|
||||
@@ -22,14 +22,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
private readonly IMemberTypeRepository _memberTypeRepository;
|
||||
|
||||
public MemberRepository(IDatabaseUnitOfWork work, IMemberTypeRepository memberTypeRepository) : base(work)
|
||||
public MemberRepository(IDatabaseUnitOfWork work, IMemberTypeRepository memberTypeRepository)
|
||||
: base(work)
|
||||
{
|
||||
if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository");
|
||||
_memberTypeRepository = memberTypeRepository;
|
||||
}
|
||||
|
||||
public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMemberTypeRepository memberTypeRepository)
|
||||
: base(work, cache)
|
||||
{
|
||||
if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository");
|
||||
_memberTypeRepository = memberTypeRepository;
|
||||
}
|
||||
|
||||
@@ -104,11 +107,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
sql.Select("umbracoNode.*", "cmsContent.contentType", "cmsContentType.alias AS ContentTypeAlias", "cmsContentVersion.VersionId",
|
||||
"cmsContentVersion.VersionDate", "cmsContentVersion.LanguageLocale", "cmsMember.Email",
|
||||
"cmsMember.LoginName", "cmsMember.Password", "cmsPropertyData.id AS PropertyDataId", "cmsPropertyData.propertytypeid",
|
||||
"cmsMember.LoginName", "cmsMember.Password", "cmsPropertyData.id AS PropertyDataId", "cmsPropertyData.propertytypeid",
|
||||
"cmsPropertyData.dataDate", "cmsPropertyData.dataInt", "cmsPropertyData.dataNtext", "cmsPropertyData.dataNvarchar",
|
||||
"cmsPropertyType.id", "cmsPropertyType.Alias", "cmsPropertyType.Description",
|
||||
"cmsPropertyType.Name", "cmsPropertyType.mandatory", "cmsPropertyType.validationRegExp",
|
||||
"cmsPropertyType.helpText", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", "cmsPropertyType.propertyTypeGroupId",
|
||||
"cmsPropertyType.helpText", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", "cmsPropertyType.propertyTypeGroupId",
|
||||
"cmsPropertyType.dataTypeId", "cmsDataType.controlId", "cmsDataType.dbType")
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentDto>().On<ContentDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
@@ -247,7 +250,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
property.Id = keyDictionary[property.PropertyTypeId];
|
||||
}
|
||||
|
||||
|
||||
((Member)entity).ResetDirtyProperties();
|
||||
}
|
||||
|
||||
@@ -256,8 +259,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//Updates Modified date
|
||||
((Member)entity).UpdatingEntity();
|
||||
|
||||
var dirtyEntity = (ICanBeDirty)entity;
|
||||
|
||||
//Look up parent to get and set the correct Path and update SortOrder if ParentId has changed
|
||||
if (((ICanBeDirty)entity).IsPropertyDirty("ParentId"))
|
||||
if (dirtyEntity.IsPropertyDirty("ParentId"))
|
||||
{
|
||||
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = ((IUmbracoEntity)entity).ParentId });
|
||||
((IUmbracoEntity)entity).Path = string.Concat(parent.Path, ",", entity.Id);
|
||||
@@ -293,13 +298,32 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//Updates the current version - cmsContentVersion
|
||||
//Assumes a Version guid exists and Version date (modified date) has been set/updated
|
||||
Database.Update(dto.ContentVersionDto);
|
||||
//Updates the cmsMember entry
|
||||
Database.Update(dto);
|
||||
|
||||
//Updates the cmsMember entry if it has changed
|
||||
var changedCols = new List<string>();
|
||||
if (dirtyEntity.IsPropertyDirty("Email"))
|
||||
{
|
||||
changedCols.Add("Email");
|
||||
}
|
||||
if (dirtyEntity.IsPropertyDirty("Username"))
|
||||
{
|
||||
changedCols.Add("LoginName");
|
||||
}
|
||||
// DO NOT update the password if it is null or empty
|
||||
if (dirtyEntity.IsPropertyDirty("Password") && entity.Password.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
changedCols.Add("Password");
|
||||
}
|
||||
//only update the changed cols
|
||||
if (changedCols.Count > 0)
|
||||
{
|
||||
Database.Update(dto, changedCols);
|
||||
}
|
||||
|
||||
//TODO ContentType for the Member entity
|
||||
|
||||
//Create the PropertyData for this version - cmsPropertyData
|
||||
var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
|
||||
var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
|
||||
var keyDictionary = new Dictionary<int, int>();
|
||||
|
||||
//Add Properties
|
||||
@@ -333,8 +357,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
property.Id = keyDictionary[property.PropertyTypeId];
|
||||
}
|
||||
}
|
||||
|
||||
((ICanBeDirty)entity).ResetDirtyProperties();
|
||||
|
||||
dirtyEntity.ResetDirtyProperties();
|
||||
}
|
||||
|
||||
protected override void PersistDeletedItem(IMember entity)
|
||||
@@ -416,9 +440,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public bool Exists(string username)
|
||||
{
|
||||
var sql = new Sql();
|
||||
var escapedUserName = Database.EscapeAtSymbols(username);
|
||||
sql.Select("COUNT(*)")
|
||||
.From<MemberDto>()
|
||||
.Where<MemberDto>(x => x.LoginName == username);
|
||||
.Where<MemberDto>(x => x.LoginName == escapedUserName);
|
||||
|
||||
return Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Umbraco.Core.Services
|
||||
IEnumerable<IMember> GetMembersByGroup(string memberGroupName);
|
||||
IEnumerable<IMember> GetAllMembers(params int[] ids);
|
||||
|
||||
//TODO: Need to get all members that start with a certain letter
|
||||
|
||||
void DeleteMembersOfType(int memberTypeId);
|
||||
}
|
||||
|
||||
@@ -51,7 +53,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
void Delete(IMember membershipUser);
|
||||
|
||||
void Save(IMember membershipUser);
|
||||
void Save(IMember membershipUser, bool raiseEvents = true);
|
||||
|
||||
IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch);
|
||||
}
|
||||
|
||||
@@ -393,8 +393,15 @@ namespace Umbraco.Core.Services
|
||||
/// Saves an updated Member
|
||||
/// </summary>
|
||||
/// <param name="member"></param>
|
||||
public void Save(IMember member)
|
||||
/// <param name="raiseEvents"></param>
|
||||
public void Save(IMember member, bool raiseEvents = true)
|
||||
{
|
||||
if (raiseEvents)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(member), this))
|
||||
return;
|
||||
}
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
|
||||
{
|
||||
@@ -404,6 +411,9 @@ namespace Umbraco.Core.Services
|
||||
var xml = member.ToXml();
|
||||
CreateAndSaveMemberXml(xml, member.Id, uow.Database);
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
Saved.RaiseEvent(new SaveEventArgs<IMember>(member, false), this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -483,14 +493,91 @@ namespace Umbraco.Core.Services
|
||||
int result = exists ? db.Update(poco) : Convert.ToInt32(db.Insert(poco));
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IMemberService, DeleteEventArgs<IMember>> Deleting;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IMemberService, DeleteEventArgs<IMember>> Deleted;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IMemberService, SaveEventArgs<IMember>> Saving;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IMemberService, SaveEventArgs<IMember>> Saved;
|
||||
|
||||
#endregion
|
||||
|
||||
///// <summary>
|
||||
///// A helper method that will create a basic/generic member for use with a generic membership provider
|
||||
///// </summary>
|
||||
///// <returns></returns>
|
||||
//internal static IMember CreateGenericMembershipProviderMember(string name, string email, string username, string password)
|
||||
//{
|
||||
// var identity = int.MaxValue;
|
||||
|
||||
// var memType = new MemberType(-1);
|
||||
// var propGroup = new PropertyGroup
|
||||
// {
|
||||
// Name = "Membership",
|
||||
// Id = --identity
|
||||
// };
|
||||
// propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext)
|
||||
// {
|
||||
// Alias = Constants.Conventions.Member.Comments,
|
||||
// Name = Constants.Conventions.Member.CommentsLabel,
|
||||
// SortOrder = 0,
|
||||
// Id = --identity
|
||||
// });
|
||||
// propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer)
|
||||
// {
|
||||
// Alias = Constants.Conventions.Member.IsApproved,
|
||||
// Name = Constants.Conventions.Member.IsApprovedLabel,
|
||||
// SortOrder = 3,
|
||||
// Id = --identity
|
||||
// });
|
||||
// propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer)
|
||||
// {
|
||||
// Alias = Constants.Conventions.Member.IsLockedOut,
|
||||
// Name = Constants.Conventions.Member.IsLockedOutLabel,
|
||||
// SortOrder = 4,
|
||||
// Id = --identity
|
||||
// });
|
||||
// propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date)
|
||||
// {
|
||||
// Alias = Constants.Conventions.Member.LastLockoutDate,
|
||||
// Name = Constants.Conventions.Member.LastLockoutDateLabel,
|
||||
// SortOrder = 5,
|
||||
// Id = --identity
|
||||
// });
|
||||
// propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date)
|
||||
// {
|
||||
// Alias = Constants.Conventions.Member.LastLoginDate,
|
||||
// Name = Constants.Conventions.Member.LastLoginDateLabel,
|
||||
// SortOrder = 6,
|
||||
// Id = --identity
|
||||
// });
|
||||
// propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date)
|
||||
// {
|
||||
// Alias = Constants.Conventions.Member.LastPasswordChangeDate,
|
||||
// Name = Constants.Conventions.Member.LastPasswordChangeDateLabel,
|
||||
// SortOrder = 7,
|
||||
// Id = --identity
|
||||
// });
|
||||
|
||||
// memType.PropertyGroups.Add(propGroup);
|
||||
|
||||
// return new Member(name, email, username, password, -1, memType);
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -221,6 +221,63 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MemberRepository_Does_Not_Replace_Password_When_Null()
|
||||
{
|
||||
IMember sut;
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MemberTypeRepository memberTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out memberTypeRepository))
|
||||
{
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberTypeRepository.AddOrUpdate(memberType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
var member = MockedMember.CreateSimpleMember(memberType, "Johnny Hefty", "johnny@example.com", "123", "hefty");
|
||||
repository.AddOrUpdate(member);
|
||||
unitOfWork.Commit();
|
||||
|
||||
sut = repository.Get(member.Id);
|
||||
//when the password is null it will not overwrite what is already there.
|
||||
sut.Password = null;
|
||||
repository.AddOrUpdate(sut);
|
||||
unitOfWork.Commit();
|
||||
sut = repository.Get(member.Id);
|
||||
|
||||
Assert.That(sut.Password, Is.EqualTo("123"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MemberRepository_Can_Update_Email_And_Login_When_Changed()
|
||||
{
|
||||
IMember sut;
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MemberTypeRepository memberTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out memberTypeRepository))
|
||||
{
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
memberTypeRepository.AddOrUpdate(memberType);
|
||||
unitOfWork.Commit();
|
||||
|
||||
var member = MockedMember.CreateSimpleMember(memberType, "Johnny Hefty", "johnny@example.com", "123", "hefty");
|
||||
repository.AddOrUpdate(member);
|
||||
unitOfWork.Commit();
|
||||
|
||||
sut = repository.Get(member.Id);
|
||||
sut.Username = "This is new";
|
||||
sut.Email = "thisisnew@hello.com";
|
||||
repository.AddOrUpdate(sut);
|
||||
unitOfWork.Commit();
|
||||
sut = repository.Get(member.Id);
|
||||
|
||||
Assert.That(sut.Email, Is.EqualTo("thisisnew@hello.com"));
|
||||
Assert.That(sut.Username, Is.EqualTo("This is new"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Create_Correct_Subquery()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.Migrations;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Services;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Web.Strategies.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// This will execute after upgrading to remove any xml cache for media that are currently in the bin
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will execute for specific versions -
|
||||
///
|
||||
/// * If current is less than or equal to 7.0.0
|
||||
/// </remarks>
|
||||
public class ClearMediaXmlCacheForDeletedItemsAfterUpgrade : IApplicationStartupHandler
|
||||
{
|
||||
public ClearMediaXmlCacheForDeletedItemsAfterUpgrade()
|
||||
{
|
||||
MigrationRunner.Migrated += MigrationRunner_Migrated;
|
||||
}
|
||||
|
||||
void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e)
|
||||
{
|
||||
var target70 = new Version(7, 0, 0);
|
||||
|
||||
if (e.ConfiguredVersion <= target70)
|
||||
{
|
||||
|
||||
var sql = @"DELETE a
|
||||
FROM cmsContentXml a
|
||||
INNER JOIN umbracoNode b
|
||||
ON a.nodeId = b.id
|
||||
WHERE nodeObjectType = 'B796F64C-1F99-4FFB-B886-4BF4BC011A9C' AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("path") + " like '%-21%'";
|
||||
|
||||
// var sql = @"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
// (SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
// INNER JOIN umbracoNode ON cmsContentXml.nodeId = umbracoNode.id
|
||||
// WHERE nodeObjectType = 'B796F64C-1F99-4FFB-B886-4BF4BC011A9C' AND " + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("path") + " like '%-21%')";
|
||||
|
||||
var count = e.MigrationContext.Database.Execute(sql);
|
||||
|
||||
LogHelper.Info<ClearMediaXmlCacheForDeletedItemsAfterUpgrade>("Cleared " + count + " items from the media xml cache that were trashed and not meant to be there");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -391,6 +391,7 @@
|
||||
<Compile Include="Search\LuceneIndexerExtensions.cs" />
|
||||
<Compile Include="Security\ValidateRequestAttempt.cs" />
|
||||
<Compile Include="Security\WebSecurity.cs" />
|
||||
<Compile Include="Strategies\Migrations\ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs" />
|
||||
<Compile Include="Strategies\Migrations\RebuildMediaXmlCacheAfterUpgrade.cs" />
|
||||
<Compile Include="UI\CdfLogger.cs" />
|
||||
<Compile Include="umbraco.presentation\CompatibilityHelper.cs" />
|
||||
@@ -421,10 +422,9 @@
|
||||
<Compile Include="umbraco.presentation\umbraco\dialogs\AssignDomain2.aspx.designer.cs">
|
||||
<DependentUpon>AssignDomain2.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="umbraco.presentation\umbraco\members\EditMember.aspx.cs">
|
||||
<Compile Include="umbraco.presentation\umbraco\members\EditMember.aspx.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
|
||||
<Compile Include="umbraco.presentation\umbraco\users\EditUser.aspx.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
|
||||
Reference in New Issue
Block a user