Skip to content

Commit bfd1784

Browse files
elit0451AndyButlandbergmania
authored
V9: Fix granular permissions for user groups (#11577)
* Fixes the treepicker for granular permissions to use a select callback instead of submit with the full selection * Introduced UserGroup2NodeDto table, to allow users to save empty arrays of permissions * Cleanup * Fixed null issue in audit logging * Fixed migration * Fixed GetDeleteClauses * Fixes for SqlCE, do not run multiple comments on one sql request * Align behavior between content>permissions and usergroups>granularPpermissions - It is now possible to save default values in content>permissions like in usergroups>granularPpermissions - It is now possible to differentiate between we save an empty collection and we remove the granular permissions in content>permissions * Fix comments Co-authored-by: Andy Butland <[email protected]> Co-authored-by: Bjarke Berg <[email protected]>
1 parent 958cd03 commit bfd1784

File tree

20 files changed

+170
-76
lines changed

20 files changed

+170
-76
lines changed

src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public void Handle(AssignedUserGroupPermissionsNotification notification)
226226
foreach (var perm in perms)
227227
{
228228
var group = _userService.GetUserGroupById(perm.UserGroupId);
229-
var assigned = string.Join(", ", perm.AssignedPermissions);
229+
var assigned = string.Join(", ", perm?.AssignedPermissions ?? Array.Empty<string>());
230230
var entity = _entityService.Get(perm.EntityId);
231231

232232
_auditService.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,

src/Umbraco.Core/Models/ContentEditing/UserGroupPermissionsSave.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
1010
/// Used to assign user group permissions to a content node
1111
/// </summary>
1212
[DataContract(Name = "contentPermission", Namespace = "")]
13-
public class UserGroupPermissionsSave : IValidatableObject
13+
public class UserGroupPermissionsSave
1414
{
1515
public UserGroupPermissionsSave()
1616
{
@@ -28,13 +28,5 @@ public UserGroupPermissionsSave()
2828
/// </summary>
2929
[DataMember(Name = "permissions")]
3030
public IDictionary<int, IEnumerable<string>> AssignedPermissions { get; set; }
31-
32-
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
33-
{
34-
if (AssignedPermissions.SelectMany(x => x.Value).Any(x => x.IsNullOrWhiteSpace()))
35-
{
36-
yield return new ValidationResult("A permission value cannot be null or empty", new[] { "Permissions" });
37-
}
38-
}
3931
}
4032
}

src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public static class Tables
5252
public const string User2UserGroup = TableNamePrefix + "User2UserGroup";
5353
public const string User2NodeNotify = TableNamePrefix + "User2NodeNotify";
5454
public const string UserGroup2App = TableNamePrefix + "UserGroup2App";
55+
public const string UserGroup2Node = TableNamePrefix + "UserGroup2Node";
5556
public const string UserGroup2NodePermission = TableNamePrefix + "UserGroup2NodePermission";
5657
public const string ExternalLogin = TableNamePrefix + "ExternalLogin";
5758
public const string ExternalLoginToken = TableNamePrefix + "ExternalLoginToken";

src/Umbraco.Core/Services/UserServiceExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Globalization;
44
using System.Linq;
@@ -59,7 +59,7 @@ public static EntityPermissionSet GetPermissionsForPath(this IUserService servic
5959
/// <param name="entityIds"></param>
6060
public static void RemoveUserGroupPermissions(this IUserService userService, int groupId, params int[] entityIds)
6161
{
62-
userService.ReplaceUserGroupPermissions(groupId, new char[] {}, entityIds);
62+
userService.ReplaceUserGroupPermissions(groupId, null, entityIds);
6363
}
6464

6565
/// <summary>
@@ -69,7 +69,7 @@ public static void RemoveUserGroupPermissions(this IUserService userService, int
6969
/// <param name="groupId"></param>
7070
public static void RemoveUserGroupPermissions(this IUserService userService, int groupId)
7171
{
72-
userService.ReplaceUserGroupPermissions(groupId, new char[] { });
72+
userService.ReplaceUserGroupPermissions(groupId, null);
7373
}
7474

7575

src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ public class DatabaseSchemaCreator
7777
typeof(DocumentCultureVariationDto),
7878
typeof(ContentScheduleDto),
7979
typeof(LogViewerQueryDto),
80-
typeof(ContentVersionCleanupPolicyDto)
80+
typeof(ContentVersionCleanupPolicyDto),
81+
typeof(UserGroup2NodeDto)
8182
};
8283

8384
private readonly IUmbracoDatabase _database;

src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_9_0;
1515
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0;
1616
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_1_0;
17+
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_2_0;
1718
using Umbraco.Extensions;
1819

1920
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade
@@ -263,6 +264,9 @@ protected void DefinePlan()
263264

264265
// TO 9.1.0
265266
To<AddContentVersionCleanupFeature>("{8BAF5E6C-DCB7-41AE-824F-4215AE4F1F98}");
267+
268+
// TO 9.2.0
269+
To<AddUserGroup2NodeTable>("{0571C395-8F0B-44E9-8E3F-47BDD08D817B}");
266270
}
267271
}
268272
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Linq;
2+
using Umbraco.Cms.Core;
3+
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
4+
using Umbraco.Extensions;
5+
6+
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_2_0
7+
{
8+
class AddUserGroup2NodeTable : MigrationBase
9+
{
10+
public AddUserGroup2NodeTable(IMigrationContext context)
11+
: base(context) { }
12+
13+
protected override void Migrate()
14+
{
15+
var tables = SqlSyntax.GetTablesInSchema(Context.Database);
16+
if (!tables.InvariantContains(UserGroup2NodeDto.TableName))
17+
{
18+
Create.Table<UserGroup2NodeDto>().Do();
19+
}
20+
21+
// Insert if there exists specific permissions today. Can't do it directly in db in any nice way.
22+
var allData = Database.Fetch<UserGroup2NodePermissionDto>();
23+
var toInsert = allData.Select(x => new UserGroup2NodeDto() { NodeId = x.NodeId, UserGroupId = x.UserGroupId }).Distinct(
24+
new DelegateEqualityComparer<UserGroup2NodeDto>(
25+
(x, y) => x.NodeId == y.NodeId && x.UserGroupId == y.UserGroupId,
26+
x => x.NodeId.GetHashCode() + x.UserGroupId.GetHashCode())).ToArray();
27+
Database.InsertBulk(toInsert);
28+
}
29+
}
30+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using NPoco;
2+
using Umbraco.Cms.Core;
3+
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
4+
5+
namespace Umbraco.Cms.Infrastructure.Persistence.Dtos
6+
{
7+
[TableName(TableName)]
8+
[ExplicitColumns]
9+
internal class UserGroup2NodeDto
10+
{
11+
public const string TableName = Constants.DatabaseSchema.Tables.UserGroup2Node;
12+
13+
[Column("userGroupId")]
14+
[PrimaryKeyColumn(AutoIncrement = false, Name = "PK_" + TableName, OnColumns = "userGroupId, nodeId")]
15+
[ForeignKey(typeof(UserGroupDto))]
16+
public int UserGroupId { get; set; }
17+
18+
[Column("nodeId")]
19+
[ForeignKey(typeof(NodeDto))]
20+
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_nodeId")]
21+
public int NodeId { get; set; }
22+
}
23+
}

src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,7 @@ protected override IEnumerable<string> GetDeleteClauses()
13831383
var list = new List<string>
13841384
{
13851385
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @id",
1386+
"DELETE FROM umbracoUserGroup2Node WHERE nodeId = @id",
13861387
"DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @id",
13871388
"DELETE FROM cmsTagRelationship WHERE nodeId = @id",
13881389
"DELETE FROM cmsContentTypeAllowedContentType WHERE Id = @id",

src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ protected override IEnumerable<string> GetDeleteClauses()
233233
"DELETE FROM " + Cms.Core.Constants.DatabaseSchema.Tables.ContentSchedule + " WHERE nodeId = @id",
234234
"DELETE FROM " + Cms.Core.Constants.DatabaseSchema.Tables.RedirectUrl + " WHERE contentKey IN (SELECT uniqueId FROM " + Cms.Core.Constants.DatabaseSchema.Tables.Node + " WHERE id = @id)",
235235
"DELETE FROM " + Cms.Core.Constants.DatabaseSchema.Tables.User2NodeNotify + " WHERE nodeId = @id",
236+
"DELETE FROM " + Cms.Core.Constants.DatabaseSchema.Tables.UserGroup2Node + " WHERE nodeId = @id",
236237
"DELETE FROM " + Cms.Core.Constants.DatabaseSchema.Tables.UserGroup2NodePermission + " WHERE nodeId = @id",
237238
"DELETE FROM " + Cms.Core.Constants.DatabaseSchema.Tables.UserStartNode + " WHERE startNode = @id",
238239
"UPDATE " + Cms.Core.Constants.DatabaseSchema.Tables.UserGroup + " SET startContentId = NULL WHERE startContentId = @id",

0 commit comments

Comments
 (0)