Added custom resolver to deal with sensitive values on member list view, some cleanup
This commit is contained in:
@@ -1,29 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Examine.LuceneEngine.SearchCriteria;
|
||||
using Examine.SearchCriteria;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -33,10 +22,7 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Binders;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using umbraco;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using Examine;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -96,16 +82,18 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (MembershipScenario == MembershipScenario.NativeUmbraco)
|
||||
{
|
||||
long totalRecords;
|
||||
var members = Services.MemberService
|
||||
.GetAll((pageNumber - 1), pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, memberTypeAlias, filter).ToArray();
|
||||
.GetAll((pageNumber - 1), pageSize, out var totalRecords, orderBy, orderDirection, orderBySystemField, memberTypeAlias, filter).ToArray();
|
||||
if (totalRecords == 0)
|
||||
{
|
||||
return new PagedResult<MemberBasic>(0, 0, 0);
|
||||
}
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize);
|
||||
pagedResult.Items = members
|
||||
.Select(Mapper.Map<IMember, MemberBasic>);
|
||||
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = members
|
||||
.Select(Mapper.Map<IMember, MemberBasic>)
|
||||
};
|
||||
return pagedResult;
|
||||
}
|
||||
else
|
||||
@@ -133,10 +121,13 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
return new PagedResult<MemberBasic>(0, 0, 0);
|
||||
}
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize);
|
||||
pagedResult.Items = members
|
||||
.Cast<MembershipUser>()
|
||||
.Select(Mapper.Map<MembershipUser, MemberBasic>);
|
||||
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = members
|
||||
.Cast<MembershipUser>()
|
||||
.Select(Mapper.Map<MembershipUser, MemberBasic>)
|
||||
};
|
||||
return pagedResult;
|
||||
}
|
||||
|
||||
@@ -437,7 +428,7 @@ namespace Umbraco.Web.Editors
|
||||
var sensitiveProperties = contentItem.PersistedContent.ContentType
|
||||
.PropertyTypes.Where(x => contentItem.PersistedContent.ContentType.IsSensitiveProperty(x.Alias))
|
||||
.ToList();
|
||||
|
||||
|
||||
foreach (var sensitiveProperty in sensitiveProperties)
|
||||
{
|
||||
//if found, change the value of the contentItem model to the persisted value so it remains unchanged
|
||||
@@ -665,7 +656,7 @@ namespace Umbraco.Web.Editors
|
||||
contentItem.Email,
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
contentItem.IsApproved,
|
||||
contentItem.IsApproved,
|
||||
contentItem.PersistedContent.Key, //custom membership provider, we'll link that based on the IMember unique id (GUID)
|
||||
out status);
|
||||
|
||||
@@ -682,7 +673,7 @@ namespace Umbraco.Web.Editors
|
||||
contentItem.Email,
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
contentItem.IsApproved,
|
||||
contentItem.IsApproved,
|
||||
newKey,
|
||||
out status);
|
||||
|
||||
@@ -828,17 +819,17 @@ namespace Umbraco.Web.Editors
|
||||
var member = ((MemberService)Services.MemberService).ExportMember(key);
|
||||
|
||||
var fileName = $"{member.Name}_{member.Email}.txt";
|
||||
|
||||
httpResponseMessage.Content = new ObjectContent<MemberExportModel>(member, new JsonMediaTypeFormatter {Indent = true});
|
||||
|
||||
httpResponseMessage.Content = new ObjectContent<MemberExportModel>(member, new JsonMediaTypeFormatter { Indent = true });
|
||||
httpResponseMessage.Content.Headers.Add("x-filename", fileName);
|
||||
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
|
||||
httpResponseMessage.StatusCode = HttpStatusCode.OK;
|
||||
|
||||
|
||||
return httpResponseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -80,17 +80,21 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//FROM IMember TO MemberBasic
|
||||
config.CreateMap<IMember, MemberBasic>()
|
||||
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
|
||||
.ForMember(display => display.Udi,
|
||||
expression =>
|
||||
expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
|
||||
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMember>()))
|
||||
.ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
|
||||
.ForMember(dto => dto.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias))
|
||||
.ForMember(dto => dto.ContentTypeAlias,
|
||||
expression => expression.MapFrom(content => content.ContentType.Alias))
|
||||
.ForMember(dto => dto.Email, expression => expression.MapFrom(content => content.Email))
|
||||
.ForMember(dto => dto.Username, expression => expression.MapFrom(content => content.Username))
|
||||
.ForMember(dto => dto.Trashed, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Published, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Updater, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Alias, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore());
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Properties, expression => expression.ResolveUsing(new MemberSensitivePropertiesResolver()));
|
||||
|
||||
//FROM MembershipUser TO MemberBasic
|
||||
config.CreateMap<MembershipUser, MemberBasic>()
|
||||
@@ -477,8 +481,41 @@ namespace Umbraco.Web.Models.Mapping
|
||||
return AutoMapperExtensions.MapWithUmbracoContext<IMember, MemberDisplay>(member, context.GetUmbracoContext());
|
||||
}
|
||||
}
|
||||
|
||||
internal class MemberSensitivePropertiesResolver : SensitivePropertiesResolver<IMember>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to assign the IsSensitive property values
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="properties"></param>
|
||||
/// <returns></returns>
|
||||
protected override List<ContentPropertyDisplay> MapProperties(UmbracoContext umbracoContext, IContentBase content, List<Property> properties)
|
||||
{
|
||||
var result = base.MapProperties(umbracoContext, content, properties);
|
||||
var member = (IMember)content;
|
||||
var memberType = member.ContentType;
|
||||
|
||||
//now update the IsSensitive value
|
||||
foreach (var prop in result)
|
||||
{
|
||||
//check if this property is flagged as sensitive
|
||||
var isSensitiveProperty = memberType.IsSensitiveProperty(prop.Alias);
|
||||
//check permissions for viewing sensitive data
|
||||
if (isSensitiveProperty && umbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
|
||||
{
|
||||
//mark this property as readonly so that it does not post any data
|
||||
prop.Readonly = true;
|
||||
//replace this editor with a sensitivevalue
|
||||
prop.View = "sensitivevalue";
|
||||
//clear the value
|
||||
prop.Value = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
internal class SensitivePropertiesResolver<TSource> : IValueResolver where TSource : IContentBase
|
||||
{
|
||||
public ResolutionResult Resolve(ResolutionResult source)
|
||||
{
|
||||
if (source.Value != null && (source.Value is TSource) == false)
|
||||
throw new AutoMapperMappingException(string.Format("Value supplied is of type {0} but expected {1}.\nChange the value resolver source type, or redirect the source value supplied to the value resolver using FromMember.", new object[]
|
||||
{
|
||||
source.Value.GetType(),
|
||||
typeof (TSource)
|
||||
}));
|
||||
return source.New(
|
||||
//perform the mapping with the current umbraco context
|
||||
ResolveCore(source.Context.GetUmbracoContext(), (TSource)source.Value), typeof(IEnumerable<ContentPropertyDisplay>));
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<ContentPropertyDisplay> ResolveCore(UmbracoContext umbracoContext, TSource content)
|
||||
{
|
||||
var properties = new List<Property>();
|
||||
|
||||
properties.AddRange(content.Properties);
|
||||
|
||||
//map the properties
|
||||
var mappedProperties = MapProperties(umbracoContext, content, properties);
|
||||
|
||||
return mappedProperties;
|
||||
}
|
||||
|
||||
protected virtual List<ContentPropertyDisplay> MapProperties(UmbracoContext umbracoContext, IContentBase content, List<Property> properties)
|
||||
{
|
||||
var result = Mapper.Map<IEnumerable<Property>, IEnumerable<ContentPropertyDisplay>>(
|
||||
// Sort properties so items from different compositions appear in correct order (see U4-9298). Map sorted properties.
|
||||
properties.OrderBy(prop => prop.PropertyType.SortOrder))
|
||||
.ToList();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
@@ -9,7 +7,6 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using umbraco;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
@@ -53,7 +50,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
//perform the mapping with the current umbraco context
|
||||
ResolveCore(source.Context.GetUmbracoContext(), (TSource)source.Value), typeof(List<Tab<ContentPropertyDisplay>>));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds the container (listview) tab to the document
|
||||
/// </summary>
|
||||
@@ -275,7 +272,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//now add the user props
|
||||
contentProps.AddRange(currProps);
|
||||
|
||||
|
||||
//re-assign
|
||||
genericProps.Properties = contentProps;
|
||||
|
||||
@@ -308,6 +305,6 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,6 +336,7 @@
|
||||
<Compile Include="Models\Mapping\AutoMapperExtensions.cs" />
|
||||
<Compile Include="Models\Mapping\ContentTreeNodeUrlResolver.cs" />
|
||||
<Compile Include="Models\Mapping\MemberTreeNodeUrlResolver.cs" />
|
||||
<Compile Include="Models\Mapping\SensitivePropertiesResolver.cs" />
|
||||
<Compile Include="Models\Trees\ExportMember.cs" />
|
||||
<Compile Include="TourFilterResolver.cs" />
|
||||
<Compile Include="Editors\UserEditorAuthorizationHelper.cs" />
|
||||
|
||||
Reference in New Issue
Block a user