diff --git a/src/Umbraco.Core/Models/Membership/EntityPermission.cs b/src/Umbraco.Core/Models/Membership/EntityPermission.cs
index 15bdb4cbe9..a1fa57d274 100644
--- a/src/Umbraco.Core/Models/Membership/EntityPermission.cs
+++ b/src/Umbraco.Core/Models/Membership/EntityPermission.cs
@@ -11,6 +11,14 @@ namespace Umbraco.Core.Models.Membership
{
EntityId = entityId;
AssignedPermissions = assignedPermissions;
+ IsDefaultPermissions = false;
+ }
+
+ public EntityPermission(int entityId, string[] assignedPermissions, bool isDefaultPermissions)
+ {
+ EntityId = entityId;
+ AssignedPermissions = assignedPermissions;
+ IsDefaultPermissions = isDefaultPermissions;
}
public int EntityId { get; private set; }
@@ -19,6 +27,14 @@ namespace Umbraco.Core.Models.Membership
/// The assigned permissions for the user/entity combo
///
public string[] AssignedPermissions { get; private set; }
+
+ ///
+ /// True if the permissions assigned to this object are the group's default permissions and not explicitly defined permissions
+ ///
+ ///
+ /// This will be the case when looking up entity permissions and falling back to the default permissions
+ ///
+ public bool IsDefaultPermissions { get; private set; }
///
/// Adds additional permissions to an existing instance of
diff --git a/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs
index beffc5862d..deebc03401 100644
--- a/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs
+++ b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs
@@ -18,6 +18,14 @@ namespace Umbraco.Core.Models.Membership
///
string Alias { get; }
+ ///
+ /// The set of default permissions
+ ///
+ ///
+ /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
+ ///
+ IEnumerable Permissions { get; set; }
+
IEnumerable AllowedSections { get; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs
index b2a7349e81..c1b8d3997f 100644
--- a/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs
+++ b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs
@@ -5,13 +5,15 @@ namespace Umbraco.Core.Models.Membership
{
public class ReadOnlyUserGroup : IReadOnlyUserGroup, IEquatable
{
- public ReadOnlyUserGroup(int id, string name, string icon, int? startContentId, int? startMediaId, string @alias, IEnumerable allowedSections)
+ public ReadOnlyUserGroup(int id, string name, string icon, int? startContentId, int? startMediaId, string @alias,
+ IEnumerable allowedSections, IEnumerable permissions)
{
Name = name;
Icon = icon;
Id = id;
Alias = alias;
AllowedSections = allowedSections;
+ Permissions = permissions;
//Zero is invalid and will be treated as Null
StartContentId = startContentId == 0 ? null : startContentId;
@@ -24,6 +26,14 @@ namespace Umbraco.Core.Models.Membership
public int? StartContentId { get; private set; }
public int? StartMediaId { get; private set; }
public string Alias { get; private set; }
+
+ ///
+ /// The set of default permissions
+ ///
+ ///
+ /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
+ ///
+ public IEnumerable Permissions { get; set; }
public IEnumerable AllowedSections { get; private set; }
public bool Equals(ReadOnlyUserGroup other)
diff --git a/src/Umbraco.Core/Models/Membership/UserGroup.cs b/src/Umbraco.Core/Models/Membership/UserGroup.cs
index 29afc86fc8..012e9b6cc2 100644
--- a/src/Umbraco.Core/Models/Membership/UserGroup.cs
+++ b/src/Umbraco.Core/Models/Membership/UserGroup.cs
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models.Membership
///
[Serializable]
[DataContract(IsReference = true)]
- internal class UserGroup : Entity, IUserGroup
+ internal class UserGroup : Entity, IUserGroup, IReadOnlyUserGroup
{
private int? _startContentId;
private int? _startMediaId;
diff --git a/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs
index d7625f0fd8..34f4b805f9 100644
--- a/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs
+++ b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs
@@ -7,12 +7,17 @@ namespace Umbraco.Core.Models.Membership
{
public static IReadOnlyUserGroup ToReadOnlyGroup(this IUserGroup group)
{
- return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon, group.StartContentId, group.StartMediaId, group.Alias, group.AllowedSections);
+ //this will generally always be the case
+ var readonlyGroup = group as IReadOnlyUserGroup;
+ if (readonlyGroup != null) return readonlyGroup;
+
+ //otherwise create one
+ return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon, group.StartContentId, group.StartMediaId, group.Alias, group.AllowedSections, group.Permissions);
}
public static IReadOnlyUserGroup ToReadOnlyGroup(this UserGroupDto group)
{
- return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon, group.StartContentId, group.StartMediaId, group.Alias, group.UserGroup2AppDtos.Select(x => x.AppAlias).ToArray());
+ return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon, group.StartContentId, group.StartMediaId, group.Alias, group.UserGroup2AppDtos.Select(x => x.AppAlias).ToArray(), group.DefaultPermissions.ToCharArray().Select(x => x.ToString()));
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
index 499f958449..f07e9c8385 100644
--- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
@@ -470,24 +470,24 @@ namespace Umbraco.Core.Persistence.Repositories
entity.SortOrder = sortOrder;
entity.Level = level;
- //Assign the same permissions to it as the parent node
- // http://issues.umbraco.org/issue/U4-2161
- var permissionsRepo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax);
- var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray();
- //if there are parent permissions then assign them, otherwise leave null and permissions will become the
- // user's default permissions.
- if (parentPermissions.Any())
- {
- var userGroupPermissions = (
- from perm in parentPermissions
- from p in perm.AssignedPermissions
- select new EntityPermissionSet.UserGroupPermission(perm.UserGroupId, p)).ToList();
+ ////Assign the same permissions to it as the parent node
+ //// http://issues.umbraco.org/issue/U4-2161
+ //var permissionsRepo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax);
+ //var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray();
+ ////if there are parent permissions then assign them, otherwise leave null and permissions will become the
+ //// user's default permissions.
+ //if (parentPermissions.Length > 0)
+ //{
+ // var userGroupPermissions = (
+ // from perm in parentPermissions
+ // from p in perm.AssignedPermissions
+ // select new EntityPermissionSet.UserGroupPermission(perm.UserGroupId, p)).ToList();
- permissionsRepo.ReplaceEntityPermissions(new EntityPermissionSet(entity.Id, userGroupPermissions));
- //flag the entity's permissions changed flag so we can track those changes.
- //Currently only used for the cache refreshers to detect if we should refresh all user permissions cache.
- ((Content)entity).PermissionsChanged = true;
- }
+ // permissionsRepo.ReplaceEntityPermissions(new EntityPermissionSet(entity.Id, userGroupPermissions));
+ // //flag the entity's permissions changed flag so we can track those changes.
+ // //Currently only used for the cache refreshers to detect if we should refresh all user permissions cache.
+ // ((Content)entity).PermissionsChanged = true;
+ //}
//Create the Content specific data - cmsContent
var contentDto = dto.ContentVersionDto.ContentDto;
diff --git a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs
index ca9045507b..5ae4efad45 100644
--- a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs
@@ -35,82 +35,68 @@ namespace Umbraco.Core.Persistence.Repositories
}
///
- /// Returns permissions for a given group for any number of nodes
+ /// Returns explicitly defined permissions for a user group for any number of nodes
///
///
///
///
public IEnumerable GetPermissionsForEntities(int groupId, params int[] entityIds)
{
- var entityIdKey = GetEntityIdKey(entityIds);
- return _runtimeCache.GetCacheItem>(
- string.Format("{0}{1}{2}",
- CacheKeys.UserGroupPermissionsCacheKey,
- groupId,
- entityIdKey),
- () =>
- {
- var whereCriteria = GetPermissionsForEntitiesCriteria(groupId, entityIds);
- var sql = new Sql();
- sql.Select("*")
- .From()
- .Where(whereCriteria);
- var result = _unitOfWork.Database.Fetch(sql).ToArray();
- // ToArray() to ensure it's all fetched from the db once
- return ConvertToPermissionList(result);
- },
- GetCacheTimeout(),
- priority: GetCachePriority());
- }
-
- private static string GetEntityIdKey(int[] entityIds)
- {
- return string.Join(",", entityIds.Select(x => x.ToString(CultureInfo.InvariantCulture)));
- }
-
- private string GetPermissionsForEntitiesCriteria(int groupId, params int[] entityIds)
- {
- var whereBuilder = new StringBuilder();
- whereBuilder.Append(_sqlSyntax.GetQuotedColumnName("userGroupId"));
- whereBuilder.Append("=");
- whereBuilder.Append(groupId);
-
- if (entityIds.Any())
+ //var whereCriteria = GetPermissionsForEntitiesCriteria(groupId, entityIds);
+ var result = new List();
+ //iterate in groups of 2000 since we don't want to exceed the max SQL param count
+ foreach (var groupOfIds in entityIds.InGroupsOf(2000))
{
- whereBuilder.Append(" AND ");
+ var ids = groupOfIds;
- //where nodeId = @nodeId1 OR nodeId = @nodeId2, etc...
- whereBuilder.Append("(");
- for (var index = 0; index < entityIds.Length; index++)
- {
- var entityId = entityIds[index];
- whereBuilder.Append(_sqlSyntax.GetQuotedColumnName("nodeId"));
- whereBuilder.Append("=");
- whereBuilder.Append(entityId);
- if (index < entityIds.Length - 1)
- {
- whereBuilder.Append(" OR ");
- }
- }
-
- whereBuilder.Append(")");
- }
-
- return whereBuilder.ToString();
+ var sql = new Sql();
+ sql.Select("*")
+ .From(_sqlSyntax)
+ .Where(dto => dto.UserGroupId == groupId && ids.Contains(dto.NodeId), _sqlSyntax);
+ var permissions = _unitOfWork.Database.Fetch(sql);
+ result.AddRange(ConvertToPermissionList(permissions));
+ }
+ return result;
+
+
+ //var entityIdKey = GetEntityIdKey(entityIds);
+
+ //return _runtimeCache.GetCacheItem>(
+ // string.Format("{0}{1}{2}",
+ // CacheKeys.UserGroupPermissionsCacheKey,
+ // groupId,
+ // entityIdKey),
+ // () =>
+ // {
+ // var whereCriteria = GetPermissionsForEntitiesCriteria(groupId, entityIds);
+ // var sql = new Sql();
+ // sql.Select("*")
+ // .From()
+ // .Where(whereCriteria);
+ // var result = _unitOfWork.Database.Fetch(sql);
+ // return ConvertToPermissionList(result);
+ // },
+ // GetCacheTimeout(),
+ // priority: GetCachePriority());
}
- private static TimeSpan GetCacheTimeout()
- {
- //Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will only have this exist in cache for 20 minutes,
- // then it will refresh from the database.
- return new TimeSpan(0, 20, 0);
- }
+ //private static string GetEntityIdKey(int[] entityIds)
+ //{
+ // return string.Join(",", entityIds.Select(x => x.ToString(CultureInfo.InvariantCulture)));
+ //}
- private static CacheItemPriority GetCachePriority()
- {
- //Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will make this priority below average
- return CacheItemPriority.BelowNormal;
- }
+ //private static TimeSpan GetCacheTimeout()
+ //{
+ // //Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will only have this exist in cache for 20 minutes,
+ // // then it will refresh from the database.
+ // return new TimeSpan(0, 20, 0);
+ //}
+
+ //private static CacheItemPriority GetCachePriority()
+ //{
+ // //Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will make this priority below average
+ // return CacheItemPriority.BelowNormal;
+ //}
private static IEnumerable ConvertToPermissionList(IEnumerable result)
{
@@ -142,8 +128,7 @@ namespace Umbraco.Core.Persistence.Repositories
.Where(dto => dto.NodeId == entityId)
.OrderBy(dto => dto.NodeId);
- var result = _unitOfWork.Database.Fetch(sql).ToArray();
- // ToArray() to ensure it's all fetched from the db once
+ var result = _unitOfWork.Database.Fetch(sql);
return ConvertToPermissionList(result);
}
diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs
index 3ac485bf2b..b55048ef4d 100644
--- a/src/Umbraco.Core/Services/IUserService.cs
+++ b/src/Umbraco.Core/Services/IUserService.cs
@@ -92,63 +92,63 @@ namespace Umbraco.Core.Services
/// User to retrieve permissions for
/// Specifiying nothing will return all user permissions for all nodes
/// An enumerable list of
+ ///
+ /// > This is the ONLY one for permissions from 7.6!
+ ///
IEnumerable GetPermissions(IUser user, params int[] nodeIds);
///
/// Get permissions set for a group and optional node Ids
///
/// Group to retrieve permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
/// Specifiying nothing will return all permissions for all nodes
/// An enumerable list of
- IEnumerable GetPermissions(string groupAlias, bool directlyAssignedOnly, params int[] nodeIds);
+ IEnumerable GetPermissions(string groupAlias, bool fallbackToDefaultPermissions, params int[] nodeIds);
///
/// Get permissions set for a group and optional node Ids
///
/// Group to retrieve permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
/// Specifiying nothing will return all permissions for all nodes
/// An enumerable list of
- IEnumerable GetPermissions(IUserGroup group, bool directlyAssignedOnly, params int[] nodeIds);
+ IEnumerable GetPermissions(IUserGroup group, bool fallbackToDefaultPermissions, params int[] nodeIds);
///
/// Gets the permissions for the provided user and path
///
/// User to check permissions for
/// Path to check permissions for
- /// String indicating permissions for provided user and path
- string GetPermissionsForPath(IUser user, string path);
+ EntityPermissionSet GetPermissionsForPath(IUser user, string path);
///
/// Gets the permissions for the provided group and path
///
/// Group alias to check permissions for
/// Path to check permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
- /// String indicating permissions for provided user and path
- string GetPermissionsForPath(string groupAlias, string path, bool directlyAssignedOnly = true);
+ EntityPermission GetPermissionsForPath(string groupAlias, string path, bool fallbackToDefaultPermissions = false);
///
/// Gets the permissions for the provided group and path
///
/// Group to check permissions for
/// Path to check permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
- /// String indicating permissions for provided user and path
- string GetPermissionsForPath(IUserGroup group, string path, bool directlyAssignedOnly = true);
+ EntityPermission GetPermissionsForPath(IUserGroup group, string path, bool fallbackToDefaultPermissions = false);
///
/// Replaces the same permission set for a single group to any number of entities
diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs
index f7cf263e91..b2a1ddec58 100644
--- a/src/Umbraco.Core/Services/UserService.cs
+++ b/src/Umbraco.Core/Services/UserService.cs
@@ -121,7 +121,7 @@ namespace Umbraco.Core.Services
Language = GlobalSettings.DefaultUILanguage,
Name = username,
RawPasswordValue = passwordValue,
- Username = username,
+ Username = username,
IsLockedOut = false,
IsApproved = isApproved
};
@@ -208,11 +208,11 @@ namespace Umbraco.Core.Services
public void Delete(IUser membershipUser)
{
//disable
- membershipUser.IsApproved = false;
-
+ membershipUser.IsApproved = false;
+
Save(membershipUser);
- }
-
+ }
+
///
/// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method
///
@@ -616,12 +616,12 @@ namespace Umbraco.Core.Services
{
return repository.GetAllNotInGroup(groupId);
}
- }
-
+ }
+
#endregion
-
+
#region Implementation of IUserService
-
+
///
/// Gets an IProfile by User Id.
///
@@ -706,8 +706,8 @@ namespace Umbraco.Core.Services
repository.AssignGroupPermission(groupId, permission, entityIds);
uow.Commit();
}
- }
-
+ }
+
///
/// Gets all UserGroups or those specified as parameters
///
@@ -720,8 +720,8 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateUserGroupRepository(uow);
return repository.GetAll(ids).OrderBy(x => x.Name);
}
- }
-
+ }
+
public IEnumerable GetUserGroupsByAlias(params string[] aliases)
{
if (aliases.Length == 0) return Enumerable.Empty();
@@ -788,8 +788,8 @@ namespace Umbraco.Core.Services
}
var repository = RepositoryFactory.CreateUserGroupRepository(uow);
- repository.AddOrUpdateGroupWithUsers(userGroup, userIds);
-
+ repository.AddOrUpdateGroupWithUsers(userGroup, userIds);
+
uow.Commit();
if (raiseEvents)
@@ -838,8 +838,8 @@ namespace Umbraco.Core.Services
uow.Commit();
//TODO: Events?
}
- }
-
+ }
+
///
/// Get permissions set for a user and node Id
///
@@ -848,16 +848,19 @@ namespace Umbraco.Core.Services
/// An enumerable list of
public IEnumerable GetPermissions(IUser user, params int[] nodeIds)
{
+ if (nodeIds.Length == 0)
+ return Enumerable.Empty();
+
var result = new List();
+
foreach (var group in user.Groups)
{
- //TODO: This may perform horribly :/
- foreach (var permission in GetPermissions(group.Alias, false, nodeIds))
+ foreach (var permission in GetPermissions(group, true, nodeIds))
{
AddOrAmendPermissionList(result, permission);
}
- }
-
+ }
+
return result;
}
@@ -865,19 +868,57 @@ namespace Umbraco.Core.Services
/// Get permissions set for a group and node Id
///
/// Group to retrieve permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
/// Specifiying nothing will return all permissions for all nodes
/// An enumerable list of
- public IEnumerable GetPermissions(string groupAlias, bool directlyAssignedOnly, params int[] nodeIds)
- {
+ public IEnumerable GetPermissions(string groupAlias, bool fallbackToDefaultPermissions, params int[] nodeIds)
+ {
+ if (nodeIds.Length == 0)
+ return Enumerable.Empty();
+
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserGroupRepository(uow);
var group = repository.Get(groupAlias);
- return GetPermissionsInternal(repository, group, directlyAssignedOnly, nodeIds);
+ if (group == null) throw new InvalidOperationException("No group found with alias " + groupAlias);
+ return GetPermissionsInternal(repository, group.ToReadOnlyGroup(), fallbackToDefaultPermissions, nodeIds);
+ }
+ }
+
+ private IEnumerable GetPermissions(IReadOnlyUserGroup group, bool fallbackToDefaultPermissions, params int[] nodeIds)
+ {
+ if (group == null) throw new ArgumentNullException("group");
+ if (nodeIds.Length == 0)
+ return Enumerable.Empty();
+
+ using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
+ {
+ var repository = RepositoryFactory.CreateUserGroupRepository(uow);
+ return GetPermissionsInternal(repository, group, fallbackToDefaultPermissions, nodeIds);
+ }
+ }
+
+ private IEnumerable GetPermissions(int groupId, bool fallbackToDefaultPermissions, params int[] nodeIds)
+ {
+ if (nodeIds.Length == 0)
+ return Enumerable.Empty();
+
+ using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
+ {
+ var repository = RepositoryFactory.CreateUserGroupRepository(uow);
+
+ if (fallbackToDefaultPermissions == false)
+ {
+ //if fallbackToDefaultPermissions is false, we don't have to lookup the group
+ return repository.GetPermissionsForEntities(groupId, nodeIds);
+ }
+
+ var group = repository.Get(groupId);
+ if (group == null) throw new InvalidOperationException("No group found with id " + groupId);
+ return GetPermissionsInternal(repository, group.ToReadOnlyGroup(), true, nodeIds);
}
}
@@ -885,35 +926,40 @@ namespace Umbraco.Core.Services
/// Get permissions set for a group and optional node Ids
///
/// Group to retrieve permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
/// Specifiying nothing will return all permissions for all nodes
/// An enumerable list of
- public IEnumerable GetPermissions(IUserGroup group, bool directlyAssignedOnly, params int[] nodeIds)
+ public IEnumerable GetPermissions(IUserGroup group, bool fallbackToDefaultPermissions, params int[] nodeIds)
{
if (group == null) throw new ArgumentNullException("group");
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserGroupRepository(uow);
- return GetPermissionsInternal(repository, group, directlyAssignedOnly, nodeIds);
+ return GetPermissionsInternal(repository, group.ToReadOnlyGroup(), fallbackToDefaultPermissions, nodeIds);
}
- }
-
- private IEnumerable GetPermissionsInternal(IUserGroupRepository repository, IUserGroup group, bool directlyAssignedOnly, params int[] nodeIds)
+ }
+
+ private static IEnumerable GetPermissionsInternal(IUserGroupRepository repository, IReadOnlyUserGroup group, bool fallbackToDefaultPermissions, params int[] nodeIds)
{
+ if (group == null) throw new ArgumentNullException("group");
+
+ if (nodeIds.Length == 0)
+ return Enumerable.Empty();
+
var explicitPermissions = repository.GetPermissionsForEntities(group.Id, nodeIds);
var result = new List(explicitPermissions);
// If requested, and no permissions are assigned to a particular node, then we will fill in those permissions with the group's defaults
- if (directlyAssignedOnly == false)
+ if (fallbackToDefaultPermissions)
{
- var missingIds = nodeIds.Except(result.Select(x => x.EntityId)).ToList();
- if (missingIds.Any())
+ var missingIds = nodeIds.Except(result.Select(x => x.EntityId)).ToArray();
+ if (missingIds.Length > 0)
{
result.AddRange(missingIds
- .Select(i => new EntityPermission(i, group.Permissions.ToArray())));
+ .Select(i => new EntityPermission(i, group.Permissions.ToArray(), isDefaultPermissions: true)));
}
}
return result;
@@ -946,91 +992,163 @@ namespace Umbraco.Core.Services
///
/// User to check permissions for
/// Path to check permissions for
- /// String indicating permissions for provided user and path
- public string GetPermissionsForPath(IUser user, string path)
- {
- var assignedPermissions = GetPermissionsForGroupsAndPath(user.Groups.Select(x => x.Alias), path);
- return GetAggregatePermissions(assignedPermissions);
+ public EntityPermissionSet GetPermissionsForPath(IUser user, string path)
+ {
+ var nodeIds = GetIdsFromPath(path);
+
+ if (nodeIds.Length == 0)
+ return null;
+
+ var permissionsByGroup = GetPermissionsForGroupsAndPath(user.Groups, nodeIds);
+
+ // not sure this will ever happen, it shouldn't since this should return defaults, but maybe those are empty?
+ if (permissionsByGroup.Count == 0)
+ return null;
+
+ var entityId = nodeIds[0];
+
+ var groupPermissions = new List();
+ foreach (var entityPermission in permissionsByGroup)
+ {
+ var groupId = entityPermission.Key;
+ foreach (var assignedPermission in entityPermission.Value.AssignedPermissions)
+ {
+ groupPermissions.Add(new EntityPermissionSet.UserGroupPermission(groupId, assignedPermission));
+ }
+ }
+
+ var permissionSet = new EntityPermissionSet(entityId, groupPermissions);
+ return permissionSet;
}
///
/// Retrieves the permissions assigned to each group for a given path
///
/// List of groups associated with the user
- /// Path to check permissions for
- /// List of strings indicating permissions for each groups
- private IEnumerable GetPermissionsForGroupsAndPath(IEnumerable groups, string path)
+ /// Path to check permissions for
+ /// A dictionary of group ids and their associated node permissions
+ private IDictionary GetPermissionsForGroupsAndPath(IEnumerable groups, int[] pathIds)
{
return groups
- .Select(g => GetPermissionsForPath(g, path, directlyAssignedOnly: false))
- .ToList();
- }
-
- ///
- /// Aggregates a set of permissions strings to return a unique permissions string containing the most permissive set
- ///
- /// List of permission strings
- /// Single permission string
- private static string GetAggregatePermissions(IEnumerable assignedPermissions)
- {
- return string.Join(string.Empty, assignedPermissions
- .SelectMany(s => s.ToCharArray())
- .Distinct());
- }
-
+ .Select(g => new
+ {
+ group = g.Id,
+ permissions = GetPermissionsForPath(g, pathIds, fallbackToDefaultPermissions: true)
+ })
+ .ToDictionary(x => x.group, x => x.permissions);
+ }
+
///
/// Gets the permissions for the provided group and path
///
/// User to check permissions for
/// Path to check permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
/// String indicating permissions for provided user and path
- public string GetPermissionsForPath(string groupAlias, string path, bool directlyAssignedOnly = true)
+ public EntityPermission GetPermissionsForPath(string groupAlias, string path, bool fallbackToDefaultPermissions = false)
{
- var nodeId = GetNodeIdFromPath(path);
- var permission = GetPermissions(groupAlias, directlyAssignedOnly, nodeId)
- .FirstOrDefault();
- return permission != null
- ? string.Join(string.Empty, permission.AssignedPermissions)
- : string.Empty;
- }
-
+ var nodeIds = GetIdsFromPath(path);
+ //get permissions for all nodes in the path
+ var permissions = GetPermissions(groupAlias, fallbackToDefaultPermissions, nodeIds);
+ return GetPermissionsForPath(permissions, nodeIds, fallbackToDefaultPermissions);
+ }
+
///
/// Gets the permissions for the provided group and path
///
/// Group to check permissions for
/// Path to check permissions for
- ///
+ ///
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
///
/// String indicating permissions for provided user and path
- public string GetPermissionsForPath(IUserGroup group, string path, bool directlyAssignedOnly = true)
+ public EntityPermission GetPermissionsForPath(IUserGroup group, string path, bool fallbackToDefaultPermissions = false)
{
- var nodeId = GetNodeIdFromPath(path);
- var permission = GetPermissions(group, directlyAssignedOnly, nodeId)
- .FirstOrDefault();
- return permission != null
- ? string.Join(string.Empty, permission.AssignedPermissions)
- : string.Empty;
+ var nodeIds = GetIdsFromPath(path);
+ return GetPermissionsForPath(group.ToReadOnlyGroup(), nodeIds, fallbackToDefaultPermissions);
}
+ private EntityPermission GetPermissionsForPath(IReadOnlyUserGroup group, int[] pathIds, bool fallbackToDefaultPermissions = false)
+ {
+ //get permissions for all nodes in the path
+ var permissions = GetPermissions(group, fallbackToDefaultPermissions, pathIds);
+ return GetPermissionsForPath(permissions, pathIds, fallbackToDefaultPermissions);
+ }
+
+ //private EntityPermission GetPermissionsForPath(int groupId, string path, bool fallbackToDefaultPermissions = false)
+ //{
+ // var nodeIds = GetIdsFromPath(path);
+ // //get permissions for all nodes in the path
+ // var permissions = GetPermissions(groupId, fallbackToDefaultPermissions, nodeIds);
+ // return GetPermissionsForPath(permissions, groupId, nodeIds, fallbackToDefaultPermissions);
+ //}
+
+ ///
+ /// Returns the permissions for the path ids
+ ///
+ ///
+ /// Must be ordered deepest to shallowest (right to left)
+ ///
+ ///
+ private static EntityPermission GetPermissionsForPath(
+ IEnumerable pathPermissions,
+ int[] pathIds,
+ bool fallbackToDefaultPermissions = false)
+ {
+ //get permissions for all nodes in the path
+ var permissionsByEntityId = pathPermissions.ToDictionary(x => x.EntityId, x => x);
+
+ //then the permissions assigned to the path will be the 'deepest' node found that has permissions
+ foreach (var id in pathIds)
+ {
+ EntityPermission permission;
+ if (permissionsByEntityId.TryGetValue(id, out permission))
+ {
+ //don't return the default permissions if that is the one assigned here (we'll do that below if nothing was found)
+ if (permission.IsDefaultPermissions == false)
+ return permission;
+ }
+ }
+
+ //if we've made it here it means that no implicit/inherited permissions were found so we return the defaults if that is specified
+ if (fallbackToDefaultPermissions == false)
+ return null;
+
+ return permissionsByEntityId[pathIds[0]];
+ }
///
- /// Parses a path to find the lowermost node id
+ /// Convert a path to node ids in the order from right to left (deepest to shallowest)
///
- /// Path as string
- /// Node id
- private static int GetNodeIdFromPath(string path)
+ ///
+ ///
+ private int[] GetIdsFromPath(string path)
{
- return path.Contains(",")
- ? int.Parse(path.Substring(path.LastIndexOf(",", StringComparison.Ordinal) + 1))
- : int.Parse(path);
- }
-
+ var nodeIds = path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(x => x.TryConvertTo())
+ .Where(x => x.Success)
+ .Select(x => x.Result)
+ .Reverse()
+ .ToArray();
+ return nodeIds;
+ }
+
+ /////
+ ///// Parses a path to find the lowermost node id
+ /////
+ ///// Path as string
+ ///// Node id
+ //private static int GetNodeIdFromPath(string path)
+ //{
+ // return path.Contains(",")
+ // ? int.Parse(path.Substring(path.LastIndexOf(",", StringComparison.Ordinal) + 1))
+ // : int.Parse(path);
+ //}
+
///
/// Checks in a set of permissions associated with a user for those related to a given nodeId
///
diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs
index a3e5510941..2b9e0b1ed3 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs
@@ -135,11 +135,11 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
{
var hasPropertiesContentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
- content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
-
+ content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
+
contentTypeRepository.AddOrUpdate(hasPropertiesContentType);
- repository.AddOrUpdate(content1);
- unitOfWork.Commit();
+ repository.AddOrUpdate(content1);
+ unitOfWork.Commit();
}
var versionDtos = new List();
@@ -167,7 +167,7 @@ namespace Umbraco.Tests.Persistence.Repositories
VersionId = version,
WriterUserId = 0,
UpdateDate = versionDate,
- TemplateId = content1.Template == null || content1.Template.Id <= 0 ? null : (int?) content1.Template.Id
+ TemplateId = content1.Template == null || content1.Template.Id <= 0 ? null : (int?)content1.Template.Id
});
}
@@ -188,7 +188,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Assert.AreEqual(contentItem.Version, versionDtos.Single(x => x.Id == versionDtos.Max(y => y.Id)).VersionId);
var allVersions = repository.GetAllVersions(content[0].Id);
- var allKnownVersions = versionDtos.Select(x => x.VersionId).Union(new[]{ content1.Version }).ToArray();
+ var allKnownVersions = versionDtos.Select(x => x.VersionId).Union(new[] { content1.Version }).ToArray();
Assert.IsTrue(allKnownVersions.ContainsAll(allVersions.Select(x => x.Version)));
Assert.IsTrue(allVersions.Select(x => x.Version).ContainsAll(allKnownVersions));
}
@@ -547,9 +547,9 @@ namespace Umbraco.Tests.Persistence.Repositories
var userGroup = MockedUserGroup.CreateUserGroup("1");
repository.AddOrUpdate(userGroup);
unitOfWork.Commit();
- }
-
- ContentTypeRepository contentTypeRepository;
+ }
+
+ ContentTypeRepository contentTypeRepository;
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
{
var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
@@ -563,7 +563,7 @@ namespace Umbraco.Tests.Persistence.Repositories
unitOfWork.Commit();
// Act
- repository.AssignEntityPermission(parentPage, 'A', new [] { 1 });
+ repository.AssignEntityPermission(parentPage, 'A', new[] { 1 });
var childPage = MockedContent.CreateSimpleContent(contentType, "child", parentPage);
repository.AddOrUpdate(childPage);
unitOfWork.Commit();
diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs
index b521172417..93202af102 100644
--- a/src/Umbraco.Tests/Services/ContentServiceTests.cs
+++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs
@@ -1458,6 +1458,178 @@ namespace Umbraco.Tests.Services
Assert.That(contents.Any(), Is.False);
}
+ [Test]
+ public void Ensures_Permissions_Are_Set_On_Copied_Entity_To_Parent_Without_Permissions()
+ {
+ // Arrange
+ var userGroup = MockedUserGroup.CreateUserGroup("1");
+ ServiceContext.UserService.Save(userGroup);
+
+ var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
+ contentType.AllowedContentTypes = new List
+ {
+ new ContentTypeSort(new Lazy(() => contentType.Id), 0, contentType.Alias)
+ };
+ ServiceContext.ContentTypeService.Save(contentType);
+
+ var parentPage = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parentPage);
+ ServiceContext.ContentService.AssignContentPermission(parentPage, 'A', new[] { 1 });
+
+ var childPage = MockedContent.CreateSimpleContent(contentType, "child", parentPage);
+ ServiceContext.ContentService.Save(childPage);
+
+ //Ok, now copy, what should happen is the childPage will not have any permissions assigned since it's new parent
+ //doesn't have any assigned
+ var parentPage2 = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parentPage2);
+
+ var copy = ServiceContext.ContentService.Copy(childPage, parentPage2.Id, false, true);
+
+ //Re-get the permissions, since there was none assigned to the new parent, the child shouldn't have any directly assigned
+ var copyPermissions = ServiceContext.ContentService.GetPermissionsForEntity(copy);
+ Assert.AreEqual(0, copyPermissions.Count());
+ }
+
+ [Test]
+ public void Ensures_Permissions_Are_Set_On_Copied_Entity_To_Parent_With_Permissions()
+ {
+ // Arrange
+ var userGroup = MockedUserGroup.CreateUserGroup("1");
+ ServiceContext.UserService.Save(userGroup);
+
+ var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
+ contentType.AllowedContentTypes = new List
+ {
+ new ContentTypeSort(new Lazy(() => contentType.Id), 0, contentType.Alias)
+ };
+ ServiceContext.ContentTypeService.Save(contentType);
+
+ var parentPage = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parentPage);
+ ServiceContext.ContentService.AssignContentPermission(parentPage, 'A', new[] { 1 });
+
+ var childPage = MockedContent.CreateSimpleContent(contentType, "child", parentPage);
+ ServiceContext.ContentService.Save(childPage);
+
+ //Ok, now copy, what should happen is the childPage will have it's new parent permissions copied over
+ var parentPage2 = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parentPage2);
+ ServiceContext.ContentService.AssignContentPermission(parentPage2, 'B', new[] { 1 });
+
+ var copy = ServiceContext.ContentService.Copy(childPage, parentPage2.Id, false, true);
+
+ //Re-get the permissions, since there was none assigned to the new parent, the child shouldn't have any directly assigned
+ var copyPermissions = ServiceContext.ContentService.GetPermissionsForEntity(copy);
+ Assert.AreEqual(1, copyPermissions.Count());
+ Assert.AreEqual("B", copyPermissions.Single().AssignedPermissions.First());
+ }
+
+ [Test]
+ public void Ensures_Permissions_Are_Set_On_Copied_Descendants_To_Parent_With_Permissions()
+ {
+ // Arrange
+ var userGroup = MockedUserGroup.CreateUserGroup("1");
+ ServiceContext.UserService.Save(userGroup);
+
+ var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
+ contentType.AllowedContentTypes = new List
+ {
+ new ContentTypeSort(new Lazy(() => contentType.Id), 0, contentType.Alias)
+ };
+ ServiceContext.ContentTypeService.Save(contentType);
+
+ var parentPage = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parentPage);
+ ServiceContext.ContentService.AssignContentPermission(parentPage, 'A', new[] { 1 });
+
+ var childPage1 = MockedContent.CreateSimpleContent(contentType, "child1", parentPage);
+ ServiceContext.ContentService.Save(childPage1);
+ var childPage2 = MockedContent.CreateSimpleContent(contentType, "child2", childPage1);
+ ServiceContext.ContentService.Save(childPage2);
+ var childPage3 = MockedContent.CreateSimpleContent(contentType, "child3", childPage2);
+ ServiceContext.ContentService.Save(childPage3);
+
+ //Ok, now copy, what should happen is the childPage will have it's new parent permissions copied over
+ var parentPage2 = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parentPage2);
+ ServiceContext.ContentService.AssignContentPermission(parentPage2, 'B', new[] { 1 });
+
+ var copy = ServiceContext.ContentService.Copy(childPage1, parentPage2.Id, false, true);
+
+ //Re-get the permissions, since there was none assigned to the new parent, the child shouldn't have any directly assigned
+ var copyPermissions = ServiceContext.ContentService.GetPermissionsForEntity(copy);
+ Assert.AreEqual(1, copyPermissions.Count());
+ Assert.AreEqual("B", copyPermissions.Single().AssignedPermissions.First());
+
+ var descendants = ServiceContext.ContentService.GetDescendants(copy).ToArray();
+ Assert.AreEqual(2, descendants.Length);
+
+ foreach (var descendant in descendants)
+ {
+ var permissions = ServiceContext.ContentService.GetPermissionsForEntity(descendant);
+ Assert.AreEqual(1, permissions.Count());
+ Assert.AreEqual("B", permissions.Single().AssignedPermissions.First());
+ }
+ }
+
+ [Test]
+ public void Ensures_Permissions_Are_Set_On_Descendants_When_Permissions_Added()
+ {
+ // Arrange
+ var userGroup = MockedUserGroup.CreateUserGroup("1");
+ ServiceContext.UserService.Save(userGroup);
+
+ var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
+ contentType.AllowedContentTypes = new List
+ {
+ new ContentTypeSort(new Lazy(() => contentType.Id), 0, contentType.Alias)
+ };
+ ServiceContext.ContentTypeService.Save(contentType);
+
+ var parentPage = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parentPage);
+ var childPage1 = MockedContent.CreateSimpleContent(contentType, "child1", parentPage);
+ ServiceContext.ContentService.Save(childPage1);
+ var childPage2 = MockedContent.CreateSimpleContent(contentType, "child2", childPage1);
+ ServiceContext.ContentService.Save(childPage2);
+ var childPage3 = MockedContent.CreateSimpleContent(contentType, "child3", childPage2);
+ ServiceContext.ContentService.Save(childPage3);
+
+ //ensure there are no permissions on any node
+
+ var permissions = ServiceContext.ContentService.GetPermissionsForEntity(parentPage);
+ Assert.AreEqual(0, permissions.Count());
+
+ var descendants = ServiceContext.ContentService.GetDescendants(parentPage).ToArray();
+ Assert.AreEqual(3, descendants.Length);
+
+ foreach (var descendant in descendants)
+ {
+ permissions = ServiceContext.ContentService.GetPermissionsForEntity(descendant);
+ Assert.AreEqual(0, permissions.Count());
+ }
+
+ //Ok, now assign permissions to the parent, all descenents should get these right?
+ ServiceContext.ContentService.AssignContentPermission(parentPage, 'A', new[] { 1 });
+
+ //re-test
+
+ permissions = ServiceContext.ContentService.GetPermissionsForEntity(parentPage);
+ Assert.AreEqual(1, permissions.Count());
+ Assert.AreEqual("A", permissions.Single().AssignedPermissions.First());
+
+ descendants = ServiceContext.ContentService.GetDescendants(parentPage).ToArray();
+ Assert.AreEqual(3, descendants.Length);
+
+ foreach (var descendant in descendants)
+ {
+ permissions = ServiceContext.ContentService.GetPermissionsForEntity(descendant);
+ Assert.AreEqual(1, permissions.Count());
+ Assert.AreEqual("A", permissions.Single().AssignedPermissions.First());
+ }
+ }
+
[Test]
public void Can_Empty_RecycleBin_With_Content_That_Has_All_Related_Data()
{
diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs
index b0ec03f754..d672229e6b 100644
--- a/src/Umbraco.Tests/Services/UserServiceTests.cs
+++ b/src/Umbraco.Tests/Services/UserServiceTests.cs
@@ -4,14 +4,10 @@ using System.Security.Cryptography;
using System.Text;
using NUnit.Framework;
using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers.Entities;
using umbraco.BusinessLogic.Actions;
using Umbraco.Core.Persistence.Querying;
-using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
-using Umbraco.Tests.TestHelpers.Entities;
-using umbraco.BusinessLogic.Actions;
using Umbraco.Core;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
@@ -37,7 +33,7 @@ namespace Umbraco.Tests.Services
}
[Test]
- public void UserService_Get_User_Permissions_For_Unassigned_Permission_Nodes()
+ public void Get_User_Permissions_For_Unassigned_Permission_Nodes()
{
// Arrange
var userService = ServiceContext.UserService;
@@ -55,17 +51,18 @@ namespace Umbraco.Tests.Services
ServiceContext.ContentService.Save(content);
// Act
- var permissions = userService.GetPermissions(user, content.ElementAt(0).Id, content.ElementAt(1).Id, content.ElementAt(2).Id);
+ var permissions = userService.GetPermissions(user, content[0].Id, content[1].Id, content[2].Id)
+ .ToArray();
//assert
- Assert.AreEqual(3, permissions.Count());
- Assert.AreEqual(17, permissions.ElementAt(0).AssignedPermissions.Count());
- Assert.AreEqual(17, permissions.ElementAt(1).AssignedPermissions.Count());
- Assert.AreEqual(17, permissions.ElementAt(2).AssignedPermissions.Count());
+ Assert.AreEqual(3, permissions.Length);
+ Assert.AreEqual(17, permissions[0].AssignedPermissions.Length);
+ Assert.AreEqual(17, permissions[1].AssignedPermissions.Length);
+ Assert.AreEqual(17, permissions[2].AssignedPermissions.Length);
}
[Test]
- public void UserService_Get_User_Permissions_For_Assigned_Permission_Nodes()
+ public void Get_User_Permissions_For_Assigned_Permission_Nodes()
{
// Arrange
var userService = ServiceContext.UserService;
@@ -99,7 +96,7 @@ namespace Umbraco.Tests.Services
}
[Test]
- public void UserService_Get_UserGroup_Assigned_Permissions()
+ public void Get_UserGroup_Assigned_Permissions()
{
// Arrange
var userService = ServiceContext.UserService;
@@ -121,38 +118,6 @@ namespace Umbraco.Tests.Services
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(2), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- // Act
- var permissions = userService.GetPermissions(userGroup, true, content.ElementAt(0).Id, content.ElementAt(1).Id, content.ElementAt(2).Id);
-
- //assert
- Assert.AreEqual(3, permissions.Count());
- Assert.AreEqual(3, permissions.ElementAt(0).AssignedPermissions.Length);
- Assert.AreEqual(2, permissions.ElementAt(1).AssignedPermissions.Length);
- Assert.AreEqual(1, permissions.ElementAt(2).AssignedPermissions.Length);
- }
-
- [Test]
- public void UserService_Get_UserGroup_Assigned_And_Default_Permissions()
- {
- // Arrange
- var userService = ServiceContext.UserService;
- var userGroup = CreateTestUserGroup();
-
- var contentType = MockedContentTypes.CreateSimpleContentType();
- ServiceContext.ContentTypeService.Save(contentType);
- var content = new[]
- {
- MockedContent.CreateSimpleContent(contentType),
- MockedContent.CreateSimpleContent(contentType),
- MockedContent.CreateSimpleContent(contentType)
- };
- ServiceContext.ContentService.Save(content);
- ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionMove.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
- ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
-
// Act
var permissions = userService.GetPermissions(userGroup, false, content.ElementAt(0).Id, content.ElementAt(1).Id, content.ElementAt(2).Id);
@@ -160,7 +125,69 @@ namespace Umbraco.Tests.Services
Assert.AreEqual(3, permissions.Count());
Assert.AreEqual(3, permissions.ElementAt(0).AssignedPermissions.Length);
Assert.AreEqual(2, permissions.ElementAt(1).AssignedPermissions.Length);
- Assert.AreEqual(17, permissions.ElementAt(2).AssignedPermissions.Length);
+ Assert.AreEqual(1, permissions.ElementAt(2).AssignedPermissions.Length);
+ }
+
+ [Test]
+ public void Get_UserGroup_Assigned_And_Default_Permissions()
+ {
+ // Arrange
+ var userService = ServiceContext.UserService;
+ var userGroup = CreateTestUserGroup();
+
+ var contentType = MockedContentTypes.CreateSimpleContentType();
+ ServiceContext.ContentTypeService.Save(contentType);
+ var content = new[]
+ {
+ MockedContent.CreateSimpleContent(contentType),
+ MockedContent.CreateSimpleContent(contentType),
+ MockedContent.CreateSimpleContent(contentType)
+ };
+ ServiceContext.ContentService.Save(content);
+ ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionMove.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
+
+ // Act
+ var permissions = userService.GetPermissions(userGroup, true, content.ElementAt(0).Id, content.ElementAt(1).Id, content.ElementAt(2).Id)
+ .ToArray();
+
+ //assert
+ Assert.AreEqual(3, permissions.Length);
+ Assert.AreEqual(3, permissions[0].AssignedPermissions.Length);
+ Assert.AreEqual(2, permissions[1].AssignedPermissions.Length);
+ Assert.AreEqual(17,permissions[2].AssignedPermissions.Length);
+ }
+
+ [Test]
+ public void Get_User_Implicit_Permissions()
+ {
+ // Arrange
+ var userService = ServiceContext.UserService;
+ var userGroup = CreateTestUserGroup();
+
+ var contentType = MockedContentTypes.CreateSimpleContentType();
+ ServiceContext.ContentTypeService.Save(contentType);
+ var parent = MockedContent.CreateSimpleContent(contentType);
+ ServiceContext.ContentService.Save(parent);
+ var child1 = MockedContent.CreateSimpleContent(contentType, "child1", parent);
+ ServiceContext.ContentService.Save(child1);
+ var child2 = MockedContent.CreateSimpleContent(contentType, "child2", child1);
+ ServiceContext.ContentService.Save(child2);
+
+ ServiceContext.ContentService.AssignContentPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(parent, ActionMove.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(parent, ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
+ ServiceContext.ContentService.AssignContentPermission(parent, ActionDelete.Instance.Letter, new int[] { userGroup.Id });
+
+ // Act
+ var permissions = userService.GetPermissionsForPath(userGroup, child2.Path);
+
+ //assert
+ Assert.AreEqual(3, permissions.AssignedPermissions.Length);
}
[Test]
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs
index aaab898ae2..ee93aec60b 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/cruds.aspx.cs
@@ -89,7 +89,7 @@ namespace umbraco.dialogs
if (a.CanBePermissionAssigned == false) continue;
var permissions = userService.GetPermissionsForPath(group, _node.Path);
- if (permissions.Contains(a.Letter))
+ if (permissions.AssignedPermissions.Contains(a.Letter.ToString()))
{
chk.Checked = true;
}
diff --git a/src/umbraco.businesslogic/User.cs b/src/umbraco.businesslogic/User.cs
index fbf226c39f..0f92a4427f 100644
--- a/src/umbraco.businesslogic/User.cs
+++ b/src/umbraco.businesslogic/User.cs
@@ -571,7 +571,8 @@ namespace umbraco.BusinessLogic
if (_lazyId.HasValue) SetupUser(_lazyId.Value);
var userService = ApplicationContext.Current.Services.UserService;
- return userService.GetPermissionsForPath(UserEntity, path);
+ return string.Join("",
+ userService.GetPermissionsForPath(UserEntity, path).PermissionsSet.SelectMany(x => x.Permission));
}
///