using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Security;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
///
/// A custom tab/property resolver for members which will ensure that the built-in membership properties are or aren't displayed
/// depending on if the member type has these properties
///
///
/// This also ensures that the IsLocked out property is readonly when the member is not locked out - this is because
/// an admin cannot actually set isLockedOut = true, they can only unlock.
///
internal class MemberTabsAndPropertiesResolver : TabsAndPropertiesResolver
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly ILocalizedTextService _localizedTextService;
private readonly IMemberTypeService _memberTypeService;
private readonly IMemberService _memberService;
private readonly IUserService _userService;
public MemberTabsAndPropertiesResolver(IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService localizedTextService, IMemberService memberService, IUserService userService, IMemberTypeService memberTypeService)
: base(localizedTextService)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
_localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService));
_memberService = memberService ?? throw new ArgumentNullException(nameof(memberService));
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
_memberTypeService = memberTypeService ?? throw new ArgumentNullException(nameof(memberTypeService));
}
///
/// Overridden to deal with custom member properties and permissions.
public override IEnumerable> Resolve(IMember source, MemberDisplay destination, IEnumerable> destMember, ResolutionContext context)
{
var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
var memberType = _memberTypeService.Get(source.ContentTypeId);
IgnoreProperties = memberType.CompositionPropertyTypes
.Where(x => x.HasIdentity == false)
.Select(x => x.Alias)
.ToArray();
var resolved = base.Resolve(source, destination, destMember, context);
if (provider.IsUmbracoMembershipProvider() == false)
{
// it's a generic provider so update the locked out property based on our known constant alias
var isLockedOutProperty = resolved.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == Constants.Conventions.Member.IsLockedOut);
if (isLockedOutProperty?.Value != null && isLockedOutProperty.Value.ToString() != "1")
{
isLockedOutProperty.View = "readonlyvalue";
isLockedOutProperty.Value = _localizedTextService.Localize("general/no");
}
}
else
{
var umbracoProvider = (IUmbracoMemberTypeMembershipProvider)provider;
// This is kind of a hack because a developer is supposed to be allowed to set their property editor - would have been much easier
// if we just had all of the membership provider fields on the member table :(
// TODO: But is there a way to map the IMember.IsLockedOut to the property ? i dunno.
var isLockedOutProperty = resolved.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == umbracoProvider.LockPropertyTypeAlias);
if (isLockedOutProperty?.Value != null && isLockedOutProperty.Value.ToString() != "1")
{
isLockedOutProperty.View = "readonlyvalue";
isLockedOutProperty.Value = _localizedTextService.Localize("general/no");
}
}
var umbracoContext = _umbracoContextAccessor.UmbracoContext;
if (umbracoContext != null
&& umbracoContext.Security.CurrentUser != null
&& umbracoContext.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
{
var memberTypeLink = string.Format("#/member/memberTypes/edit/{0}", source.ContentTypeId);
// Replace the doctype property
var docTypeProperty = resolved.SelectMany(x => x.Properties)
.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
docTypeProperty.Value = new List