From 2d9aeb3aa1595c715dcd5cc8ed8282259e63bda3 Mon Sep 17 00:00:00 2001 From: AndyButland Date: Thu, 27 Oct 2016 18:11:46 +0200 Subject: [PATCH] Removed relationship between users and applications and got back to a compiling state. Set up editing screens for group/node permissions. --- src/Umbraco.Core/Cache/CacheKeys.cs | 2 + .../Models/Identity/BackOfficeIdentityUser.cs | 1 + .../Models/Identity/IdentityModelMappings.cs | 2 + .../Models/Membership/EntityPermission.cs | 6 +- .../Models/Membership/EntityPermissionSet.cs | 25 +- src/Umbraco.Core/Models/Membership/IUser.cs | 4 - src/Umbraco.Core/Models/Membership/User.cs | 92 +--- .../Membership/UserGroupEntityPermission.cs | 16 + src/Umbraco.Core/Models/Rdbms/User2AppDto.cs | 20 - .../Models/Rdbms/User2NodePermissionDto.cs | 23 - src/Umbraco.Core/Models/Rdbms/UserDto.cs | 3 - .../Persistence/Factories/UserFactory.cs | 23 - .../Factories/UserSectionFactory.cs | 35 -- .../Migrations/Initial/BaseDataCreation.cs | 16 - .../Relators/UserSectionRelator.cs | 50 --- .../Repositories/ContentRepository.cs | 8 +- .../DataTypeDefinitionRepository.cs | 2 +- .../Interfaces/IContentRepository.cs | 2 +- .../Interfaces/IUserGroupRepository.cs | 2 - .../Interfaces/IUserRepository.cs | 31 -- .../Repositories/PermissionRepository.cs | 239 +++++----- .../Repositories/UserGroupRepository.cs | 16 +- .../Repositories/UserRepository.cs | 136 +----- .../Security/BackOfficeUserStore.cs | 40 +- src/Umbraco.Core/Security/UserData.cs | 3 + src/Umbraco.Core/Services/ContentService.cs | 2 +- .../Services/ContentServiceExtensions.cs | 2 +- src/Umbraco.Core/Services/IContentService.cs | 2 +- src/Umbraco.Core/Services/ISectionService.cs | 2 +- src/Umbraco.Core/Services/IUserService.cs | 30 +- src/Umbraco.Core/Services/UserService.cs | 92 ++-- .../Services/UserServiceExtensions.cs | 13 +- src/Umbraco.Core/Umbraco.Core.csproj | 5 +- src/Umbraco.Tests/Models/UserTests.cs | 13 - .../Repositories/UserGroupRepositoryTest.cs | 425 ++++++++++++++++++ .../Repositories/UserRepositoryTest.cs | 139 +----- .../Services/SectionServiceTests.cs | 2 - .../Services/UserServiceTests.cs | 138 +++--- .../TestHelpers/Entities/MockedUser.cs | 17 +- .../TestHelpers/Entities/MockedUserGroup.cs | 17 + .../TreesAndSections/SectionTests.cs | 58 --- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 + .../ContentControllerUnitTests.cs | 12 +- ...terAllowedOutgoingContentAttributeTests.cs | 8 +- src/Umbraco.Web.UI/config/trees.config | 2 +- .../umbraco/users/PermissionEditor.aspx | 2 +- .../Cache/CacheRefresherEventHandler.cs | 34 +- src/Umbraco.Web/Cache/DistributedCache.cs | 5 +- .../Cache/DistributedCacheExtensions.cs | 14 +- .../Cache/UserGroupCacheRefresher.cs | 66 +++ .../UserGroupPermissionsCacheRefresher.cs | 58 +++ .../Cache/UserPermissionsCacheRefresher.cs | 58 --- src/Umbraco.Web/Security/WebSecurity.cs | 1 - src/Umbraco.Web/Umbraco.Web.csproj | 16 +- ...Permissions.cs => UserGroupPermissions.cs} | 165 ++++--- .../umbraco/dialogs/cruds.aspx.cs | 72 ++- .../umbraco/dialogs/moveOrCopy.aspx.cs | 7 +- .../umbraco/users/EditUser.aspx.cs | 54 +-- .../umbraco/users/NodePermissions.ascx.cs | 103 ++--- .../umbraco/users/PermissionEditor.aspx | 2 +- .../umbraco/users/PermissionEditor.aspx.cs | 79 ++-- .../umbraco/users/PermissionsHandler.asmx.cs | 85 ++-- ...Permissions.cs => UserGroupPermissions.cs} | 292 ++++++------ src/umbraco.businesslogic/User.cs | 54 --- src/umbraco.cms/businesslogic/CMSNode.cs | 5 +- src/umbraco.cms/businesslogic/Permission.cs | 105 +++-- 66 files changed, 1430 insertions(+), 1625 deletions(-) create mode 100644 src/Umbraco.Core/Models/Membership/UserGroupEntityPermission.cs delete mode 100644 src/Umbraco.Core/Models/Rdbms/User2AppDto.cs delete mode 100644 src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs delete mode 100644 src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs delete mode 100644 src/Umbraco.Core/Persistence/Relators/UserSectionRelator.cs create mode 100644 src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs create mode 100644 src/Umbraco.Tests/TestHelpers/Entities/MockedUserGroup.cs create mode 100644 src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs create mode 100644 src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs delete mode 100644 src/Umbraco.Web/Cache/UserPermissionsCacheRefresher.cs rename src/Umbraco.Web/umbraco.presentation/umbraco/Trees/{UserPermissions.cs => UserGroupPermissions.cs} (57%) rename src/Umbraco.Web/umbraco.presentation/umbraco/users/{UserPermissions.cs => UserGroupPermissions.cs} (77%) diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index 0c1a202b66..596bf2455b 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -58,6 +58,8 @@ namespace Umbraco.Core.Cache public const string UserPermissionsCacheKey = "UmbracoUserPermissions"; + public const string UserGroupPermissionsCacheKey = "UmbracoUserGroupPermissions"; + [UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")] public const string ContentTypeCacheKey = "UmbracoContentType"; diff --git a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs index 50dc7d06f8..1618150851 100644 --- a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs @@ -34,6 +34,7 @@ namespace Umbraco.Core.Models.Identity public int StartContentId { get; set; } public int StartMediaId { get; set; } public string[] AllowedSections { get; set; } + public string[] Groups { get; set; } public string Culture { get; set; } public string UserTypeAlias { get; set; } diff --git a/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs b/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs index 0dc95a8987..74fd602a7e 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs @@ -24,12 +24,14 @@ namespace Umbraco.Core.Models.Identity .ForMember(user => user.StartContentId, expression => expression.MapFrom(user => user.StartContentId)) .ForMember(user => user.UserTypeAlias, expression => expression.MapFrom(user => user.UserType.Alias)) .ForMember(user => user.AccessFailedCount, expression => expression.MapFrom(user => user.FailedPasswordAttempts)) + .ForMember(user => user.Groups, expression => expression.MapFrom(user => user.Groups.Select(x => x.Name).ToArray())) .ForMember(user => user.AllowedSections, expression => expression.MapFrom(user => user.AllowedSections.ToArray())); config.CreateMap() .ConstructUsing((BackOfficeIdentityUser user) => new UserData(Guid.NewGuid().ToString("N"))) //this is the 'session id' .ForMember(detail => detail.Id, opt => opt.MapFrom(user => user.Id)) .ForMember(detail => detail.AllowedApplications, opt => opt.MapFrom(user => user.AllowedSections)) + .ForMember(detail => detail.Groups, opt => opt.MapFrom(user => user.Groups)) .ForMember(detail => detail.RealName, opt => opt.MapFrom(user => user.Name)) .ForMember(detail => detail.Roles, opt => opt.MapFrom(user => new[] { user.UserTypeAlias })) .ForMember(detail => detail.StartContentNode, opt => opt.MapFrom(user => user.StartContentId)) diff --git a/src/Umbraco.Core/Models/Membership/EntityPermission.cs b/src/Umbraco.Core/Models/Membership/EntityPermission.cs index 520a9b8d37..90430e26a8 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermission.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermission.cs @@ -3,18 +3,16 @@ namespace Umbraco.Core.Models.Membership { /// - /// Represents a user -> entity permission + /// Represents an entity permission (defined on the user group and derived to retrieve permissions for a given user) /// public class EntityPermission { - public EntityPermission(int userId, int entityId, string[] assignedPermissions) + public EntityPermission(int entityId, string[] assignedPermissions) { - UserId = userId; EntityId = entityId; AssignedPermissions = assignedPermissions; } - public int UserId { get; private set; } public int EntityId { get; private set; } /// diff --git a/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs b/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs index c4669caf59..ea1e927a59 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs @@ -13,30 +13,31 @@ namespace Umbraco.Core.Models.Membership public int EntityId { get; private set; } /// - /// The key/value pairs of user id & single permission + /// The key/value pairs of user group id & single permission /// - public IEnumerable UserPermissionsSet { get; private set; } + public IEnumerable PermissionsSet { get; private set; } - public EntityPermissionSet(int entityId, IEnumerable userPermissionsSet) + public EntityPermissionSet(int entityId, IEnumerable permissionsSet) { EntityId = entityId; - UserPermissionsSet = userPermissionsSet; + PermissionsSet = permissionsSet; } - public class UserPermission + public class UserGroupPermission { - public UserPermission(int userId, string permission) + public UserGroupPermission(int groupId, string permission) { - UserId = userId; + UserGroupId = groupId; Permission = permission; } - public int UserId { get; private set; } + public int UserGroupId { get; private set; } + public string Permission { get; private set; } - protected bool Equals(UserPermission other) + protected bool Equals(UserGroupPermission other) { - return UserId == other.UserId && string.Equals(Permission, other.Permission); + return UserGroupId == other.UserGroupId && string.Equals(Permission, other.Permission); } public override bool Equals(object obj) @@ -44,14 +45,14 @@ namespace Umbraco.Core.Models.Membership if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; - return Equals((UserPermission) obj); + return Equals((UserGroupPermission) obj); } public override int GetHashCode() { unchecked { - return (UserId*397) ^ Permission.GetHashCode(); + return (UserGroupId * 397) ^ Permission.GetHashCode(); } } } diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs index 095044c47e..a3cea0b232 100644 --- a/src/Umbraco.Core/Models/Membership/IUser.cs +++ b/src/Umbraco.Core/Models/Membership/IUser.cs @@ -47,10 +47,6 @@ namespace Umbraco.Core.Models.Membership IEnumerable AllowedSections { get; } - void RemoveAllowedSection(string sectionAlias); - - void AddAllowedSection(string sectionAlias); - /// /// Exposes the basic profile data /// diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs index 6fad1a6f78..41bcb5ee80 100644 --- a/src/Umbraco.Core/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -25,12 +25,8 @@ namespace Umbraco.Core.Models.Membership _defaultPermissions = _userType.Permissions == null ? Enumerable.Empty() : new List(_userType.Permissions); //Groups = new List { userType }; SessionTimeout = 60; - _sectionCollection = new ObservableCollection(); - _addedSections = new List(); - _removedSections = new List(); _groupCollection = new List(); _language = GlobalSettings.DefaultUILanguage; - _sectionCollection.CollectionChanged += SectionCollectionChanged; _isApproved = true; _isLockedOut = false; _startContentId = -1; @@ -55,9 +51,6 @@ namespace Umbraco.Core.Models.Membership private IUserType _userType; private string _name; private string _securityStamp; - private List _addedSections; - private List _removedSections; - private ObservableCollection _sectionCollection; private List _groupCollection; private bool _groupsLoaded; private int _sessionTimeout; @@ -92,7 +85,6 @@ namespace Umbraco.Core.Models.Membership public readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo(x => x.SessionTimeout); public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.StartContentId); public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo(x => x.StartMediaId); - public readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedSections); public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); public readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo(x => x.Username); @@ -200,22 +192,16 @@ namespace Umbraco.Core.Models.Membership public IEnumerable AllowedSections { - get { return _sectionCollection; } - } - - public void RemoveAllowedSection(string sectionAlias) - { - if (_sectionCollection.Contains(sectionAlias)) + get { - _sectionCollection.Remove(sectionAlias); - } - } + if (GroupsLoaded == false) + { + return Enumerable.Empty(); + } - public void AddAllowedSection(string sectionAlias) - { - if (_sectionCollection.Contains(sectionAlias) == false) - { - _sectionCollection.Add(sectionAlias); + return Groups + .SelectMany(x => x.AllowedSections) + .Distinct(); } } @@ -234,22 +220,6 @@ namespace Umbraco.Core.Models.Membership set { SetPropertyValueAndDetectChanges(value, ref _securityStamp, Ps.Value.SecurityStampSelector); } } - /// - /// Used internally to check if we need to add a section in the repository to the db - /// - internal IEnumerable AddedSections - { - get { return _addedSections; } - } - - /// - /// Used internally to check if we need to remove a section in the repository to the db - /// - internal IEnumerable RemovedSections - { - get { return _removedSections; } - } - /// /// Gets or sets the session timeout. /// @@ -363,61 +333,15 @@ namespace Umbraco.Core.Models.Membership #endregion - /// - /// Whenever resetting occurs, clear the remembered add/removed collections, even if - /// rememberPreviouslyChangedProperties is true, the AllowedSections property will still - /// be flagged as dirty. - /// - /// - public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties) - { - _addedSections.Clear(); - _removedSections.Clear(); - base.ResetDirtyProperties(rememberPreviouslyChangedProperties); - } - - /// - /// Handles the collection changed event in order for us to flag the AllowedSections property as changed - /// - /// - /// - void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(Ps.Value.AllowedSectionsSelector); - - if (e.Action == NotifyCollectionChangedAction.Add) - { - var item = e.NewItems.Cast().First(); - - if (_addedSections.Contains(item) == false) - { - _addedSections.Add(item); - } - } - else if (e.Action == NotifyCollectionChangedAction.Remove) - { - var item = e.OldItems.Cast().First(); - - if (_removedSections.Contains(item) == false) - { - _removedSections.Add(item); - } - } - } - public override object DeepClone() { var clone = (User)base.DeepClone(); //turn off change tracking clone.DisableChangeTracking(); //need to create new collections otherwise they'll get copied by ref - clone._addedSections = new List(); - clone._removedSections = new List(); - clone._sectionCollection = new ObservableCollection(_sectionCollection.ToList()); clone._groupCollection = new List(_groupCollection.ToList()); clone._defaultPermissions = new List(_defaultPermissions.ToList()); //re-create the event handler - clone._sectionCollection.CollectionChanged += clone.SectionCollectionChanged; //this shouldn't really be needed since we're not tracking clone.ResetDirtyProperties(false); //re-enable tracking diff --git a/src/Umbraco.Core/Models/Membership/UserGroupEntityPermission.cs b/src/Umbraco.Core/Models/Membership/UserGroupEntityPermission.cs new file mode 100644 index 0000000000..619223f01a --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/UserGroupEntityPermission.cs @@ -0,0 +1,16 @@ +namespace Umbraco.Core.Models.Membership +{ + /// + /// Represents a user group -> entity permission + /// + public class UserGroupEntityPermission : EntityPermission + { + public UserGroupEntityPermission(int groupId, int entityId, string[] assignedPermissions) + : base(entityId, assignedPermissions) + { + UserGroupId = groupId; + } + + public int UserGroupId { get; private set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/User2AppDto.cs b/src/Umbraco.Core/Models/Rdbms/User2AppDto.cs deleted file mode 100644 index eafc6be230..0000000000 --- a/src/Umbraco.Core/Models/Rdbms/User2AppDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.DatabaseAnnotations; - -namespace Umbraco.Core.Models.Rdbms -{ - [TableName("umbracoUser2app")] - [PrimaryKey("user", autoIncrement = false)] - [ExplicitColumns] - internal class User2AppDto - { - [Column("user")] - [PrimaryKeyColumn(AutoIncrement = false, Name = "PK_user2app", OnColumns = "user, app")] - [ForeignKey(typeof(UserDto))] - public int UserId { get; set; } - - [Column("app")] - [Length(50)] - public string AppAlias { get; set; } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs b/src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs deleted file mode 100644 index 1e6662735f..0000000000 --- a/src/Umbraco.Core/Models/Rdbms/User2NodePermissionDto.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.DatabaseAnnotations; - -namespace Umbraco.Core.Models.Rdbms -{ - [TableName("umbracoUser2NodePermission")] - [PrimaryKey("userId", autoIncrement = false)] - [ExplicitColumns] - internal class User2NodePermissionDto - { - [Column("userId")] - [PrimaryKeyColumn(AutoIncrement = false, Name = "PK_umbracoUser2NodePermission", OnColumns = "userId, nodeId, permission")] - [ForeignKey(typeof(UserDto))] - public int UserId { get; set; } - - [Column("nodeId")] - [ForeignKey(typeof(NodeDto))] - public int NodeId { get; set; } - - [Column("permission")] - public string Permission { get; set; } - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/UserDto.cs b/src/Umbraco.Core/Models/Rdbms/UserDto.cs index 05a93c86bf..d05cf1086b 100644 --- a/src/Umbraco.Core/Models/Rdbms/UserDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/UserDto.cs @@ -73,8 +73,5 @@ namespace Umbraco.Core.Models.Rdbms [Column("lastLoginDate")] [NullSetting(NullSetting = NullSettings.Null)] public DateTime? LastLoginDate { get; set; } - - [ResultColumn] - public List User2AppDtos { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs index 322e8b5b65..a404c43450 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs @@ -43,14 +43,6 @@ namespace Umbraco.Core.Persistence.Factories user.LastLoginDate = dto.LastLoginDate ?? DateTime.MinValue; user.LastPasswordChangeDate = dto.LastPasswordChangeDate ?? DateTime.MinValue; - if (dto.User2AppDtos != null) - { - foreach (var app in dto.User2AppDtos) - { - user.AddAllowedSection(app.AppAlias); - } - } - //on initial construction we don't want to have dirty properties tracked // http://issues.umbraco.org/issue/U4-1946 user.ResetDirtyProperties(false); @@ -77,7 +69,6 @@ namespace Umbraco.Core.Persistence.Factories UserLanguage = entity.Language, UserName = entity.Name, Type = short.Parse(entity.UserType.Id.ToString(CultureInfo.InvariantCulture)), - User2AppDtos = new List(), SecurityStampToken = entity.SecurityStamp, FailedLoginAttempts = entity.FailedPasswordAttempts, LastLockoutDate = entity.LastLockoutDate == DateTime.MinValue ? (DateTime?)null : entity.LastLockoutDate, @@ -85,20 +76,6 @@ namespace Umbraco.Core.Persistence.Factories LastPasswordChangeDate = entity.LastPasswordChangeDate == DateTime.MinValue ? (DateTime?)null : entity.LastPasswordChangeDate, }; - foreach (var app in entity.AllowedSections) - { - var appDto = new User2AppDto - { - AppAlias = app - }; - if (entity.HasIdentity) - { - appDto.UserId = entity.Id; - } - - dto.User2AppDtos.Add(appDto); - } - if (entity.HasIdentity) { dto.Id = entity.Id.SafeCast(); diff --git a/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs deleted file mode 100644 index 0e6a17594f..0000000000 --- a/src/Umbraco.Core/Persistence/Factories/UserSectionFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using AutoMapper; -using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Factories -{ - internal class UserSectionFactory - { - private readonly IUser _user; - - public UserSectionFactory(IUser user) - { - _user = user; - } - - public IEnumerable BuildEntity(IEnumerable dto) - { - return dto.Select(x => x.AppAlias); - } - - public IEnumerable BuildDto(IEnumerable entity) - { - return entity.Select(x => new User2AppDto - { - //NOTE: We're force casting to int here! this might not work in the future - UserId = (int)_user.Id, - AppAlias = x - }); - } - - } -} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 9570024b09..68d43a1acd 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -48,11 +48,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial CreateUmbracoUserTypeData(); } - if (tableName.Equals("umbracoUser2app")) - { - CreateUmbracoUser2AppData(); - } - if (tableName.Equals("cmsPropertyTypeGroup")) { CreateCmsPropertyTypeGroupData(); @@ -168,17 +163,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("umbracoUserType", "id", false, new UserTypeDto { Id = 4, Alias = "translator", Name = "Translator", DefaultPermissions = "AF" }); } - private void CreateUmbracoUser2AppData() - { - _database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Content }); - _database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Developer }); - _database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Media }); - _database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Members }); - _database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Settings }); - _database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Users }); - _database.Insert("umbracoUser2app", "user", false, new User2AppDto { UserId = 0, AppAlias = Constants.Applications.Forms }); - } - private void CreateCmsPropertyTypeGroupData() { _database.Insert("cmsPropertyTypeGroup", "id", false, new PropertyTypeGroupDto { Id = 3, ContentTypeNodeId = 1032, Text = "Image", SortOrder = 1, UniqueId = new Guid(Constants.PropertyTypeGroups.Image) }); diff --git a/src/Umbraco.Core/Persistence/Relators/UserSectionRelator.cs b/src/Umbraco.Core/Persistence/Relators/UserSectionRelator.cs deleted file mode 100644 index 923348e729..0000000000 --- a/src/Umbraco.Core/Persistence/Relators/UserSectionRelator.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using Umbraco.Core.Models.Rdbms; - -namespace Umbraco.Core.Persistence.Relators -{ - internal class UserSectionRelator - { - internal UserDto Current; - - internal UserDto Map(UserDto a, User2AppDto p) - { - // Terminating call. Since we can return null from this function - // we need to be ready for PetaPoco to callback later with null - // parameters - if (a == null) - return Current; - - // Is this the same DictionaryItem as the current one we're processing - if (Current != null && Current.Id == a.Id) - { - if (p.AppAlias.IsNullOrWhiteSpace() == false) - { - // Yes, just add this User2AppDto to the current item's collection - Current.User2AppDtos.Add(p); - } - - // Return null to indicate we're not done with this User yet - return null; - } - - // This is a different User to the current one, or this is the - // first time through and we don't have one yet - - // Save the current User - var prev = Current; - - // Setup the new current User - Current = a; - Current.User2AppDtos = new List(); - //this can be null since we are doing a left join - if (p.AppAlias.IsNullOrWhiteSpace() == false) - { - Current.User2AppDtos.Add(p); - } - - // Return the now populated previous User (or null if first time through) - return prev; - } - } -} \ 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 cafbabd286..03b3b9e6e9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -394,12 +394,12 @@ namespace Umbraco.Core.Persistence.Repositories // user's default permissions. if (parentPermissions.Any()) { - var userPermissions = ( + var userGroupPermissions = ( from perm in parentPermissions from p in perm.AssignedPermissions - select new EntityPermissionSet.UserPermission(perm.UserId, p)).ToList(); + select new EntityPermissionSet.UserGroupPermission(perm.UserGroupId, p)).ToList(); - permissionsRepo.ReplaceEntityPermissions(new EntityPermissionSet(entity.Id, userPermissions)); + 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; @@ -791,7 +791,7 @@ order by umbracoNode.level, umbracoNode.parentID, umbracoNode.sortOrder"; repo.AssignEntityPermission(entity, permission, userIds); } - public IEnumerable GetPermissionsForEntity(int entityId) + public IEnumerable GetPermissionsForEntity(int entityId) { var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); return repo.GetPermissionsForEntity(entityId); diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs index a4d71885f8..b95d3f0d62 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs @@ -248,7 +248,7 @@ AND umbracoNode.id <> @id", Database.Delete("WHERE nodeId = @Id", new { Id = entity.Id }); //Remove Permissions - Database.Delete("WHERE nodeId = @Id", new { Id = entity.Id }); + Database.Delete("WHERE nodeId = @Id", new { Id = entity.Id }); //Remove associated tags Database.Delete("WHERE nodeId = @Id", new { Id = entity.Id }); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs index e2555995d2..5f74a21d7a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs @@ -60,7 +60,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - IEnumerable GetPermissionsForEntity(int entityId); + IEnumerable GetPermissionsForEntity(int entityId); /// /// Used to add/update published xml for the content item diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserGroupRepository.cs index e50d265228..45abdc70b4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserGroupRepository.cs @@ -24,7 +24,6 @@ namespace Umbraco.Core.Persistence.Repositories /// Ids of users void AddUsersToGroup(int groupId, int[] userIds); - /* /// /// Gets the group permissions for the specified entities /// @@ -47,6 +46,5 @@ namespace Umbraco.Core.Persistence.Repositories /// Permissions as enumerable list of /// Specify the nodes to replace permissions for void AssignGroupPermission(int groupId, char permission, params int[] entityIds); - */ } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs index 5645cafa2a..620350f563 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs @@ -22,12 +22,6 @@ namespace Umbraco.Core.Persistence.Repositories /// bool Exists(string username); - /// - /// This is useful when an entire section is removed from config - /// - /// - IEnumerable GetUsersAssignedToSection(string sectionAlias); - /// /// Gets all groups for a given user /// @@ -57,30 +51,5 @@ namespace Umbraco.Core.Persistence.Repositories /// /// IEnumerable GetPagedResultsByQuery(IQuery query, int pageIndex, int pageSize, out int totalRecords, Expression> orderBy); - - - /// - /// Gets the user permissions for the specified entities - /// - /// - /// - /// - IEnumerable GetUserPermissionsForEntities(int userId, params int[] entityIds); - - /// - /// Replaces the same permission set for a single user to any number of entities - /// - /// - /// - /// - void ReplaceUserPermissions(int userId, IEnumerable permissions, params int[] entityIds); - - /// - /// Assigns the same permission set for a single user to any number of entities - /// - /// - /// - /// - void AssignUserPermission(int userId, char permission, params int[] entityIds); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs index aa671dccec..83c31f6651 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs @@ -15,6 +15,15 @@ using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Services; using CacheKeys = Umbraco.Core.Cache.CacheKeys; using Umbraco.Core.Cache; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Persistence.Repositories { @@ -38,196 +47,227 @@ namespace Umbraco.Core.Persistence.Repositories } /// - /// Returns permissions for a given user for any number of nodes + /// Returns permissions for a given group for any number of nodes /// - /// + /// /// /// - public IEnumerable GetUserPermissionsForEntities(int userId, params int[] entityIds) + public IEnumerable GetPermissionsForEntities(int groupId, params int[] entityIds) { - var entityIdKey = string.Join(",", entityIds.Select(x => x.ToString(CultureInfo.InvariantCulture))); + var entityIdKey = GetEntityIdKey(entityIds); return _runtimeCache.GetCacheItem>( - string.Format("{0}{1}{2}", CacheKeys.UserPermissionsCacheKey, userId, entityIdKey), + string.Format("{0}{1}{2}", + CacheKeys.UserGroupPermissionsCacheKey, + groupId, + entityIdKey), () => - { - - var whereBuilder = new StringBuilder(); - - //where userId = @userId AND - whereBuilder.Append(_sqlSyntax.GetQuotedColumnName("userId")); - whereBuilder.Append("="); - whereBuilder.Append(userId); - - if (entityIds.Any()) - { - whereBuilder.Append(" AND "); - - //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(")"); - } - + { + var whereCriteria = GetPermissionsForEntitiesCriteria(groupId, entityIds); var sql = new Sql(); sql.Select("*") - .From() - .Where(whereBuilder.ToString()); - - //ToArray() to ensure it's all fetched from the db once. - var result = _unitOfWork.Database.Fetch(sql).ToArray(); + .From() + .Where(whereCriteria); + var result = _unitOfWork.Database.Fetch(sql).ToArray(); + // ToArray() to ensure it's all fetched from the db once return ConvertToPermissionList(result); - }, - //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. - new TimeSpan(0, 20, 0), - //Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will make this priority below average - priority: CacheItemPriority.BelowNormal); + 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()) + { + whereBuilder.Append(" AND "); + + //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(); + } + + 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) + { + var permissions = new List(); + var nodePermissions = result.GroupBy(x => x.NodeId); + foreach (var np in nodePermissions) + { + var userGroupPermissions = np.GroupBy(x => x.UserGroupId); + foreach (var permission in userGroupPermissions) + { + var perms = permission.Select(x => x.Permission).ToArray(); + permissions.Add(new UserGroupEntityPermission(permission.Key, permission.First().NodeId, perms)); + } + } + + return permissions; + } /// - /// Returns permissions for all users for a given entity + /// Returns permissions for all groups for a given entity /// /// /// - public IEnumerable GetPermissionsForEntity(int entityId) + public IEnumerable GetPermissionsForEntity(int entityId) { var sql = new Sql(); sql.Select("*") - .From() - .Where(dto => dto.NodeId == entityId) - .OrderBy(dto => dto.NodeId); + .From() + .Where(dto => dto.NodeId == entityId) + .OrderBy(dto => dto.NodeId); - //ToArray() to ensure it's all fetched from the db once. - var result = _unitOfWork.Database.Fetch(sql).ToArray(); + var result = _unitOfWork.Database.Fetch(sql).ToArray(); + // ToArray() to ensure it's all fetched from the db once return ConvertToPermissionList(result); } /// - /// Assigns the same permission set for a single user to any number of entities + /// Assigns the same permission set for a single group to any number of entities /// - /// + /// /// /// /// /// This will first clear the permissions for this user and entities and recreate them /// - public void ReplaceUserPermissions(int userId, IEnumerable permissions, params int[] entityIds) + public void ReplacePermissions(int groupId, IEnumerable permissions, params int[] entityIds) { var db = _unitOfWork.Database; using (var trans = db.GetTransaction()) { //we need to batch these in groups of 2000 so we don't exceed the max 2100 limit + var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND nodeId in (@nodeIds)"; foreach (var idGroup in entityIds.InGroupsOf(2000)) { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND nodeId in (@nodeIds)", - new { userId = userId, nodeIds = idGroup }); + db.Execute(sql, new {groupId = groupId, nodeIds = idGroup}); } - var toInsert = new List(); + var toInsert = new List(); foreach (var p in permissions) { foreach (var e in entityIds) { - toInsert.Add(new User2NodePermissionDto + toInsert.Add(new UserGroup2NodePermissionDto { NodeId = e, Permission = p.ToString(CultureInfo.InvariantCulture), - UserId = userId + UserGroupId = groupId }); } } _unitOfWork.Database.BulkInsertRecords(toInsert, trans); - trans.Complete(); - //Raise the event AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(toInsert), false), this); + new SaveEventArgs(ConvertToPermissionList(toInsert), false), this); } } /// /// Assigns one permission for a user to many entities /// - /// + /// /// /// - public void AssignUserPermission(int userId, char permission, params int[] entityIds) + public void AssignPermission(int groupId, char permission, params int[] entityIds) { var db = _unitOfWork.Database; using (var trans = db.GetTransaction()) { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND permission=@permission AND nodeId in (@entityIds)", + var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND permission=@permission AND nodeId in (@entityIds)"; + db.Execute(sql, new { - userId = userId, + groupId = groupId, permission = permission.ToString(CultureInfo.InvariantCulture), entityIds = entityIds }); - var actions = entityIds.Select(id => new User2NodePermissionDto + var actions = entityIds.Select(id => new UserGroup2NodePermissionDto { NodeId = id, Permission = permission.ToString(CultureInfo.InvariantCulture), - UserId = userId + UserGroupId = groupId }).ToArray(); _unitOfWork.Database.BulkInsertRecords(actions, trans); - trans.Complete(); - //Raise the event AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(actions), false), this); + new SaveEventArgs(ConvertToPermissionList(actions), false), this); } - } + } /// - /// Assigns one permission to an entity for multiple users + /// Assigns one permission to an entity for multiple groups /// /// /// - /// - public void AssignEntityPermission(TEntity entity, char permission, IEnumerable userIds) + /// + public void AssignEntityPermission(TEntity entity, char permission, IEnumerable groupIds) { var db = _unitOfWork.Database; using (var trans = db.GetTransaction()) { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId AND permission=@permission AND userId in (@userIds)", + var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @nodeId AND permission = @permission AND userGroupId in (@groupIds)"; + db.Execute(sql, new { - nodeId = entity.Id, + nodeId = entity.Id, permission = permission.ToString(CultureInfo.InvariantCulture), - userIds = userIds + groupIds = groupIds }); - var actions = userIds.Select(id => new User2NodePermissionDto + var actions = groupIds.Select(id => new UserGroup2NodePermissionDto { NodeId = entity.Id, Permission = permission.ToString(CultureInfo.InvariantCulture), - UserId = id + UserGroupId = id }).ToArray(); _unitOfWork.Database.BulkInsertRecords(actions, trans); - trans.Complete(); - //Raise the event AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(actions), false), this); + new SaveEventArgs(ConvertToPermissionList(actions), false), this); } } @@ -244,41 +284,24 @@ namespace Umbraco.Core.Persistence.Repositories var db = _unitOfWork.Database; using (var trans = db.GetTransaction()) { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId", new { nodeId = permissionSet.EntityId }); + var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @nodeId"; + db.Execute(sql, new {nodeId = permissionSet.EntityId}); - var actions = permissionSet.UserPermissionsSet.Select(p => new User2NodePermissionDto + var actions = permissionSet.PermissionsSet.Select(p => new UserGroup2NodePermissionDto { NodeId = permissionSet.EntityId, Permission = p.Permission, - UserId = p.UserId + UserGroupId = p.UserGroupId }).ToArray(); _unitOfWork.Database.BulkInsertRecords(actions, trans); - trans.Complete(); - //Raise the event AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(actions), false), this); - } - } - - private static IEnumerable ConvertToPermissionList(IEnumerable result) - { - var permissions = new List(); - var nodePermissions = result.GroupBy(x => x.NodeId); - foreach (var np in nodePermissions) - { - var userPermissions = np.GroupBy(x => x.UserId); - foreach (var up in userPermissions) - { - var perms = up.Select(x => x.Permission).ToArray(); - permissions.Add(new EntityPermission(up.Key, up.First().NodeId, perms)); - } + new SaveEventArgs(ConvertToPermissionList(actions), false), this); } - return permissions; } - public static event TypedEventHandler, SaveEventArgs> AssignedPermissions; + public static event TypedEventHandler, SaveEventArgs> AssignedPermissions; } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs index ba47270379..b13033c7b3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs @@ -76,16 +76,15 @@ namespace Umbraco.Core.Persistence.Repositories } } - /* /// /// Gets the group permissions for the specified entities /// /// Id of group /// Array of entity Ids - public IEnumerable GetGroupPermissionsForEntities(int groupId, params int[] entityIds) + public IEnumerable GetPermissionsForEntities(int groupId, params int[] entityIds) { - var repo = new GroupPermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); - return repo.GetGroupPermissionsForEntities(groupId, entityIds); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); + return repo.GetPermissionsForEntities(groupId, entityIds); } /// @@ -96,8 +95,8 @@ namespace Umbraco.Core.Persistence.Repositories /// Specify the nodes to replace permissions for. If nothing is specified all permissions are removed. public void ReplaceGroupPermissions(int groupId, IEnumerable permissions, params int[] entityIds) { - var repo = new GroupPermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); - repo.ReplaceGroupPermissions(groupId, permissions, entityIds); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); + repo.ReplacePermissions(groupId, permissions, entityIds); } /// @@ -108,10 +107,9 @@ namespace Umbraco.Core.Persistence.Repositories /// Specify the nodes to replace permissions for public void AssignGroupPermission(int groupId, char permission, params int[] entityIds) { - var repo = new GroupPermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); - repo.AssignGroupPermission(groupId, permission, entityIds); + var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); + repo.AssignPermission(groupId, permission, entityIds); } - */ #region Overrides of RepositoryBase diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs index 72d20ff660..f5e3fda7c5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false); sql.Where(GetBaseWhereClause(), new { Id = id }); - var dto = Database.Fetch(new UserSectionRelator().Map, sql).FirstOrDefault(); + var dto = Database.Fetch(sql).FirstOrDefault(); if (dto == null) return null; @@ -74,7 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories sql.Where("umbracoUser.id in (@ids)", new {ids = ids}); } - return ConvertFromDtos(Database.Fetch(new UserSectionRelator().Map, sql)) + return ConvertFromDtos(Database.Fetch(sql)) .ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching. } @@ -84,7 +84,7 @@ namespace Umbraco.Core.Persistence.Repositories var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate(); - var dtos = Database.Fetch(new UserSectionRelator().Map, sql) + var dtos = Database.Fetch(sql) .DistinctBy(x => x.Id); var users = ConvertFromDtos(dtos) @@ -121,9 +121,7 @@ namespace Umbraco.Core.Persistence.Repositories { var sql = new Sql(); sql.Select(columns) - .From() - .LeftJoin() - .On(left => left.Id, right => right.UserId); + .From(); return sql; } @@ -139,9 +137,8 @@ namespace Umbraco.Core.Persistence.Repositories { "DELETE FROM cmsTask WHERE userId = @Id", "DELETE FROM cmsTask WHERE parentUserId = @Id", - "DELETE FROM umbracoUser2NodePermission WHERE userId = @Id", + "DELETE FROM umbracoUser2UserGroup WHERE userId = @Id", "DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id", - "DELETE FROM umbracoUser2app WHERE " + SqlSyntax.GetQuotedColumnName("user") + "=@Id", "DELETE FROM umbracoUser WHERE id = @Id", "DELETE FROM umbracoExternalLogin WHERE id = @Id" }; @@ -168,13 +165,6 @@ namespace Umbraco.Core.Persistence.Repositories var id = Convert.ToInt32(Database.Insert(userDto)); entity.Id = id; - foreach (var sectionDto in userDto.User2AppDtos) - { - //need to set the id explicitly here - sectionDto.UserId = id; - Database.Insert(sectionDto); - } - entity.ResetDirtyProperties(); } @@ -238,52 +228,23 @@ namespace Umbraco.Core.Persistence.Repositories { Database.Update(userDto, changedCols); } - - //update the sections if they've changed + + //update the groups var user = (User)entity; - if (user.IsPropertyDirty("AllowedSections")) + + //first delete all + Database.Delete("WHERE UserId = @UserId", + new { UserId = user.Id }); + + //then re-add any associated with the user + foreach (var group in user.Groups) { - //now we need to delete any applications that have been removed - foreach (var section in user.RemovedSections) + var dto = new User2UserGroupDto { - //we need to manually delete this record because it has a composite key - Database.Delete("WHERE app = @Section AND " + SqlSyntax.GetQuotedColumnName("user") + "= @UserId", - new { Section = section, UserId = user.Id }); - } - - //for any that exist on the object, we need to determine if we need to update or insert - //NOTE: the User2AppDtos collection wil always be equal to the User.AllowedSections - foreach (var sectionDto in userDto.User2AppDtos) - { - //if something has been added then insert it - if (user.AddedSections.Contains(sectionDto.AppAlias)) - { - //we need to insert since this was added - Database.Insert(sectionDto); - } - else - { - //we need to manually update this record because it has a composite key - Database.Update("SET app=@Section WHERE app=@Section AND " + SqlSyntax.GetQuotedColumnName("user") + "=@UserId", - new { Section = sectionDto.AppAlias, UserId = sectionDto.UserId }); - } - } - - //update the groups - //first delete all - Database.Delete("WHERE UserId = @UserId", - new { UserId = user.Id }); - - //then re-add any associated with the user - foreach (var group in user.Groups) - { - var dto = new User2UserGroupDto - { - UserGroupId = group.Id, - UserId = user.Id - }; - Database.Insert(dto); - } + UserGroupId = group.Id, + UserId = user.Id + }; + Database.Insert(dto); } entity.ResetDirtyProperties(); @@ -316,29 +277,6 @@ namespace Umbraco.Core.Persistence.Repositories return Database.ExecuteScalar(sql) > 0; } - public IEnumerable GetUsersAssignedToSection(string sectionAlias) - { - //Here we're building up a query that looks like this, a sub query is required because the resulting structure - // needs to still contain all of the section rows per user. - - //SELECT * - //FROM [umbracoUser] - //LEFT JOIN [umbracoUser2app] - //ON [umbracoUser].[id] = [umbracoUser2app].[user] - //WHERE umbracoUser.id IN (SELECT umbracoUser.id - // FROM [umbracoUser] - // LEFT JOIN [umbracoUser2app] - // ON [umbracoUser].[id] = [umbracoUser2app].[user] - // WHERE umbracoUser2app.app = 'content') - - var sql = GetBaseQuery(false); - var innerSql = GetBaseQuery("umbracoUser.id"); - innerSql.Where("umbracoUser2app.app = " + SqlSyntax.GetQuotedValue(sectionAlias)); - sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL)); - - return ConvertFromDtos(Database.Fetch(new UserSectionRelator().Map, sql)); - } - /// /// Gets all groups for a given user /// @@ -462,42 +400,6 @@ namespace Umbraco.Core.Persistence.Repositories return ids.Length == 0 ? Enumerable.Empty() : GetAll(ids).OrderBy(x => x.Id); } - /// - /// Returns permissions for a given user for any number of nodes - /// - /// - /// - /// - public IEnumerable GetUserPermissionsForEntities(int userId, params int[] entityIds) - { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); - return repo.GetUserPermissionsForEntities(userId, entityIds); - } - - /// - /// Replaces the same permission set for a single user to any number of entities - /// - /// - /// - /// - public void ReplaceUserPermissions(int userId, IEnumerable permissions, params int[] entityIds) - { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); - repo.ReplaceUserPermissions(userId, permissions, entityIds); - } - - /// - /// Assigns the same permission set for a single user to any number of entities - /// - /// - /// - /// - public void AssignUserPermission(int userId, char permission, params int[] entityIds) - { - var repo = new PermissionRepository(UnitOfWork, _cacheHelper, SqlSyntax); - repo.AssignUserPermission(userId, permission, entityIds); - } - #endregion private IEnumerable ConvertFromDtos(IEnumerable dtos) diff --git a/src/Umbraco.Core/Security/BackOfficeUserStore.cs b/src/Umbraco.Core/Security/BackOfficeUserStore.cs index c6714e256a..fcdf623dba 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserStore.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserStore.cs @@ -389,7 +389,7 @@ namespace Umbraco.Core.Security /// - /// Adds a user to a role (section) + /// Adds a user to a role (user group) /// /// /// @@ -406,18 +406,19 @@ namespace Umbraco.Core.Security throw new InvalidOperationException("The user id must be an integer to work with the Umbraco"); } - var found = _userService.GetUserById(asInt.Result); + var foundUser = _userService.GetUserById(asInt.Result); + var foundGroup = _userService.GetUserGroupByName(roleName); - if (found != null) + if (foundUser != null && foundGroup != null) { - found.AddAllowedSection(roleName); + foundUser.AddGroup(foundGroup); } return Task.FromResult(0); } /// - /// Removes the role (allowed section) for the user + /// Removes the role (user group) for the user /// /// /// @@ -434,18 +435,19 @@ namespace Umbraco.Core.Security throw new InvalidOperationException("The user id must be an integer to work with the Umbraco"); } - var found = _userService.GetUserById(asInt.Result); + var foundUser = _userService.GetUserById(asInt.Result); + var foundGroup = _userService.GetUserGroupByName(roleName); - if (found != null) + if (foundUser != null && foundGroup != null) { - found.RemoveAllowedSection(roleName); + foundUser.RemoveGroup(foundGroup); } return Task.FromResult(0); } /// - /// Returns the roles for this user + /// Returns the roles (user groups) for this user /// /// /// @@ -453,7 +455,7 @@ namespace Umbraco.Core.Security { ThrowIfDisposed(); if (user == null) throw new ArgumentNullException("user"); - return Task.FromResult((IList)user.AllowedSections.ToList()); + return Task.FromResult((IList)user.Groups.ToList()); } /// @@ -465,7 +467,7 @@ namespace Umbraco.Core.Security { ThrowIfDisposed(); if (user == null) throw new ArgumentNullException("user"); - return Task.FromResult(user.AllowedSections.InvariantContains(roleName)); + return Task.FromResult(user.Groups.InvariantContains(roleName)); } /// @@ -677,17 +679,21 @@ namespace Umbraco.Core.Security user.SecurityStamp = identityUser.SecurityStamp; } - if (user.AllowedSections.ContainsAll(identityUser.AllowedSections) == false - || identityUser.AllowedSections.ContainsAll(user.AllowedSections) == false) + if (user.Groups.Select(x => x.Name).ContainsAll(identityUser.Groups) == false + || identityUser.Groups.ContainsAll(user.Groups.Select(x => x.Name)) == false) { anythingChanged = true; - foreach (var allowedSection in user.AllowedSections) + foreach (var group in user.Groups) { - user.RemoveAllowedSection(allowedSection); + user.RemoveGroup(group); } - foreach (var allowedApplication in identityUser.AllowedSections) + foreach (var group in identityUser.Groups) { - user.AddAllowedSection(allowedApplication); + var foundGroup = _userService.GetUserGroupByName(group); + if (foundGroup != null) + { + user.AddGroup(foundGroup); + } } } diff --git a/src/Umbraco.Core/Security/UserData.cs b/src/Umbraco.Core/Security/UserData.cs index 407d2782dd..b1a8b08507 100644 --- a/src/Umbraco.Core/Security/UserData.cs +++ b/src/Umbraco.Core/Security/UserData.cs @@ -56,6 +56,9 @@ namespace Umbraco.Core.Security [DataMember(Name = "allowedApps")] public string[] AllowedApplications { get; set; } + [DataMember(Name = "groups")] + public string[] Groups { get; set; } + [DataMember(Name = "culture")] public string Culture { get; set; } } diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 38b7aec9d7..8aa7030a8f 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -126,7 +126,7 @@ namespace Umbraco.Core.Services /// /// /// - public IEnumerable GetPermissionsForEntity(IContent content) + public IEnumerable GetPermissionsForEntity(IContent content) { var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateContentRepository(uow)) diff --git a/src/Umbraco.Core/Services/ContentServiceExtensions.cs b/src/Umbraco.Core/Services/ContentServiceExtensions.cs index 4919a81217..9c56cf28eb 100644 --- a/src/Umbraco.Core/Services/ContentServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentServiceExtensions.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Services /// public static void RemoveContentPermissions(this IContentService contentService, int contentId) { - contentService.ReplaceContentPermissions(new EntityPermissionSet(contentId, Enumerable.Empty())); + contentService.ReplaceContentPermissions(new EntityPermissionSet(contentId, Enumerable.Empty())); } /// diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index ec5db8c4fb..6ee384c413 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -135,7 +135,7 @@ namespace Umbraco.Core.Services /// /// /// - IEnumerable GetPermissionsForEntity(IContent content); + IEnumerable GetPermissionsForEntity(IContent content); bool SendToPublication(IContent content, int userId = 0); diff --git a/src/Umbraco.Core/Services/ISectionService.cs b/src/Umbraco.Core/Services/ISectionService.cs index df5c89d4bf..d726179224 100644 --- a/src/Umbraco.Core/Services/ISectionService.cs +++ b/src/Umbraco.Core/Services/ISectionService.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Services IEnumerable
GetSections(); /// - /// Get the user's allowed sections + /// Get the user group's allowed sections /// /// /// diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index 2a3ebf9828..fa69cb30a3 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -48,19 +48,19 @@ namespace Umbraco.Core.Services IUser GetUserById(int id); /// - /// Removes a specific section from all users + /// Removes a specific section from all user groups /// /// This is useful when an entire section is removed from config /// Alias of the section to remove - void DeleteSectionFromAllUsers(string sectionAlias); - + void DeleteSectionFromAllUserGroups(string sectionAlias); + /// - /// Add a specific section to all users or those specified as parameters + /// Add a specific section to all user groups or those specified as parameters /// - /// This is useful when a new section is created to allow specific users accessing it + /// This is useful when a new section is created to allow specific user groups to access it /// Alias of the section to add - /// Specifiying nothing will add the section to all user - void AddSectionToAllUsers(string sectionAlias, params int[] userIds); + /// Specifiying nothing will add the section to all user + void AddSectionToAllUserGroups(string sectionAlias, params int[] groupIds); /// /// Get permissions set for a user and optional node ids @@ -96,24 +96,24 @@ namespace Umbraco.Core.Services string GetPermissionsForPath(IUserGroup group, string path); /// - /// Replaces the same permission set for a single user to any number of entities + /// Replaces the same permission set for a single group to any number of entities /// - /// Id of the user + /// Id of the group /// /// Permissions as enumerable list of , - /// if no permissions are specified then all permissions for this node are removed for this user + /// if no permissions are specified then all permissions for this node are removed for this group /// /// Specify the nodes to replace permissions for. If nothing is specified all permissions are removed. - /// If no 'entityIds' are specified all permissions will be removed for the specified user. - void ReplaceUserPermissions(int userId, IEnumerable permissions, params int[] entityIds); + /// If no 'entityIds' are specified all permissions will be removed for the specified group. + void ReplaceUserGroupPermissions(int groupId, IEnumerable permissions, params int[] entityIds); /// - /// Assigns the same permission set for a single user to any number of entities + /// Assigns the same permission set for a single user group to any number of entities /// - /// Id of the user + /// Id of the group /// /// Specify the nodes to replace permissions for - void AssignUserPermission(int userId, char permission, params int[] entityIds); + void AssignUserGroupPermission(int groupId, char permission, params int[] entityIds); /// /// Gets a list of objects associated with a given group diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index fcd8c45536..1a5abb8ee7 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -147,9 +147,6 @@ namespace Umbraco.Core.Services IsLockedOut = false, IsApproved = true }; - //adding default sections content and media - user.AddAllowedSection("content"); - user.AddAllowedSection("media"); if (SavingUser.IsRaisedEventCancelled(new SaveEventArgs(user), this)) return user; @@ -584,33 +581,33 @@ namespace Umbraco.Core.Services } /// - /// Replaces the same permission set for a single user to any number of entities + /// Replaces the same permission set for a single group to any number of entities /// - /// If no 'entityIds' are specified all permissions will be removed for the specified user. - /// Id of the user + /// If no 'entityIds' are specified all permissions will be removed for the specified group. + /// Id of the group /// Permissions as enumerable list of /// Specify the nodes to replace permissions for. If nothing is specified all permissions are removed. - public void ReplaceUserPermissions(int userId, IEnumerable permissions, params int[] entityIds) + public void ReplaceUserGroupPermissions(int groupId, IEnumerable permissions, params int[] entityIds) { var uow = UowProvider.GetUnitOfWork(); - using (var repository = RepositoryFactory.CreateUserRepository(uow)) + using (var repository = RepositoryFactory.CreateUserGroupRepository(uow)) { - repository.ReplaceUserPermissions(userId, permissions, entityIds); + repository.ReplaceGroupPermissions(groupId, permissions, entityIds); } } /// - /// Assigns the same permission set for a single user to any number of entities + /// Assigns the same permission set for a single user group to any number of entities /// - /// Id of the user + /// Id of the user group /// /// Specify the nodes to replace permissions for - public void AssignUserPermission(int userId, char permission, params int[] entityIds) + public void AssignUserGroupPermission(int groupId, char permission, params int[] entityIds) { var uow = UowProvider.GetUnitOfWork(); - using (var repository = RepositoryFactory.CreateUserRepository(uow)) + using (var repository = RepositoryFactory.CreateUserGroupRepository(uow)) { - repository.AssignUserPermission(userId, permission, entityIds); + repository.AssignGroupPermission(groupId, permission, entityIds); } } @@ -843,48 +840,50 @@ namespace Umbraco.Core.Services /// /// This is useful when an entire section is removed from config /// Alias of the section to remove - public void DeleteSectionFromAllUsers(string sectionAlias) + public void DeleteSectionFromAllUserGroups(string sectionAlias) { var uow = UowProvider.GetUnitOfWork(); - using (var repository = RepositoryFactory.CreateUserRepository(uow)) + using (var repository = RepositoryFactory.CreateUserGroupRepository(uow)) { - var assignedUsers = repository.GetUsersAssignedToSection(sectionAlias); - foreach (var user in assignedUsers) + var assignedGroups = repository.GetGroupsAssignedToSection(sectionAlias); + foreach (var group in assignedGroups) { //now remove the section for each user and commit - user.RemoveAllowedSection(sectionAlias); - repository.AddOrUpdate(user); + group.RemoveAllowedSection(sectionAlias); + repository.AddOrUpdate(group); } + uow.Commit(); } } - + /// - /// Add a specific section to all users or those specified as parameters + /// Add a specific section to all user groups or those specified as parameters /// - /// This is useful when a new section is created to allow specific users accessing it + /// This is useful when a new section is created to allow specific user groups to access it /// Alias of the section to add - /// Specifiying nothing will add the section to all user - public void AddSectionToAllUsers(string sectionAlias, params int[] userIds) + /// Specifiying nothing will add the section to all user + public void AddSectionToAllUserGroups(string sectionAlias, params int[] groupIds) { var uow = UowProvider.GetUnitOfWork(); - using (var repository = RepositoryFactory.CreateUserRepository(uow)) + using (var repository = RepositoryFactory.CreateUserGroupRepository(uow)) { - IEnumerable users; - if (userIds.Any()) + IEnumerable groups; + if (groupIds.Any()) { - users = repository.GetAll(userIds); + groups = repository.GetAll(groupIds); } else { - users = repository.GetAll(); + groups = repository.GetAll(); } - foreach (var user in users.Where(u => !u.AllowedSections.InvariantContains(sectionAlias))) + foreach (var group in groups.Where(g => g.AllowedSections.InvariantContains(sectionAlias) == false)) { - //now add the section for each user and commit - user.AddAllowedSection(sectionAlias); - repository.AddOrUpdate(user); + //now add the section for each group and commit + group.AddAllowedSection(sectionAlias); + repository.AddOrUpdate(group); } + uow.Commit(); } } @@ -901,16 +900,15 @@ namespace Umbraco.Core.Services var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateUserRepository(uow)) { - var explicitPermissions = repository.GetUserPermissionsForEntities(user.Id, nodeIds); + // TODO: rework (to use groups - currently defaulting to user type) //if no permissions are assigned to a particular node then we will fill in those permissions with the user's defaults - var result = new List(explicitPermissions); + var result = new List(); var missingIds = nodeIds.Except(result.Select(x => x.EntityId)); foreach (var id in missingIds) { result.Add( new EntityPermission( - user.Id, id, user.DefaultPermissions.ToArray())); } @@ -939,16 +937,9 @@ namespace Umbraco.Core.Services /// An enumerable list of private IEnumerable GetPermissions(IUserRepository repository, IUser user, params int[] nodeIds) { - var explicitPermissions = repository.GetUserPermissionsForEntities(user.Id, nodeIds); - var result = new List(explicitPermissions); + var result = new List(); - // Save list of nodes that user has explicit permissions for - these take priority so we don't want - // to amend with any settings from groups (we'll take the special "null" action as not being defined - // as this is set if someone sets permissions on a user and then removes them) - var explicitlyDefinedEntityIds = result - .Where(IsNotNullActionPermission) - .Select(x => x.EntityId) - .ToArray(); + // TODO: rework to groups first, then user type // If no permissions are assigned to a particular node then, we will fill in those permissions with the user's defaults var missingIds = nodeIds.Except(result.Select(x => x.EntityId)); @@ -956,7 +947,6 @@ namespace Umbraco.Core.Services { result.Add( new EntityPermission( - user.Id, id, user.DefaultPermissions.ToArray())); } @@ -967,12 +957,8 @@ namespace Umbraco.Core.Services var groupPermissions = GetPermissions(group, nodeIds).ToList(); foreach (var groupPermission in groupPermissions) { - // Check if we already have this from explicitly set user permissions, if so, ignore it - if (explicitlyDefinedEntityIds.Contains(groupPermission.EntityId) == false) - { - // Add group permission, ensuring we keep a unique value for the entity Id in the list - AddOrAmendPermission(result, groupPermission); - } + // Add group permission, ensuring we keep a unique value for the entity Id in the list + AddOrAmendPermission(result, groupPermission); } } diff --git a/src/Umbraco.Core/Services/UserServiceExtensions.cs b/src/Umbraco.Core/Services/UserServiceExtensions.cs index afb679afa1..a1f480a1f5 100644 --- a/src/Umbraco.Core/Services/UserServiceExtensions.cs +++ b/src/Umbraco.Core/Services/UserServiceExtensions.cs @@ -10,21 +10,21 @@ namespace Umbraco.Core.Services /// Remove all permissions for this user for all nodes specified /// /// - /// + /// /// - public static void RemoveUserPermissions(this IUserService userService, int userId, params int[] entityIds) + public static void RemoveUserGroupPermissions(this IUserService userService, int groupId, params int[] entityIds) { - userService.ReplaceUserPermissions(userId, new char[] {}, entityIds); + userService.ReplaceUserGroupPermissions(groupId, new char[] {}, entityIds); } /// /// Remove all permissions for this user for all nodes /// /// - /// - public static void RemoveUserPermissions(this IUserService userService, int userId) + /// + public static void RemoveUserGroupPermissions(this IUserService userService, int groupId) { - userService.ReplaceUserPermissions(userId, new char[] { }); + userService.ReplaceUserGroupPermissions(groupId, new char[] { }); } /// @@ -62,7 +62,6 @@ namespace Umbraco.Core.Services member.ProviderUserKey == null ? member.UserName : member.ProviderUserKey.ToString(), Guid.NewGuid().ToString("N"), //pass cannot be empty writer); - user.AddAllowedSection(Constants.Applications.Content); userService.Save(user); return user; } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 555c76eb4c..07256fda05 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -385,6 +385,7 @@ + @@ -787,7 +788,6 @@ - @@ -1034,7 +1034,6 @@ - @@ -1205,9 +1204,7 @@ - - diff --git a/src/Umbraco.Tests/Models/UserTests.cs b/src/Umbraco.Tests/Models/UserTests.cs index 189a4a17a8..9f974ee9fa 100644 --- a/src/Umbraco.Tests/Models/UserTests.cs +++ b/src/Umbraco.Tests/Models/UserTests.cs @@ -41,8 +41,6 @@ namespace Umbraco.Tests.Models Username = "username" }; - item.AddAllowedSection("test"); - var clone = (User)item.DeepClone(); Assert.AreNotSame(clone, item); @@ -61,17 +59,6 @@ namespace Umbraco.Tests.Models { Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null)); } - - //ensure internal collections are differet - Assert.AreNotSame(item.AddedSections, clone.AddedSections); - Assert.AreNotSame(item.RemovedSections, clone.RemovedSections); - - //ensure event handlers are still wired on clone - clone.AddAllowedSection("blah"); - Assert.AreEqual(1, clone.AddedSections.Count()); - clone.RemoveAllowedSection("blah"); - Assert.AreEqual(1, clone.RemovedSections.Count()); - } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs new file mode 100644 index 0000000000..a29aeb8c29 --- /dev/null +++ b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs @@ -0,0 +1,425 @@ +using System.Linq; +using Moq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Persistence; + +using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; + +namespace Umbraco.Tests.Persistence.Repositories +{ + [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] + [TestFixture] + public class UserGroupRepositoryTest : BaseDatabaseFactoryTest + { + [SetUp] + public override void Initialize() + { + base.Initialize(); + } + + [TearDown] + public override void TearDown() + { + base.TearDown(); + } + + private UserGroupRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + { + return new UserGroupRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); + } + + [Test] + public void Can_Perform_Add_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + + var userType = MockedUserGroup.CreateUserGroup(); + + // Act + repository.AddOrUpdate(userType); + unitOfWork.Commit(); + + // Assert + Assert.That(userType.HasIdentity, Is.True); + } + } + + [Test] + public void Can_Perform_Multiple_Adds_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + + var userType1 = MockedUserGroup.CreateUserGroup("1"); + var userType2 = MockedUserGroup.CreateUserGroup("2"); + + // Act + repository.AddOrUpdate(userType1); + unitOfWork.Commit(); + repository.AddOrUpdate(userType2); + unitOfWork.Commit(); + + // Assert + Assert.That(userType1.HasIdentity, Is.True); + Assert.That(userType2.HasIdentity, Is.True); + } + } + + [Test] + public void Can_Verify_Fresh_Entity_Is_Not_Dirty() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var userType = MockedUserGroup.CreateUserGroup(); + repository.AddOrUpdate(userType); + unitOfWork.Commit(); + + // Act + var resolved = repository.Get(userType.Id); + bool dirty = ((UserGroup) resolved).IsDirty(); + + // Assert + Assert.That(dirty, Is.False); + } + } + + [Test] + public void Can_Perform_Update_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var userType = MockedUserGroup.CreateUserGroup(); + repository.AddOrUpdate(userType); + unitOfWork.Commit(); + + // Act + var resolved = repository.Get(userType.Id); + resolved.Name = "New Name"; + resolved.Permissions = new[]{"Z", "Y", "X"}; + repository.AddOrUpdate(resolved); + unitOfWork.Commit(); + var updatedItem = repository.Get(userType.Id); + + // Assert + Assert.That(updatedItem.Id, Is.EqualTo(resolved.Id)); + Assert.That(updatedItem.Name, Is.EqualTo(resolved.Name)); + Assert.That(updatedItem.Permissions, Is.EqualTo(resolved.Permissions)); + } + } + + [Test] + public void Can_Perform_Delete_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + + var userType = MockedUserGroup.CreateUserGroup(); + + // Act + repository.AddOrUpdate(userType); + unitOfWork.Commit(); + var id = userType.Id; + + using (var repository2 = new UserGroupRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax)) + { + repository2.Delete(userType); + unitOfWork.Commit(); + + var resolved = repository2.Get(id); + + // Assert + Assert.That(resolved, Is.Null); + } + + } + } + + [Test] + public void Can_Perform_Get_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var userType = MockedUserGroup.CreateUserGroup(); + repository.AddOrUpdate(userType); + unitOfWork.Commit(); + + // Act + var resolved = repository.Get(userType.Id); + + // Assert + Assert.That(resolved.Id, Is.EqualTo(userType.Id)); + //Assert.That(resolved.CreateDate, Is.GreaterThan(DateTime.MinValue)); + //Assert.That(resolved.UpdateDate, Is.GreaterThan(DateTime.MinValue)); + Assert.That(resolved.Name, Is.EqualTo(userType.Name)); + Assert.That(resolved.Alias, Is.EqualTo(userType.Alias)); + Assert.That(resolved.Permissions, Is.EqualTo(userType.Permissions)); + } + } + + [Test] + public void Can_Perform_GetByQuery_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + var query = Query.Builder.Where(x => x.Alias == "testUserGroup1"); + var result = repository.GetByQuery(query); + + // Assert + Assert.That(result.Count(), Is.GreaterThanOrEqualTo(1)); + } + } + + [Test] + public void Can_Perform_GetAll_By_Param_Ids_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var userTypes = CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + var result = repository.GetAll(userTypes[0].Id, userTypes[1].Id); + + // Assert + Assert.That(result, Is.Not.Null); + Assert.That(result.Any(), Is.True); + Assert.That(result.Count(), Is.EqualTo(2)); + } + } + + [Test] + public void Can_Perform_GetAll_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + var result = repository.GetAll(); + + // Assert + Assert.That(result, Is.Not.Null); + Assert.That(result.Any(), Is.True); + Assert.That(result.Count(), Is.GreaterThanOrEqualTo(3)); + } + } + + [Test] + public void Can_Perform_Exists_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var userTypes = CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + var exists = repository.Exists(userTypes[0].Id); + + // Assert + Assert.That(exists, Is.True); + } + } + + [Test] + public void Can_Perform_Count_On_UserGroupRepository() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var userTypes = CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + var query = Query.Builder.Where(x => x.Alias == "testUserGroup1" || x.Alias == "testUserGroup2"); + var result = repository.Count(query); + + // Assert + Assert.That(result, Is.GreaterThanOrEqualTo(2)); + } + } + + [Test] + public void Can_Remove_Section_For_Group() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var groups = CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + + //add and remove a few times, this tests the internal collection + groups[0].RemoveAllowedSection("content"); + groups[0].RemoveAllowedSection("content"); + groups[0].AddAllowedSection("content"); + groups[0].RemoveAllowedSection("content"); + + groups[1].RemoveAllowedSection("media"); + groups[1].RemoveAllowedSection("media"); + + repository.AddOrUpdate(groups[0]); + repository.AddOrUpdate(groups[1]); + unitOfWork.Commit(); + + // Assert + var result = repository.GetAll((int)groups[0].Id, (int)groups[1].Id).ToArray(); + Assert.AreEqual(1, result[0].AllowedSections.Count()); + Assert.AreEqual("media", result[0].AllowedSections.First()); + Assert.AreEqual(1, result[1].AllowedSections.Count()); + Assert.AreEqual("content", result[1].AllowedSections.First()); + } + } + + [Test] + public void Can_Add_Section_ForGroup() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var groups = CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + + //add and remove a few times, this tests the internal collection + groups[0].AddAllowedSection("settings"); + groups[0].AddAllowedSection("settings"); + groups[0].RemoveAllowedSection("settings"); + groups[0].AddAllowedSection("settings"); + + groups[1].AddAllowedSection("developer"); + + //add the same even though it's already there + groups[2].AddAllowedSection("content"); + + repository.AddOrUpdate(groups[0]); + repository.AddOrUpdate(groups[1]); + unitOfWork.Commit(); + + // Assert + var result = repository.GetAll((int)groups[0].Id, (int)groups[1].Id, (int)groups[2].Id).ToArray(); + Assert.AreEqual(3, result[0].AllowedSections.Count()); + Assert.IsTrue(result[0].AllowedSections.Contains("content")); + Assert.IsTrue(result[0].AllowedSections.Contains("media")); + Assert.IsTrue(result[0].AllowedSections.Contains("settings")); + Assert.AreEqual(3, result[1].AllowedSections.Count()); + Assert.IsTrue(result[1].AllowedSections.Contains("content")); + Assert.IsTrue(result[1].AllowedSections.Contains("media")); + Assert.IsTrue(result[1].AllowedSections.Contains("developer")); + Assert.AreEqual(2, result[2].AllowedSections.Count()); + Assert.IsTrue(result[1].AllowedSections.Contains("content")); + Assert.IsTrue(result[1].AllowedSections.Contains("media")); + } + } + + [Test] + public void Can_Update_Section_For_Group() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var groups = CreateAndCommitMultipleUserGroups(repository, unitOfWork); + + // Act + + groups[0].RemoveAllowedSection("content"); + groups[0].AddAllowedSection("settings"); + + repository.AddOrUpdate(groups[0]); + unitOfWork.Commit(); + + // Assert + var result = repository.Get((int)groups[0].Id); + Assert.AreEqual(2, result.AllowedSections.Count()); + Assert.IsTrue(result.AllowedSections.Contains("settings")); + Assert.IsTrue(result.AllowedSections.Contains("media")); + } + } + + + [Test] + public void Get_Groups_Assigned_To_Section() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var user1 = MockedUserGroup.CreateUserGroup("1", new[] { "media" }); + var user2 = MockedUserGroup.CreateUserGroup("2", new[] { "settings" }); + var user3 = MockedUserGroup.CreateUserGroup("3", new[] { "settings" }); + repository.AddOrUpdate(user1); + repository.AddOrUpdate(user2); + repository.AddOrUpdate(user3); + unitOfWork.Commit(); + + // Act + + var groups = repository.GetGroupsAssignedToSection("test"); + + // Assert + Assert.AreEqual(2, groups.Count()); + var names = groups.Select(x => x.Name).ToArray(); + Assert.IsTrue(names.Contains("TestGroup1")); + Assert.IsTrue(names.Contains("TestGroup3")); + } + } + + private IUserGroup[] CreateAndCommitMultipleUserGroups(IUserGroupRepository repository, IUnitOfWork unitOfWork) + { + var userGroup1 = MockedUserGroup.CreateUserGroup("1"); + var userGroup2 = MockedUserGroup.CreateUserGroup("2"); + var userGroup3 = MockedUserGroup.CreateUserGroup("3"); + repository.AddOrUpdate(userGroup1); + repository.AddOrUpdate(userGroup2); + repository.AddOrUpdate(userGroup3); + unitOfWork.Commit(); + return new IUserGroup[] { userGroup1, userGroup2, userGroup3 }; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 1d26e59113..2a92cb39c8 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -135,7 +135,6 @@ namespace Umbraco.Tests.Persistence.Repositories resolved.StartMediaId = 11; resolved.Email = "new@new.com"; resolved.Username = "newName"; - resolved.RemoveAllowedSection("content"); repository.AddOrUpdate(resolved); unitOfWork.Commit(); @@ -341,142 +340,6 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [Test] - public void Can_Remove_Section_For_User() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); - var unitOfWork = provider.GetUnitOfWork(); - UserTypeRepository userTypeRepository; - using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) - { - var users = CreateAndCommitMultipleUsers(repository, unitOfWork); - - // Act - - //add and remove a few times, this tests the internal collection - users[0].RemoveAllowedSection("content"); - users[0].RemoveAllowedSection("content"); - users[0].AddAllowedSection("content"); - users[0].RemoveAllowedSection("content"); - - users[1].RemoveAllowedSection("media"); - users[1].RemoveAllowedSection("media"); - - repository.AddOrUpdate(users[0]); - repository.AddOrUpdate(users[1]); - unitOfWork.Commit(); - - // Assert - var result = repository.GetAll((int) users[0].Id, (int) users[1].Id).ToArray(); - Assert.AreEqual(1, result[0].AllowedSections.Count()); - Assert.AreEqual("media", result[0].AllowedSections.First()); - Assert.AreEqual(1, result[1].AllowedSections.Count()); - Assert.AreEqual("content", result[1].AllowedSections.First()); - } - } - - [Test] - public void Can_Add_Section_For_User() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); - var unitOfWork = provider.GetUnitOfWork(); - UserTypeRepository userTypeRepository; - using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) - { - var users = CreateAndCommitMultipleUsers(repository, unitOfWork); - - // Act - - //add and remove a few times, this tests the internal collection - users[0].AddAllowedSection("settings"); - users[0].AddAllowedSection("settings"); - users[0].RemoveAllowedSection("settings"); - users[0].AddAllowedSection("settings"); - - users[1].AddAllowedSection("developer"); - - //add the same even though it's already there - users[2].AddAllowedSection("content"); - - repository.AddOrUpdate(users[0]); - repository.AddOrUpdate(users[1]); - unitOfWork.Commit(); - - // Assert - var result = repository.GetAll((int) users[0].Id, (int) users[1].Id, (int) users[2].Id).ToArray(); - Assert.AreEqual(3, result[0].AllowedSections.Count()); - Assert.IsTrue(result[0].AllowedSections.Contains("content")); - Assert.IsTrue(result[0].AllowedSections.Contains("media")); - Assert.IsTrue(result[0].AllowedSections.Contains("settings")); - Assert.AreEqual(3, result[1].AllowedSections.Count()); - Assert.IsTrue(result[1].AllowedSections.Contains("content")); - Assert.IsTrue(result[1].AllowedSections.Contains("media")); - Assert.IsTrue(result[1].AllowedSections.Contains("developer")); - Assert.AreEqual(2, result[2].AllowedSections.Count()); - Assert.IsTrue(result[1].AllowedSections.Contains("content")); - Assert.IsTrue(result[1].AllowedSections.Contains("media")); - } - } - - [Test] - public void Can_Update_Section_For_User() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); - var unitOfWork = provider.GetUnitOfWork(); - UserTypeRepository userTypeRepository; - using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) - { - var users = CreateAndCommitMultipleUsers(repository, unitOfWork); - - // Act - - users[0].RemoveAllowedSection("content"); - users[0].AddAllowedSection("settings"); - - repository.AddOrUpdate(users[0]); - unitOfWork.Commit(); - - // Assert - var result = repository.Get((int) users[0].Id); - Assert.AreEqual(2, result.AllowedSections.Count()); - Assert.IsTrue(result.AllowedSections.Contains("settings")); - Assert.IsTrue(result.AllowedSections.Contains("media")); - } - } - - - [Test] - public void Get_Users_Assigned_To_Section() - { - // Arrange - var provider = new PetaPocoUnitOfWorkProvider(Logger); - var unitOfWork = provider.GetUnitOfWork(); - UserTypeRepository userTypeRepository; - using (var repository = CreateRepository(unitOfWork, out userTypeRepository)) - { - var user1 = MockedUser.CreateUser(CreateAndCommitUserType(), "1", "test", "media"); - var user2 = MockedUser.CreateUser(CreateAndCommitUserType(), "2", "media", "settings"); - var user3 = MockedUser.CreateUser(CreateAndCommitUserType(), "3", "test", "settings"); - repository.AddOrUpdate(user1); - repository.AddOrUpdate(user2); - repository.AddOrUpdate(user3); - unitOfWork.Commit(); - - // Act - - var users = repository.GetUsersAssignedToSection("test"); - - // Assert - Assert.AreEqual(2, users.Count()); - var names = users.Select(x => x.Username).ToArray(); - Assert.IsTrue(names.Contains("TestUser1")); - Assert.IsTrue(names.Contains("TestUser3")); - } - } - [Test] public void Default_User_Permissions_Based_On_User_Type() { @@ -488,7 +351,7 @@ namespace Umbraco.Tests.Persistence.Repositories { // Act - var user1 = MockedUser.CreateUser(CreateAndCommitUserType(), "1", "test", "media"); + var user1 = MockedUser.CreateUser(CreateAndCommitUserType(), "1"); repository.AddOrUpdate(user1); unitOfWork.Commit(); diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index e574d749f4..3bfba08e76 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -71,8 +71,6 @@ namespace Umbraco.Tests.Services Username = "testUser", Email = "testuser@test.com", }; - user.AddAllowedSection("content"); - user.AddAllowedSection("media"); ServiceContext.UserService.Save(user, false); if (withGroups) diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index c7002ce79d..35013ca69b 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -185,7 +185,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10); + var users = MockedUser.CreateMulipleUsers(userType, 10); ServiceContext.UserService.Save(users); //don't find this var customUser = MockedUser.CreateUser(userType); @@ -203,7 +203,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10); + var users = MockedUser.CreateMulipleUsers(userType, 10); ServiceContext.UserService.Save(users); //include this var customUser = MockedUser.CreateUser(userType); @@ -221,7 +221,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10); + var users = MockedUser.CreateMulipleUsers(userType, 10); ServiceContext.UserService.Save(users); //include this var customUser = MockedUser.CreateUser(userType); @@ -239,7 +239,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10); + var users = MockedUser.CreateMulipleUsers(userType, 10); ServiceContext.UserService.Save(users); //include this var customUser = MockedUser.CreateUser(userType); @@ -257,7 +257,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10); + var users = MockedUser.CreateMulipleUsers(userType, 10); ServiceContext.UserService.Save(users); int totalRecs; @@ -275,7 +275,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10); + var users = MockedUser.CreateMulipleUsers(userType, 10); ServiceContext.UserService.Save(users); var customUser = MockedUser.CreateUser(userType); ServiceContext.UserService.Save(customUser); @@ -292,7 +292,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10, (i, member) => member.LastLoginDate = DateTime.Now.AddMinutes(i * -2)); + var users = MockedUser.CreateMulipleUsers(userType, 10, (i, member) => member.LastLoginDate = DateTime.Now.AddMinutes(i * -2)); ServiceContext.UserService.Save(users); var customUser = MockedUser.CreateUser(userType); @@ -304,7 +304,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10, (i, member) => member.IsLockedOut = i % 2 == 0); + var users = MockedUser.CreateMulipleUsers(userType, 10, (i, member) => member.IsLockedOut = i % 2 == 0); ServiceContext.UserService.Save(users); var customUser = MockedUser.CreateUser(userType); @@ -321,7 +321,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var users = MockedUser.CreateUser(userType, 10, (i, member) => member.IsApproved = i % 2 == 0); + var users = MockedUser.CreateMulipleUsers(userType, 10, (i, member) => member.IsApproved = i % 2 == 0); ServiceContext.UserService.Save(users); var customUser = MockedUser.CreateUser(userType); @@ -392,102 +392,124 @@ namespace Umbraco.Tests.Services } [Test] - public void Can_Add_And_Remove_Sections_From_User() + public void Can_Add_And_Remove_Sections_From_UserGroup() { - var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); + var userGroup = new UserGroup + { + Id = 1, + Alias = "Group1", + }; + userGroup.AddAllowedSection("content"); + userGroup.AddAllowedSection("mediat"); + ServiceContext.UserService.SaveUserGroup(userGroup); - var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); + var result1 = ServiceContext.UserService.GetUserGroupById(userGroup.Id); - var result1 = ServiceContext.UserService.GetUserById((int)user1.Id); - //expect 2 sections by default Assert.AreEqual(2, result1.AllowedSections.Count()); //adds some allowed sections - user1.AddAllowedSection("test1"); - user1.AddAllowedSection("test2"); - user1.AddAllowedSection("test3"); - user1.AddAllowedSection("test4"); - ServiceContext.UserService.Save(user1); + userGroup.AddAllowedSection("test1"); + userGroup.AddAllowedSection("test2"); + userGroup.AddAllowedSection("test3"); + userGroup.AddAllowedSection("test4"); + ServiceContext.UserService.SaveUserGroup(userGroup); + + result1 = ServiceContext.UserService.GetUserGroupById(userGroup.Id); - result1 = ServiceContext.UserService.GetUserById((int)user1.Id); - //expect 6 sections including the two default sections Assert.AreEqual(6, result1.AllowedSections.Count()); //simulate clearing the sections - foreach (var s in user1.AllowedSections) + foreach (var s in userGroup.AllowedSections) { result1.RemoveAllowedSection(s); } + //now just re-add a couple result1.AddAllowedSection("test3"); result1.AddAllowedSection("test4"); - ServiceContext.UserService.Save(result1); + ServiceContext.UserService.SaveUserGroup(result1); //assert //re-get - result1 = ServiceContext.UserService.GetUserById((int)user1.Id); + result1 = ServiceContext.UserService.GetUserGroupById(userGroup.Id); Assert.AreEqual(2, result1.AllowedSections.Count()); } [Test] - public void Can_Remove_Section_From_All_Assigned_Users() - { - var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); + public void Can_Remove_Section_From_All_Assigned_UserGroups() + { + var userGroup1 = new UserGroup + { + Id = 1, + Alias = "Group1", + }; + var userGroup2 = new UserGroup + { + Id = 2, + Alias = "Group2", + }; + ServiceContext.UserService.SaveUserGroup(userGroup1); + ServiceContext.UserService.SaveUserGroup(userGroup2); - var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); - var user2 = ServiceContext.UserService.CreateUserWithIdentity("test2", "test2@test.com", userType); - //adds some allowed sections - user1.AddAllowedSection("test"); - user2.AddAllowedSection("test"); - ServiceContext.UserService.Save(user1); - ServiceContext.UserService.Save(user2); + userGroup1.AddAllowedSection("test"); + userGroup2.AddAllowedSection("test"); + ServiceContext.UserService.SaveUserGroup(userGroup1); + ServiceContext.UserService.SaveUserGroup(userGroup2); //now clear the section from all users - ServiceContext.UserService.DeleteSectionFromAllUsers("test"); + ServiceContext.UserService.DeleteSectionFromAllUserGroups("test"); //assert - var result1 = ServiceContext.UserService.GetUserById((int)user1.Id); - var result2 = ServiceContext.UserService.GetUserById((int)user2.Id); + var result1 = ServiceContext.UserService.GetUserGroupById(userGroup1.Id); + var result2 = ServiceContext.UserService.GetUserGroupById(userGroup2.Id); Assert.IsFalse(result1.AllowedSections.Contains("test")); Assert.IsFalse(result2.AllowedSections.Contains("test")); } [Test] - public void Can_Add_Section_To_All_Users() + public void Can_Add_Section_To_All_UserGroups() { - var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); + var userGroup1 = new UserGroup + { + Id = 1, + Alias = "Group1", + }; + var userGroup2 = new UserGroup + { + Id = 2, + Alias = "Group2", + }; + var userGroup3 = new UserGroup + { + Id = 2, + Alias = "Group3", + }; + ServiceContext.UserService.SaveUserGroup(userGroup1); + ServiceContext.UserService.SaveUserGroup(userGroup2); + ServiceContext.UserService.SaveUserGroup(userGroup3); - var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); - var user2 = ServiceContext.UserService.CreateUserWithIdentity("test2", "test2@test.com", userType); - var user3 = ServiceContext.UserService.CreateUserWithIdentity("test3", "test3@test.com", userType); - var user4 = ServiceContext.UserService.CreateUserWithIdentity("test4", "test4@test.com", userType); - - //now add the section to specific users - ServiceContext.UserService.AddSectionToAllUsers("test", (int)user1.Id, (int)user2.Id); + //now add the section to specific groups + ServiceContext.UserService.AddSectionToAllUserGroups("test", userGroup1.Id, userGroup2.Id); //assert - var result1 = ServiceContext.UserService.GetUserById((int)user1.Id); - var result2 = ServiceContext.UserService.GetUserById((int)user2.Id); - var result3 = ServiceContext.UserService.GetUserById((int)user3.Id); - var result4 = ServiceContext.UserService.GetUserById((int)user4.Id); + var result1 = ServiceContext.UserService.GetUserGroupById(userGroup1.Id); + var result2 = ServiceContext.UserService.GetUserGroupById(userGroup2.Id); + var result3 = ServiceContext.UserService.GetUserGroupById(userGroup3.Id); Assert.IsTrue(result1.AllowedSections.Contains("test")); Assert.IsTrue(result2.AllowedSections.Contains("test")); Assert.IsFalse(result3.AllowedSections.Contains("test")); - Assert.IsFalse(result4.AllowedSections.Contains("test")); - //now add the section to all users - ServiceContext.UserService.AddSectionToAllUsers("test"); + //now add the section to all groups + ServiceContext.UserService.AddSectionToAllUserGroups("test"); //assert - result1 = ServiceContext.UserService.GetUserById((int)user1.Id); - result2 = ServiceContext.UserService.GetUserById((int)user2.Id); - result3 = ServiceContext.UserService.GetUserById((int)user3.Id); - result4 = ServiceContext.UserService.GetUserById((int)user4.Id); + result1 = ServiceContext.UserService.GetUserGroupById(userGroup1.Id); + result2 = ServiceContext.UserService.GetUserGroupById(userGroup2.Id); + result3 = ServiceContext.UserService.GetUserGroupById(userGroup3.Id); Assert.IsTrue(result1.AllowedSections.Contains("test")); Assert.IsTrue(result2.AllowedSections.Contains("test")); Assert.IsTrue(result3.AllowedSections.Contains("test")); - Assert.IsTrue(result4.AllowedSections.Contains("test")); } [Test] diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs index 15d1ab76fd..3ccdd70966 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs @@ -8,7 +8,7 @@ namespace Umbraco.Tests.TestHelpers.Entities { public class MockedUser { - internal static User CreateUser(IUserType userType = null, string suffix = "", params string[] allowedSections) + internal static User CreateUser(IUserType userType = null, string suffix = "") { if (userType == null) { @@ -29,23 +29,10 @@ namespace Umbraco.Tests.TestHelpers.Entities Username = "TestUser" + suffix }; - if (allowedSections.Any()) - { - foreach (var s in allowedSections) - { - user.AddAllowedSection(s); - } - } - else - { - user.AddAllowedSection("content"); - user.AddAllowedSection("media"); - } - return user; } - internal static IEnumerable CreateUser(IUserType userType, int amount, Action onCreating = null) + internal static IEnumerable CreateMulipleUsers(IUserType userType, int amount, Action onCreating = null) { var list = new List(); diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedUserGroup.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedUserGroup.cs new file mode 100644 index 0000000000..f266f55332 --- /dev/null +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedUserGroup.cs @@ -0,0 +1,17 @@ +using Umbraco.Core.Models.Membership; + +namespace Umbraco.Tests.TestHelpers.Entities +{ + public class MockedUserGroup + { + internal static UserGroup CreateUserGroup(string suffix = "", string[] permissions = null) + { + return new UserGroup() + { + Alias = "testUserGroup" + suffix, + Name = "TestUserGroup" + suffix, + Permissions = permissions ?? new[]{"A", "B", "C"} + }; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs index 67ef50af38..1edd10aec7 100644 --- a/src/Umbraco.Tests/TreesAndSections/SectionTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/SectionTests.cs @@ -70,64 +70,6 @@ namespace Umbraco.Tests.TreesAndSections Assert.IsNull(ApplicationContext.Current.Services.SectionService.GetByAlias(name)); } - /// - /// Creates a new user, assigns the user to existing application, - /// then deletes the user - /// - [Test()] - public void Application_Create_New_User_Assign_Application_And_Delete_User() - { - var name = Guid.NewGuid().ToString("N"); - - //new user - var ut = UserType.GetAllUserTypes().First(); - var user = User.MakeNew(name, name, name, ut); - - //get application - //var app = Application.getAll().First(); - - //assign the app - user.addApplication(Constants.Applications.Content); - //ensure it's added - Assert.AreEqual(1, user.Applications.Count(x => x.alias == Constants.Applications.Content)); - - //delete the user - user.delete(); - - //make sure the assigned applications are gone - Assert.AreEqual(0, user.Applications.Count(x => x.alias == name)); - } - - /// - /// create a new application and assigne an new user and deletes the application making sure the assignments are removed - /// - [Test()] - public void Application_Make_New_Assign_User_And_Delete() - { - var name = Guid.NewGuid().ToString("N"); - - //new user - var ut = UserType.GetAllUserTypes().First(); - var user = User.MakeNew(name, name, name, ut); - - ApplicationContext.Current.Services.SectionService.MakeNew(name, name, "icon.jpg"); - - //check if it exists - var app = ApplicationContext.Current.Services.SectionService.GetByAlias(name); - Assert.IsNotNull(app); - - //assign the app - user.addApplication(app.Alias); - //ensure it's added - Assert.AreEqual(1, user.Applications.Count(x => x.alias == app.Alias)); - - //delete the app - ApplicationContext.Current.Services.SectionService.DeleteSection(app); - - //make sure the assigned applications are gone - Assert.AreEqual(0, user.Applications.Count(x => x.alias == name)); - } - #region Tests to write diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 89053a2d5a..c0f43220d9 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -179,8 +179,10 @@ + + diff --git a/src/Umbraco.Tests/Web/Controllers/WebApiEditors/ContentControllerUnitTests.cs b/src/Umbraco.Tests/Web/Controllers/WebApiEditors/ContentControllerUnitTests.cs index 4b78df671d..9634bb164a 100644 --- a/src/Umbraco.Tests/Web/Controllers/WebApiEditors/ContentControllerUnitTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/WebApiEditors/ContentControllerUnitTests.cs @@ -100,7 +100,7 @@ namespace Umbraco.Tests.Web.Controllers.WebApiEditors var userServiceMock = new Mock(); var permissions = new List { - new EntityPermission(9, 1234, new string[]{ "A", "B", "C" }) + new EntityPermission(1234, new string[]{ "A", "B", "C" }) }; userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions); var userService = userServiceMock.Object; @@ -129,7 +129,7 @@ namespace Umbraco.Tests.Web.Controllers.WebApiEditors var userServiceMock = new Mock(); var permissions = new List { - new EntityPermission(9, 1234, new string[]{ "A", "F", "C" }) + new EntityPermission(1234, new string[]{ "A", "F", "C" }) }; userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions); var userService = userServiceMock.Object; @@ -217,7 +217,7 @@ namespace Umbraco.Tests.Web.Controllers.WebApiEditors var userServiceMock = new Mock(); var permissions = new List { - new EntityPermission(9, 1234, new string[]{ "A" }) + new EntityPermission(1234, new string[]{ "A" }) }; userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions); var userService = userServiceMock.Object; @@ -241,7 +241,7 @@ namespace Umbraco.Tests.Web.Controllers.WebApiEditors var userServiceMock = new Mock(); var permissions = new List { - new EntityPermission(9, 1234, new string[]{ "A" }) + new EntityPermission(1234, new string[]{ "A" }) }; userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions); var userService = userServiceMock.Object; @@ -265,7 +265,7 @@ namespace Umbraco.Tests.Web.Controllers.WebApiEditors var userServiceMock = new Mock(); var permissions = new List { - new EntityPermission(9, 1234, new string[]{ "A" }) + new EntityPermission(1234, new string[]{ "A" }) }; userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions); var userService = userServiceMock.Object; @@ -289,7 +289,7 @@ namespace Umbraco.Tests.Web.Controllers.WebApiEditors var userServiceMock = new Mock(); var permissions = new List { - new EntityPermission(9, 1234, new string[]{ "A" }) + new EntityPermission(1234, new string[]{ "A" }) }; userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions); var userService = userServiceMock.Object; diff --git a/src/Umbraco.Tests/Web/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs b/src/Umbraco.Tests/Web/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs index 1ebe2fc748..c776924af7 100644 --- a/src/Umbraco.Tests/Web/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs +++ b/src/Umbraco.Tests/Web/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs @@ -112,10 +112,10 @@ namespace Umbraco.Tests.Web.Controllers.WebApiEditors //we're only assigning 3 nodes browse permissions so that is what we expect as a result var permissions = new List { - new EntityPermission(9, 1, new string[]{ "F" }), - new EntityPermission(9, 2, new string[]{ "F" }), - new EntityPermission(9, 3, new string[]{ "F" }), - new EntityPermission(9, 4, new string[]{ "A" }) + new EntityPermission(1, new string[]{ "F" }), + new EntityPermission(2, new string[]{ "F" }), + new EntityPermission(3, new string[]{ "F" }), + new EntityPermission(4, new string[]{ "A" }) }; userServiceMock.Setup(x => x.GetPermissions(user, ids)).Returns(permissions); var userService = userServiceMock.Object; diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config index 30563647f8..cc63766afc 100644 --- a/src/Umbraco.Web.UI/config/trees.config +++ b/src/Umbraco.Web.UI/config/trees.config @@ -27,7 +27,7 @@ - + diff --git a/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx b/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx index 815a420f88..fc9270e370 100644 --- a/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx +++ b/src/Umbraco.Web.UI/umbraco/users/PermissionEditor.aspx @@ -27,7 +27,7 @@