Merge remote-tracking branch 'origin/netcore/dev' into netcore/feature/align-infrastructure-namespaces
# Conflicts: # src/Umbraco.Infrastructure/Cache/DistributedCacheBinder_Handlers.cs # src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.MappingProfiles.cs # src/Umbraco.Infrastructure/PropertyEditors/PropertyEditorsComponent.cs # src/Umbraco.Infrastructure/Security/BackOfficeClaimsPrincipalFactory.cs # src/Umbraco.Infrastructure/Security/IBackOfficeUserManager.cs # src/Umbraco.Infrastructure/Security/IUmbracoUserManager.cs # src/Umbraco.Infrastructure/Security/SignOutAuditEventArgs.cs # src/Umbraco.Infrastructure/Security/UmbracoUserManager.cs # src/Umbraco.Infrastructure/Security/UserInviteEventArgs.cs # src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs # src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/BackOffice/BackOfficeLookupNormalizerTests.cs # src/Umbraco.Web.BackOffice/Controllers/MemberController.cs # src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs # src/Umbraco.Web/Security/Providers/MembersRoleProvider.cs
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
namespace Umbraco.Cms.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// The password configuration for back office users
|
||||
/// The password configuration for members
|
||||
/// </summary>
|
||||
public class MemberPasswordConfiguration : PasswordConfiguration, IMemberPasswordConfiguration
|
||||
{
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace Umbraco.Cms.Core
|
||||
|
||||
public const string EmptyPasswordPrefix = "___UIDEMPTYPWORD__";
|
||||
|
||||
public const string DefaultMemberTypeAlias = "Member";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The prefix used for external identity providers for their authentication type
|
||||
/// </summary>
|
||||
|
||||
33
src/Umbraco.Core/Models/Mapping/MemberMapDefinition.cs
Normal file
33
src/Umbraco.Core/Models/Mapping/MemberMapDefinition.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Core.Models.Mapping
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class MemberMapDefinition : IMapDefinition
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void DefineMaps(UmbracoMapper mapper) => mapper.Define<MemberSave, IMember>(Map);
|
||||
|
||||
private static void Map(MemberSave source, IMember target, MapperContext context)
|
||||
{
|
||||
target.IsApproved = source.IsApproved;
|
||||
target.Name = source.Name;
|
||||
target.Email = source.Email;
|
||||
target.Key = source.Key;
|
||||
target.Username = source.Username;
|
||||
target.Comments = source.Comments;
|
||||
target.CreateDate = source.CreateDate;
|
||||
target.UpdateDate = source.UpdateDate;
|
||||
target.Email = source.Email;
|
||||
|
||||
// TODO: ensure all properties are mapped as required
|
||||
//target.Id = source.Id;
|
||||
//target.ParentId = -1;
|
||||
//target.Path = "-1," + source.Id;
|
||||
|
||||
//TODO: add groups as required
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
@@ -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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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.Cms.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>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.Membership
|
||||
@@ -10,6 +10,7 @@ namespace Umbraco.Cms.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.Cms.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; }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace Umbraco.Cms.Core.Models.Membership
|
||||
int[] StartMediaIds { get; set; }
|
||||
string Language { get; set; }
|
||||
|
||||
DateTime? EmailConfirmedDate { get; set; }
|
||||
DateTime? InvitedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -38,11 +37,6 @@ namespace Umbraco.Cms.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>
|
||||
|
||||
@@ -6,7 +6,6 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Security
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A custom user identity for the Umbraco backoffice
|
||||
/// </summary>
|
||||
|
||||
@@ -1,29 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Membership;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services
|
||||
{
|
||||
public interface IMembershipRoleService<out T>
|
||||
public interface IMembershipRoleService<out T>
|
||||
where T : class, IMembershipUser
|
||||
{
|
||||
void AddRole(string roleName);
|
||||
IEnumerable<string> GetAllRoles();
|
||||
|
||||
IEnumerable<IMemberGroup> GetAllRoles();
|
||||
|
||||
IEnumerable<string> GetAllRoles(int memberId);
|
||||
|
||||
IEnumerable<string> GetAllRoles(string username);
|
||||
|
||||
IEnumerable<int> GetAllRolesIds();
|
||||
|
||||
IEnumerable<int> GetAllRolesIds(int memberId);
|
||||
|
||||
IEnumerable<int> GetAllRolesIds(string username);
|
||||
|
||||
IEnumerable<T> GetMembersInRole(string roleName);
|
||||
|
||||
IEnumerable<T> FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
|
||||
|
||||
bool DeleteRole(string roleName, bool throwIfBeingUsed);
|
||||
|
||||
void AssignRole(string username, string roleName);
|
||||
|
||||
void AssignRoles(string[] usernames, string[] roleNames);
|
||||
|
||||
void DissociateRole(string username, string roleName);
|
||||
|
||||
void DissociateRoles(string[] usernames, string[] roleNames);
|
||||
|
||||
void AssignRole(int memberId, string roleName);
|
||||
|
||||
void AssignRoles(int[] memberIds, string[] roleNames);
|
||||
|
||||
void DissociateRole(int memberId, string roleName);
|
||||
|
||||
void DissociateRoles(int[] memberIds, string[] roleNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
||||
Reference in New Issue
Block a user