Now checks for the sensitiveData group to view sensitive data
This commit is contained in:
@@ -9,6 +9,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
|
||||
public const string AdminGroupAlias = "admin";
|
||||
public const string SensitiveDataGroupAlias = "sensitiveData";
|
||||
public const string TranslatorGroupAlias = "translator";
|
||||
|
||||
public const string BackOfficeAuthenticationType = "UmbracoBackOffice";
|
||||
@@ -36,4 +37,4 @@ namespace Umbraco.Core
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +261,16 @@ namespace Umbraco.Core.Models
|
||||
return user.Groups != null && user.Groups.Any(x => x.Alias == Constants.Security.AdminGroupAlias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this user has access to view sensitive data
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
public static bool HasAccessToSensitiveData(this IUser user)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
return user.Groups != null && user.Groups.Any(x => x.Alias == Constants.Security.SensitiveDataGroupAlias);
|
||||
}
|
||||
|
||||
// calc. start nodes, combining groups' and user's, and excluding what's in the bin
|
||||
public static int[] CalculateContentStartNodeIds(this IUser user, IEntityService entityService)
|
||||
{
|
||||
@@ -413,4 +423,4 @@ namespace Umbraco.Core.Models
|
||||
return lsn.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace Umbraco.Web.Editors
|
||||
Path = "-1," + Constants.System.RecycleBinContent
|
||||
};
|
||||
|
||||
TabsAndPropertiesResolver.AddListView(display, "content", Services.DataTypeService, Services.TextService);
|
||||
TabsAndPropertiesResolver<IContent>.AddListView(display, "content", Services.DataTypeService, Services.TextService);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Umbraco.Web.Editors
|
||||
Path = "-1," + Constants.System.RecycleBinMedia
|
||||
};
|
||||
|
||||
TabsAndPropertiesResolver.AddListView(display, "media", Services.DataTypeService, Services.TextService);
|
||||
TabsAndPropertiesResolver<IMedia>.AddListView(display, "media", Services.DataTypeService, Services.TextService);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Umbraco.Web.Editors
|
||||
ParentId = -1
|
||||
};
|
||||
|
||||
TabsAndPropertiesResolver.AddListView(display, "member", Services.DataTypeService, Services.TextService);
|
||||
TabsAndPropertiesResolver<IMember>.AddListView(display, "member", Services.DataTypeService, Services.TextService);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
expression.MapFrom(content => content.ContentType.AllowedTemplates
|
||||
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
|
||||
.ToDictionary(t => t.Alias, t => t.Name)))
|
||||
.ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService)))
|
||||
.ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver<IContent>(applicationContext.Services.TextService)))
|
||||
.ForMember(display => display.AllowedActions, expression => expression.ResolveUsing(
|
||||
new ActionButtonsResolver(new Lazy<IUserService>(() => applicationContext.Services.UserService), new Lazy<IContentService>(() => applicationContext.Services.ContentService))))
|
||||
.AfterMap((content, display) => AfterMap(content, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService,
|
||||
@@ -100,6 +100,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService,
|
||||
ILocalizedTextService localizedText, IContentTypeService contentTypeService)
|
||||
{
|
||||
//TODO: All of this logic should be moved to the TabsAndPropertiesResolver and not in AfterMap
|
||||
|
||||
// map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
//TODO: STOP using these extension methods, they are not testable and require singletons to be setup
|
||||
var parent = content.Parent();
|
||||
@@ -113,7 +115,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
if (content.ContentType.IsContainer)
|
||||
{
|
||||
TabsAndPropertiesResolver.AddListView(display, "content", dataTypeService, localizedText);
|
||||
TabsAndPropertiesResolver<IContent>.AddListView(display, "content", dataTypeService, localizedText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(display => display.Alias, expression => expression.Ignore())
|
||||
.ForMember(display => display.IsContainer, expression => expression.Ignore())
|
||||
.ForMember(display => display.HasPublishedVersion, expression => expression.Ignore())
|
||||
.ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService)))
|
||||
.ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver<IMedia>(applicationContext.Services.TextService)))
|
||||
.ForMember(display => display.ContentType, expression => expression.ResolveUsing<MediaTypeBasicResolver>())
|
||||
.ForMember(display => display.MediaLink, expression => expression.ResolveUsing(
|
||||
content => string.Join(",", content.GetUrls(UmbracoConfig.For.UmbracoSettings().Content, applicationContext.ProfilingLogger.Logger))))
|
||||
@@ -70,6 +70,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore());
|
||||
}
|
||||
|
||||
//TODO: All of this logic should be moved to the TabsAndPropertiesResolver and not in AfterMap
|
||||
private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, IContentTypeService contentTypeService, ILogger logger)
|
||||
{
|
||||
// Adapted from ContentModelMapper
|
||||
@@ -80,7 +81,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
if (media.ContentType.IsContainer)
|
||||
{
|
||||
TabsAndPropertiesResolver.AddListView(display, "media", dataTypeService, localizedText);
|
||||
TabsAndPropertiesResolver<IMedia>.AddListView(display, "media", dataTypeService, localizedText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
///
|
||||
/// This also ensures that the IsSensitive property display value is set based on the configured IMemberType property type
|
||||
/// </remarks>
|
||||
internal class MemberTabsAndPropertiesResolver : TabsAndPropertiesResolver, IValueResolver
|
||||
internal class MemberTabsAndPropertiesResolver : TabsAndPropertiesResolver<IMember>
|
||||
{
|
||||
private readonly ILocalizedTextService _localizedTextService;
|
||||
private readonly IMemberService _memberService;
|
||||
@@ -238,45 +238,23 @@ namespace Umbraco.Web.Models.Mapping
|
||||
_memberService = memberService;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly implement to override behavior
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is required to get access to the <see cref="ResolutionResult"/> object which allows us access to the mapping options
|
||||
/// </remarks>
|
||||
ResolutionResult IValueResolver.Resolve(ResolutionResult source)
|
||||
{
|
||||
//call the base class logic
|
||||
var result = base.Resolve(source);
|
||||
|
||||
var member = (IMember)source.Value;
|
||||
//now we can customize the result and use the ResolutionResult options to get the UmbracoContext
|
||||
var tabs = (List<Tab<ContentPropertyDisplay>>) result.Value;
|
||||
|
||||
//now we can customize the result with the current context, we can get the UmbracoContext from the options
|
||||
CustomizeProperties(source.Context.GetUmbracoContext(), member, tabs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to deal with custom member properties
|
||||
/// Overridden to deal with custom member properties and permissions
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
protected override List<Tab<ContentPropertyDisplay>> ResolveCore(IContentBase content)
|
||||
protected override List<Tab<ContentPropertyDisplay>> ResolveCore(UmbracoContext umbracoContext, IMember content)
|
||||
{
|
||||
var provider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
|
||||
|
||||
|
||||
IgnoreProperties = content.PropertyTypes
|
||||
.Where(x => x.HasIdentity == false)
|
||||
.Select(x => x.Alias)
|
||||
.ToArray();
|
||||
|
||||
var result = base.ResolveCore(content);
|
||||
var result = base.ResolveCore(umbracoContext, content);
|
||||
|
||||
if (provider.IsUmbracoMembershipProvider() == false)
|
||||
{
|
||||
@@ -303,6 +281,39 @@ namespace Umbraco.Web.Models.Mapping
|
||||
}
|
||||
}
|
||||
|
||||
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}", content.ContentTypeId);
|
||||
|
||||
//Replace the doctype property
|
||||
var docTypeProperty = result.SelectMany(x => x.Properties)
|
||||
.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||
docTypeProperty.Value = new List<object>
|
||||
{
|
||||
new
|
||||
{
|
||||
linkText = content.ContentType.Name,
|
||||
url = memberTypeLink,
|
||||
target = "_self",
|
||||
icon = "icon-item-arrangement"
|
||||
}
|
||||
};
|
||||
docTypeProperty.View = "urllist";
|
||||
}
|
||||
|
||||
//check if there's an approval field
|
||||
var legacyProvider = provider as global::umbraco.providers.members.UmbracoMembershipProvider;
|
||||
if (content.HasIdentity == false && legacyProvider != null)
|
||||
{
|
||||
var approvedField = legacyProvider.ApprovedPropertyTypeAlias;
|
||||
var prop = result.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == approvedField);
|
||||
if (prop != null)
|
||||
{
|
||||
prop.Value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -362,63 +373,17 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
return genericProperties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs some customizations for the properties based on the current context
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="member"></param>
|
||||
/// <param name="tabs">The current tab collection</param>
|
||||
/// <remarks>
|
||||
/// If this is a new entity and there is an approved field then we'll set it to true by default.
|
||||
/// </remarks>
|
||||
private void CustomizeProperties(UmbracoContext umbracoContext, IMember member, List<Tab<ContentPropertyDisplay>> tabs)
|
||||
{
|
||||
var membersProvider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
|
||||
|
||||
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}", member.ContentTypeId);
|
||||
|
||||
//Replace the doctype property
|
||||
var docTypeProperty = tabs.SelectMany(x => x.Properties)
|
||||
.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||
docTypeProperty.Value = new List<object>
|
||||
{
|
||||
new
|
||||
{
|
||||
linkText = member.ContentType.Name,
|
||||
url = memberTypeLink,
|
||||
target = "_self",
|
||||
icon = "icon-item-arrangement"
|
||||
}
|
||||
};
|
||||
docTypeProperty.View = "urllist";
|
||||
}
|
||||
|
||||
//check if there's an approval field
|
||||
var provider = membersProvider as global::umbraco.providers.members.UmbracoMembershipProvider;
|
||||
if (member.HasIdentity == false && provider != null)
|
||||
{
|
||||
var approvedField = provider.ApprovedPropertyTypeAlias;
|
||||
var prop = tabs.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == approvedField);
|
||||
if (prop != null)
|
||||
{
|
||||
prop.Value = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <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(IContentBase content, List<Property> properties)
|
||||
protected override List<ContentPropertyDisplay> MapProperties(UmbracoContext umbracoContext, IContentBase content, List<Property> properties)
|
||||
{
|
||||
var result = base.MapProperties(content, properties);
|
||||
var result = base.MapProperties(umbracoContext, content, properties);
|
||||
var member = (IMember)content;
|
||||
var memberType = member.ContentType;
|
||||
var labelPropEditor = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View;
|
||||
@@ -427,8 +392,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
prop.IsSensitive = memberType.IsSensitiveProperty(prop.Alias);
|
||||
//check permissions for viewing sensitive data
|
||||
|
||||
if (prop.IsSensitive)
|
||||
if (prop.IsSensitive && umbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
|
||||
{
|
||||
//replace this editor with a label
|
||||
prop.View = labelPropEditor;
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
/// <summary>
|
||||
/// Creates the tabs collection with properties assigned for display models
|
||||
/// </summary>
|
||||
internal class TabsAndPropertiesResolver : ValueResolver<IContentBase, List<Tab<ContentPropertyDisplay>>>
|
||||
internal class TabsAndPropertiesResolver<TSource> : IValueResolver
|
||||
where TSource : IContentBase
|
||||
{
|
||||
private readonly ILocalizedTextService _localizedTextService;
|
||||
protected IEnumerable<string> IgnoreProperties { get; set; }
|
||||
@@ -35,6 +36,24 @@ namespace Umbraco.Web.Models.Mapping
|
||||
IgnoreProperties = ignoreProperties;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="IValueResolver"/>
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
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(List<Tab<ContentPropertyDisplay>>));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the container (listview) tab to the document
|
||||
/// </summary>
|
||||
@@ -145,7 +164,13 @@ namespace Umbraco.Web.Models.Mapping
|
||||
display.Tabs = tabs;
|
||||
}
|
||||
|
||||
protected override List<Tab<ContentPropertyDisplay>> ResolveCore(IContentBase content)
|
||||
/// <summary>
|
||||
/// Create the list of tabs for the <see cref="IContentBase"/>
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="content">Source value</param>
|
||||
/// <returns>Destination</returns>
|
||||
protected virtual List<Tab<ContentPropertyDisplay>> ResolveCore(UmbracoContext umbracoContext, TSource content)
|
||||
{
|
||||
var tabs = new List<Tab<ContentPropertyDisplay>>();
|
||||
|
||||
@@ -171,7 +196,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
continue;
|
||||
|
||||
//map the properties
|
||||
var mappedProperties = MapProperties(content, properties);
|
||||
var mappedProperties = MapProperties(umbracoContext, content, properties);
|
||||
|
||||
// add the tab
|
||||
// we need to pick an identifier... there is no "right" way...
|
||||
@@ -189,7 +214,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
});
|
||||
}
|
||||
|
||||
MapGenericProperties(content, tabs);
|
||||
MapGenericProperties(umbracoContext, content, tabs);
|
||||
|
||||
// activate the first tab
|
||||
tabs[0].IsActive = true;
|
||||
@@ -209,20 +234,21 @@ namespace Umbraco.Web.Models.Mapping
|
||||
/// <summary>
|
||||
/// Maps properties on to the generic properties tab
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="tabs"></param>
|
||||
/// <remarks>
|
||||
/// The generic properties tab is responsible for
|
||||
/// setting up the properties such as Created date, updated date, template selected, etc...
|
||||
/// </remarks>
|
||||
protected virtual void MapGenericProperties(IContentBase content, List<Tab<ContentPropertyDisplay>> tabs)
|
||||
protected virtual void MapGenericProperties(UmbracoContext umbracoContext, IContentBase content, List<Tab<ContentPropertyDisplay>> tabs)
|
||||
{
|
||||
// add the generic properties tab, for properties that don't belong to a tab
|
||||
// get the properties, map and translate them, then add the tab
|
||||
var noGroupProperties = content.GetNonGroupedProperties()
|
||||
.Where(x => IgnoreProperties.Contains(x.Alias) == false) // skip ignored
|
||||
.ToList();
|
||||
var genericproperties = MapProperties(content, noGroupProperties);
|
||||
var genericproperties = MapProperties(umbracoContext, content, noGroupProperties);
|
||||
|
||||
tabs.Add(new Tab<ContentPropertyDisplay>
|
||||
{
|
||||
@@ -268,10 +294,11 @@ namespace Umbraco.Web.Models.Mapping
|
||||
/// <summary>
|
||||
/// Maps a list of <see cref="Property"/> to a list of <see cref="ContentPropertyDisplay"/>
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="properties"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual List<ContentPropertyDisplay> MapProperties(IContentBase content, List<Property> properties)
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user