Merge branch v8/dev into v8/bugfix/4963-fixing-models-and-member-repo
This commit is contained in:
@@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -170,23 +166,23 @@ namespace Umbraco.Core.Models
|
||||
/// Sets the publishing values for names and properties.
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="culture"></param>
|
||||
/// <param name="impact"></param>
|
||||
/// <returns>A value indicating whether it was possible to publish the names and values for the specified
|
||||
/// culture(s). The method may fail if required names are not set, but it does NOT validate property data</returns>
|
||||
public static bool PublishCulture(this IContent content, string culture = "*")
|
||||
public static bool PublishCulture(this IContent content, CultureImpact impact)
|
||||
{
|
||||
culture = culture.NullOrWhiteSpaceAsNull();
|
||||
if (impact == null) throw new ArgumentNullException(nameof(impact));
|
||||
|
||||
// the variation should be supported by the content type properties
|
||||
// if the content type is invariant, only '*' and 'null' is ok
|
||||
// if the content type varies, everything is ok because some properties may be invariant
|
||||
if (!content.ContentType.SupportsPropertyVariation(culture, "*", true))
|
||||
throw new NotSupportedException($"Culture \"{culture}\" is not supported by content type \"{content.ContentType.Alias}\" with variation \"{content.ContentType.Variations}\".");
|
||||
if (!content.ContentType.SupportsPropertyVariation(impact.Culture, "*", true))
|
||||
throw new NotSupportedException($"Culture \"{impact.Culture}\" is not supported by content type \"{content.ContentType.Alias}\" with variation \"{content.ContentType.Variations}\".");
|
||||
|
||||
var alsoInvariant = false;
|
||||
if (culture == "*") // all cultures
|
||||
// set names
|
||||
if (impact.ImpactsAllCultures)
|
||||
{
|
||||
foreach (var c in content.AvailableCultures)
|
||||
foreach (var c in content.AvailableCultures) // does NOT contain the invariant culture
|
||||
{
|
||||
var name = content.GetCultureName(c);
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
@@ -194,26 +190,31 @@ namespace Umbraco.Core.Models
|
||||
content.SetPublishInfo(c, name, DateTime.Now);
|
||||
}
|
||||
}
|
||||
else if (culture == null) // invariant culture
|
||||
else if (impact.ImpactsOnlyInvariantCulture)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(content.Name))
|
||||
return false;
|
||||
// PublishName set by repository - nothing to do here
|
||||
}
|
||||
else // one single culture
|
||||
else if (impact.ImpactsExplicitCulture)
|
||||
{
|
||||
var name = content.GetCultureName(culture);
|
||||
var name = content.GetCultureName(impact.Culture);
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return false;
|
||||
content.SetPublishInfo(culture, name, DateTime.Now);
|
||||
alsoInvariant = true; // we also want to publish invariant values
|
||||
content.SetPublishInfo(impact.Culture, name, DateTime.Now);
|
||||
}
|
||||
|
||||
// property.PublishValues only publishes what is valid, variation-wise
|
||||
// set values
|
||||
// property.PublishValues only publishes what is valid, variation-wise,
|
||||
// but accepts any culture arg: null, all, specific
|
||||
foreach (var property in content.Properties)
|
||||
{
|
||||
property.PublishValues(culture);
|
||||
if (alsoInvariant)
|
||||
// for the specified culture (null or all or specific)
|
||||
property.PublishValues(impact.Culture);
|
||||
|
||||
// maybe the specified culture did not impact the invariant culture, so PublishValues
|
||||
// above would skip it, yet it *also* impacts invariant properties
|
||||
if (impact.ImpactsAlsoInvariantProperties)
|
||||
property.PublishValues(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -225,9 +225,7 @@ namespace Umbraco.Core.Models
|
||||
return Variations.ValidateVariation(culture, segment, false, true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of PropertyGroups available on this ContentType
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// <para>A PropertyGroup corresponds to a Tab in the UI</para>
|
||||
/// <para>Marked DoNotClone because we will manually deal with cloning and the event handlers</para>
|
||||
@@ -245,9 +243,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all property types, across all property groups.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[IgnoreDataMember]
|
||||
[DoNotClone]
|
||||
public IEnumerable<PropertyType> PropertyTypes
|
||||
@@ -258,12 +254,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property types that are not in a group.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Marked DoNotClone because we will manually deal with cloning and the event handlers
|
||||
/// </remarks>
|
||||
/// <inheritdoc />
|
||||
[DoNotClone]
|
||||
public IEnumerable<PropertyType> NoGroupPropertyTypes
|
||||
{
|
||||
|
||||
@@ -43,9 +43,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property groups for the entire composition.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[IgnoreDataMember]
|
||||
public IEnumerable<PropertyGroup> CompositionPropertyGroups
|
||||
{
|
||||
@@ -76,9 +74,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property types for the entire composition.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[IgnoreDataMember]
|
||||
public IEnumerable<PropertyType> CompositionPropertyTypes
|
||||
{
|
||||
|
||||
257
src/Umbraco.Core/Models/CultureImpact.cs
Normal file
257
src/Umbraco.Core/Models/CultureImpact.cs
Normal file
@@ -0,0 +1,257 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the impact of a culture set.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>A set of cultures can be either all cultures (including the invariant culture), or
|
||||
/// the invariant culture, or a specific culture.</para>
|
||||
/// </remarks>
|
||||
internal class CultureImpact
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility method to return the culture used for invariant property errors based on what cultures are being actively saved,
|
||||
/// the default culture and the state of the current content item
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="savingCultures"></param>
|
||||
/// <param name="defaultCulture"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetCultureForInvariantErrors(IContent content, string[] savingCultures, string defaultCulture)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (savingCultures == null) throw new ArgumentNullException(nameof(savingCultures));
|
||||
if (savingCultures.Length == 0) throw new ArgumentException(nameof(savingCultures));
|
||||
|
||||
var cultureForInvariantErrors = savingCultures.Any(x => x.InvariantEquals(defaultCulture))
|
||||
//the default culture is being flagged for saving so use it
|
||||
? defaultCulture
|
||||
//If the content has no published version, we need to affiliate validation with the first variant being saved.
|
||||
//If the content has a published version we will not affiliate the validation with any culture (null)
|
||||
: !content.Published ? savingCultures[0] : null;
|
||||
|
||||
return cultureForInvariantErrors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CultureImpact"/> class.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture code.</param>
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
private CultureImpact(string culture, bool isDefault = false)
|
||||
{
|
||||
if (culture != null && culture.IsNullOrWhiteSpace())
|
||||
throw new ArgumentException("Culture \"\" is not valid here.");
|
||||
|
||||
Culture = culture;
|
||||
|
||||
if ((culture == null || culture == "*") && isDefault)
|
||||
throw new ArgumentException("The invariant or 'all' culture can not be the default culture.");
|
||||
|
||||
ImpactsOnlyDefaultCulture = isDefault;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the impact of 'all' cultures (including the invariant culture).
|
||||
/// </summary>
|
||||
public static CultureImpact All { get; } = new CultureImpact("*");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the impact of the invariant culture.
|
||||
/// </summary>
|
||||
public static CultureImpact Invariant { get; } = new CultureImpact(null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an impact instance representing the impact of a specific culture.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture code.</param>
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
public static CultureImpact Explicit(string culture, bool isDefault)
|
||||
{
|
||||
if (culture == null)
|
||||
throw new ArgumentException("Culture <null> is not explicit.");
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
throw new ArgumentException("Culture \"\" is not explicit.");
|
||||
if (culture == "*")
|
||||
throw new ArgumentException("Culture \"*\" is not explicit.");
|
||||
|
||||
return new CultureImpact(culture, isDefault);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an impact instance representing the impact of a culture set,
|
||||
/// in the context of a content item variation.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture code.</param>
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
/// <param name="content">The content item.</param>
|
||||
/// <remarks>
|
||||
/// <para>Validates that the culture is compatible with the variation.</para>
|
||||
/// </remarks>
|
||||
public static CultureImpact Create(string culture, bool isDefault, IContent content)
|
||||
{
|
||||
// throws if not successful
|
||||
TryCreate(culture, isDefault, content.ContentType.Variations, true, out var impact);
|
||||
return impact;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to create an impact instance representing the impact of a culture set,
|
||||
/// in the context of a content item variation.
|
||||
/// </summary>
|
||||
/// <param name="culture">The culture code.</param>
|
||||
/// <param name="isDefault">A value indicating whether the culture is the default culture.</param>
|
||||
/// <param name="variation">A content variation.</param>
|
||||
/// <param name="throwOnFail">A value indicating whether to throw if the impact cannot be created.</param>
|
||||
/// <param name="impact">The impact if it could be created, otherwise null.</param>
|
||||
/// <returns>A value indicating whether the impact could be created.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Validates that the culture is compatible with the variation.</para>
|
||||
/// </remarks>
|
||||
internal static bool TryCreate(string culture, bool isDefault, ContentVariation variation, bool throwOnFail, out CultureImpact impact)
|
||||
{
|
||||
impact = null;
|
||||
|
||||
// if culture is invariant...
|
||||
if (culture == null)
|
||||
{
|
||||
// ... then variation must not vary by culture ...
|
||||
if (variation.VariesByCulture())
|
||||
{
|
||||
if (throwOnFail)
|
||||
throw new InvalidOperationException("The invariant culture is not compatible with a varying variation.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... and it cannot be default
|
||||
if (isDefault)
|
||||
{
|
||||
if (throwOnFail)
|
||||
throw new InvalidOperationException("The invariant culture can not be the default culture.");
|
||||
return false;
|
||||
}
|
||||
|
||||
impact = Invariant;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if culture is 'all'...
|
||||
if (culture == "*")
|
||||
{
|
||||
// ... it cannot be default
|
||||
if (isDefault)
|
||||
{
|
||||
if (throwOnFail)
|
||||
throw new InvalidOperationException("The 'all' culture can not be the default culture.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// if variation does not vary by culture, then impact is invariant
|
||||
impact = variation.VariesByCulture() ? All : Invariant;
|
||||
return true;
|
||||
}
|
||||
|
||||
// neither null nor "*" - cannot be the empty string
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
{
|
||||
if (throwOnFail)
|
||||
throw new ArgumentException("Cannot be the empty string.", nameof(culture));
|
||||
return false;
|
||||
}
|
||||
|
||||
// if culture is specific, then variation must vary
|
||||
if (!variation.VariesByCulture())
|
||||
{
|
||||
if (throwOnFail)
|
||||
throw new InvalidOperationException($"The variant culture {culture} is not compatible with an invariant variation.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// return specific impact
|
||||
impact = new CultureImpact(culture, isDefault);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the culture code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Can be null (invariant) or * (all cultures) or a specific culture code.</para>
|
||||
/// </remarks>
|
||||
public string Culture { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this impact impacts all cultures, including,
|
||||
/// indirectly, the invariant culture.
|
||||
/// </summary>
|
||||
public bool ImpactsAllCultures => Culture == "*";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this impact impacts only the invariant culture,
|
||||
/// directly, not because all cultures are impacted.
|
||||
/// </summary>
|
||||
public bool ImpactsOnlyInvariantCulture => Culture == null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this impact impacts an implicit culture.
|
||||
/// </summary>
|
||||
/// <remarks>And then it does not impact the invariant culture. The impacted
|
||||
/// explicit culture could be the default culture.</remarks>
|
||||
public bool ImpactsExplicitCulture => Culture != null && Culture != "*";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this impact impacts the default culture, directly,
|
||||
/// not because all cultures are impacted.
|
||||
/// </summary>
|
||||
public bool ImpactsOnlyDefaultCulture {get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this impact impacts the invariant properties, either
|
||||
/// directly, or because all cultures are impacted, or because the default culture is impacted.
|
||||
/// </summary>
|
||||
public bool ImpactsInvariantProperties => Culture == null || Culture == "*" || ImpactsOnlyDefaultCulture;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this also impact impacts the invariant properties,
|
||||
/// even though it does not impact the invariant culture, neither directly (ImpactsInvariantCulture)
|
||||
/// nor indirectly (ImpactsAllCultures).
|
||||
/// </summary>
|
||||
public bool ImpactsAlsoInvariantProperties => !ImpactsOnlyInvariantCulture &&
|
||||
!ImpactsAllCultures &&
|
||||
ImpactsOnlyDefaultCulture;
|
||||
|
||||
public Behavior CultureBehavior
|
||||
{
|
||||
get
|
||||
{
|
||||
//null can only be invariant
|
||||
if (Culture == null) return Behavior.InvariantCulture | Behavior.InvariantProperties;
|
||||
|
||||
// * is All which means its also invariant properties since this will include the default language
|
||||
if (Culture == "*") return (Behavior.AllCultures | Behavior.InvariantProperties);
|
||||
|
||||
//else it's explicit
|
||||
var result = Behavior.ExplicitCulture;
|
||||
|
||||
//if the explicit culture is the default, then the behavior is also InvariantProperties
|
||||
if (ImpactsOnlyDefaultCulture)
|
||||
result |= Behavior.InvariantProperties;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Flags]
|
||||
public enum Behavior : byte
|
||||
{
|
||||
AllCultures = 1,
|
||||
InvariantCulture = 2,
|
||||
ExplicitCulture = 4,
|
||||
InvariantProperties = 8
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Models
|
||||
/// * when the setter performs additional required logic other than just setting the underlying field
|
||||
///
|
||||
/// </remarks>
|
||||
internal class DoNotCloneAttribute : Attribute
|
||||
public class DoNotCloneAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -96,17 +96,17 @@ namespace Umbraco.Core.Models
|
||||
IEnumerable<ContentTypeSort> AllowedContentTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets a collection of Property Groups
|
||||
/// Gets or sets the local property groups.
|
||||
/// </summary>
|
||||
PropertyGroupCollection PropertyGroups { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all property types, across all property groups.
|
||||
/// Gets all local property types belonging to a group, across all local property groups.
|
||||
/// </summary>
|
||||
IEnumerable<PropertyType> PropertyTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property types that are not in a group.
|
||||
/// Gets or sets the local property types that do not belong to a group.
|
||||
/// </summary>
|
||||
IEnumerable<PropertyType> NoGroupPropertyTypes { get; set; }
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(username));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture));
|
||||
|
||||
var user = new BackOfficeIdentityUser();
|
||||
var user = new BackOfficeIdentityUser(Array.Empty<IReadOnlyUserGroup>());
|
||||
user.DisableChangeTracking();
|
||||
user._userName = username;
|
||||
user._email = email;
|
||||
@@ -54,16 +54,19 @@ namespace Umbraco.Core.Models.Identity
|
||||
return user;
|
||||
}
|
||||
|
||||
private BackOfficeIdentityUser()
|
||||
private BackOfficeIdentityUser(IReadOnlyUserGroup[] groups)
|
||||
{
|
||||
_startMediaIds = new int[] { };
|
||||
_startContentIds = new int[] { };
|
||||
_groups = new IReadOnlyUserGroup[] { };
|
||||
_allowedSections = new string[] { };
|
||||
_startMediaIds = Array.Empty<int>();
|
||||
_startContentIds = Array.Empty<int>();
|
||||
_allowedSections = Array.Empty<string>();
|
||||
_culture = Current.Configs.Global().DefaultUILanguage; // TODO: inject
|
||||
_groups = new IReadOnlyUserGroup[0];
|
||||
|
||||
// must initialize before setting groups
|
||||
_roles = new ObservableCollection<IdentityUserRole<string>>();
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
|
||||
// use the property setters - they do more than just setting a field
|
||||
Groups = groups;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -72,19 +75,10 @@ namespace Umbraco.Core.Models.Identity
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="groups"></param>
|
||||
public BackOfficeIdentityUser(int userId, IEnumerable<IReadOnlyUserGroup> groups)
|
||||
: this(groups.ToArray())
|
||||
{
|
||||
_startMediaIds = new int[] { };
|
||||
_startContentIds = new int[] { };
|
||||
_groups = new IReadOnlyUserGroup[] { };
|
||||
_allowedSections = new string[] { };
|
||||
_culture = Current.Configs.Global().DefaultUILanguage; // TODO: inject
|
||||
_groups = groups.ToArray();
|
||||
_roles = new ObservableCollection<IdentityUserRole<string>>(_groups.Select(x => new IdentityUserRole<string>
|
||||
{
|
||||
RoleId = x.Alias,
|
||||
UserId = userId.ToString()
|
||||
}));
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
// use the property setters - they do more than just setting a field
|
||||
Id = userId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -226,6 +220,8 @@ namespace Umbraco.Core.Models.Identity
|
||||
//so they recalculate
|
||||
_allowedSections = null;
|
||||
|
||||
_groups = value;
|
||||
|
||||
//now clear all roles and re-add them
|
||||
_roles.CollectionChanged -= _roles_CollectionChanged;
|
||||
_roles.Clear();
|
||||
|
||||
80
src/Umbraco.Core/Models/Identity/IdentityMapDefinition.cs
Normal file
80
src/Umbraco.Core/Models/Identity/IdentityMapDefinition.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
public class IdentityMapDefinition : IMapDefinition
|
||||
{
|
||||
private readonly ILocalizedTextService _textService;
|
||||
private readonly IEntityService _entityService;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public IdentityMapDefinition(ILocalizedTextService textService, IEntityService entityService, IGlobalSettings globalSettings)
|
||||
{
|
||||
_textService = textService;
|
||||
_entityService = entityService;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public void DefineMaps(UmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<IUser, BackOfficeIdentityUser>(
|
||||
(source, context) =>
|
||||
{
|
||||
var target = new BackOfficeIdentityUser(source.Id, source.Groups);
|
||||
target.DisableChangeTracking();
|
||||
return target;
|
||||
},
|
||||
(source, target, context) =>
|
||||
{
|
||||
Map(source, target);
|
||||
target.ResetDirtyProperties(true);
|
||||
target.EnableChangeTracking();
|
||||
});
|
||||
}
|
||||
|
||||
// Umbraco.Code.MapAll -Id -Groups -LockoutEnabled -PhoneNumber -PhoneNumberConfirmed -TwoFactorEnabled
|
||||
private void Map(IUser source, BackOfficeIdentityUser target)
|
||||
{
|
||||
// well, the ctor has been fixed
|
||||
/*
|
||||
// these two are already set in ctor but BackOfficeIdentityUser ctor is CompletelyBroken
|
||||
target.Id = source.Id;
|
||||
target.Groups = source.Groups.ToArray();
|
||||
*/
|
||||
|
||||
target.CalculatedMediaStartNodeIds = source.CalculateMediaStartNodeIds(_entityService);
|
||||
target.CalculatedContentStartNodeIds = source.CalculateContentStartNodeIds(_entityService);
|
||||
target.Email = source.Email;
|
||||
target.UserName = source.Username;
|
||||
target.LastPasswordChangeDateUtc = source.LastPasswordChangeDate.ToUniversalTime();
|
||||
target.LastLoginDateUtc = source.LastLoginDate.ToUniversalTime();
|
||||
target.EmailConfirmed = source.EmailConfirmedDate.HasValue;
|
||||
target.Name = source.Name;
|
||||
target.AccessFailedCount = source.FailedPasswordAttempts;
|
||||
target.PasswordHash = GetPasswordHash(source.RawPasswordValue);
|
||||
target.StartContentIds = source.StartContentIds;
|
||||
target.StartMediaIds = source.StartMediaIds;
|
||||
target.Culture = source.GetUserCulture(_textService, _globalSettings).ToString(); // project CultureInfo to string
|
||||
target.IsApproved = source.IsApproved;
|
||||
target.SecurityStamp = source.SecurityStamp;
|
||||
target.LockoutEndDateUtc = source.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null;
|
||||
|
||||
// this was in AutoMapper but does not have a setter anyways
|
||||
//target.AllowedSections = source.AllowedSections.ToArray(),
|
||||
|
||||
// these were marked as ignored for AutoMapper but don't have a setter anyways
|
||||
//target.Logins =;
|
||||
//target.Claims =;
|
||||
//target.Roles =;
|
||||
}
|
||||
|
||||
private static string GetPasswordHash(string storedPass)
|
||||
{
|
||||
return storedPass.StartsWith(Constants.Security.EmptyPasswordPrefix) ? null : storedPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
public class IdentityMapperProfile : Profile
|
||||
{
|
||||
public IdentityMapperProfile(ILocalizedTextService textService, IEntityService entityService, IGlobalSettings globalSettings)
|
||||
{
|
||||
CreateMap<IUser, BackOfficeIdentityUser>()
|
||||
.BeforeMap((src, dest) =>
|
||||
{
|
||||
dest.DisableChangeTracking();
|
||||
})
|
||||
.ConstructUsing(src => new BackOfficeIdentityUser(src.Id, src.Groups))
|
||||
.ForMember(dest => dest.LastLoginDateUtc, opt => opt.MapFrom(src => src.LastLoginDate.ToUniversalTime()))
|
||||
.ForMember(user => user.LastPasswordChangeDateUtc, expression => expression.MapFrom(user => user.LastPasswordChangeDate.ToUniversalTime()))
|
||||
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
|
||||
.ForMember(dest => dest.EmailConfirmed, opt => opt.MapFrom(src => src.EmailConfirmedDate.HasValue))
|
||||
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
|
||||
.ForMember(dest => dest.LockoutEndDateUtc, opt => opt.MapFrom(src => src.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null))
|
||||
.ForMember(dest => dest.IsApproved, opt => opt.MapFrom(src => src.IsApproved))
|
||||
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Username))
|
||||
.ForMember(dest => dest.PasswordHash, opt => opt.MapFrom(user => GetPasswordHash(user.RawPasswordValue)))
|
||||
.ForMember(dest => dest.Culture, opt => opt.MapFrom(src => src.GetUserCulture(textService, globalSettings)))
|
||||
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
|
||||
.ForMember(dest => dest.StartMediaIds, opt => opt.MapFrom(src => src.StartMediaIds))
|
||||
.ForMember(dest => dest.StartContentIds, opt => opt.MapFrom(src => src.StartContentIds))
|
||||
.ForMember(dest => dest.AccessFailedCount, opt => opt.MapFrom(src => src.FailedPasswordAttempts))
|
||||
.ForMember(dest => dest.CalculatedContentStartNodeIds, opt => opt.MapFrom(src => src.CalculateContentStartNodeIds(entityService)))
|
||||
.ForMember(dest => dest.CalculatedMediaStartNodeIds, opt => opt.MapFrom(src => src.CalculateMediaStartNodeIds(entityService)))
|
||||
.ForMember(dest => dest.AllowedSections, opt => opt.MapFrom(src => src.AllowedSections.ToArray()))
|
||||
.ForMember(dest => dest.LockoutEnabled, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Logins, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.PhoneNumber, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.PhoneNumberConfirmed, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.TwoFactorEnabled, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Roles, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Claims, opt => opt.Ignore())
|
||||
.AfterMap((src, dest) =>
|
||||
{
|
||||
dest.ResetDirtyProperties(true);
|
||||
dest.EnableChangeTracking();
|
||||
});
|
||||
}
|
||||
|
||||
private static string GetPasswordHash(string storedPass)
|
||||
{
|
||||
return storedPass.StartsWith(Constants.Security.EmptyPasswordPrefix) ? null : storedPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,22 +151,22 @@ namespace Umbraco.Core.Models
|
||||
|
||||
internal static bool HasContentRootAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.Root.ToInvariantString(), user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RootString, user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
}
|
||||
|
||||
internal static bool HasContentBinAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinContent.ToInvariantString(), user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinContentString, user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
|
||||
}
|
||||
|
||||
internal static bool HasMediaRootAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.Root.ToInvariantString(), user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RootString, user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
}
|
||||
|
||||
internal static bool HasMediaBinAccess(this IUser user, IEntityService entityService)
|
||||
{
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinMedia.ToInvariantString(), user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
return ContentPermissionsHelper.HasPathAccess(Constants.System.RecycleBinMediaString, user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
|
||||
}
|
||||
|
||||
internal static bool HasPathAccess(this IUser user, IContent content, IEntityService entityService)
|
||||
@@ -327,7 +327,7 @@ namespace Umbraco.Core.Models
|
||||
? entityService.GetAllPaths(objectType, asn).ToDictionary(x => x.Id, x => x.Path)
|
||||
: new Dictionary<int, string>();
|
||||
|
||||
paths[Constants.System.Root] = Constants.System.Root.ToString(); // entityService does not get that one
|
||||
paths[Constants.System.Root] = Constants.System.RootString; // entityService does not get that one
|
||||
|
||||
var binPath = GetBinPath(objectType);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user