-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refine error handling and MIME types in MS Graph integration
Refactor several components to enhance the Microsoft Graph integration: - Improve exception clarity when Azure AppConfig connection strings are missing by using a more descriptive check. - Streamline the definition of Microsoft Graph MIME types through XML documentation and interpolated strings, aiding future maintenance and readability. - Standardize URI paths with leading slashes and add a new route for DirectoryObjects to align with API design conventions. - Introduce DirectoryObjectsController with functionality to retrieve extension properties, expanding the API surface. - Refine MeController and UsersController by adjusting authorization scopes and resource access patterns, ensuring consistency and restricting permissions to the minimal required. - Abstract common functionality into a new MsGraphController base class, reducing code duplication and separating concerns. - Update project configurations, adding a logging extension and including new auxiliary classes for MVC patterns. - Perform various code cleanups like modifying internal visibility, enhancing logging extension methods, and fixing minor inconsistencies. These changes solidify the foundation of Microsoft Graph features in the application and streamline future extension and maintenance efforts.
- Loading branch information
Showing
19 changed files
with
313 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,47 @@ | ||
namespace Dgmjr.Graph.Constants; | ||
|
||
using Dgmjr.Mime; | ||
|
||
public static class MimeTypes | ||
{ | ||
/// <value>msgraph</value> | ||
private const string MsGraph = "msgraph"; | ||
|
||
/// <value><inheritdoc cref="MsGraph" path="/value" />-extension-properties</value> | ||
public const string MsGraphExtensionPropertiesList = $"{MsGraph}-extension-properties"; | ||
public const string MsGraphExtensionPropertiesListJson = $"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.Json.DisplayName}"; | ||
public const string MsGraphExtensionPropertiesListXml = $"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.Xml.DisplayName}"; | ||
public const string MsGraphExtensionPropertiesListBson = $"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.Bson.DisplayName}"; | ||
public const string MsGraphExtensionPropertiesListMsgPack = $"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.MessagePack.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.Json.DisplayName" path="/value" /></value> | ||
public const string MsGraphExtensionPropertiesListJson = | ||
$"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.Json.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.Xml.DisplayName" path="/value" /></value> | ||
public const string MsGraphExtensionPropertiesListXml = | ||
$"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.Xml.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.Bson.DisplayName" path="/value" /></value> | ||
public const string MsGraphExtensionPropertiesListBson = | ||
$"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.Bson.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.MessagePack.DisplayName" path="/value" /></value> | ||
public const string MsGraphExtensionPropertiesListMsgPack = | ||
$"{Application.Base.DisplayName}/{MsGraphExtensionPropertiesList}{Suffixes.MessagePack.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="MsGraph" path="/value" />-user</value> | ||
public const string MsGraphUser = $"{MsGraph}-user"; | ||
public const string MsGraphUserJson = $"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.Json.DisplayName}"; | ||
public const string MsGraphUserXml = $"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.Xml.DisplayName}"; | ||
public const string MsGraphUserBson = $"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.Bson.DisplayName}"; | ||
public const string MsGraphUserMsgPack = $"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.MessagePack.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.Json.DisplayName" path="/value" /></value> | ||
public const string MsGraphUserJson = | ||
$"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.Json.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.Xml.DisplayName" path="/value" /></value> | ||
public const string MsGraphUserXml = | ||
$"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.Xml.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.Bson.DisplayName" path="/value" /></value> | ||
public const string MsGraphUserBson = | ||
$"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.Bson.DisplayName}"; | ||
|
||
/// <value><inheritdoc cref="Application.Base.DisplayName" path="/value" />/<inheritdoc cref="MsGraphExtensionPropertiesList" path="/value" /><inheritdoc cref="Suffixes.MessagePack.DisplayName" path="/value" /></value> | ||
public const string MsGraphUserMsgPack = | ||
$"{Application.Base.DisplayName}/{MsGraphUser}{Suffixes.MessagePack.DisplayName}"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
namespace Dgmjr.Graph.Constants; | ||
|
||
using Dgmjr.Mime; | ||
|
||
public static class Uris | ||
{ | ||
public const string Api = "api"; | ||
public const string MsGraph = "msgraph"; | ||
public const string Users = "users"; | ||
public const string MsGraphApi = $"{Api}/{MsGraph}"; | ||
public const string Me = "me"; | ||
public const string Api = "/api"; | ||
public const string MsGraph = "/msgraph"; | ||
public const string Users = "/users"; | ||
public const string MsGraphApi = $"{Api}{MsGraph}"; | ||
public const string Me = "/me"; | ||
public const string DirectoryObjects = "/directoryObjects"; | ||
public const string ExtensionProperties = "extensionProperties"; | ||
} |
37 changes: 37 additions & 0 deletions
37
src/MicrosoftGraph/Controllers/DirectoryObjectsController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* DirectoryObjectsController.cs | ||
* | ||
* Created: 2024-55-16T14:55:21-05:00 | ||
* Modified: 2024-55-16T14:55:21-05:00 | ||
* | ||
* Author: David G. Moore, Jr. <[email protected]> | ||
* | ||
* Copyright © 2024 David G. Moore, Jr., All Rights Reserved | ||
* License: MIT (https://opensource.org/licenses/MIT) | ||
*/ | ||
|
||
namespace Dgmjr.Graph.Controllers; | ||
|
||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
[Route($"{MsGraphApi}{DirectoryObjects}")] | ||
public class DirectoryObjectsController( | ||
ILogger<DirectoryObjectsController> logger, | ||
IServiceProvider services | ||
) : MsGraphController(logger, services) | ||
{ | ||
private IDirectoryObjectsService DirectoryObjectsService => | ||
services.GetRequiredService<IDirectoryObjectsService>(); | ||
|
||
[HttpGet(Uris.ExtensionProperties)] | ||
public async Task<IActionResult> GetExtensionPropertiesAsync() | ||
{ | ||
Logger.PageVisited(Http.Get, Request.Path); | ||
return Ok( | ||
( | ||
await DirectoryObjectsService.GetExtensionPropertiesAsync(default) | ||
).Cast<DGraphExtensionProperty>() | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* MsGraphController.cs | ||
* | ||
* Created: 2024-55-16T14:55:53-05:00 | ||
* Modified: 2024-55-16T14:55:54-05:00 | ||
* | ||
* Author: David G. Moore, Jr. <[email protected]> | ||
* | ||
* Copyright © 2024 David G. Moore, Jr., All Rights Reserved | ||
* License: MIT (https://opensource.org/licenses/MIT) | ||
*/ | ||
|
||
namespace Dgmjr.Graph.Controllers; | ||
|
||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
[Route(MsGraphApi)] | ||
public abstract class MsGraphController(ILogger logger, IServiceProvider services) | ||
: ControllerBase, | ||
IHaveAGraphClient | ||
{ | ||
public ILogger Logger => logger; | ||
public GraphServiceClient Graph => services.GetRequiredService<GraphServiceClient>(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,72 @@ | ||
namespace Dgmjr.Graph.Controllers; | ||
|
||
using Dgmjr.Graph.Abstractions; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Application = Dgmjr.Mime.Application; | ||
using Dgmjr.Abstractions; | ||
|
||
[Route($"{MsGraphApi}/{Users}")] | ||
[AuthorizeForScopes(ScopeKeySection = DownstreamApis_MicrosoftGraph_Scopes)] | ||
public class UsersController(ILogger<UsersController> logger, IServiceProvider services) : ControllerBase, ILog | ||
[Route($"{MsGraphApi}{Users}")] | ||
public class UsersController(ILogger<UsersController> logger, IServiceProvider services) | ||
: MsGraphController(logger, services) | ||
{ | ||
public ILogger Logger => logger; | ||
private readonly IUsersService _users = services.GetRequiredService<IUsersService>(); | ||
|
||
[HttpGet("{userId:guid}")] | ||
[ProducesResponseType(typeof(User), Status200OK)] | ||
[Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] | ||
public async Task<IActionResult> Get([FromRoute] guid userId) | ||
{ | ||
Logger.PageVisited(Http.Get, $"{Users}/{userId}"); | ||
Logger.PageVisited(Http.Get, Request.Path); | ||
return Ok(await _users.GetAsync(userId.ToString())); | ||
} | ||
|
||
[HttpGet("{property}")] | ||
[Produces(Text.Plain.DisplayName, Application.Json.DisplayName, Application.Xml.DisplayName, Application.Bson.DisplayName, Application.MessagePack.DisplayName)] | ||
[Produces( | ||
Text.Plain.DisplayName, | ||
Application.Json.DisplayName, | ||
Application.Xml.DisplayName, | ||
Application.Bson.DisplayName, | ||
Application.MessagePack.DisplayName | ||
)] | ||
[ProducesResponseType(typeof(string), Status200OK)] | ||
[ProducesResponseType(typeof(int), Status200OK)] | ||
[ProducesResponseType(typeof(long), Status200OK)] | ||
public async Task<IActionResult> Get([FromRoute] string property) | ||
{ | ||
Logger.PageVisited(Http.Get, $"{Users}/{property}"); | ||
Logger.PageVisited(Http.Get, Request.Path); | ||
var result = await _users.GetAsync((await _users.GetMyIdAsync()).ToString(), property); | ||
var value = result.AdditionalData[new DGraphExtensionProperty(property).Name]; | ||
return Ok(value); | ||
} | ||
|
||
[HttpPost("{userId}/{property}")] | ||
[Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] | ||
public async Task<IActionResult> Post([FromRoute] guid userId, [FromRoute] string property, [FromQuery] string value) | ||
public async Task<IActionResult> Post( | ||
[FromRoute] guid userId, | ||
[FromRoute] string property, | ||
[FromQuery] string value | ||
) | ||
{ | ||
Logger.PageVisited(Http.Post, $"{Users}/{userId}/{property}"); | ||
Logger.PageVisited(Http.Post, Request.Path); | ||
var user = await _users.UpdateAsync(userId.ToString(), property, value); | ||
return Ok(user); | ||
} | ||
|
||
[HttpGet(Uris.ExtensionProperties)] | ||
[ProducesResponseType(typeof(DGraphExtensionProperty[]), Status200OK)] | ||
[Produces(MsGraphExtensionPropertiesListJson, MsGraphExtensionPropertiesListXml, MsGraphExtensionPropertiesListBson, MsGraphExtensionPropertiesListMsgPack)] | ||
[Produces( | ||
MsGraphExtensionPropertiesListJson, | ||
MsGraphExtensionPropertiesListXml, | ||
MsGraphExtensionPropertiesListBson, | ||
MsGraphExtensionPropertiesListMsgPack | ||
)] | ||
public async Task<IActionResult> GetExtensionProperties() | ||
{ | ||
Logger.PageVisited(Http.Get, $"{Users}/{Uris.ExtensionProperties}"); | ||
return Ok((await _users.GetExtensionPropertiesAsync(default)).Cast<DGraphExtensionProperty>()); | ||
Logger.PageVisited(Http.Get, Request.Path); | ||
return Ok( | ||
(await _users.GetExtensionPropertiesAsync(default)).Cast<DGraphExtensionProperty>() | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,24 @@ | ||
namespace Dgmjr.Graph; | ||
|
||
public static partial class LoggingExtensions | ||
internal static partial class LoggingExtensions | ||
{ | ||
[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "{Method} {Path}", EventName = nameof(PageVisited))] | ||
public static partial void PageVisited(this ILogger logger, System.Net.Http.HttpMethod method, string path); | ||
[LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "{Method} {Path}", EventName = nameof(PageVisited))] | ||
[LoggerMessage( | ||
EventId = 1, | ||
Level = LogLevel.Information, | ||
Message = "{Method} {Path}", | ||
EventName = nameof(PageVisited) | ||
)] | ||
public static partial void PageVisited( | ||
this ILogger logger, | ||
System.Net.Http.HttpMethod method, | ||
string path | ||
); | ||
|
||
[LoggerMessage( | ||
EventId = 1, | ||
Level = LogLevel.Information, | ||
Message = "{Method} {Path}", | ||
EventName = nameof(PageVisited) | ||
)] | ||
public static partial void PageVisited(this ILogger logger, string method, string path); | ||
} |
Oops, something went wrong.