diff --git a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs index 6c40643766..4645b5d749 100644 --- a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs @@ -201,10 +201,24 @@ namespace Umbraco.Web.Models.Mapping var allContentPermissions = applicationContext.Services.UserService.GetPermissions(@group, true) .ToDictionary(x => x.EntityId, x => x); - - var contentEntities = allContentPermissions.Keys.Count == 0 - ? new IUmbracoEntity[0] - : applicationContext.Services.EntityService.GetAll(UmbracoObjectTypes.Document, allContentPermissions.Keys.ToArray()); + + IEnumerable contentEntities; + if (allContentPermissions.Keys.Count == 0) + { + contentEntities = new IUmbracoEntity[0]; + } + else + { + // a group can end up with way more than 2000 assigned permissions, + // so we need to break them into groups in order to avoid breaking + // the entity service due to too many Sql parameters. + + var list = new List(); + contentEntities = list; + var entityService = applicationContext.Services.EntityService; + foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(2000)) + list.AddRange(entityService.GetAll(UmbracoObjectTypes.Document, idGroup.ToArray())); + } var allAssignedPermissions = new List(); foreach (var entity in contentEntities) @@ -229,7 +243,7 @@ namespace Umbraco.Web.Models.Mapping }); //Important! Currently we are never mapping to multiple UserDisplay objects but if we start doing that - // this will cause an N+1 and we'll need to change how this works. + // this will cause an N+1 and we'll need to change how this works. config.CreateMap() .ForMember(detail => detail.Avatars, opt => opt.MapFrom(user => user.GetCurrentUserAvatarUrls(applicationContext.Services.UserService, applicationContext.ApplicationCache.RuntimeCache))) .ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.Username)) @@ -253,7 +267,7 @@ namespace Umbraco.Web.Models.Mapping "media/mediaRoot"))) .ForMember( detail => detail.StartContentIds, - opt => opt.MapFrom(user => GetStartNodeValues( + opt => opt.MapFrom(user => GetStartNodeValues( user.StartContentIds.ToArray(), applicationContext.Services.TextService, applicationContext.Services.EntityService, @@ -261,7 +275,7 @@ namespace Umbraco.Web.Models.Mapping "content/contentRoot"))) .ForMember( detail => detail.StartMediaIds, - opt => opt.MapFrom(user => GetStartNodeValues( + opt => opt.MapFrom(user => GetStartNodeValues( user.StartMediaIds.ToArray(), applicationContext.Services.TextService, applicationContext.Services.EntityService, @@ -328,7 +342,7 @@ namespace Umbraco.Web.Models.Mapping //the best we can do here is to return the user's first user group as a IUserType object //but we should attempt to return any group that is the built in ones first var groups = user.Groups.ToArray(); - detail.UserGroups = user.Groups.Select(x => x.Alias).ToArray(); + detail.UserGroups = user.Groups.Select(x => x.Alias).ToArray(); if (groups.Length == 0) { @@ -369,8 +383,8 @@ namespace Umbraco.Web.Models.Mapping } - private IEnumerable GetStartNodeValues(int[] startNodeIds, - ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType, + private IEnumerable GetStartNodeValues(int[] startNodeIds, + ILocalizedTextService textService, IEntityService entityService, UmbracoObjectTypes objectType, string localizedKey) { if (startNodeIds.Length > 0) @@ -385,7 +399,7 @@ namespace Umbraco.Web.Models.Mapping return startNodes; } return Enumerable.Empty(); - } + } private void MapUserGroupBasic(ServiceContext services, dynamic group, UserGroupBasic display) {