Skip to content

Commit feab41a

Browse files
authored
Merge pull request #74 from microsoftgraph/refactor
Removed obsolete GetRootParseNode
2 parents 20d8070 + a9dc7ad commit feab41a

6 files changed

Lines changed: 59 additions & 72 deletions

File tree

‎src/Extensions/IssueExtensions.cs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,26 @@ public static async Task<ExternalItem> ToExternalItem(
2525
return new ExternalItem
2626
{
2727
Id = issue.Number.ToString(),
28-
Acl = new()
29-
{
28+
Acl =
29+
[
3030
new()
3131
{
3232
Type = AclType.Everyone,
3333
Value = "everyone",
3434
AccessType = AccessType.Grant,
3535
},
36-
},
36+
],
3737
Properties = issue.ToProperties(events),
38-
Activities = new()
39-
{
38+
Activities =
39+
[
4040
new()
4141
{
4242
OdataType = "#microsoft.graph.externalConnectors.externalActivity",
4343
Type = ExternalActivityType.Created,
4444
StartDateTime = issue.CreatedAt,
4545
PerformedBy = await connectorService.GetIdentityForGitHubUserAsync(issue.User.Login),
4646
},
47-
},
47+
],
4848
};
4949
}
5050

‎src/Extensions/RepositoryExtensions.cs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,26 @@ public static async Task<ExternalItem> ToExternalItem(
2525
return new ExternalItem
2626
{
2727
Id = repository.Id.ToString(),
28-
Acl = new()
29-
{
28+
Acl =
29+
[
3030
new()
3131
{
3232
Type = AclType.Everyone,
3333
Value = "everyone",
3434
AccessType = AccessType.Grant,
3535
},
36-
},
36+
],
3737
Properties = repository.ToProperties(events),
38-
Activities = new()
39-
{
38+
Activities =
39+
[
4040
new()
4141
{
4242
OdataType = "#microsoft.graph.externalConnectors.externalActivity",
4343
Type = ExternalActivityType.Created,
4444
StartDateTime = repository.CreatedAt,
4545
PerformedBy = await connectorService.GetIdentityForGitHubUserAsync(repository.Owner.Login),
4646
},
47-
},
47+
],
4848
};
4949
}
5050

‎src/Middleware/PollForSchemaStatusHandler.cs‎

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,46 @@ namespace GitHubConnector.Middleware;
1212
/// <summary>
1313
/// Middleware handler for asynchronous creation of connector schema.
1414
/// </summary>
15-
public partial class PollForSchemaStatusHandler : DelegatingHandler
15+
/// <remarks>
16+
/// Initializes a new instance of the <see cref="PollForSchemaStatusHandler"/> class.
17+
/// </remarks>
18+
/// <param name="delay">The number of milliseconds to wait between poll requests.</param>
19+
public partial class PollForSchemaStatusHandler(int delay = 60000) : DelegatingHandler
1620
{
17-
// Match URL like:
18-
// /external/connections/{connection-id}/schema
19-
private static readonly Regex PostSchemaRegex =
20-
new("\\/external\\/connections\\/[0-9a-zA-Z]+\\/schema", RegexOptions.IgnoreCase);
21-
22-
// Match URL like:
23-
// /external/connections/{connection-id}/operations/{operation-id}
24-
private static readonly Regex GetOperationRegex =
25-
new("\\/external\\/connections\\/[0-9a-zA-Z]+\\/operations\\/.*", RegexOptions.IgnoreCase);
26-
27-
/// <summary>
28-
/// Initializes a new instance of the <see cref="PollForSchemaStatusHandler"/> class.
29-
/// </summary>
30-
/// <param name="delay">The number of milliseconds to wait between poll requests.</param>
31-
public PollForSchemaStatusHandler(int delay = 60000)
32-
{
33-
Delay = delay;
34-
}
35-
3621
/// <summary>
3722
/// Gets the delay setting in milliseconds.
3823
/// </summary>
39-
public int Delay { get; private set; }
24+
public int Delay { get; private set; } = delay;
4025

4126
/// <inheritdoc/>
4227
protected override Task<HttpResponseMessage> SendAsync(
4328
HttpRequestMessage request, CancellationToken cancellationToken)
4429
{
4530
if (request.Method == HttpMethod.Patch &&
46-
PostSchemaRegex.IsMatch(request.RequestUri?.AbsolutePath ?? string.Empty))
31+
PostSchemaRegex().IsMatch(request.RequestUri?.AbsolutePath ?? string.Empty))
4732
{
4833
return HandlePatchSchemaRequestAsync(request, cancellationToken);
4934
}
5035

5136
if (request.Method == HttpMethod.Get &&
52-
GetOperationRegex.IsMatch(request.RequestUri?.AbsolutePath ?? string.Empty))
37+
GetOperationRegex().IsMatch(request.RequestUri?.AbsolutePath ?? string.Empty))
5338
{
5439
return HandleGetOperationStatusRequestAsync(request, cancellationToken);
5540
}
5641

5742
return base.SendAsync(request, cancellationToken);
5843
}
5944

45+
// Match URL like:
46+
// /external/connections/{connection-id}/operations/{operation-id}
47+
[GeneratedRegex("\\/external\\/connections\\/[0-9a-zA-Z]+\\/operations\\/.*", RegexOptions.IgnoreCase)]
48+
private static partial Regex GetOperationRegex();
49+
50+
// Match URL like:
51+
// /external/connections/{connection-id}/schema
52+
[GeneratedRegex("\\/external\\/connections\\/[0-9a-zA-Z]+\\/schema", RegexOptions.IgnoreCase)]
53+
private static partial Regex PostSchemaRegex();
54+
6055
private async Task<HttpResponseMessage> HandlePatchSchemaRequestAsync(
6156
HttpRequestMessage request, CancellationToken cancellationToken)
6257
{
@@ -69,7 +64,7 @@ private async Task<HttpResponseMessage> HandlePatchSchemaRequestAsync(
6964
if (location is not null)
7065
{
7166
Console.WriteLine($"Waiting {Delay}ms to poll {location.AbsoluteUri}");
72-
await Task.Delay(Delay);
67+
await Task.Delay(Delay, cancellationToken);
7368

7469
request.RequestUri = location;
7570
request.Method = HttpMethod.Get;
@@ -96,17 +91,17 @@ private async Task<HttpResponseMessage> HandleGetOperationStatusRequestAsync(
9691
if (response.IsSuccessStatusCode)
9792
{
9893
// Use Graph SDK's parsers to deserialize the body
99-
var body = await response.Content.ReadAsStringAsync();
94+
var body = await response.Content.ReadAsStringAsync(cancellationToken);
10095
using var responseBody = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(body));
101-
var parseNode = ParseNodeFactoryRegistry.DefaultInstance.GetRootParseNode("application/json", responseBody);
96+
var parseNode = await ParseNodeFactoryRegistry.DefaultInstance.GetRootParseNodeAsync("application/json", responseBody, cancellationToken);
10297
var operation = parseNode.GetObjectValue(ConnectionOperation.CreateFromDiscriminatorValue) ??
10398
throw new ServiceException("Could not get operation from API.");
10499

105100
if (operation.Status == ConnectionOperationStatus.Inprogress)
106101
{
107102
// Schema registration is in progress, poll again
108103
Console.WriteLine($"Waiting {Delay}ms to poll {request.RequestUri?.AbsoluteUri}");
109-
await Task.Delay(Delay);
104+
await Task.Delay(Delay, cancellationToken);
110105
return await SendAsync(request, cancellationToken);
111106
}
112107

‎src/Program.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static async Task ListenForSimplifiedAdminAsync(
7575
Console.WriteLine("Received post");
7676

7777
// Parse the POST body
78-
var changeNotifications = m365AppConfigService.DeserializePostBody(request.InputStream);
78+
var changeNotifications = await M365AppConfigService.DeserializePostBody(request.InputStream);
7979

8080
// Ensure the body deserialized into the expected form
8181
// and that the validation tokens are valid.

‎src/Services/M365AppConfigService.cs‎

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,26 @@ namespace GitHubConnector.Services;
1414
/// <summary>
1515
/// Contains methods for listening for configuration changes from a Microsoft 365 app.
1616
/// </summary>
17-
public class M365AppConfigService
17+
/// <remarks>
18+
/// Initializes a new instance of the <see cref="M365AppConfigService"/> class.
19+
/// </remarks>
20+
/// <param name="settings">The application settings.</param>
21+
public class M365AppConfigService(AppSettings settings)
1822
{
19-
private readonly HttpListener listener;
20-
private readonly int port;
21-
private readonly string tenantId;
22-
private readonly string clientId;
23+
private readonly HttpListener listener = new();
24+
private readonly int port = settings.PortNumber;
25+
private readonly string tenantId = settings.TenantId ?? throw new ArgumentException("tenantId not set in app settings");
26+
private readonly string clientId = settings.ClientId ?? throw new ArgumentException("clientId not set in app settings");
2327

2428
/// <summary>
25-
/// Initializes a new instance of the <see cref="M365AppConfigService"/> class.
29+
/// Deserializes the body of an incoming HTTP POST request.
2630
/// </summary>
27-
/// <param name="settings">The application settings.</param>
28-
public M365AppConfigService(AppSettings settings)
31+
/// <param name="postBody">The input <see cref="Stream"/> to deserialize.</param>
32+
/// <returns>An instance of the <see cref="Changes"/> class.</returns>
33+
public static async Task<Changes?> DeserializePostBody(Stream postBody)
2934
{
30-
tenantId = settings.TenantId ?? throw new ArgumentException("tenantId not set in app settings");
31-
clientId = settings.ClientId ?? throw new ArgumentException("clientId not set in app settings");
32-
port = settings.PortNumber;
33-
listener = new();
35+
var parseNode = await new JsonParseNodeFactory().GetRootParseNodeAsync("application/json", postBody);
36+
return parseNode.GetObjectValue(Changes.CreateFromDiscriminatorValue);
3437
}
3538

3639
/// <summary>
@@ -53,17 +56,6 @@ public void Stop()
5356
listener.Stop();
5457
}
5558

56-
/// <summary>
57-
/// Deserializes the body of an incoming HTTP POST request.
58-
/// </summary>
59-
/// <param name="postBody">The input <see cref="Stream"/> to deserialize.</param>
60-
/// <returns>An instance of the <see cref="Changes"/> class.</returns>
61-
public Changes? DeserializePostBody(Stream postBody)
62-
{
63-
var parseNode = new JsonParseNodeFactory().GetRootParseNode("application/json", postBody);
64-
return parseNode.GetObjectValue(Changes.CreateFromDiscriminatorValue);
65-
}
66-
6759
/// <summary>
6860
/// Validates the tokens sent by Microsoft Graph.
6961
/// </summary>

‎src/Services/SearchConnectorService.cs‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ public SearchConnectorService(AppSettings settings)
125125
Description = description,
126126
ActivitySettings = new()
127127
{
128-
UrlToItemResolvers = new()
129-
{
128+
UrlToItemResolvers =
129+
[
130130
new ItemIdResolver
131131
{
132132
Priority = 1,
@@ -136,15 +136,15 @@ public SearchConnectorService(AppSettings settings)
136136
UrlPattern = itemType == "issues" ?
137137
$"/{gitHubOwner}/{gitHubRepo}/issues/(?<issueId>[0-9]+)" :
138138
$"/{gitHubOwner}/(?<repo>.*)/",
139-
BaseUrls = new() { "https://github.com" },
139+
BaseUrls = ["https://github.com"],
140140
},
141141
},
142-
},
142+
],
143143
},
144144
SearchSettings = new()
145145
{
146-
SearchResultTemplates = new()
147-
{
146+
SearchResultTemplates =
147+
[
148148
new()
149149
{
150150
Id = itemType == "issues" ? "issueDisplay" : "repoDisplay",
@@ -154,7 +154,7 @@ public SearchConnectorService(AppSettings settings)
154154
AdditionalData = await GetResultTemplateAsync(resultCardJsonFile),
155155
},
156156
},
157-
},
157+
],
158158
},
159159
};
160160

@@ -173,7 +173,7 @@ public SearchConnectorService(AppSettings settings)
173173
{
174174
if (useM365Properties)
175175
{
176-
config.Headers.Add("GraphConnectors-Ticket", new[] { connectorTicket! });
176+
config.Headers.Add("GraphConnectors-Ticket", [connectorTicket!]);
177177
}
178178
});
179179
}
@@ -280,7 +280,7 @@ public Task<Identity> GetIdentityForGitHubUserAsync(string? gitHubLogin)
280280
});
281281
}
282282

283-
private async Task<Dictionary<string, object>> GetResultTemplateAsync(string resultCardJsonFile)
283+
private static async Task<Dictionary<string, object>> GetResultTemplateAsync(string resultCardJsonFile)
284284
{
285285
var cardContents = await File.ReadAllTextAsync(resultCardJsonFile);
286286
return JsonSerializer.Deserialize<Dictionary<string, object>>(cardContents) ??

0 commit comments

Comments
 (0)