1
- using Umbraco . Cms . Api . Management . Routing ;
1
+ using Microsoft . Extensions . DependencyInjection ;
2
2
using Microsoft . Extensions . Options ;
3
+ using Umbraco . Cms . Api . Management . Routing ;
3
4
using Umbraco . Cms . Api . Management . Security ;
4
5
using Umbraco . Cms . Api . Management . ViewModels ;
5
6
using Umbraco . Cms . Api . Management . ViewModels . User ;
6
7
using Umbraco . Cms . Api . Management . ViewModels . User . Current ;
7
- using Umbraco . Cms . Core ;
8
8
using Umbraco . Cms . Api . Management . ViewModels . User . Item ;
9
+ using Umbraco . Cms . Api . Management . ViewModels . UserGroup ;
10
+ using Umbraco . Cms . Api . Management . ViewModels . UserGroup . Permissions ;
11
+ using Umbraco . Cms . Core ;
9
12
using Umbraco . Cms . Core . Cache ;
10
13
using Umbraco . Cms . Core . Configuration . Models ;
14
+ using Umbraco . Cms . Core . DependencyInjection ;
11
15
using Umbraco . Cms . Core . IO ;
12
16
using Umbraco . Cms . Core . Mail ;
13
17
using Umbraco . Cms . Core . Media ;
@@ -20,7 +24,6 @@ namespace Umbraco.Cms.Api.Management.Factories;
20
24
21
25
public class UserPresentationFactory : IUserPresentationFactory
22
26
{
23
-
24
27
private readonly IEntityService _entityService ;
25
28
private readonly AppCaches _appCaches ;
26
29
private readonly MediaFileManager _mediaFileManager ;
@@ -31,7 +34,10 @@ public class UserPresentationFactory : IUserPresentationFactory
31
34
private readonly IPasswordConfigurationPresentationFactory _passwordConfigurationPresentationFactory ;
32
35
private readonly IBackOfficeExternalLoginProviders _externalLoginProviders ;
33
36
private readonly SecuritySettings _securitySettings ;
37
+ private readonly IUserService _userService ;
38
+ private readonly IContentService _contentService ;
34
39
40
+ [ Obsolete ( "Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17." ) ]
35
41
public UserPresentationFactory (
36
42
IEntityService entityService ,
37
43
AppCaches appCaches ,
@@ -43,6 +49,35 @@ public UserPresentationFactory(
43
49
IPasswordConfigurationPresentationFactory passwordConfigurationPresentationFactory ,
44
50
IOptionsSnapshot < SecuritySettings > securitySettings ,
45
51
IBackOfficeExternalLoginProviders externalLoginProviders )
52
+ : this (
53
+ entityService ,
54
+ appCaches ,
55
+ mediaFileManager ,
56
+ imageUrlGenerator ,
57
+ userGroupPresentationFactory ,
58
+ absoluteUrlBuilder ,
59
+ emailSender ,
60
+ passwordConfigurationPresentationFactory ,
61
+ securitySettings ,
62
+ externalLoginProviders ,
63
+ StaticServiceProvider . Instance . GetRequiredService < IUserService > ( ) ,
64
+ StaticServiceProvider . Instance . GetRequiredService < IContentService > ( ) )
65
+ {
66
+ }
67
+
68
+ public UserPresentationFactory (
69
+ IEntityService entityService ,
70
+ AppCaches appCaches ,
71
+ MediaFileManager mediaFileManager ,
72
+ IImageUrlGenerator imageUrlGenerator ,
73
+ IUserGroupPresentationFactory userGroupPresentationFactory ,
74
+ IAbsoluteUrlBuilder absoluteUrlBuilder ,
75
+ IEmailSender emailSender ,
76
+ IPasswordConfigurationPresentationFactory passwordConfigurationPresentationFactory ,
77
+ IOptionsSnapshot < SecuritySettings > securitySettings ,
78
+ IBackOfficeExternalLoginProviders externalLoginProviders ,
79
+ IUserService userService ,
80
+ IContentService contentService )
46
81
{
47
82
_entityService = entityService ;
48
83
_appCaches = appCaches ;
@@ -54,6 +89,8 @@ public UserPresentationFactory(
54
89
_externalLoginProviders = externalLoginProviders ;
55
90
_securitySettings = securitySettings . Value ;
56
91
_absoluteUrlBuilder = absoluteUrlBuilder ;
92
+ _userService = userService ;
93
+ _contentService = contentService ;
57
94
}
58
95
59
96
public UserResponseModel CreateResponseModel ( IUser user )
@@ -195,7 +232,7 @@ public async Task<CurrentUserResponseModel> CreateCurrentUserResponseModelAsync(
195
232
var contentStartNodeIds = user . CalculateContentStartNodeIds ( _entityService , _appCaches ) ;
196
233
var documentStartNodeKeys = GetKeysFromIds ( contentStartNodeIds , UmbracoObjectTypes . Document ) ;
197
234
198
- var permissions = presentationGroups . SelectMany ( x => x . Permissions ) . ToHashSet ( ) ;
235
+ var permissions = GetAggregatedGranularPermissions ( user , presentationGroups ) ;
199
236
var fallbackPermissions = presentationGroups . SelectMany ( x => x . FallbackPermissions ) . ToHashSet ( ) ;
200
237
201
238
var hasAccessToAllLanguages = presentationGroups . Any ( x => x . HasAccessToAllLanguages ) ;
@@ -225,6 +262,42 @@ public async Task<CurrentUserResponseModel> CreateCurrentUserResponseModelAsync(
225
262
} ) ;
226
263
}
227
264
265
+ private HashSet < IPermissionPresentationModel > GetAggregatedGranularPermissions ( IUser user , IEnumerable < UserGroupResponseModel > presentationGroups )
266
+ {
267
+ var permissions = presentationGroups . SelectMany ( x => x . Permissions ) . ToHashSet ( ) ;
268
+
269
+ // The raw permission data consists of several permissions for each document. We want to aggregate this server-side so
270
+ // we return one set of aggregate permissions per document that the client will use.
271
+
272
+ // Get the unique document keys that have granular permissions.
273
+ IEnumerable < Guid > documentKeysWithGranularPermissions = permissions
274
+ . Where ( x => x is DocumentPermissionPresentationModel )
275
+ . Cast < DocumentPermissionPresentationModel > ( )
276
+ . Select ( x => x . Document . Id )
277
+ . Distinct ( ) ;
278
+
279
+ var aggregatedPermissions = new HashSet < IPermissionPresentationModel > ( ) ;
280
+ foreach ( Guid documentKey in documentKeysWithGranularPermissions )
281
+ {
282
+ // Retrieve the path of the document.
283
+ var path = _contentService . GetById ( documentKey ) ? . Path ;
284
+ if ( string . IsNullOrEmpty ( path ) )
285
+ {
286
+ continue ;
287
+ }
288
+
289
+ // With the path we can call the same logic as used server-side for authorizing access to resources.
290
+ EntityPermissionSet permissionsForPath = _userService . GetPermissionsForPath ( user , path ) ;
291
+ aggregatedPermissions . Add ( new DocumentPermissionPresentationModel
292
+ {
293
+ Document = new ReferenceByIdModel ( documentKey ) ,
294
+ Verbs = permissionsForPath . GetAllPermissions ( )
295
+ } ) ;
296
+ }
297
+
298
+ return aggregatedPermissions ;
299
+ }
300
+
228
301
public async Task < CalculatedUserStartNodesResponseModel > CreateCalculatedUserStartNodesResponseModelAsync ( IUser user )
229
302
{
230
303
var mediaStartNodeIds = user . CalculateMediaStartNodeIds ( _entityService , _appCaches ) ;
0 commit comments