1
1
// Copyright (c) Microsoft Corporation.
2
2
// Licensed under the MIT License.
3
3
4
- using System . Text . RegularExpressions ;
5
4
using Microsoft . Extensions . Configuration ;
6
- using Microsoft . OpenApi . Models ;
7
- using Microsoft . OpenApi . Readers ;
8
5
using Microsoft365 . DeveloperProxy . Abstractions ;
9
6
using Titanium . Web . Proxy . Http ;
10
7
@@ -13,94 +10,17 @@ namespace Microsoft365.DeveloperProxy.Plugins.Guidance;
13
10
public class GraphSelectGuidancePlugin : BaseProxyPlugin
14
11
{
15
12
public override string Name => nameof ( GraphSelectGuidancePlugin ) ;
16
- private readonly Dictionary < string , OpenApiDocument > _openApiDocuments = new ( ) ;
17
13
18
14
public override void Register ( IPluginEvents pluginEvents ,
19
15
IProxyContext context ,
20
16
ISet < UrlToWatch > urlsToWatch ,
21
17
IConfigurationSection ? configSection = null )
22
18
{
23
- var proxyFolder = Path . GetDirectoryName ( context . Configuration . ConfigFile ) ;
24
- var stopwatch = new System . Diagnostics . Stopwatch ( ) ;
25
- stopwatch . Start ( ) ;
26
- LoadOpenAPIFiles ( proxyFolder ! ) ;
27
- stopwatch . Stop ( ) ;
28
- UpdateOpenAPIGraphFilesIfNecessary ( proxyFolder ! ) ;
29
-
30
19
base . Register ( pluginEvents , context , urlsToWatch , configSection ) ;
31
20
32
21
pluginEvents . AfterResponse += AfterResponse ;
33
22
}
34
23
35
- private async Task UpdateOpenAPIGraphFilesIfNecessary ( string proxyFolder )
36
- {
37
- _logger ? . LogDebug ( "Checking for updated OpenAPI files..." ) ;
38
-
39
- var modified = false ;
40
- var versions = new [ ] { "v1.0" , "beta" } ;
41
- foreach ( var version in versions )
42
- {
43
- try
44
- {
45
- var file = new FileInfo ( Path . Combine ( proxyFolder , "plugins" , $ "graph-{ version . Replace ( "." , "_" ) } -openapi.yaml") ) ;
46
- _logger ? . LogDebug ( $ "Checking for updated OpenAPI file for { file } ...") ;
47
- if ( file . LastWriteTime . Date == DateTime . Now . Date )
48
- {
49
- _logger ? . LogDebug ( $ "File { file } already updated today") ;
50
- // file already updated today
51
- continue ;
52
- }
53
-
54
- var url = $ "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/{ version } /openapi.yaml";
55
- _logger ? . LogDebug ( $ "Downloading OpenAPI file from { url } ...") ;
56
-
57
- var client = new HttpClient ( ) ;
58
- var response = await client . GetStringAsync ( url ) ;
59
- File . WriteAllText ( file . FullName , response ) ;
60
-
61
- _logger ? . LogDebug ( $ "Downloaded OpenAPI file from { url } to { file } ") ;
62
- modified = true ;
63
- }
64
- catch ( Exception ex )
65
- {
66
- _logger ? . LogError ( ex . Message ) ;
67
- }
68
- }
69
-
70
- if ( modified )
71
- {
72
- LoadOpenAPIFiles ( proxyFolder ) ;
73
- }
74
- }
75
-
76
- private async void LoadOpenAPIFiles ( string proxyFolder )
77
- {
78
- _logger ? . LogDebug ( "Loading OpenAPI files..." ) ;
79
-
80
- var versions = new [ ] { "v1.0" , "beta" } ;
81
- foreach ( var version in versions )
82
- {
83
- var file = new FileInfo ( Path . Combine ( proxyFolder , "plugins" , $ "graph-{ version . Replace ( "." , "_" ) } -openapi.yaml") ) ;
84
- _logger ? . LogDebug ( $ "Loading OpenAPI file for { file } ...") ;
85
-
86
- if ( ! file . Exists )
87
- {
88
- _logger ? . LogDebug ( $ "File { file } does not exist") ;
89
- continue ;
90
- }
91
-
92
- try {
93
- var openApiDocument = await new OpenApiStreamReader ( ) . ReadAsync ( file . OpenRead ( ) ) ;
94
- _openApiDocuments [ version ] = openApiDocument . OpenApiDocument ;
95
-
96
- _logger ? . LogDebug ( $ "Added OpenAPI file { file } for { version } ") ;
97
- }
98
- catch ( Exception ex ) {
99
- _logger ? . LogDebug ( $ "Error loading OpenAPI file { file } : { ex . Message } ") ;
100
- }
101
- }
102
- }
103
-
104
24
private async Task AfterResponse ( object ? sender , ProxyResponseArgs e )
105
25
{
106
26
Request request = e . Session . HttpClient . Request ;
@@ -134,25 +54,23 @@ private bool EndpointSupportsSelect(string graphVersion, string relativeUrl)
134
54
{
135
55
var fallback = relativeUrl . Contains ( "$value" , StringComparison . OrdinalIgnoreCase ) ;
136
56
137
- if ( ! _openApiDocuments . ContainsKey ( graphVersion ) )
57
+ try
138
58
{
139
- return fallback ;
59
+ var dbConnection = ProxyUtils . MsGraphDbConnection ;
60
+ // lookup information from the database
61
+ var selectEndpoint = dbConnection . CreateCommand ( ) ;
62
+ selectEndpoint . CommandText = "SELECT hasSelect FROM endpoints WHERE path = @path AND graphVersion = @graphVersion" ;
63
+ selectEndpoint . Parameters . AddWithValue ( "@path" , relativeUrl ) ;
64
+ selectEndpoint . Parameters . AddWithValue ( "@graphVersion" , graphVersion ) ;
65
+ var result = selectEndpoint . ExecuteScalar ( ) ;
66
+ var hasSelect = result != null && Convert . ToInt32 ( result ) == 1 ;
67
+ return hasSelect ;
140
68
}
141
-
142
- var relativeUrlPattern = Regex . Replace ( relativeUrl , @"{[^}]+}" , @"{[a-zA-Z-]+}" ) ;
143
- var relativeUrlRegex = new Regex ( $ "^{ relativeUrlPattern } $") ;
144
-
145
- var openApiDocument = _openApiDocuments [ graphVersion ] ;
146
- var pathString = openApiDocument . Paths . Keys . FirstOrDefault ( k => relativeUrlRegex . IsMatch ( k ) ) ;
147
- if ( pathString is null ||
148
- ! openApiDocument . Paths [ pathString ] . Operations . ContainsKey ( OperationType . Get ) )
69
+ catch ( Exception ex )
149
70
{
71
+ _logger ? . LogError ( ex . Message ) ;
150
72
return fallback ;
151
73
}
152
-
153
- var operation = openApiDocument . Paths [ pathString ] . Operations [ OperationType . Get ] ;
154
- var parameters = operation . Parameters ;
155
- return parameters . Any ( p => p . Name == "$select" ) ;
156
74
}
157
75
158
76
private static string GetSelectParameterGuidanceUrl ( ) => "https://aka.ms/m365/proxy/guidance/select" ;
0 commit comments