Skip to content

Commit f9c0235

Browse files
[v14] Add missing alias and id to usergroup related api models (#16154)
* Added missing alias and Id to usergroup models create/update/response/item * Changed userGroup IsSystemGroup to more meaningfull fields Also enforced the AliasCanBeChanged businessrule 🙈 --------- Co-authored-by: Sven Geusens <[email protected]> Co-authored-by: Mads Rasmussen <[email protected]>
1 parent 8ad6c36 commit f9c0235

File tree

13 files changed

+175
-28
lines changed

13 files changed

+175
-28
lines changed

src/Umbraco.Cms.Api.Management/Controllers/UserGroup/ByKeyUserGroupController.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using Microsoft.AspNetCore.Http;
44
using Microsoft.AspNetCore.Mvc;
55
using Umbraco.Cms.Api.Management.Factories;
6-
using Umbraco.Cms.Api.Management.Security.Authorization.UserGroup;
76
using Umbraco.Cms.Api.Management.ViewModels.UserGroup;
87
using Umbraco.Cms.Core.Models.Membership;
98
using Umbraco.Cms.Core.Security.Authorization;

src/Umbraco.Cms.Api.Management/Controllers/UserGroup/UserGroupControllerBase.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,15 @@ protected IActionResult UserGroupOperationStatusResult(UserGroupOperationStatus
2929
.WithTitle("Duplicate alias")
3030
.WithDetail("A user group already exists with the attempted alias.")
3131
.Build()),
32+
UserGroupOperationStatus.CanNotUpdateAliasIsSystemUserGroup => BadRequest(problemDetailsBuilder
33+
.WithTitle("System user group")
34+
.WithDetail("Changing the alias is not allowed on a system user group.")
35+
.Build()),
3236
UserGroupOperationStatus.MissingUser => Unauthorized(problemDetailsBuilder
3337
.WithTitle("Missing user")
3438
.WithDetail("A performing user was not found when attempting the operation.")
3539
.Build()),
36-
UserGroupOperationStatus.IsSystemUserGroup => BadRequest(problemDetailsBuilder
40+
UserGroupOperationStatus.CanNotDeleteIsSystemUserGroup => BadRequest(problemDetailsBuilder
3741
.WithTitle("System user group")
3842
.WithDetail("The operation is not allowed on a system user group.")
3943
.Build()),

src/Umbraco.Cms.Api.Management/Factories/UserGroupPresentationFactory.cs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ public async Task<UserGroupResponseModel> CreateAsync(IUserGroup userGroup)
5151

5252
return new UserGroupResponseModel
5353
{
54-
Name = userGroup.Name ?? string.Empty,
5554
Id = userGroup.Key,
55+
Name = userGroup.Name ?? string.Empty,
56+
Alias = userGroup.Alias,
5657
DocumentStartNode = ReferenceByIdModel.ReferenceOrNull(contentStartNodeKey),
5758
DocumentRootAccess = contentRootAccess,
5859
MediaStartNode = ReferenceByIdModel.ReferenceOrNull(mediaStartNodeKey),
@@ -63,7 +64,8 @@ public async Task<UserGroupResponseModel> CreateAsync(IUserGroup userGroup)
6364
FallbackPermissions = userGroup.Permissions,
6465
Permissions = await _permissionPresentationFactory.CreateAsync(userGroup.GranularPermissions),
6566
Sections = userGroup.AllowedSections.Select(SectionMapper.GetName),
66-
IsSystemGroup = userGroup.IsSystemUserGroup()
67+
IsDeletable = !userGroup.IsSystemUserGroup(),
68+
AliasCanBeChanged = !userGroup.IsSystemUserGroup(),
6769
};
6870
}
6971

@@ -83,8 +85,9 @@ public async Task<UserGroupResponseModel> CreateAsync(IReadOnlyUserGroup userGro
8385

8486
return new UserGroupResponseModel
8587
{
86-
Name = userGroup.Name ?? string.Empty,
8788
Id = userGroup.Key,
89+
Name = userGroup.Name ?? string.Empty,
90+
Alias = userGroup.Alias,
8891
DocumentStartNode = ReferenceByIdModel.ReferenceOrNull(contentStartNodeKey),
8992
MediaStartNode = ReferenceByIdModel.ReferenceOrNull(mediaStartNodeKey),
9093
Icon = userGroup.Icon,
@@ -93,6 +96,8 @@ public async Task<UserGroupResponseModel> CreateAsync(IReadOnlyUserGroup userGro
9396
FallbackPermissions = userGroup.Permissions,
9497
Permissions = await _permissionPresentationFactory.CreateAsync(userGroup.GranularPermissions),
9598
Sections = userGroup.AllowedSections.Select(SectionMapper.GetName),
99+
IsDeletable = !userGroup.IsSystemUserGroup(),
100+
AliasCanBeChanged = !userGroup.IsSystemUserGroup(),
96101
};
97102
}
98103

@@ -107,6 +112,7 @@ public async Task<IEnumerable<UserGroupResponseModel>> CreateMultipleAsync(IEnum
107112

108113
return userGroupViewModels;
109114
}
115+
110116
/// <inheritdoc />
111117
public async Task<IEnumerable<UserGroupResponseModel>> CreateMultipleAsync(IEnumerable<IReadOnlyUserGroup> userGroups)
112118
{
@@ -122,18 +128,21 @@ public async Task<IEnumerable<UserGroupResponseModel>> CreateMultipleAsync(IEnum
122128
/// <inheritdoc />
123129
public async Task<Attempt<IUserGroup, UserGroupOperationStatus>> CreateAsync(CreateUserGroupRequestModel requestModel)
124130
{
125-
var cleanedName = requestModel.Name.CleanForXss('[', ']', '(', ')', ':');
126-
127131
var group = new UserGroup(_shortStringHelper)
128132
{
129-
Name = cleanedName,
130-
Alias = cleanedName,
133+
Name = CleanUserGroupNameOrAliasForXss(requestModel.Name),
134+
Alias = CleanUserGroupNameOrAliasForXss(requestModel.Alias),
131135
Icon = requestModel.Icon,
132136
HasAccessToAllLanguages = requestModel.HasAccessToAllLanguages,
133137
Permissions = requestModel.FallbackPermissions,
134-
GranularPermissions = await _permissionPresentationFactory.CreatePermissionSetsAsync(requestModel.Permissions)
138+
GranularPermissions = await _permissionPresentationFactory.CreatePermissionSetsAsync(requestModel.Permissions),
135139
};
136140

141+
if (requestModel.Id.HasValue)
142+
{
143+
group.Key = requestModel.Id.Value;
144+
}
145+
137146
Attempt<UserGroupOperationStatus> assignmentAttempt = AssignStartNodesToUserGroup(requestModel, group);
138147
if (assignmentAttempt.Success is false)
139148
{
@@ -186,7 +195,8 @@ public async Task<Attempt<IUserGroup, UserGroupOperationStatus>> UpdateAsync(IUs
186195
current.AddAllowedSection(SectionMapper.GetAlias(sectionName));
187196
}
188197

189-
current.Name = request.Name.CleanForXss('[', ']', '(', ')', ':');
198+
current.Name = CleanUserGroupNameOrAliasForXss(request.Name);
199+
current.Alias = CleanUserGroupNameOrAliasForXss(request.Alias);
190200
current.Icon = request.Icon;
191201
current.HasAccessToAllLanguages = request.HasAccessToAllLanguages;
192202

@@ -196,6 +206,9 @@ public async Task<Attempt<IUserGroup, UserGroupOperationStatus>> UpdateAsync(IUs
196206
return Attempt.SucceedWithStatus(UserGroupOperationStatus.Success, current);
197207
}
198208

209+
private static string CleanUserGroupNameOrAliasForXss(string input)
210+
=> input.CleanForXss('[', ']', '(', ')', ':');
211+
199212
private async Task<Attempt<IEnumerable<string>, UserGroupOperationStatus>> MapLanguageIdsToIsoCodeAsync(IEnumerable<int> ids)
200213
{
201214
IEnumerable<ILanguage> languages = await _languageService.GetAllAsync();

src/Umbraco.Cms.Api.Management/Mapping/Item/ItemTypeMapDefinition.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ private static void Map(IUserGroup source, UserGroupItemResponseModel target, Ma
112112
target.Id = source.Key;
113113
target.Name = source.Name ?? source.Alias;
114114
target.Icon = source.Icon;
115+
target.Alias = source.Alias;
115116
}
116117

117118
// Umbraco.Code.MapAll

src/Umbraco.Cms.Api.Management/OpenApi.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34131,6 +34131,7 @@
3413134131
},
3413234132
"CreateUserGroupRequestModel": {
3413334133
"required": [
34134+
"alias",
3413434135
"documentRootAccess",
3413534136
"fallbackPermissions",
3413634137
"hasAccessToAllLanguages",
@@ -34145,6 +34146,9 @@
3414534146
"name": {
3414634147
"type": "string"
3414734148
},
34149+
"alias": {
34150+
"type": "string"
34151+
},
3414834152
"icon": {
3414934153
"type": "string",
3415034154
"nullable": true
@@ -34206,6 +34210,11 @@
3420634210
}
3420734211
]
3420834212
}
34213+
},
34214+
"id": {
34215+
"type": "string",
34216+
"format": "uuid",
34217+
"nullable": true
3420934218
}
3421034219
},
3421134220
"additionalProperties": false
@@ -43105,6 +43114,7 @@
4310543114
},
4310643115
"UpdateUserGroupRequestModel": {
4310743116
"required": [
43117+
"alias",
4310843118
"documentRootAccess",
4310943119
"fallbackPermissions",
4311043120
"hasAccessToAllLanguages",
@@ -43119,6 +43129,9 @@
4311943129
"name": {
4312043130
"type": "string"
4312143131
},
43132+
"alias": {
43133+
"type": "string"
43134+
},
4312243135
"icon": {
4312343136
"type": "string",
4312443137
"nullable": true
@@ -43432,12 +43445,17 @@
4343243445
"icon": {
4343343446
"type": "string",
4343443447
"nullable": true
43448+
},
43449+
"alias": {
43450+
"type": "string",
43451+
"nullable": true
4343543452
}
4343643453
},
4343743454
"additionalProperties": false
4343843455
},
4343943456
"UserGroupResponseModel": {
4344043457
"required": [
43458+
"alias",
4344143459
"documentRootAccess",
4344243460
"fallbackPermissions",
4344343461
"hasAccessToAllLanguages",
@@ -43454,6 +43472,9 @@
4345443472
"name": {
4345543473
"type": "string"
4345643474
},
43475+
"alias": {
43476+
"type": "string"
43477+
},
4345743478
"icon": {
4345843479
"type": "string",
4345943480
"nullable": true

src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/CreateUserGroupRequestModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
public class CreateUserGroupRequestModel : UserGroupBase
44
{
5-
5+
public Guid? Id { get; set; }
66
}

src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Item/UserGroupItemResponseModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ namespace Umbraco.Cms.Api.Management.ViewModels.UserGroup.Item;
55
public class UserGroupItemResponseModel : NamedItemResponseModelBase
66
{
77
public string? Icon { get; set; }
8+
9+
public string? Alias { get; set; }
810
}

src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/UserGroupBase.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ public class UserGroupBase
1717
/// </summary>
1818
public required string Name { get; init; }
1919

20+
/// <summary>
21+
/// The alias of the user groups
22+
/// </summary>
23+
public required string Alias { get; init; }
24+
2025
/// <summary>
2126
/// The Icon for the user group
2227
/// </summary>

src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/UserGroupResponseModel.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,10 @@ public class UserGroupResponseModel : UserGroupBase
1010
/// <summary>
1111
/// Whether this user group is required at system level (thus cannot be removed)
1212
/// </summary>
13-
public bool IsSystemGroup { get; set; }
13+
public bool IsDeletable { get; set; }
14+
15+
/// <summary>
16+
/// Whether this user group is required at system level (thus alias needs to be fixed)
17+
/// </summary>
18+
public bool AliasCanBeChanged { get; set; }
1419
}

src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ public enum UserGroupOperationStatus
88
AlreadyExists,
99
DuplicateAlias,
1010
MissingUser,
11-
IsSystemUserGroup,
11+
CanNotDeleteIsSystemUserGroup,
12+
CanNotUpdateAliasIsSystemUserGroup,
1213
CancelledByNotification,
1314
MediaStartNodeKeyNotFound,
1415
DocumentStartNodeKeyNotFound,

0 commit comments

Comments
 (0)