1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
-
4
- using System . Net . Http . Json ;
5
- using Microsoft . DevProxy . Plugins . MinimalPermissions ;
6
- using Microsoft . Extensions . Logging ;
7
- using Titanium . Web . Proxy . Http ;
8
-
9
- namespace Microsoft . DevProxy . Plugins ;
10
-
11
- public class GraphUtils
12
- {
13
- // throttle requests per workload
14
- public static string BuildThrottleKey ( Request r ) => BuildThrottleKey ( r . RequestUri ) ;
15
-
16
- public static string BuildThrottleKey ( Uri uri )
17
- {
18
- if ( uri . Segments . Length < 3 )
19
- {
20
- return uri . Host ;
21
- }
22
-
23
- // first segment is /
24
- // second segment is Graph version (v1.0, beta)
25
- // third segment is the workload (users, groups, etc.)
26
- // segment can end with / if there are other segments following
27
- var workload = uri . Segments [ 2 ] . Trim ( '/' ) ;
28
-
29
- // TODO: handle 'me' which is a proxy to other resources
30
-
31
- return workload ;
32
- }
33
-
34
- internal static string GetScopeTypeString ( PermissionsType type )
35
- {
36
- return type switch
37
- {
38
- PermissionsType . Application => "Application" ,
39
- PermissionsType . Delegated => "DelegatedWork" ,
40
- _ => throw new InvalidOperationException ( $ "Unknown scope type: { type } ")
41
- } ;
42
- }
43
-
44
- internal static async Task < IEnumerable < string > > UpdateUserScopesAsync ( IEnumerable < string > minimalScopes , IEnumerable < ( string method , string url ) > endpoints , PermissionsType permissionsType , ILogger logger )
45
- {
46
- var userEndpoints = endpoints . Where ( e => e . url . Contains ( "/users/{" , StringComparison . OrdinalIgnoreCase ) ) ;
47
- if ( ! userEndpoints . Any ( ) )
48
- {
49
- return minimalScopes ;
50
- }
51
-
52
- var newMinimalScopes = new HashSet < string > ( minimalScopes ) ;
53
-
54
- var url = $ "https://graphexplorerapi.azurewebsites.net/permissions?scopeType={ GetScopeTypeString ( permissionsType ) } ";
55
- using var httpClient = new HttpClient ( ) ;
56
- var urls = userEndpoints . Select ( e => {
57
- logger . LogDebug ( "Getting permissions for {method} {url}" , e . method , e . url ) ;
58
- return $ "{ url } &requesturl={ e . url } &method={ e . method } ";
59
- } ) ;
60
- var tasks = urls . Select ( u => {
61
- logger . LogTrace ( "Calling {url}..." , u ) ;
62
- return httpClient . GetFromJsonAsync < PermissionInfo [ ] > ( u ) ;
63
- } ) ;
64
- await Task . WhenAll ( tasks ) ;
65
-
66
- foreach ( var task in tasks )
67
- {
68
- var response = await task ;
69
- if ( response is null )
70
- {
71
- continue ;
72
- }
73
-
74
- // there's only one scope so it must be minimal already
75
- if ( response . Length < 2 )
76
- {
77
- continue ;
78
- }
79
-
80
- if ( newMinimalScopes . Contains ( response [ 0 ] . Value ) )
81
- {
82
- logger . LogDebug ( "Replacing scope {old} with {new}" , response [ 0 ] . Value , response [ 1 ] . Value ) ;
83
- newMinimalScopes . Remove ( response [ 0 ] . Value ) ;
84
- newMinimalScopes . Add ( response [ 1 ] . Value ) ;
85
- }
86
- }
87
-
88
- logger . LogDebug ( "Updated minimal scopes. Original: {original}, New: {new}" , string . Join ( ", " , minimalScopes ) , string . Join ( ", " , newMinimalScopes ) ) ;
89
-
90
- return newMinimalScopes ;
91
- }
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ using System . Net . Http . Json ;
5
+ using Microsoft . DevProxy . Plugins . MinimalPermissions ;
6
+ using Microsoft . Extensions . Logging ;
7
+ using Titanium . Web . Proxy . Http ;
8
+
9
+ namespace Microsoft . DevProxy . Plugins ;
10
+
11
+ public class GraphUtils
12
+ {
13
+ // throttle requests per workload
14
+ public static string BuildThrottleKey ( Request r ) => BuildThrottleKey ( r . RequestUri ) ;
15
+
16
+ public static string BuildThrottleKey ( Uri uri )
17
+ {
18
+ if ( uri . Segments . Length < 3 )
19
+ {
20
+ return uri . Host ;
21
+ }
22
+
23
+ // first segment is /
24
+ // second segment is Graph version (v1.0, beta)
25
+ // third segment is the workload (users, groups, etc.)
26
+ // segment can end with / if there are other segments following
27
+ var workload = uri . Segments [ 2 ] . Trim ( '/' ) ;
28
+
29
+ // TODO: handle 'me' which is a proxy to other resources
30
+
31
+ return workload ;
32
+ }
33
+
34
+ internal static string GetScopeTypeString ( GraphPermissionsType type )
35
+ {
36
+ return type switch
37
+ {
38
+ GraphPermissionsType . Application => "Application" ,
39
+ GraphPermissionsType . Delegated => "DelegatedWork" ,
40
+ _ => throw new InvalidOperationException ( $ "Unknown scope type: { type } ")
41
+ } ;
42
+ }
43
+
44
+ internal static async Task < IEnumerable < string > > UpdateUserScopesAsync ( IEnumerable < string > minimalScopes , IEnumerable < ( string method , string url ) > endpoints , GraphPermissionsType permissionsType , ILogger logger )
45
+ {
46
+ var userEndpoints = endpoints . Where ( e => e . url . Contains ( "/users/{" , StringComparison . OrdinalIgnoreCase ) ) ;
47
+ if ( ! userEndpoints . Any ( ) )
48
+ {
49
+ return minimalScopes ;
50
+ }
51
+
52
+ var newMinimalScopes = new HashSet < string > ( minimalScopes ) ;
53
+
54
+ var url = $ "https://graphexplorerapi.azurewebsites.net/permissions?scopeType={ GetScopeTypeString ( permissionsType ) } ";
55
+ using var httpClient = new HttpClient ( ) ;
56
+ var urls = userEndpoints . Select ( e => {
57
+ logger . LogDebug ( "Getting permissions for {method} {url}" , e . method , e . url ) ;
58
+ return $ "{ url } &requesturl={ e . url } &method={ e . method } ";
59
+ } ) ;
60
+ var tasks = urls . Select ( u => {
61
+ logger . LogTrace ( "Calling {url}..." , u ) ;
62
+ return httpClient . GetFromJsonAsync < GraphPermissionInfo [ ] > ( u ) ;
63
+ } ) ;
64
+ await Task . WhenAll ( tasks ) ;
65
+
66
+ foreach ( var task in tasks )
67
+ {
68
+ var response = await task ;
69
+ if ( response is null )
70
+ {
71
+ continue ;
72
+ }
73
+
74
+ // there's only one scope so it must be minimal already
75
+ if ( response . Length < 2 )
76
+ {
77
+ continue ;
78
+ }
79
+
80
+ if ( newMinimalScopes . Contains ( response [ 0 ] . Value ) )
81
+ {
82
+ logger . LogDebug ( "Replacing scope {old} with {new}" , response [ 0 ] . Value , response [ 1 ] . Value ) ;
83
+ newMinimalScopes . Remove ( response [ 0 ] . Value ) ;
84
+ newMinimalScopes . Add ( response [ 1 ] . Value ) ;
85
+ }
86
+ }
87
+
88
+ logger . LogDebug ( "Updated minimal scopes. Original: {original}, New: {new}" , string . Join ( ", " , minimalScopes ) , string . Join ( ", " , newMinimalScopes ) ) ;
89
+
90
+ return newMinimalScopes ;
91
+ }
92
92
}
0 commit comments