Skip to content

Commit

Permalink
Adds GraphConnectorGuidancePlugin. Closes #603 (#604)
Browse files Browse the repository at this point in the history
* WIP: Adds GraphConnectorGuidancePlugin

* Adds GraphConnectorGuidancePlugin. Closes #603

* Updates message
  • Loading branch information
waldekmastykarz authored Mar 13, 2024
1 parent d750294 commit c0381c7
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 32 deletions.
115 changes: 115 additions & 0 deletions dev-proxy-plugins/Guidance/GraphConnectorGuidancePlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.Extensions.Configuration;
using Microsoft.DevProxy.Abstractions;
using System.Text.Json;
using Microsoft.Extensions.Logging;

namespace Microsoft.DevProxy.Plugins.Guidance;

class ExternalConnectionSchema
{
public string? BaseType { get; set; }
public ExternalConnectionSchemaProperty[]? Properties { get; set; }
}

class ExternalConnectionSchemaProperty
{
public string[]? Aliases { get; set; }
public bool? IsQueryable { get; set; }
public bool? IsRefinable { get; set; }
public bool? IsRetrievable { get; set; }
public bool? IsSearchable { get; set; }
public string[]? Labels { get; set; }
public string? Name { get; set; }
public string? Type { get; set; }
}

public class GraphConnectorGuidancePlugin : BaseProxyPlugin
{
public override string Name => nameof(GraphConnectorGuidancePlugin);

public override void Register(IPluginEvents pluginEvents,
IProxyContext context,
ISet<UrlToWatch> urlsToWatch,
IConfigurationSection? configSection = null)
{
base.Register(pluginEvents, context, urlsToWatch, configSection);

pluginEvents.BeforeRequest += BeforeRequest;
}

private Task BeforeRequest(object sender, ProxyRequestArgs e)
{
if (_urlsToWatch is null ||
!e.HasRequestUrlMatch(_urlsToWatch) ||
e.Session.HttpClient.Request.Method.ToUpper() != "PATCH")
{
return Task.CompletedTask;
}

try
{
var schemaString = e.Session.HttpClient.Request.BodyString;
if (string.IsNullOrEmpty(schemaString))
{
_logger?.LogRequest([ "No schema found in the request body." ], MessageType.Failed, new LoggingContext(e.Session));
return Task.CompletedTask;
}

var schema = JsonSerializer.Deserialize<ExternalConnectionSchema>(schemaString, ProxyUtils.JsonSerializerOptions);
if (schema is null || schema.Properties is null)
{
_logger?.LogRequest([ "Invalid schema found in the request body." ], MessageType.Failed, new LoggingContext(e.Session));
return Task.CompletedTask;
}

bool hasTitle = false, hasIconUrl = false, hasUrl = false;
foreach (var property in schema.Properties)
{
if (property.Labels is null)
{
continue;
}

if (property.Labels.Contains("title", StringComparer.OrdinalIgnoreCase))
{
hasTitle = true;
}
if (property.Labels.Contains("iconUrl", StringComparer.OrdinalIgnoreCase))
{
hasIconUrl = true;
}
if (property.Labels.Contains("url", StringComparer.OrdinalIgnoreCase))
{
hasUrl = true;
}
}

if (!hasTitle || !hasIconUrl || !hasUrl)
{
string[] missingLabels = [
!hasTitle ? "title" : "",
!hasIconUrl ? "iconUrl" : "",
!hasUrl ? "url" : ""
];

_logger?.LogRequest(
[
$"The schema is missing the following semantic labels: {string.Join(", ", missingLabels.Where(s => s != ""))}.",
"Ingested content might not show up in Microsoft Copilot for Microsoft 365.",
"More information: https://aka.ms/devproxy/guidance/gc/ux"
],
MessageType.Failed, new LoggingContext(e.Session)
);
}
}
catch (Exception ex)
{
_logger?.LogError(ex, "An error has occurred while deserializing the request body");
}

return Task.CompletedTask;
}
}
9 changes: 8 additions & 1 deletion dev-proxy/ConsoleLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,14 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
return;
}

var message = formatter(state, exception).ReplaceLineEndings();
var message = formatter(state, exception);
// temporary fix to log exceptions
// long term we should move this to the formatter
if (exception is not null)
{
message += Environment.NewLine + exception;
}
message = message.ReplaceLineEndings();
switch (logLevel)
{
case LogLevel.Debug:
Expand Down
2 changes: 1 addition & 1 deletion dev-proxy/presets/m365-mocks.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/dev-proxy/main/schemas/v0.15.0/mockresponseplugin.schema.json",
"$schema": "https://raw.githubusercontent.com/microsoft/dev-proxy/main/schemas/v0.16.0/mockresponseplugin.schema.json",
"mocks": [
{
"request": {
Expand Down
51 changes: 31 additions & 20 deletions dev-proxy/presets/m365.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/dev-proxy/main/schemas/v0.15.0/rc.schema.json",
"$schema": "https://raw.githubusercontent.com/microsoft/dev-proxy/main/schemas/v0.16.0/rc.schema.json",
"plugins": [
{
"name": "DevToolsPlugin",
"enabled": false,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "devTools"
},
{
"name": "LatencyPlugin",
"enabled": false,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "latencyPlugin"
},
{
"name": "RetryAfterPlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphSelectGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
Expand All @@ -36,7 +36,7 @@
{
"name": "ODSPSearchGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
Expand All @@ -51,18 +51,29 @@
{
"name": "GraphBetaSupportGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
},
{
"name": "GraphConnectorGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/*/external/connections/*/schema",
"https://graph.microsoft.us/*/external/connections/*/schema",
"https://dod-graph.microsoft.us/*/external/connections/*/schema",
"https://microsoftgraph.chinacloudapi.cn/*/external/connections/*/schema"
]
},
{
"name": "GraphSdkGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
Expand All @@ -77,12 +88,12 @@
{
"name": "ODataPagingGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphClientRequestIdGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/v1.0/*",
"https://graph.microsoft.com/beta/*",
Expand All @@ -97,54 +108,54 @@
{
"name": "CachingGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "cachingGuidance"
},
{
"name": "RateLimitingPlugin",
"enabled": false,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "rateLimiting"
},
{
"name": "MockResponsePlugin",
"enabled": false,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mocksPlugin"
},
{
"name": "GraphMockResponsePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "mocksPlugin"
},
{
"name": "GraphRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphRandomErrorsPlugin"
},
{
"name": "ExecutionSummaryPlugin",
"enabled": false,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "executionSummaryPlugin"
},
{
"name": "MinimalPermissionsPlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "minimalPermissionsPlugin"
},
{
"name": "MinimalPermissionsGuidancePlugin",
"enabled": false,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "MockGeneratorPlugin",
"enabled": false,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
Expand Down Expand Up @@ -190,6 +201,6 @@
},
"rate": 50,
"labelMode": "text",
"logLevel": "info"
"logLevel": "information"
}

5 changes: 3 additions & 2 deletions dev-proxy/presets/microsoft-graph-rate-limiting.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/dev-proxy/main/schemas/v0.16.0/rc.schema.json",
"plugins": [
{
"name": "RateLimitingPlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
}
],
"urlsToWatch": [
Expand All @@ -21,5 +22,5 @@
"https://microsoftgraph.chinacloudapi.cn/*/sites/*"
],
"labelMode": "text",
"logLevel": "info"
"logLevel": "information"
}
28 changes: 20 additions & 8 deletions dev-proxy/presets/microsoft-graph.json
Original file line number Diff line number Diff line change
@@ -1,46 +1,58 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/dev-proxy/main/schemas/v0.16.0/rc.schema.json",
"plugins": [
{
"name": "GraphSelectGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphBetaSupportGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/beta/*",
"https://graph.microsoft.us/beta/*",
"https://dod-graph.microsoft.us/beta/*",
"https://microsoftgraph.chinacloudapi.cn/beta/*"
]
},
{
"name": "GraphConnectorGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"urlsToWatch": [
"https://graph.microsoft.com/*/external/connections/*/schema",
"https://graph.microsoft.us/*/external/connections/*/schema",
"https://dod-graph.microsoft.us/*/external/connections/*/schema",
"https://microsoftgraph.chinacloudapi.cn/*/external/connections/*/schema"
]
},
{
"name": "GraphSdkGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "ODataPagingGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphClientRequestIdGuidancePlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll"
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll"
},
{
"name": "GraphRandomErrorPlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "graphRandomErrorsPlugin"
},
{
"name": "ExecutionSummaryPlugin",
"enabled": true,
"pluginPath": "~appFolder\\plugins\\dev-proxy-plugins.dll",
"pluginPath": "~appFolder/plugins/dev-proxy-plugins.dll",
"configSection": "executionSummaryPlugin"
}
],
Expand All @@ -62,5 +74,5 @@
},
"rate": 50,
"labelMode": "text",
"logLevel": "info"
"logLevel": "information"
}

0 comments on commit c0381c7

Please sign in to comment.