Moved EmailConfirmed and SecurityStamp properties to shared IMembershipUser (for both IMember and IUser to use)

This commit is contained in:
Emma Garland
2021-02-09 16:14:32 +00:00
parent da2a0713cc
commit 093548b933
5 changed files with 107 additions and 54 deletions

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
@@ -19,8 +19,11 @@ namespace Umbraco.Core.Models
private string _email;
private string _rawPasswordValue;
private string _passwordConfig;
private DateTime? _emailConfirmedDate;
private string _securityStamp;
/// <summary>
/// Initializes a new instance of the <see cref="Member"/> class.
/// Constructor for creating an empty Member object
/// </summary>
/// <param name="contentType">ContentType for the current Content object</param>
@@ -29,13 +32,14 @@ namespace Umbraco.Core.Models
{
IsApproved = true;
//this cannot be null but can be empty
// this cannot be null but can be empty
_rawPasswordValue = "";
_email = "";
_username = "";
}
/// <summary>
/// Initializes a new instance of the <see cref="Member"/> class.
/// Constructor for creating a Member object
/// </summary>
/// <param name="name">Name of the content</param>
@@ -43,18 +47,21 @@ namespace Umbraco.Core.Models
public Member(string name, IMemberType contentType)
: base(name, -1, contentType, new PropertyCollection())
{
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (name == null)
throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
IsApproved = true;
//this cannot be null but can be empty
// this cannot be null but can be empty
_rawPasswordValue = "";
_email = "";
_username = "";
}
/// <summary>
/// Initializes a new instance of the <see cref="Member"/> class.
/// Constructor for creating a Member object
/// </summary>
/// <param name="name"></param>
@@ -64,22 +71,29 @@ namespace Umbraco.Core.Models
public Member(string name, string email, string username, IMemberType contentType, bool isApproved = true)
: base(name, -1, contentType, new PropertyCollection())
{
if (name == null) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (email == null) throw new ArgumentNullException(nameof(email));
if (string.IsNullOrWhiteSpace(email)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(email));
if (username == null) throw new ArgumentNullException(nameof(username));
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(username));
if (name == null)
throw new ArgumentNullException(nameof(name));
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
if (email == null)
throw new ArgumentNullException(nameof(email));
if (string.IsNullOrWhiteSpace(email))
throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(email));
if (username == null)
throw new ArgumentNullException(nameof(username));
if (string.IsNullOrWhiteSpace(username))
throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(username));
_email = email;
_username = username;
IsApproved = isApproved;
//this cannot be null but can be empty
// this cannot be null but can be empty
_rawPasswordValue = "";
}
/// <summary>
/// Initializes a new instance of the <see cref="Member"/> class.
/// Constructor for creating a Member object
/// </summary>
/// <param name="name"></param>
@@ -99,6 +113,7 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Initializes a new instance of the <see cref="Member"/> class.
/// Constructor for creating a Member object
/// </summary>
/// <param name="name"></param>
@@ -138,6 +153,13 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _email, nameof(Email));
}
[DataMember]
public DateTime? EmailConfirmedDate
{
get => _emailConfirmedDate;
set => SetPropertyValueAndDetectChanges(value, ref _emailConfirmedDate, nameof(EmailConfirmedDate));
}
/// <summary>
/// Gets or sets the raw password value
/// </summary>
@@ -190,7 +212,8 @@ namespace Umbraco.Core.Models
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.Comments, nameof(Comments), default(string));
if (a.Success == false) return a.Result;
if (a.Success == false)
return a.Result;
return Properties[Constants.Conventions.Member.Comments].GetValue() == null
? string.Empty
@@ -200,7 +223,8 @@ namespace Umbraco.Core.Models
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.Comments,
nameof(Comments)) == false) return;
nameof(Comments)) == false)
return;
Properties[Constants.Conventions.Member.Comments].SetValue(value);
}
@@ -221,8 +245,10 @@ namespace Umbraco.Core.Models
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.IsApproved, nameof(IsApproved),
//This is the default value if the prop is not found
true);
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.IsApproved].GetValue() == null) return true;
if (a.Success == false)
return a.Result;
if (Properties[Constants.Conventions.Member.IsApproved].GetValue() == null)
return true;
var tryConvert = Properties[Constants.Conventions.Member.IsApproved].GetValue().TryConvertTo<bool>();
if (tryConvert.Success)
{
@@ -235,7 +261,8 @@ namespace Umbraco.Core.Models
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.IsApproved,
nameof(IsApproved)) == false) return;
nameof(IsApproved)) == false)
return;
Properties[Constants.Conventions.Member.IsApproved].SetValue(value);
}
@@ -254,8 +281,10 @@ namespace Umbraco.Core.Models
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.IsLockedOut, nameof(IsLockedOut), false);
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.IsLockedOut].GetValue() == null) return false;
if (a.Success == false)
return a.Result;
if (Properties[Constants.Conventions.Member.IsLockedOut].GetValue() == null)
return false;
var tryConvert = Properties[Constants.Conventions.Member.IsLockedOut].GetValue().TryConvertTo<bool>();
if (tryConvert.Success)
{
@@ -268,7 +297,8 @@ namespace Umbraco.Core.Models
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.IsLockedOut,
nameof(IsLockedOut)) == false) return;
nameof(IsLockedOut)) == false)
return;
Properties[Constants.Conventions.Member.IsLockedOut].SetValue(value);
}
@@ -287,8 +317,10 @@ namespace Umbraco.Core.Models
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLoginDate, nameof(LastLoginDate), default(DateTime));
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.LastLoginDate].GetValue() == null) return default(DateTime);
if (a.Success == false)
return a.Result;
if (Properties[Constants.Conventions.Member.LastLoginDate].GetValue() == null)
return default(DateTime);
var tryConvert = Properties[Constants.Conventions.Member.LastLoginDate].GetValue().TryConvertTo<DateTime>();
if (tryConvert.Success)
{
@@ -301,7 +333,8 @@ namespace Umbraco.Core.Models
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastLoginDate,
nameof(LastLoginDate)) == false) return;
nameof(LastLoginDate)) == false)
return;
Properties[Constants.Conventions.Member.LastLoginDate].SetValue(value);
}
@@ -320,8 +353,10 @@ namespace Umbraco.Core.Models
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastPasswordChangeDate, nameof(LastPasswordChangeDate), default(DateTime));
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].GetValue() == null) return default(DateTime);
if (a.Success == false)
return a.Result;
if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].GetValue() == null)
return default(DateTime);
var tryConvert = Properties[Constants.Conventions.Member.LastPasswordChangeDate].GetValue().TryConvertTo<DateTime>();
if (tryConvert.Success)
{
@@ -334,7 +369,8 @@ namespace Umbraco.Core.Models
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastPasswordChangeDate,
nameof(LastPasswordChangeDate)) == false) return;
nameof(LastPasswordChangeDate)) == false)
return;
Properties[Constants.Conventions.Member.LastPasswordChangeDate].SetValue(value);
}
@@ -353,8 +389,10 @@ namespace Umbraco.Core.Models
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLockoutDate, nameof(LastLockoutDate), default(DateTime));
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.LastLockoutDate].GetValue() == null) return default(DateTime);
if (a.Success == false)
return a.Result;
if (Properties[Constants.Conventions.Member.LastLockoutDate].GetValue() == null)
return default(DateTime);
var tryConvert = Properties[Constants.Conventions.Member.LastLockoutDate].GetValue().TryConvertTo<DateTime>();
if (tryConvert.Success)
{
@@ -367,7 +405,8 @@ namespace Umbraco.Core.Models
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastLockoutDate,
nameof(LastLockoutDate)) == false) return;
nameof(LastLockoutDate)) == false)
return;
Properties[Constants.Conventions.Member.LastLockoutDate].SetValue(value);
}
@@ -387,8 +426,10 @@ namespace Umbraco.Core.Models
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.FailedPasswordAttempts, nameof(FailedPasswordAttempts), 0);
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].GetValue() == null) return default(int);
if (a.Success == false)
return a.Result;
if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].GetValue() == null)
return default(int);
var tryConvert = Properties[Constants.Conventions.Member.FailedPasswordAttempts].GetValue().TryConvertTo<int>();
if (tryConvert.Success)
{
@@ -401,7 +442,8 @@ namespace Umbraco.Core.Models
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.FailedPasswordAttempts,
nameof(FailedPasswordAttempts)) == false) return;
nameof(FailedPasswordAttempts)) == false)
return;
Properties[Constants.Conventions.Member.FailedPasswordAttempts].SetValue(value);
}
@@ -413,6 +455,17 @@ namespace Umbraco.Core.Models
[DataMember]
public virtual string ContentTypeAlias => ContentType.Alias;
/// <summary>
/// The security stamp used by ASP.Net identity
/// </summary>
[IgnoreDataMember]
public string SecurityStamp
{
get => _securityStamp;
set => SetPropertyValueAndDetectChanges(value, ref _securityStamp, nameof(SecurityStamp));
}
/// <summary>
/// Internal/Experimental - only used for mapping queries.
/// </summary>

View File

@@ -1,4 +1,4 @@
using System;
using System;
using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models.Membership
@@ -10,6 +10,7 @@ namespace Umbraco.Core.Models.Membership
{
string Username { get; set; }
string Email { get; set; }
DateTime? EmailConfirmedDate { get; set; }
/// <summary>
/// Gets or sets the raw password value
@@ -38,6 +39,11 @@ namespace Umbraco.Core.Models.Membership
/// </remarks>
int FailedPasswordAttempts { get; set; }
/// <summary>
/// Gets or sets the security stamp used by ASP.NET Identity
/// </summary>
string SecurityStamp { get; set; }
//object ProfileId { get; set; }
//IEnumerable<object> Groups { get; set; }
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Models.Entities;
@@ -20,7 +20,6 @@ namespace Umbraco.Core.Models.Membership
int[] StartMediaIds { get; set; }
string Language { get; set; }
DateTime? EmailConfirmedDate { get; set; }
DateTime? InvitedDate { get; set; }
/// <summary>
@@ -39,11 +38,6 @@ namespace Umbraco.Core.Models.Membership
/// </summary>
IProfile ProfileData { get; }
/// <summary>
/// The security stamp used by ASP.Net identity
/// </summary>
string SecurityStamp { get; set; }
/// <summary>
/// Will hold the media file system relative path of the users custom avatar if they uploaded one
/// </summary>

View File

@@ -96,13 +96,13 @@ namespace Umbraco.Infrastructure.Security
target.UserName = source.Username;
target.LastPasswordChangeDateUtc = source.LastPasswordChangeDate.ToUniversalTime();
target.LastLoginDateUtc = source.LastLoginDate.ToUniversalTime();
//target.EmailConfirmed = source.EmailConfirmedDate.HasValue;
target.EmailConfirmed = source.EmailConfirmedDate.HasValue;
target.Name = source.Name;
target.AccessFailedCount = source.FailedPasswordAttempts;
target.PasswordHash = GetPasswordHash(source.RawPasswordValue);
target.PasswordConfig = source.PasswordConfiguration;
target.IsApproved = source.IsApproved;
//target.SecurityStamp = source.SecurityStamp;
target.SecurityStamp = source.SecurityStamp;
target.LockoutEnd = source.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?)null;
// NB: same comments re AutoMapper as per BackOfficeUser

View File

@@ -554,13 +554,13 @@ namespace Umbraco.Infrastructure.Security
member.LastPasswordChangeDate = identityUserMember.LastPasswordChangeDateUtc.Value.ToLocalTime();
}
//if (identityUser.IsPropertyDirty(nameof(MembersIdentityUser.EmailConfirmed))
// || (user.EmailConfirmedDate.HasValue && user.EmailConfirmedDate.Value != default && identityUser.EmailConfirmed == false)
// || ((user.EmailConfirmedDate.HasValue == false || user.EmailConfirmedDate.Value == default) && identityUser.EmailConfirmed))
//{
// anythingChanged = true;
// user.EmailConfirmedDate = identityUser.EmailConfirmed ? (DateTime?)DateTime.Now : null;
//}
if (identityUserMember.IsPropertyDirty(nameof(MembersIdentityUser.EmailConfirmed))
|| (member.EmailConfirmedDate.HasValue && member.EmailConfirmedDate.Value != default && identityUserMember.EmailConfirmed == false)
|| ((member.EmailConfirmedDate.HasValue == false || member.EmailConfirmedDate.Value == default) && identityUserMember.EmailConfirmed))
{
anythingChanged = true;
member.EmailConfirmedDate = identityUserMember.EmailConfirmed ? (DateTime?)DateTime.Now : null;
}
if (identityUserMember.IsPropertyDirty(nameof(MembersIdentityUser.Name))
&& member.Name != identityUserMember.Name && identityUserMember.Name.IsNullOrWhiteSpace() == false)
@@ -610,11 +610,11 @@ namespace Umbraco.Infrastructure.Security
member.PasswordConfiguration = identityUserMember.PasswordConfig;
}
//if (user.SecurityStamp != identityUser.SecurityStamp)
//{
// anythingChanged = true;
// user.SecurityStamp = identityUser.SecurityStamp;
//}
if (member.SecurityStamp != identityUserMember.SecurityStamp)
{
anythingChanged = true;
member.SecurityStamp = identityUserMember.SecurityStamp;
}
// TODO: Fix this for Groups too (as per backoffice comment)
if (identityUserMember.IsPropertyDirty(nameof(MembersIdentityUser.Roles)) || identityUserMember.IsPropertyDirty(nameof(MembersIdentityUser.Groups)))