From 3f92a6783e6fc242295b54be4c228a4d0b0d98ba Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 22:52:08 +0000 Subject: [PATCH] style: format code with dotnet-format This commit fixes the style issues introduced in fda3c0b according to the output from dotnet-format. Details: None --- src/AzureAdB2C/Api/ClaimsGeneratorApi.cs | 54 +-- src/AzureAdB2C/Api/ClaimsValidatorApi.cs | 44 +- src/AzureAdB2C/Services/ClaimsGenerator.cs | 10 +- src/AzureAdB2C/Services/ClaimsValidator.cs | 10 +- .../Services/Graph/AppRolesService.cs | 262 +++++------ src/AzureAdB2C/Services/Models/ApiResponse.cs | 12 +- .../JsonApiContinueResponseConverter.cs | 2 +- .../AutoConfiguratorConfiguration.cs | 62 +-- .../HttpServicesExtensions.UseHttpServices.cs | 148 +++---- .../HttpServicesOptionsAutoConfigurator.cs | 30 +- .../Configuration/UserAppRolesConfigurator.cs | 159 +++---- .../Controllers/DirectoryObjectsController.cs | 24 +- .../Controllers/MeController.cs | 86 ++-- .../Controllers/UsersController.cs | 116 ++--- src/MicrosoftGraph/Services/UsersService.cs | 364 ++++++++-------- .../TokenAcquisitionTokenProvider.cs | 72 ++-- src/Mvc/MvcAutoConfigurator.cs | 32 +- src/Mvc/MvcOptions.cs | 407 +++++++++--------- src/Mvc/TypeNameAndAssemblyConfigurator.cs | 68 +-- .../BasicAuthenticationHandler.cs | 4 +- .../BasicAuthenticationHandlerWithUsers.cs | 96 ++--- .../Bootstrap/ActiveAnchorTagHelper.cs | 152 +++---- .../Bootstrap/PageElements/Footer.cs | 82 ++-- 23 files changed, 1150 insertions(+), 1146 deletions(-) diff --git a/src/AzureAdB2C/Api/ClaimsGeneratorApi.cs b/src/AzureAdB2C/Api/ClaimsGeneratorApi.cs index 4f67a89c..1e8eded2 100644 --- a/src/AzureAdB2C/Api/ClaimsGeneratorApi.cs +++ b/src/AzureAdB2C/Api/ClaimsGeneratorApi.cs @@ -14,31 +14,31 @@ public abstract class ClaimsGeneratorApi( IUserHydrator userHydrator ) : ApiControllerBase(logger) { - public virtual IClaimsGenerator ClaimsGenerator => claimsGenerator; - public virtual IUserHydrator UserHydrator => userHydrator; - - [HttpPost] - [Route("api/claims/validate")] - public async Task ValidateAsync( - [FromBody] ApiRequest request, - CancellationToken cancellationToken = default - ) - { - var result = await ClaimsGenerator.GenerateClaimsAsync( - request, - cancellationToken - ); - - return result.StatusCode switch - { - StatusCodes.Status200OK => Ok(result), - StatusCodes.Status400BadRequest => BadRequest(result), - StatusCodes.Status401Unauthorized => Unauthorized(result), - StatusCodes.Status403Forbidden => Forbid((result as ApiBlockResponse)!.UserMessage), - StatusCodes.Status404NotFound => NotFound(result), - StatusCodes.Status409Conflict => Conflict(result), - StatusCodes.Status500InternalServerError => Problem((result as ApiErrorResponse)!.DeveloperMessage, statusCode: result.StatusCode), - _ => StatusCode(result.StatusCode ?? StatusCodes.Status200OK, result), - }; - } + public virtual IClaimsGenerator ClaimsGenerator => claimsGenerator; +public virtual IUserHydrator UserHydrator => userHydrator; + +[HttpPost] +[Route("api/claims/validate")] +public async Task ValidateAsync( + [FromBody] ApiRequest request, + CancellationToken cancellationToken = default +) +{ + var result = await ClaimsGenerator.GenerateClaimsAsync( + request, + cancellationToken + ); + + return result.StatusCode switch + { + StatusCodes.Status200OK => Ok(result), + StatusCodes.Status400BadRequest => BadRequest(result), + StatusCodes.Status401Unauthorized => Unauthorized(result), + StatusCodes.Status403Forbidden => Forbid((result as ApiBlockResponse)!.UserMessage), + StatusCodes.Status404NotFound => NotFound(result), + StatusCodes.Status409Conflict => Conflict(result), + StatusCodes.Status500InternalServerError => Problem((result as ApiErrorResponse)!.DeveloperMessage, statusCode: result.StatusCode), + _ => StatusCode(result.StatusCode ?? StatusCodes.Status200OK, result), + }; +} } diff --git a/src/AzureAdB2C/Api/ClaimsValidatorApi.cs b/src/AzureAdB2C/Api/ClaimsValidatorApi.cs index c549d927..fd7a6db3 100644 --- a/src/AzureAdB2C/Api/ClaimsValidatorApi.cs +++ b/src/AzureAdB2C/Api/ClaimsValidatorApi.cs @@ -14,26 +14,26 @@ public abstract class ClaimsValidatorApi( IClaimsValidator claimsValidator ) : ApiControllerBase(logger) { - public virtual IClaimsValidator ClaimsValidator => claimsValidator; - - [HttpPost] - [Route("api/claims/generate")] - public async Task GenerateAsync( - [FromBody] ApiRequest request, - CancellationToken cancellationToken = default - ) - { - var result = await ClaimsValidator.ValidateAsync(request, cancellationToken); - - if(IsNullOrWhiteSpace(result.ErrorMessage)) - { - var response = new ApiContinueResponse { Version = ClaimsValidator.Version }; - return Ok(response); - } - else - { - var response = new ApiValidationErrorResponse(result.ErrorMessage) { Version = ClaimsValidator.Version }; - return BadRequest(response); - } - } + public virtual IClaimsValidator ClaimsValidator => claimsValidator; + +[HttpPost] +[Route("api/claims/generate")] +public async Task GenerateAsync( + [FromBody] ApiRequest request, + CancellationToken cancellationToken = default +) +{ + var result = await ClaimsValidator.ValidateAsync(request, cancellationToken); + + if (IsNullOrWhiteSpace(result.ErrorMessage)) + { + var response = new ApiContinueResponse { Version = ClaimsValidator.Version }; + return Ok(response); + } + else + { + var response = new ApiValidationErrorResponse(result.ErrorMessage) { Version = ClaimsValidator.Version }; + return BadRequest(response); + } +} } diff --git a/src/AzureAdB2C/Services/ClaimsGenerator.cs b/src/AzureAdB2C/Services/ClaimsGenerator.cs index bc9bcc91..fe4f45df 100644 --- a/src/AzureAdB2C/Services/ClaimsGenerator.cs +++ b/src/AzureAdB2C/Services/ClaimsGenerator.cs @@ -17,9 +17,9 @@ Task GenerateClaimsAsync( public abstract class ClaimsGenerator(IOptions version) : IClaimsGenerator { - public virtual Version Version => version.Value; - public abstract Task GenerateClaimsAsync( - ApiRequest request, - CancellationToken cancellationToken = default - ); + public virtual Version Version => version.Value; +public abstract Task GenerateClaimsAsync( + ApiRequest request, + CancellationToken cancellationToken = default +); } diff --git a/src/AzureAdB2C/Services/ClaimsValidator.cs b/src/AzureAdB2C/Services/ClaimsValidator.cs index 0668532c..63813a98 100644 --- a/src/AzureAdB2C/Services/ClaimsValidator.cs +++ b/src/AzureAdB2C/Services/ClaimsValidator.cs @@ -35,9 +35,9 @@ public virtual ValidationResult Validate(ApiRequest request) public abstract class ClaimsValidator(IOptions options) : IClaimsValidator { - public Version Version => options.Value.Version; - public abstract Task ValidateAsync( - ApiRequest request, - CancellationToken cancellationToken = default - ); + public Version Version => options.Value.Version; +public abstract Task ValidateAsync( + ApiRequest request, + CancellationToken cancellationToken = default +); } diff --git a/src/AzureAdB2C/Services/Graph/AppRolesService.cs b/src/AzureAdB2C/Services/Graph/AppRolesService.cs index ff3d907d..f8a22344 100644 --- a/src/AzureAdB2C/Services/Graph/AppRolesService.cs +++ b/src/AzureAdB2C/Services/Graph/AppRolesService.cs @@ -33,135 +33,135 @@ public class AppRolesService( ILogger logger ) : IClaimsGenerator, IAppRolesService, ILog { - public ILogger Logger => logger; - private readonly Dgmjr.AzureAd.Web.MicrosoftIdentityOptions _msidOptions = - msidOptions.CurrentValue; - public Version Version => version.Value; - - private string clientId => _msidOptions.ClientId; - private string clientSecret => _msidOptions.ClientSecret; - private string tenantId => _msidOptions.TenantId; - - private GraphServiceClient _graph; - private GraphServiceClient Graph => _graph ??= GetGraphServiceClient().Result; - - private readonly AzureAdB2CGraphOptions _graphClientOptions = graphClientOptions.Value; - - public async Task GenerateClaimsAsync( - ApiRequest request, - CancellationToken cancellationToken = default - ) - { - Logger.LogDebug("request: {request}", request); - - var app = await Graph.Applications[ - _graphClientOptions.AzureAdB2CExtensionsApplicationId.ToString() - ] - .Request() - .GetAsync(cancellationToken); - Logger.LogDebug("app: {app}", app); - - var user = await Graph.Users[request.ObjectId.ToString()] - // .Request(new Option[] { new QueryOption("$expand", "appRoleAssignments") }) - .Request() - .Expand("appRoleAssignments") - .GetAsync(cancellationToken); - Logger.LogDebug("user: {user}", user); - - var appRoles = app.AppRoles; - var myAppRoles = user.AppRoleAssignments - .Where(x => x.ResourceId == _graphClientOptions.AzureAdB2CExtensionsApplicationId) - .ToList(); - var myAppsAppRoles = myAppRoles.Select( - appRole => appRoles.FirstOrDefault(x => x.Id.ToString() == appRole.Id) - ); - return new ApiContinueResponse - { - Claims = new StringDictionary() { { ClaimTypes.Role, Serialize(myAppsAppRoles) } }, - Version = Version - }; - } - - - private async Task GetGraphServiceClient() - { - var app = ConfidentialClientApplicationBuilder - .Create(clientId) - .WithClientSecret(clientSecret) - .WithAuthority($"https://login.microsoftonline.com/{tenantId}") - .Build(); - - var authResult = await app.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }) - .ExecuteAsync(); - - var graphClient = new GraphServiceClient( - new DelegateAuthenticationProvider((requestMessage) => - { - requestMessage.Headers.Authorization = - new AuthenticationHeaderValue("Bearer", authResult.AccessToken); - - return Task.CompletedTask; - })); - return graphClient; - } - - - // public static async Task> GetApplicationRolesForUserAsync(string userId) - // { - // var applicationRoles = new List(); - - // var app = ConfidentialClientApplicationBuilder - // .Create(clientId) - // .WithClientSecret(clientSecret) - // .WithAuthority($"https://login.microsoftonline.com/{tenantId}") - // .Build(); - - // var authResult = await app.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }) - // .ExecuteAsync(); - - // var graphClient = new GraphServiceClient( - // new DelegateAuthenticationProvider((requestMessage) => - // { - // requestMessage.Headers.Authorization = - // new AuthenticationHeaderValue("Bearer", authResult.AccessToken); - - // return Task.CompletedTask; - // })); - - // try - // { - // // Query Microsoft Graph to get the user's assigned directory roles - // var userDirectoryRoles = await graphClient.Users[userId].MemberOf.Request().GetAsync(); - - // foreach (var directoryRole in userDirectoryRoles.OfType()) - // { - // // Query each directory role to get its assigned application roles - // var applicationRoleAssignments = await graphClient.DirectoryRoles[directoryRole.Id].AppRoleAssignedTo.Request().GetAsync(); - - // foreach (var applicationRoleAssignment in applicationRoleAssignments) - // { - // applicationRoles.Add(applicationRoleAssignment.AppRoleId); - // } - // } - // } - // catch (ServiceException ex) - // { - // Console.WriteLine($"Error retrieving application roles: {ex.Message}"); - // } - - // return applicationRoles; - // } - - // public static async Task Main(string[] args) - // { - // string userId = "user_id_goes_here"; - // List applicationRoles = await GetApplicationRolesForUserAsync(userId); - - // // Print the application roles for the user - // foreach (var role in applicationRoles) - // { - // Console.WriteLine(role); - // } - // } - // } + public ILogger Logger => logger; +private readonly Dgmjr.AzureAd.Web.MicrosoftIdentityOptions _msidOptions = + msidOptions.CurrentValue; +public Version Version => version.Value; + +private string clientId => _msidOptions.ClientId; +private string clientSecret => _msidOptions.ClientSecret; +private string tenantId => _msidOptions.TenantId; + +private GraphServiceClient _graph; +private GraphServiceClient Graph => _graph ??= GetGraphServiceClient().Result; + +private readonly AzureAdB2CGraphOptions _graphClientOptions = graphClientOptions.Value; + +public async Task GenerateClaimsAsync( + ApiRequest request, + CancellationToken cancellationToken = default +) +{ + Logger.LogDebug("request: {request}", request); + + var app = await Graph.Applications[ + _graphClientOptions.AzureAdB2CExtensionsApplicationId.ToString() + ] + .Request() + .GetAsync(cancellationToken); + Logger.LogDebug("app: {app}", app); + + var user = await Graph.Users[request.ObjectId.ToString()] + // .Request(new Option[] { new QueryOption("$expand", "appRoleAssignments") }) + .Request() + .Expand("appRoleAssignments") + .GetAsync(cancellationToken); + Logger.LogDebug("user: {user}", user); + + var appRoles = app.AppRoles; + var myAppRoles = user.AppRoleAssignments + .Where(x => x.ResourceId == _graphClientOptions.AzureAdB2CExtensionsApplicationId) + .ToList(); + var myAppsAppRoles = myAppRoles.Select( + appRole => appRoles.FirstOrDefault(x => x.Id.ToString() == appRole.Id) + ); + return new ApiContinueResponse + { + Claims = new StringDictionary() { { ClaimTypes.Role, Serialize(myAppsAppRoles) } }, + Version = Version + }; +} + + +private async Task GetGraphServiceClient() +{ + var app = ConfidentialClientApplicationBuilder + .Create(clientId) + .WithClientSecret(clientSecret) + .WithAuthority($"https://login.microsoftonline.com/{tenantId}") + .Build(); + + var authResult = await app.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }) + .ExecuteAsync(); + + var graphClient = new GraphServiceClient( + new DelegateAuthenticationProvider((requestMessage) => + { + requestMessage.Headers.Authorization = + new AuthenticationHeaderValue("Bearer", authResult.AccessToken); + + return Task.CompletedTask; + })); + return graphClient; +} + + +// public static async Task> GetApplicationRolesForUserAsync(string userId) +// { +// var applicationRoles = new List(); + +// var app = ConfidentialClientApplicationBuilder +// .Create(clientId) +// .WithClientSecret(clientSecret) +// .WithAuthority($"https://login.microsoftonline.com/{tenantId}") +// .Build(); + +// var authResult = await app.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }) +// .ExecuteAsync(); + +// var graphClient = new GraphServiceClient( +// new DelegateAuthenticationProvider((requestMessage) => +// { +// requestMessage.Headers.Authorization = +// new AuthenticationHeaderValue("Bearer", authResult.AccessToken); + +// return Task.CompletedTask; +// })); + +// try +// { +// // Query Microsoft Graph to get the user's assigned directory roles +// var userDirectoryRoles = await graphClient.Users[userId].MemberOf.Request().GetAsync(); + +// foreach (var directoryRole in userDirectoryRoles.OfType()) +// { +// // Query each directory role to get its assigned application roles +// var applicationRoleAssignments = await graphClient.DirectoryRoles[directoryRole.Id].AppRoleAssignedTo.Request().GetAsync(); + +// foreach (var applicationRoleAssignment in applicationRoleAssignments) +// { +// applicationRoles.Add(applicationRoleAssignment.AppRoleId); +// } +// } +// } +// catch (ServiceException ex) +// { +// Console.WriteLine($"Error retrieving application roles: {ex.Message}"); +// } + +// return applicationRoles; +// } + +// public static async Task Main(string[] args) +// { +// string userId = "user_id_goes_here"; +// List applicationRoles = await GetApplicationRolesForUserAsync(userId); + +// // Print the application roles for the user +// foreach (var role in applicationRoles) +// { +// Console.WriteLine(role); +// } +// } +// } } diff --git a/src/AzureAdB2C/Services/Models/ApiResponse.cs b/src/AzureAdB2C/Services/Models/ApiResponse.cs index b74971ca..06aff891 100644 --- a/src/AzureAdB2C/Services/Models/ApiResponse.cs +++ b/src/AzureAdB2C/Services/Models/ApiResponse.cs @@ -29,11 +29,11 @@ public class ApiContinueResponse : ApiResponse public abstract class ApiErrorResponse(string userMessage, string? developerMessage = default) : ApiResponse { - public virtual string? UserMessage => userMessage; - public virtual string? DeveloperMessage => developerMessage ?? userMessage; + public virtual string? UserMessage => userMessage; +public virtual string? DeveloperMessage => developerMessage ?? userMessage; } -public class ApiBlockResponse(string userMessage, string? developerMessage = default) +public class ApiBlockResponse(string userMessage, string ? developerMessage = default) : ApiErrorResponse(userMessage, developerMessage) { public override ApiResponseAction Action => ApiResponseAction.ShowBlockPage; @@ -41,11 +41,11 @@ public class ApiBlockResponse(string userMessage, string? developerMessage = def public class ApiValidationErrorResponse( string userMessage, - string? developerMessage = default + string ? developerMessage = default ) : ApiErrorResponse(userMessage, developerMessage) { - public override int? StatusCode => StatusCodes.Status400BadRequest; - public override ApiResponseAction Action => ApiResponseAction.ValidationError; + public override int? StatusCode => StatusCodes.Status400BadRequest; +public override ApiResponseAction Action => ApiResponseAction.ValidationError; } [JsonConverter(typeof(JStringEnumConverter))] diff --git a/src/AzureAdB2C/Services/Models/JsonApiContinueResponseConverter.cs b/src/AzureAdB2C/Services/Models/JsonApiContinueResponseConverter.cs index de948cac..d35f136f 100644 --- a/src/AzureAdB2C/Services/Models/JsonApiContinueResponseConverter.cs +++ b/src/AzureAdB2C/Services/Models/JsonApiContinueResponseConverter.cs @@ -18,7 +18,7 @@ public override void Write(Utf8JsonWriter writer, ApiContinueResponse value, Jso writer.WriteString("version", value.Version.ToString()); writer.WriteString("action", value.Action.ToString()); writer.WriteNumber("status", value.StatusCode ?? StatusCodes.Status200OK); - foreach(var (claimType, claimValue) in value.Claims) + foreach (var (claimType, claimValue) in value.Claims) { writer.WriteString(claimType, claimValue); } diff --git a/src/Configuration/Configuration/AutoConfiguratorConfiguration.cs b/src/Configuration/Configuration/AutoConfiguratorConfiguration.cs index 497548b0..ec36d1e1 100644 --- a/src/Configuration/Configuration/AutoConfiguratorConfiguration.cs +++ b/src/Configuration/Configuration/AutoConfiguratorConfiguration.cs @@ -10,35 +10,35 @@ public class AutoConfiguratorConfiguration : Collection public class AutoConfiguratorConfigurator(IConfiguration configuration) : IConfigureOptions { - public void Configure(AutoConfiguratorConfiguration options) - { - var section = configuration.GetSection(AutoConfiguratorConfiguration.SectionName); - Console.WriteLine(section?.ToJson()); - if (section.Exists()) - { - foreach ( - var configurator in section - .GetChildren() - .Select( - configurator => - configurator.Value.Split( - ",", - StringSplitOptions.RemoveEmptyEntries - | StringSplitOptions.TrimEntries - ) - ) - ) - { - var assembly = Assembly.Load(configurator[1]); - if (assembly != null) - { - var type = assembly.GetType(configurator[0]); - if (type != null) - { - options.Add(type); - } - } - } - } - } + public void Configure(AutoConfiguratorConfiguration options) +{ + var section = configuration.GetSection(AutoConfiguratorConfiguration.SectionName); + Console.WriteLine(section?.ToJson()); + if (section.Exists()) + { + foreach ( + var configurator in section + .GetChildren() + .Select( + configurator => + configurator.Value.Split( + ",", + StringSplitOptions.RemoveEmptyEntries + | StringSplitOptions.TrimEntries + ) + ) + ) + { + var assembly = Assembly.Load(configurator[1]); + if (assembly != null) + { + var type = assembly.GetType(configurator[0]); + if (type != null) + { + options.Add(type); + } + } + } + } +} } diff --git a/src/Http/Services/HttpServicesExtensions.UseHttpServices.cs b/src/Http/Services/HttpServicesExtensions.UseHttpServices.cs index 831015de..ae8fd7ef 100644 --- a/src/Http/Services/HttpServicesExtensions.UseHttpServices.cs +++ b/src/Http/Services/HttpServicesExtensions.UseHttpServices.cs @@ -14,7 +14,7 @@ public static IApplicationBuilder UseHttpServices(this IApplicationBuilder app, { var options = app.ApplicationServices.GetRequiredService>().Value; - if(options.UseRequestDecompression) + if (options.UseRequestDecompression) { logger?.AddingHttpServiceToThePipeline(nameof(RequestDecompression)); app.UseRequestDecompression(); @@ -26,116 +26,116 @@ public static IApplicationBuilder UseHttpServices(this IApplicationBuilder app, app.UseResponseCompression(); } - if(options.UseFileServer) + if (options.UseFileServer) { logger?.AddingHttpServiceToThePipeline(nameof(options.FileServer)); app.UseFileServer(options.FileServer); - if(options.FileServer.EnableDefaultFiles) + if (options.FileServer.EnableDefaultFiles) { app.UseDefaultFiles(options.FileServer.DefaultFilesOptions); } - if(options.FileServer.EnableDirectoryBrowsing) + if (options.FileServer.EnableDirectoryBrowsing) { app.UseDirectoryBrowser(options.FileServer.DirectoryBrowserOptions); } - if(options.FileServer.StaticFileOptions != null || options.UseStaticFiles) + if (options.FileServer.StaticFileOptions != null || options.UseStaticFiles) { app.UseStaticFiles(options.FileServer.StaticFileOptions); } } - if(options.UseResponseCaching) + if (options.UseResponseCaching) { logger?.AddingHttpServiceToThePipeline(nameof(ResponseCaching)); app.UseResponseCaching(); } - if(options.UseForwardedHeaders) + if (options.UseForwardedHeaders) { logger?.AddingHttpServiceToThePipeline(nameof(options.ForwardedHeaders)); app.UseForwardedHeaders(options.ForwardedHeaders); } - if(options.UseCors) + if (options.UseCors) { logger?.AddingHttpServiceToThePipeline(nameof(Cors)); var corsOptions = app.ApplicationServices.GetRequiredService>().Value; app.UseCors(builder => - { - var defaultPolicy = corsOptions.GetPolicy(options.Cors.DefaultPolicyName); - builder.WithExposedHeaders([.. defaultPolicy.ExposedHeaders]) - .WithHeaders([.. defaultPolicy.Headers]) - .WithMethods([.. defaultPolicy.Methods]) - .WithOrigins([.. defaultPolicy.Origins]) - - .SetPreflightMaxAge(defaultPolicy.PreflightMaxAge ?? duration.Zero); - if(defaultPolicy.AllowAnyHeader) - { - builder.AllowAnyHeader(); - } - if(defaultPolicy.AllowAnyMethod) - { - builder.AllowAnyMethod(); - } - if(defaultPolicy.AllowAnyOrigin) - { - builder.AllowAnyOrigin(); - } - }); - // _ = app.UseCors(corsOptions => corsOptions - // .WithExposedHeaders(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).ExposedHeaders.ToArray()) - // .WithHeaders(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).Headers.ToArray()) - // .WithMethods(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).Methods.ToArray()) - // .WithOrigins(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).Origins.ToArray()) - // .SetPreflightMaxAge(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).PreflightMaxAge ?? TimeSpan.Zero) - // ); - } + { + var defaultPolicy = corsOptions.GetPolicy(options.Cors.DefaultPolicyName); + builder.WithExposedHeaders([..defaultPolicy.ExposedHeaders]) + .WithHeaders([..defaultPolicy.Headers]) + .WithMethods([..defaultPolicy.Methods]) + .WithOrigins([..defaultPolicy.Origins]) + + .SetPreflightMaxAge(defaultPolicy.PreflightMaxAge ?? duration.Zero); + if (defaultPolicy.AllowAnyHeader) + { + builder.AllowAnyHeader(); + } + if (defaultPolicy.AllowAnyMethod) + { + builder.AllowAnyMethod(); + } + if (defaultPolicy.AllowAnyOrigin) + { + builder.AllowAnyOrigin(); + } + }); + // _ = app.UseCors(corsOptions => corsOptions + // .WithExposedHeaders(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).ExposedHeaders.ToArray()) + // .WithHeaders(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).Headers.ToArray()) + // .WithMethods(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).Methods.ToArray()) + // .WithOrigins(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).Origins.ToArray()) + // .SetPreflightMaxAge(options.Cors.GetPolicy(options.Cors.DefaultPolicyName).PreflightMaxAge ?? TimeSpan.Zero) + // ); + } if(options.UseCookiePolicy) { - logger?.AddingHttpServiceToThePipeline(Cookies); - app.UseCookiePolicy(options.CookiePolicy); + logger?.AddingHttpServiceToThePipeline(Cookies); + app.UseCookiePolicy(options.CookiePolicy); } if(options.UseSession) { - logger?.AddingHttpServiceToThePipeline(Session); - app.UseSession(options.Session); - } - - if(options.UseHsts) - { - logger?.AddingHttpServiceToThePipeline(Hsts); - app.UseHsts(); - } - - if(options.UseHttpsRedirection) - { - logger?.AddingHttpServiceToThePipeline(nameof(options.UseHttpsRedirection)); - app.UseHttpsRedirection(); - } - - if(options.ExceptionHandling?.UseDeveloperExceptionPage == true) - { - logger?.AddingHttpServiceToThePipeline($"{nameof(options.ExceptionHandling)}:{nameof(options.ExceptionHandling.UseDeveloperExceptionPage)}"); - app.UseDeveloperExceptionPage(); - } - - if(options.UseExceptionHandler) - { - logger?.AddingHttpServiceToThePipeline(nameof(options.ExceptionHandling)); - app.UseExceptionHandler(options.ExceptionHandling); - } - - if(options.UseWelcomePage) - { - logger?.AddingHttpServiceToThePipeline(nameof(options.WelcomePage)); - app.UseWelcomePage(options.WelcomePage); - } - - return app; + logger?.AddingHttpServiceToThePipeline(Session); +app.UseSession(options.Session); + } + +if (options.UseHsts) +{ + logger?.AddingHttpServiceToThePipeline(Hsts); + app.UseHsts(); +} + +if (options.UseHttpsRedirection) +{ + logger?.AddingHttpServiceToThePipeline(nameof(options.UseHttpsRedirection)); + app.UseHttpsRedirection(); +} + +if (options.ExceptionHandling?.UseDeveloperExceptionPage == true) +{ + logger?.AddingHttpServiceToThePipeline($"{nameof(options.ExceptionHandling)}:{nameof(options.ExceptionHandling.UseDeveloperExceptionPage)}"); + app.UseDeveloperExceptionPage(); +} + +if (options.UseExceptionHandler) +{ + logger?.AddingHttpServiceToThePipeline(nameof(options.ExceptionHandling)); + app.UseExceptionHandler(options.ExceptionHandling); +} + +if (options.UseWelcomePage) +{ + logger?.AddingHttpServiceToThePipeline(nameof(options.WelcomePage)); + app.UseWelcomePage(options.WelcomePage); +} + +return app; } } diff --git a/src/Http/Services/HttpServicesOptionsAutoConfigurator.cs b/src/Http/Services/HttpServicesOptionsAutoConfigurator.cs index 1a185db9..1f67a7f1 100644 --- a/src/Http/Services/HttpServicesOptionsAutoConfigurator.cs +++ b/src/Http/Services/HttpServicesOptionsAutoConfigurator.cs @@ -10,19 +10,19 @@ public class HttpServicesOptionsAutoConfigurator(ILogger logger; - - public ConfigurationOrder Order => ConfigurationOrder.VeryEarly; - - public void Configure(WebApplicationBuilder builder) - { - Logger?.HttpServicesOptionsAutoConfiguratorConfigureWebApplicationBuilder(); - builder.AddHttpServices(logger: Logger); - } - - public void Configure(IApplicationBuilder app) - { - Logger?.HttpServicesOptionsAutoConfiguratorConfigureIApplicationBuilder(); - app.UseHttpServices(logger: Logger); - } + public ILogger? Logger => logger; + +public ConfigurationOrder Order => ConfigurationOrder.VeryEarly; + +public void Configure(WebApplicationBuilder builder) +{ + Logger?.HttpServicesOptionsAutoConfiguratorConfigureWebApplicationBuilder(); + builder.AddHttpServices(logger: Logger); +} + +public void Configure(IApplicationBuilder app) +{ + Logger?.HttpServicesOptionsAutoConfiguratorConfigureIApplicationBuilder(); + app.UseHttpServices(logger: Logger); +} } diff --git a/src/MicrosoftGraph/Configuration/UserAppRolesConfigurator.cs b/src/MicrosoftGraph/Configuration/UserAppRolesConfigurator.cs index f482f0b9..cdd4736a 100644 --- a/src/MicrosoftGraph/Configuration/UserAppRolesConfigurator.cs +++ b/src/MicrosoftGraph/Configuration/UserAppRolesConfigurator.cs @@ -13,83 +13,84 @@ namespace Dgmjr.Graph.Configuration; public class UserAppRolesConfigurator(ILogger logger, IHttpContextAccessor httpContextAccessor) : IConfigureOptions, ILog { - public ILogger Logger => logger; - private HttpContext HttpContext => httpContextAccessor.HttpContext!; - private IServiceProvider Services => HttpContext.RequestServices; - - public void Configure(MicrosoftIdentityOptions options) - { - options.Events.OnTokenValidated += OnTokenValidated; - options.Events.OnAuthenticationFailed += OnAuthenticationFailed; - options.Events.OnAuthorizationCodeReceived += OnAuthorizationCodeReceived; - options.Events.OnMessageReceived += OnMessageReceived; - options.Events.OnRedirectToIdentityProvider += OnRedirectToIdentityProvider; - options.Events.OnRemoteFailure += OnRemoteFailure; - } - - private async Task OnRemoteFailure(RemoteFailureContext context) - { - Logger.RemoteFailure(context.Failure); - } - - private async Task OnRedirectToIdentityProvider(RedirectContext context) - { - Logger.RedirectToIdentityProvider(context.ProtocolMessage); - } - - private async Task OnMessageReceived(MessageReceivedContext context) - { - Logger.MessageReceived(context.ProtocolMessage); - } - - private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context) - { - Logger.AuthorizationCodeReceived(context.TokenEndpointResponse); - } - - private async Task OnAuthenticationFailed(AuthenticationFailedContext context) - { - Logger.AuthenticationFailed(context.Exception); - } - - private static async Task OnTokenValidated(TokenValidatedContext context) - { - using var scope = context.HttpContext.RequestServices.CreateScope(); - using var activity = Dgmjr.Graph.Telemetry.Activities.TokenAcquisitionActivitySource.StartActivity( - nameof(OnTokenValidated), - ActivityKind.Client - ); - var logger = scope.ServiceProvider.GetRequiredService>(); - logger.BeginningSupplementaryTokenAcquisitionAndCreation(context.Principal); - activity.AddTag("UserObjectId", context.Principal.GetObjectId()); - activity.AddTag("UserTenantId", context.Principal.GetTenantId()); - - var services = scope.ServiceProvider; - var tokenAcquisition = services.GetRequiredService(); - var graphClientOptions = services.GetRequiredService>().Value; - - var graphClient = new GraphServiceClient( - (Microsoft.Graph.IAuthenticationProvider)(new BaseBearerTokenAuthenticationProvider( - new TokenAcquisitionTokenProvider( - tokenAcquisition, - [MsGraphScopes.Default], - context.Principal - ) - ) as IAuthenticationProvider) - ); - var me = await graphClient.Me.Request().GetAsync(); - var app = await graphClient.Applications[graphClientOptions.AzureAdB2CExtensionsApplicationId.ToString()].Request().GetAsync(); - var appRoles = app.AppRoles; - var myAppRoles = me.AppRoleAssignments.Where(x => x.ResourceId == graphClientOptions.AzureAdB2CExtensionsApplicationId).ToList(); - var claims = new List(); - foreach (var appRole in myAppRoles) - { - var theAppRole = appRoles.FirstOrDefault(x => x.Id.ToString() == appRole.Id); - if(theAppRole != null) - { - claims.Add(new(ClaimTypes.Role, theAppRole.Value)); - } - } - logger.SupplementaryTokenAcquisitionAndCreationComplete(context.Principal); - } + public ILogger Logger => logger; +private HttpContext HttpContext => httpContextAccessor.HttpContext!; +private IServiceProvider Services => HttpContext.RequestServices; + +public void Configure(MicrosoftIdentityOptions options) +{ + options.Events.OnTokenValidated += OnTokenValidated; + options.Events.OnAuthenticationFailed += OnAuthenticationFailed; + options.Events.OnAuthorizationCodeReceived += OnAuthorizationCodeReceived; + options.Events.OnMessageReceived += OnMessageReceived; + options.Events.OnRedirectToIdentityProvider += OnRedirectToIdentityProvider; + options.Events.OnRemoteFailure += OnRemoteFailure; +} + +private async Task OnRemoteFailure(RemoteFailureContext context) +{ + Logger.RemoteFailure(context.Failure); +} + +private async Task OnRedirectToIdentityProvider(RedirectContext context) +{ + Logger.RedirectToIdentityProvider(context.ProtocolMessage); +} + +private async Task OnMessageReceived(MessageReceivedContext context) +{ + Logger.MessageReceived(context.ProtocolMessage); +} + +private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context) +{ + Logger.AuthorizationCodeReceived(context.TokenEndpointResponse); +} + +private async Task OnAuthenticationFailed(AuthenticationFailedContext context) +{ + Logger.AuthenticationFailed(context.Exception); +} + +private static async Task OnTokenValidated(TokenValidatedContext context) +{ + using var scope = context.HttpContext.RequestServices.CreateScope(); + using var activity = Dgmjr.Graph.Telemetry.Activities.TokenAcquisitionActivitySource.StartActivity( + nameof(OnTokenValidated), + ActivityKind.Client + ); + var logger = scope.ServiceProvider.GetRequiredService>(); + logger.BeginningSupplementaryTokenAcquisitionAndCreation(context.Principal); + activity.AddTag("UserObjectId", context.Principal.GetObjectId()); + activity.AddTag("UserTenantId", context.Principal.GetTenantId()); + + var services = scope.ServiceProvider; + var tokenAcquisition = services.GetRequiredService(); + var graphClientOptions = services.GetRequiredService>().Value; + + var graphClient = new GraphServiceClient( + (Microsoft.Graph.IAuthenticationProvider)(new BaseBearerTokenAuthenticationProvider( + new TokenAcquisitionTokenProvider( + tokenAcquisition, + + [MsGraphScopes.Default], + context.Principal + ) + ) as IAuthenticationProvider) + ); + var me = await graphClient.Me.Request().GetAsync(); + var app = await graphClient.Applications[graphClientOptions.AzureAdB2CExtensionsApplicationId.ToString()].Request().GetAsync(); + var appRoles = app.AppRoles; + var myAppRoles = me.AppRoleAssignments.Where(x => x.ResourceId == graphClientOptions.AzureAdB2CExtensionsApplicationId).ToList(); + var claims = new List(); + foreach (var appRole in myAppRoles) + { + var theAppRole = appRoles.FirstOrDefault(x => x.Id.ToString() == appRole.Id); + if (theAppRole != null) + { + claims.Add(new(ClaimTypes.Role, theAppRole.Value)); + } + } + logger.SupplementaryTokenAcquisitionAndCreationComplete(context.Principal); +} } diff --git a/src/MicrosoftGraph/Controllers/DirectoryObjectsController.cs b/src/MicrosoftGraph/Controllers/DirectoryObjectsController.cs index 68622dee..9c1e6a45 100644 --- a/src/MicrosoftGraph/Controllers/DirectoryObjectsController.cs +++ b/src/MicrosoftGraph/Controllers/DirectoryObjectsController.cs @@ -23,16 +23,16 @@ IServiceProvider services ) : MsGraphController(logger, services) { private IDirectoryObjectsService DirectoryObjectsService => - services.GetRequiredService(); - - [HttpGet(Uris.ExtensionProperties)] - public async Task GetExtensionPropertiesAsync() - { - Logger.Get(Request.Path); - return Ok( - ( - await DirectoryObjectsService.GetExtensionPropertiesAsync(default) - ).Cast() - ); - } + services.GetRequiredService(); + +[HttpGet(Uris.ExtensionProperties)] +public async Task GetExtensionPropertiesAsync() +{ + Logger.Get(Request.Path); + return Ok( + ( + await DirectoryObjectsService.GetExtensionPropertiesAsync(default) + ).Cast() + ); +} } diff --git a/src/MicrosoftGraph/Controllers/MeController.cs b/src/MicrosoftGraph/Controllers/MeController.cs index 5f3bb052..5a557acf 100644 --- a/src/MicrosoftGraph/Controllers/MeController.cs +++ b/src/MicrosoftGraph/Controllers/MeController.cs @@ -13,47 +13,47 @@ namespace Dgmjr.Graph.Controllers; [Route($"{MsGraphApi}{Me}")] public class MeController(ILogger logger, IServiceProvider services) : MsGraphController(logger, services) { - private readonly IUsersService _users = services.GetRequiredService(); - - [HttpGet] - [ProducesResponseType(typeof(User), Status200OK)] - [Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] - public async Task Get() - { - Logger.Get(Me); - return Ok(await _users.GetMeAsync()); - } - - [HttpGet("{property}")] - [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 Get([FromRoute] string property) - { - Logger.Get(Request.Path); - var propertyFullName = new DGraphExtensionProperty(property).Name; - var result = await Graph.Me.Request().Select(u => u.AdditionalData[propertyFullName]).GetAsync(); - var value = result.AdditionalData[new DGraphExtensionProperty(property).Name]; - return Ok(value); - } - - [HttpPost("{property}")] - [Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] - public async Task Post([FromRoute] string property, [FromQuery] string value) - { - Logger.Post(Request.Path); - var me = await Graph.Me.Request().GetAsync(); - me.AdditionalData[property] = value; - return Ok(await Graph.Me.Request().UpdateAsync(me)); - } - - [HttpGet(Uris.ExtensionProperties)] - [ProducesResponseType(typeof(DGraphExtensionProperty[]), Status200OK)] - [Produces(MsGraphExtensionPropertiesListJson, MsGraphExtensionPropertiesListXml, MsGraphExtensionPropertiesListBson, MsGraphExtensionPropertiesListMsgPack)] - public async Task GetExtensionProperties() - { - Logger.Get($"{Me}/{Uris.ExtensionProperties}"); - return Ok((await _users.GetExtensionPropertiesAsync(default)).Cast()); - } + private readonly IUsersService _users = services.GetRequiredService(); + +[HttpGet] +[ProducesResponseType(typeof(User), Status200OK)] +[Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] +public async Task Get() +{ + Logger.Get(Me); + return Ok(await _users.GetMeAsync()); +} + +[HttpGet("{property}")] +[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 Get([FromRoute] string property) +{ + Logger.Get(Request.Path); + var propertyFullName = new DGraphExtensionProperty(property).Name; + var result = await Graph.Me.Request().Select(u => u.AdditionalData[propertyFullName]).GetAsync(); + var value = result.AdditionalData[new DGraphExtensionProperty(property).Name]; + return Ok(value); +} + +[HttpPost("{property}")] +[Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] +public async Task Post([FromRoute] string property, [FromQuery] string value) +{ + Logger.Post(Request.Path); + var me = await Graph.Me.Request().GetAsync(); + me.AdditionalData[property] = value; + return Ok(await Graph.Me.Request().UpdateAsync(me)); +} + +[HttpGet(Uris.ExtensionProperties)] +[ProducesResponseType(typeof(DGraphExtensionProperty[]), Status200OK)] +[Produces(MsGraphExtensionPropertiesListJson, MsGraphExtensionPropertiesListXml, MsGraphExtensionPropertiesListBson, MsGraphExtensionPropertiesListMsgPack)] +public async Task GetExtensionProperties() +{ + Logger.Get($"{Me}/{Uris.ExtensionProperties}"); + return Ok((await _users.GetExtensionPropertiesAsync(default)).Cast()); +} } diff --git a/src/MicrosoftGraph/Controllers/UsersController.cs b/src/MicrosoftGraph/Controllers/UsersController.cs index e5b351cd..d84262e6 100644 --- a/src/MicrosoftGraph/Controllers/UsersController.cs +++ b/src/MicrosoftGraph/Controllers/UsersController.cs @@ -12,62 +12,62 @@ namespace Dgmjr.Graph.Controllers; public class UsersController(ILogger logger, IServiceProvider services) : MsGraphController(logger, services) { - private readonly IUsersService _users = services.GetRequiredService(); - - [HttpGet("{userId:guid}")] - [ProducesResponseType(typeof(User), Status200OK)] - [Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] - public async Task Get([FromRoute] guid userId) - { - Logger.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 - )] - [ProducesResponseType(typeof(string), Status200OK)] - [ProducesResponseType(typeof(int), Status200OK)] - [ProducesResponseType(typeof(long), Status200OK)] - public async Task Get([FromRoute] string property) - { - Logger.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 Post( - [FromRoute] guid userId, - [FromRoute] string property, - [FromQuery] string value - ) - { - Logger.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 - )] - public async Task GetExtensionProperties() - { - Logger.Get(Request.Path); - return Ok( - (await _users.GetExtensionPropertiesAsync(default)).Cast() - ); - } + private readonly IUsersService _users = services.GetRequiredService(); + +[HttpGet("{userId:guid}")] +[ProducesResponseType(typeof(User), Status200OK)] +[Produces(MsGraphUserJson, MsGraphUserXml, MsGraphUserBson, MsGraphUserMsgPack)] +public async Task Get([FromRoute] guid userId) +{ + Logger.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 +)] +[ProducesResponseType(typeof(string), Status200OK)] +[ProducesResponseType(typeof(int), Status200OK)] +[ProducesResponseType(typeof(long), Status200OK)] +public async Task Get([FromRoute] string property) +{ + Logger.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 Post( + [FromRoute] guid userId, + [FromRoute] string property, + [FromQuery] string value +) +{ + Logger.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 +)] +public async Task GetExtensionProperties() +{ + Logger.Get(Request.Path); + return Ok( + (await _users.GetExtensionPropertiesAsync(default)).Cast() + ); +} } diff --git a/src/MicrosoftGraph/Services/UsersService.cs b/src/MicrosoftGraph/Services/UsersService.cs index a05cbfd9..737a1ba2 100644 --- a/src/MicrosoftGraph/Services/UsersService.cs +++ b/src/MicrosoftGraph/Services/UsersService.cs @@ -3,186 +3,186 @@ namespace Dgmjr.Graph.Services; public class UsersService(GraphServiceClient graph, ILogger logger, IOptionsMonitor options, IOptionsMonitor msidOptions, IDistributedCache cache) : MsGraphService(graph, logger, options, msidOptions, cache), IUsersService { - public async Task GetMeAsync(CancellationToken cancellationToken = default) - { - return await Graph.Me.Request().GetAsync(cancellationToken); - } - public async Task GetMyIdAsync(CancellationToken cancellationToken = default) - { - return new ((await GetMeAsync(cancellationToken)).Id); - } - - public async Task UpdateAsync(User user, CancellationToken cancellationToken = default) - { - return await Graph.Users[user.Id].Request().UpdateAsync(user, cancellationToken); - } - - public async Task UpdateAsync(guid id, string property, string value, CancellationToken cancellationToken = default) - => await UpdateAsync(id.ToString(), property, value, cancellationToken); - - public async Task UpdateAsync(string id, string property, string value, CancellationToken cancellationToken = default) - { - var user = await Graph.Users[id].Request().GetAsync(cancellationToken); - user.AdditionalData[property] = value; - return await Graph.Users[id].Request().UpdateAsync(user, cancellationToken); - } - - public async Task GetAsync(string id, CancellationToken cancellationToken = default) - { - return await Graph.Users[id].Request().GetAsync(cancellationToken); - } - - public async Task GetAsync(string id, string property, CancellationToken cancellationToken = default) - { - var extensionPropertyName = (property, ExtensionsAppClientId).GetExtensionPropertyName(); - return await Graph.Users[id].Request().Select(property).Select(extensionPropertyName).GetAsync(cancellationToken); - } - - public async Task CreateAsync(User user, CancellationToken cancellationToken = default) - { - return await Graph.Users.Request().AddAsync(user, cancellationToken); - } - - public async Task DeleteAsync(string id, CancellationToken cancellationToken = default) - { - await Graph.Users[id].Request().DeleteAsync(cancellationToken); - } - - public async Task IsInAppRoleAsync(string id, string appId, string appRoleId, CancellationToken cancellationToken = default) - => (await Graph.Users[id].Request().GetAsync(cancellationToken)).AppRoleAssignments.Any(a => a.AppRoleId == new guid(appRoleId) && a.ResourceId == new guid(appId)); - - public async Task AssignToAppRoleAsync(string userId, string appId, string appRoleId, CancellationToken cancellationToken = default) - => await AssignToAppRoleAsync(new guid(userId), new guid(appId), new guid(appRoleId), cancellationToken); - - public async Task AssignToAppRoleAsync(guid userId, guid appId, guid appRoleId, CancellationToken cancellationToken = default) - { - return await Graph.Users[userId.ToString()].AppRoleAssignments.Request().AddAsync(new AppRoleAssignment - { - PrincipalId = userId, - ResourceId = appId, - AppRoleId = appRoleId - }, cancellationToken); - } - - public async Task UnassignAppRoleAsync(string userId, string appId, string appRoleId, CancellationToken cancellationToken = default) - => await UnassignAppRoleAsync(new guid(userId), new(appId), new(appRoleId), cancellationToken); - - public async Task UnassignAppRoleAsync(guid userId, guid appId, guid appRoleId, CancellationToken cancellationToken = default) - { - var assignments = await Graph.Users[userId.ToString()].AppRoleAssignments.Request().GetAsync(cancellationToken); - var assignment = assignments.FirstOrDefault(a => a.AppRoleId == appRoleId && a.ResourceId == appId) ?? throw new KeyNotFoundException($"No app role assignment found for user {userId} with app {appId} and role {appRoleId}"); - await Graph.Users[userId.ToString()].AppRoleAssignments[assignment.Id].Request().DeleteAsync(cancellationToken); - } - - public async Task FindByEmailAsync( - string normalizedEmail, - CancellationToken cancellationToken = default - ) - { - return ( - await Graph.Users - .Request() - .Filter($"mail eq '{normalizedEmail}'") - .GetAsync(cancellationToken) - ).FirstOrDefault(); - } - - public async Task FindBySignInNameAsync(string name, CancellationToken cancellationToken = default) - { - try - { - // Get user by sign-in name - var result = (await Graph.Users - .Request() - .Filter($"identities/any(c:c/issuerAssignedId eq '{name}')") - .Select(e => new - { - e.DisplayName, - e.Id, - e.Identities - }) - .GetAsync(cancellationToken)) - .SingleOrDefault(); - - if (result != null) - { - Logger.LogInformation(Serialize(result)); - return result; - } - - Logger.LogError($"User with login name {name} not found."); - return null; - } - catch (Exception ex) - { - Logger.LogError(ex, "Error retrieving user by sign-in name."); - } - - return null; - } - - public async Task SetPasswordByUserId(string userId, string password, bool forceChangePasswordNextSignIn = false, CancellationToken cancellationToken = default) - { - Logger.LogInformation($"Looking for user with object ID '{userId}'..."); - - var user = new User - { - PasswordPolicies = "DisablePasswordExpiration,DisableStrongPassword", - PasswordProfile = new PasswordProfile - { - ForceChangePasswordNextSignIn = forceChangePasswordNextSignIn, - Password = password, - } - }; - - try - { - // Update user by object ID - await Graph.Users[userId] - .Request() - .UpdateAsync(user, cancellationToken); - - Logger.LogInformation($"User with object ID '{userId}' successfully updated."); - } - catch (ClientException ex) - { - Logger.LogError(ex, $"Error updating user with object ID '{userId}'."); - throw; - } - } - - public async Task> GetUsersWithCustomAttribute(GraphServiceClient graphClient, string attributeName, CancellationToken cancellationToken = default) - { - var extensionAttribute = new DGraphExtensionProperty(attributeName, ExtensionsAppClientId); - - Logger.LogInformation($"Getting list of users with the custom attributes '{attributeName}' (string)"); - - // Get all users (one page) - var result = await graphClient.Users - .Request() - .Select($"id,displayName,identities,{extensionAttribute}") - .GetAsync(cancellationToken); - - return [.. result]; - } - - // public async Task RemoveAppRoleByNameAsync(string userId, string appId, string appRoleName, CancellationToken cancellationToken = default) - // => await RemoveAppRoleByNameAsync(new guid(userId), new (appId), appRoleName); - - // public async Task RemoveAppRoleByNameAsync(guid userId, guid appId, string appRoleName, CancellationToken cancellationToken = default) - // { - // var assignments = await Graph.Users[userId.ToString()].AppRoleAssignments.Request().GetAsync(); - // graph..AppRoles.Request().Filter($"displayName eq '{appRoleName}'").GetAsync(); - // var assignment = assignments.FirstOrDefault(a => a..AppRoleId == appRoleId && a.ResourceId == appId); - // if (assignment is null) - // { - // throw new KeyNotFoundException($"No app role assignment found for user {userId} with app {appId} and role {appRoleId}"); - // } - // await Graph.Users[userId.ToString()].AppRoleAssignments[assignment.Id].Request().DeleteAsync(); - // } - - // public async Task GetAsync(string id, string property, string value, CancellationToken cancellationToken = default) - // { - // return await Graph.Users[id].Request().Filter($"{property} eq '{value}'").GetAsync(); - // } + public async Task GetMeAsync(CancellationToken cancellationToken = default) +{ + return await Graph.Me.Request().GetAsync(cancellationToken); +} +public async Task GetMyIdAsync(CancellationToken cancellationToken = default) +{ + return new((await GetMeAsync(cancellationToken)).Id); +} + +public async Task UpdateAsync(User user, CancellationToken cancellationToken = default) +{ + return await Graph.Users[user.Id].Request().UpdateAsync(user, cancellationToken); +} + +public async Task UpdateAsync(guid id, string property, string value, CancellationToken cancellationToken = default) + => await UpdateAsync(id.ToString(), property, value, cancellationToken); + +public async Task UpdateAsync(string id, string property, string value, CancellationToken cancellationToken = default) +{ + var user = await Graph.Users[id].Request().GetAsync(cancellationToken); + user.AdditionalData[property] = value; + return await Graph.Users[id].Request().UpdateAsync(user, cancellationToken); +} + +public async Task GetAsync(string id, CancellationToken cancellationToken = default) +{ + return await Graph.Users[id].Request().GetAsync(cancellationToken); +} + +public async Task GetAsync(string id, string property, CancellationToken cancellationToken = default) +{ + var extensionPropertyName = (property, ExtensionsAppClientId).GetExtensionPropertyName(); + return await Graph.Users[id].Request().Select(property).Select(extensionPropertyName).GetAsync(cancellationToken); +} + +public async Task CreateAsync(User user, CancellationToken cancellationToken = default) +{ + return await Graph.Users.Request().AddAsync(user, cancellationToken); +} + +public async Task DeleteAsync(string id, CancellationToken cancellationToken = default) +{ + await Graph.Users[id].Request().DeleteAsync(cancellationToken); +} + +public async Task IsInAppRoleAsync(string id, string appId, string appRoleId, CancellationToken cancellationToken = default) + => (await Graph.Users[id].Request().GetAsync(cancellationToken)).AppRoleAssignments.Any(a => a.AppRoleId == new guid(appRoleId) && a.ResourceId == new guid(appId)); + +public async Task AssignToAppRoleAsync(string userId, string appId, string appRoleId, CancellationToken cancellationToken = default) + => await AssignToAppRoleAsync(new guid(userId), new guid(appId), new guid(appRoleId), cancellationToken); + +public async Task AssignToAppRoleAsync(guid userId, guid appId, guid appRoleId, CancellationToken cancellationToken = default) +{ + return await Graph.Users[userId.ToString()].AppRoleAssignments.Request().AddAsync(new AppRoleAssignment + { + PrincipalId = userId, + ResourceId = appId, + AppRoleId = appRoleId + }, cancellationToken); +} + +public async Task UnassignAppRoleAsync(string userId, string appId, string appRoleId, CancellationToken cancellationToken = default) + => await UnassignAppRoleAsync(new guid(userId), new(appId), new(appRoleId), cancellationToken); + +public async Task UnassignAppRoleAsync(guid userId, guid appId, guid appRoleId, CancellationToken cancellationToken = default) +{ + var assignments = await Graph.Users[userId.ToString()].AppRoleAssignments.Request().GetAsync(cancellationToken); + var assignment = assignments.FirstOrDefault(a => a.AppRoleId == appRoleId && a.ResourceId == appId) ?? throw new KeyNotFoundException($"No app role assignment found for user {userId} with app {appId} and role {appRoleId}"); + await Graph.Users[userId.ToString()].AppRoleAssignments[assignment.Id].Request().DeleteAsync(cancellationToken); +} + +public async Task FindByEmailAsync( + string normalizedEmail, + CancellationToken cancellationToken = default +) +{ + return ( + await Graph.Users + .Request() + .Filter($"mail eq '{normalizedEmail}'") + .GetAsync(cancellationToken) + ).FirstOrDefault(); +} + +public async Task FindBySignInNameAsync(string name, CancellationToken cancellationToken = default) +{ + try + { + // Get user by sign-in name + var result = (await Graph.Users + .Request() + .Filter($"identities/any(c:c/issuerAssignedId eq '{name}')") + .Select(e => new + { + e.DisplayName, + e.Id, + e.Identities + }) + .GetAsync(cancellationToken)) + .SingleOrDefault(); + + if (result != null) + { + Logger.LogInformation(Serialize(result)); + return result; + } + + Logger.LogError($"User with login name {name} not found."); + return null; + } + catch (Exception ex) + { + Logger.LogError(ex, "Error retrieving user by sign-in name."); + } + + return null; +} + +public async Task SetPasswordByUserId(string userId, string password, bool forceChangePasswordNextSignIn = false, CancellationToken cancellationToken = default) +{ + Logger.LogInformation($"Looking for user with object ID '{userId}'..."); + + var user = new User + { + PasswordPolicies = "DisablePasswordExpiration,DisableStrongPassword", + PasswordProfile = new PasswordProfile + { + ForceChangePasswordNextSignIn = forceChangePasswordNextSignIn, + Password = password, + } + }; + + try + { + // Update user by object ID + await Graph.Users[userId] + .Request() + .UpdateAsync(user, cancellationToken); + + Logger.LogInformation($"User with object ID '{userId}' successfully updated."); + } + catch (ClientException ex) + { + Logger.LogError(ex, $"Error updating user with object ID '{userId}'."); + throw; + } +} + +public async Task> GetUsersWithCustomAttribute(GraphServiceClient graphClient, string attributeName, CancellationToken cancellationToken = default) +{ + var extensionAttribute = new DGraphExtensionProperty(attributeName, ExtensionsAppClientId); + + Logger.LogInformation($"Getting list of users with the custom attributes '{attributeName}' (string)"); + + // Get all users (one page) + var result = await graphClient.Users + .Request() + .Select($"id,displayName,identities,{extensionAttribute}") + .GetAsync(cancellationToken); + + return [..result]; +} + +// public async Task RemoveAppRoleByNameAsync(string userId, string appId, string appRoleName, CancellationToken cancellationToken = default) +// => await RemoveAppRoleByNameAsync(new guid(userId), new (appId), appRoleName); + +// public async Task RemoveAppRoleByNameAsync(guid userId, guid appId, string appRoleName, CancellationToken cancellationToken = default) +// { +// var assignments = await Graph.Users[userId.ToString()].AppRoleAssignments.Request().GetAsync(); +// graph..AppRoles.Request().Filter($"displayName eq '{appRoleName}'").GetAsync(); +// var assignment = assignments.FirstOrDefault(a => a..AppRoleId == appRoleId && a.ResourceId == appId); +// if (assignment is null) +// { +// throw new KeyNotFoundException($"No app role assignment found for user {userId} with app {appId} and role {appRoleId}"); +// } +// await Graph.Users[userId.ToString()].AppRoleAssignments[assignment.Id].Request().DeleteAsync(); +// } + +// public async Task GetAsync(string id, string property, string value, CancellationToken cancellationToken = default) +// { +// return await Graph.Users[id].Request().Filter($"{property} eq '{value}'").GetAsync(); +// } } diff --git a/src/MicrosoftGraph/TokenProviders/TokenAcquisitionTokenProvider.cs b/src/MicrosoftGraph/TokenProviders/TokenAcquisitionTokenProvider.cs index 97a2bc7d..f505aa62 100644 --- a/src/MicrosoftGraph/TokenProviders/TokenAcquisitionTokenProvider.cs +++ b/src/MicrosoftGraph/TokenProviders/TokenAcquisitionTokenProvider.cs @@ -33,40 +33,40 @@ public class TokenAcquisitionTokenProvider( "dod-graph.microsoft.us", "graph.microsoft.de", "microsoftgraph.chinacloudapi.cn", - }; - private readonly ClaimsPrincipal _user = - user ?? throw new SecurityException("User claims principal is required."); - - /// - /// Gets the allowed host validator. - /// - public AllowedHostsValidator AllowedHostsValidator => new(validHosts); - - /// - /// Gets an access token for the user. - /// - /// The API URI of the request that the token will be added to. - /// Additional name value pairs to add to the token request. - /// The cancellation token. - /// The access token. - /// Thrown if the URI is not HTTPS. - public async Task GetAuthorizationTokenAsync( - Uri uri, - Dictionary? additionalAuthenticationContext = null, - CancellationToken cancellationToken = default - ) - { - if (!AllowedHostsValidator.IsUrlHostValid(uri)) - { - return string.Empty; - } - - if (uri.Scheme != "https") - { - throw new ArgumentOutOfRangeException(nameof(uri), "URL must use https."); - } - - return await tokenAcquisition.GetAccessTokenForUserAsync(scopes, user: _user); - } - } + }; + private readonly ClaimsPrincipal _user = + user ?? throw new SecurityException("User claims principal is required."); + + /// + /// Gets the allowed host validator. + /// + public AllowedHostsValidator AllowedHostsValidator => new(validHosts); + + /// + /// Gets an access token for the user. + /// + /// The API URI of the request that the token will be added to. + /// Additional name value pairs to add to the token request. + /// The cancellation token. + /// The access token. + /// Thrown if the URI is not HTTPS. + public async Task GetAuthorizationTokenAsync( + Uri uri, + Dictionary? additionalAuthenticationContext = null, + CancellationToken cancellationToken = default + ) + { + if (!AllowedHostsValidator.IsUrlHostValid(uri)) + { + return string.Empty; + } + + if (uri.Scheme != "https") + { + throw new ArgumentOutOfRangeException(nameof(uri), "URL must use https."); + } + + return await tokenAcquisition.GetAccessTokenForUserAsync(scopes, user: _user); + } +} } diff --git a/src/Mvc/MvcAutoConfigurator.cs b/src/Mvc/MvcAutoConfigurator.cs index 8da0f229..bd4bb1cd 100644 --- a/src/Mvc/MvcAutoConfigurator.cs +++ b/src/Mvc/MvcAutoConfigurator.cs @@ -8,20 +8,20 @@ namespace Microsoft.Extensions.DependencyInjection; public class MvcAutoConfigurator(ILogger logger) : IConfigureIHostApplicationBuilder, IConfigureIApplicationBuilder, ILog { - public ILogger? Logger => logger; - private const string Mvc = nameof(Mvc); - private const string JsonSerializer = nameof(JsonSerializer); - public ConfigurationOrder Order => ConfigurationOrder.Late; - - public void Configure(WebApplicationBuilder builder) - { - Logger?.MvcAutoConfiguratorConfigureWebApplicationBuilder(); - builder.AddMvc(Mvc, Logger); - } - - public void Configure(IApplicationBuilder builder) - { - Logger.MvcAutoConfiguratorConfigureIApplicationBuilder(); - builder.UseMvc(Mvc, Logger); - } + public ILogger? Logger => logger; +private const string Mvc = nameof(Mvc); +private const string JsonSerializer = nameof(JsonSerializer); +public ConfigurationOrder Order => ConfigurationOrder.Late; + +public void Configure(WebApplicationBuilder builder) +{ + Logger?.MvcAutoConfiguratorConfigureWebApplicationBuilder(); + builder.AddMvc(Mvc, Logger); +} + +public void Configure(IApplicationBuilder builder) +{ + Logger.MvcAutoConfiguratorConfigureIApplicationBuilder(); + builder.UseMvc(Mvc, Logger); +} } diff --git a/src/Mvc/MvcOptions.cs b/src/Mvc/MvcOptions.cs index 3441f46c..44dcd35a 100644 --- a/src/Mvc/MvcOptions.cs +++ b/src/Mvc/MvcOptions.cs @@ -21,207 +21,208 @@ public MvcOptions() AllowEmptyInputInBodyModelBinding = false, RespectBrowserAcceptHeader = true } - ) { } - - /// if you want to add controllers with views, otherwise - public virtual bool AddControllersWithViews { get; set; } = false; - public virtual bool AddControllersAsServices { get; set; } = false; - - /// if you want to add controllers with views, otherwise - public virtual bool AddRazorPages { get; set; } = false; - - /// if you want to add controllers with views, otherwise - /// public virtual bool AddControllersAsServices { get; set; } = false; - - /// if you want to add the Microsoft Identity UI, otherwise - public virtual bool AddMicrosoftIdentityUI { get; set; } = false; - - /// if you want to add JSON serializer otherwise - public virtual bool AddJsonOptions { get; set; } = false; - - /// if you want to add XML serializer formatters, otherwise - public virtual bool AddXmlSerializerFormatters { get; set; } = false; - - /// if you want to add XML data contract serializer formatters, otherwise - public virtual bool AddXmlDataContractSerializerFormatters { get; set; } = false; - - /// if you want to add the DGMJR MVC conventions, otherwise - public virtual bool AddMvcConventions { get; set; } = false; - - /// if you want to add controllers, otherwise - public virtual bool AddControllers { get; set; } = false; - - /// - public virtual bool AllowEmptyInputInBodyModelBinding { get; set; } = - mvc.AllowEmptyInputInBodyModelBinding; - - /// - public virtual bool EnableActionInvokers { get; set; } = mvc.EnableActionInvokers; - - /// - public virtual bool EnableEndpointRouting { get; set; } = mvc.EnableEndpointRouting; - - /// - public virtual bool RespectBrowserAcceptHeader { get; set; } = mvc.RespectBrowserAcceptHeader; - - /// - public virtual bool RequireHttpsPermanent { get; set; } = mvc.RequireHttpsPermanent; - - /// - public virtual bool SuppressAsyncSuffixInActionNames { get; set; } = - mvc.SuppressAsyncSuffixInActionNames; - - /// - public virtual bool SuppressInputFormatterBuffering { get; set; } = - mvc.SuppressInputFormatterBuffering; - - /// - public virtual bool SuppressOutputFormatterBuffering { get; set; } = - mvc.SuppressOutputFormatterBuffering; - - /// - public virtual bool ValidateComplexTypesIfChildValidationFails { get; set; } = - mvc.ValidateComplexTypesIfChildValidationFails; - - /// - public virtual bool SuppressImplicitRequiredAttributeForNonNullableReferenceTypes { get; set; } = - mvc.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes; - - /// - public virtual bool ReturnHttpNotAcceptable { get; set; } = mvc.ReturnHttpNotAcceptable; - - /// - public virtual IDictionary CacheProfiles { get; set; } = - mvc.CacheProfiles; - - /// - public virtual IList Conventions { get; set; } = mvc.Conventions; - - /// - public virtual FilterCollection Filters { get; set; } = mvc.Filters; - - /// - public virtual FormatterMappings FormatterMappings { get; set; } = mvc.FormatterMappings; - - /// - public virtual FormatterCollection InputFormatters { get; set; } = - mvc.InputFormatters; - - /// - public virtual int MaxModelValidationErrors { get; set; } = mvc.MaxModelValidationErrors; - - /// - public virtual IList ModelBinderProviders { get; set; } = - mvc.ModelBinderProviders; - - /// - public virtual DefaultModelBindingMessageProvider ModelBindingMessageProvider { get; set; } = - mvc.ModelBindingMessageProvider; - - /// - public virtual IList ModelMetadataDetailsProviders { get; set; } = - mvc.ModelMetadataDetailsProviders; - - /// - public virtual IList ModelValidatorProviders { get; set; } = - mvc.ModelValidatorProviders; - - /// - public virtual FormatterCollection OutputFormatters { get; set; } = - mvc.OutputFormatters; - - /// - public virtual IList ValueProviderFactories { get; set; } = - mvc.ValueProviderFactories; - - /// - public virtual int? SslPort { get; set; } = mvc.SslPort; - - /// - public virtual int? MaxValidationDepth { get; set; } = mvc.MaxValidationDepth; - - /// - public virtual int MaxModelBindingCollectionSize { get; set; } = - mvc.MaxModelBindingCollectionSize; - - /// - public virtual int MaxModelBindingRecursionDepth { get; set; } = - mvc.MaxModelBindingRecursionDepth; - - /// - public virtual int MaxIAsyncEnumerableBufferLimit { get; set; } = - mvc.MaxIAsyncEnumerableBufferLimit; - - public static implicit operator MsMvcOptions(MvcOptions options) => - options.CopyTo(new MsMvcOptions()); - - public virtual MsMvcOptions CopyTo(MsMvcOptions mvcOpts) - { - mvcOpts.AllowEmptyInputInBodyModelBinding = AllowEmptyInputInBodyModelBinding; - mvcOpts.EnableActionInvokers = EnableActionInvokers; - mvcOpts.EnableEndpointRouting = EnableEndpointRouting; - mvcOpts.MaxIAsyncEnumerableBufferLimit = MaxIAsyncEnumerableBufferLimit; - mvcOpts.MaxModelBindingCollectionSize = MaxModelBindingCollectionSize; - mvcOpts.MaxModelBindingRecursionDepth = MaxModelBindingRecursionDepth; - mvcOpts.MaxModelValidationErrors = MaxModelValidationErrors; - mvcOpts.MaxValidationDepth = MaxValidationDepth; - mvcOpts.RequireHttpsPermanent = RequireHttpsPermanent; - mvcOpts.RespectBrowserAcceptHeader = RespectBrowserAcceptHeader; - mvcOpts.ReturnHttpNotAcceptable = ReturnHttpNotAcceptable; - mvcOpts.SslPort = SslPort; - mvcOpts.SuppressAsyncSuffixInActionNames = SuppressAsyncSuffixInActionNames; - mvcOpts.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = - SuppressImplicitRequiredAttributeForNonNullableReferenceTypes; - mvcOpts.SuppressInputFormatterBuffering = SuppressInputFormatterBuffering; - mvcOpts.SuppressOutputFormatterBuffering = SuppressOutputFormatterBuffering; - mvcOpts.ValidateComplexTypesIfChildValidationFails = - ValidateComplexTypesIfChildValidationFails; - - // mvcOpts.CacheProfiles.Clear(); - foreach (var profile in CacheProfiles) - { - mvcOpts.CacheProfiles[profile.Key] = profile.Value; - } - // mvcOpts.Filters.Clear(); - foreach (var v in Filters) - { - mvcOpts.Filters.Add(v); - } - // mvcOpts.InputFormatters.Clear(); - foreach (var v in InputFormatters) - { - mvcOpts.InputFormatters.Add(v); - } - // mvcOpts.OutputFormatters.Clear(); - foreach (var v in OutputFormatters) - { - mvcOpts.OutputFormatters.Add(v); - } - // mvcOpts.Conventions.Clear(); - foreach (var v in Conventions) - { - mvcOpts.Conventions.Add(v); - } - // mvcOpts.ValueProviderFactories.Clear(); - foreach (var v in ValueProviderFactories) - { - mvcOpts.ValueProviderFactories.Add(v); - } - // mvcOpts.ModelBinderProviders.Clear(); - foreach (var v in ModelBinderProviders) - { - mvcOpts.ModelBinderProviders.Add(v); - } - // mvcOpts.ModelMetadataDetailsProviders.Clear(); - foreach (var v in ModelMetadataDetailsProviders) - { - mvcOpts.ModelMetadataDetailsProviders.Add(v); - } - // mvcOpts.ModelValidatorProviders.Clear(); - foreach (var v in ModelValidatorProviders) - { - mvcOpts.ModelValidatorProviders.Add(v); - } - return mvcOpts; - } + ) +{ } + +/// if you want to add controllers with views, otherwise +public virtual bool AddControllersWithViews { get; set; } = false; +public virtual bool AddControllersAsServices { get; set; } = false; + +/// if you want to add controllers with views, otherwise +public virtual bool AddRazorPages { get; set; } = false; + +/// if you want to add controllers with views, otherwise +/// public virtual bool AddControllersAsServices { get; set; } = false; + +/// if you want to add the Microsoft Identity UI, otherwise +public virtual bool AddMicrosoftIdentityUI { get; set; } = false; + +/// if you want to add JSON serializer otherwise +public virtual bool AddJsonOptions { get; set; } = false; + +/// if you want to add XML serializer formatters, otherwise +public virtual bool AddXmlSerializerFormatters { get; set; } = false; + +/// if you want to add XML data contract serializer formatters, otherwise +public virtual bool AddXmlDataContractSerializerFormatters { get; set; } = false; + +/// if you want to add the DGMJR MVC conventions, otherwise +public virtual bool AddMvcConventions { get; set; } = false; + +/// if you want to add controllers, otherwise +public virtual bool AddControllers { get; set; } = false; + +/// +public virtual bool AllowEmptyInputInBodyModelBinding { get; set; } = + mvc.AllowEmptyInputInBodyModelBinding; + +/// +public virtual bool EnableActionInvokers { get; set; } = mvc.EnableActionInvokers; + +/// +public virtual bool EnableEndpointRouting { get; set; } = mvc.EnableEndpointRouting; + +/// +public virtual bool RespectBrowserAcceptHeader { get; set; } = mvc.RespectBrowserAcceptHeader; + +/// +public virtual bool RequireHttpsPermanent { get; set; } = mvc.RequireHttpsPermanent; + +/// +public virtual bool SuppressAsyncSuffixInActionNames { get; set; } = + mvc.SuppressAsyncSuffixInActionNames; + +/// +public virtual bool SuppressInputFormatterBuffering { get; set; } = + mvc.SuppressInputFormatterBuffering; + +/// +public virtual bool SuppressOutputFormatterBuffering { get; set; } = + mvc.SuppressOutputFormatterBuffering; + +/// +public virtual bool ValidateComplexTypesIfChildValidationFails { get; set; } = + mvc.ValidateComplexTypesIfChildValidationFails; + +/// +public virtual bool SuppressImplicitRequiredAttributeForNonNullableReferenceTypes { get; set; } = + mvc.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes; + +/// +public virtual bool ReturnHttpNotAcceptable { get; set; } = mvc.ReturnHttpNotAcceptable; + +/// +public virtual IDictionary CacheProfiles { get; set; } = + mvc.CacheProfiles; + +/// +public virtual IList Conventions { get; set; } = mvc.Conventions; + +/// +public virtual FilterCollection Filters { get; set; } = mvc.Filters; + +/// +public virtual FormatterMappings FormatterMappings { get; set; } = mvc.FormatterMappings; + +/// +public virtual FormatterCollection InputFormatters { get; set; } = + mvc.InputFormatters; + +/// +public virtual int MaxModelValidationErrors { get; set; } = mvc.MaxModelValidationErrors; + +/// +public virtual IList ModelBinderProviders { get; set; } = + mvc.ModelBinderProviders; + +/// +public virtual DefaultModelBindingMessageProvider ModelBindingMessageProvider { get; set; } = + mvc.ModelBindingMessageProvider; + +/// +public virtual IList ModelMetadataDetailsProviders { get; set; } = + mvc.ModelMetadataDetailsProviders; + +/// +public virtual IList ModelValidatorProviders { get; set; } = + mvc.ModelValidatorProviders; + +/// +public virtual FormatterCollection OutputFormatters { get; set; } = + mvc.OutputFormatters; + +/// +public virtual IList ValueProviderFactories { get; set; } = + mvc.ValueProviderFactories; + +/// +public virtual int? SslPort { get; set; } = mvc.SslPort; + +/// +public virtual int? MaxValidationDepth { get; set; } = mvc.MaxValidationDepth; + +/// +public virtual int MaxModelBindingCollectionSize { get; set; } = + mvc.MaxModelBindingCollectionSize; + +/// +public virtual int MaxModelBindingRecursionDepth { get; set; } = + mvc.MaxModelBindingRecursionDepth; + +/// +public virtual int MaxIAsyncEnumerableBufferLimit { get; set; } = + mvc.MaxIAsyncEnumerableBufferLimit; + +public static implicit operator MsMvcOptions(MvcOptions options) => + options.CopyTo(new MsMvcOptions()); + +public virtual MsMvcOptions CopyTo(MsMvcOptions mvcOpts) +{ + mvcOpts.AllowEmptyInputInBodyModelBinding = AllowEmptyInputInBodyModelBinding; + mvcOpts.EnableActionInvokers = EnableActionInvokers; + mvcOpts.EnableEndpointRouting = EnableEndpointRouting; + mvcOpts.MaxIAsyncEnumerableBufferLimit = MaxIAsyncEnumerableBufferLimit; + mvcOpts.MaxModelBindingCollectionSize = MaxModelBindingCollectionSize; + mvcOpts.MaxModelBindingRecursionDepth = MaxModelBindingRecursionDepth; + mvcOpts.MaxModelValidationErrors = MaxModelValidationErrors; + mvcOpts.MaxValidationDepth = MaxValidationDepth; + mvcOpts.RequireHttpsPermanent = RequireHttpsPermanent; + mvcOpts.RespectBrowserAcceptHeader = RespectBrowserAcceptHeader; + mvcOpts.ReturnHttpNotAcceptable = ReturnHttpNotAcceptable; + mvcOpts.SslPort = SslPort; + mvcOpts.SuppressAsyncSuffixInActionNames = SuppressAsyncSuffixInActionNames; + mvcOpts.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = + SuppressImplicitRequiredAttributeForNonNullableReferenceTypes; + mvcOpts.SuppressInputFormatterBuffering = SuppressInputFormatterBuffering; + mvcOpts.SuppressOutputFormatterBuffering = SuppressOutputFormatterBuffering; + mvcOpts.ValidateComplexTypesIfChildValidationFails = + ValidateComplexTypesIfChildValidationFails; + + // mvcOpts.CacheProfiles.Clear(); + foreach (var profile in CacheProfiles) + { + mvcOpts.CacheProfiles[profile.Key] = profile.Value; + } + // mvcOpts.Filters.Clear(); + foreach (var v in Filters) + { + mvcOpts.Filters.Add(v); + } + // mvcOpts.InputFormatters.Clear(); + foreach (var v in InputFormatters) + { + mvcOpts.InputFormatters.Add(v); + } + // mvcOpts.OutputFormatters.Clear(); + foreach (var v in OutputFormatters) + { + mvcOpts.OutputFormatters.Add(v); + } + // mvcOpts.Conventions.Clear(); + foreach (var v in Conventions) + { + mvcOpts.Conventions.Add(v); + } + // mvcOpts.ValueProviderFactories.Clear(); + foreach (var v in ValueProviderFactories) + { + mvcOpts.ValueProviderFactories.Add(v); + } + // mvcOpts.ModelBinderProviders.Clear(); + foreach (var v in ModelBinderProviders) + { + mvcOpts.ModelBinderProviders.Add(v); + } + // mvcOpts.ModelMetadataDetailsProviders.Clear(); + foreach (var v in ModelMetadataDetailsProviders) + { + mvcOpts.ModelMetadataDetailsProviders.Add(v); + } + // mvcOpts.ModelValidatorProviders.Clear(); + foreach (var v in ModelValidatorProviders) + { + mvcOpts.ModelValidatorProviders.Add(v); + } + return mvcOpts; +} } diff --git a/src/Mvc/TypeNameAndAssemblyConfigurator.cs b/src/Mvc/TypeNameAndAssemblyConfigurator.cs index 67b827a0..25114590 100644 --- a/src/Mvc/TypeNameAndAssemblyConfigurator.cs +++ b/src/Mvc/TypeNameAndAssemblyConfigurator.cs @@ -11,38 +11,38 @@ public class TypeNameAndAssemblyConfigurator( where T : class where U : class { - public virtual void Configure(T options) - { - var configurationSection = configuration; - if (configurationSectionKey is not null) - { - configurationSection = configuration.GetRequiredSection(configurationSectionKey); - } - - var list = property.Compile().Invoke(options); - - foreach (var (assemblyName, typeName) in configurationSection.GetChildren().Select(GetType)) - { - var u = Activator.CreateInstance(assemblyName, typeName).Unwrap() as U; - if(u is not null) - { - list.Add(u); - } - } - } - - private (string assemblyName, string typeName) GetType(IConfigurationSection section) - { - var parts = section.Value.Split( - ',', - StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries - ); - var assemblyName = parts[1]; - var typeName = parts[0]; - return (assemblyName, typeName); - // var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName( - // new AssemblyName(assemblyName) - // ); - // return assembly.GetType(typeName); - } + public virtual void Configure(T options) +{ + var configurationSection = configuration; + if (configurationSectionKey is not null) + { + configurationSection = configuration.GetRequiredSection(configurationSectionKey); + } + + var list = property.Compile().Invoke(options); + + foreach (var (assemblyName, typeName) in configurationSection.GetChildren().Select(GetType)) + { + var u = Activator.CreateInstance(assemblyName, typeName).Unwrap() as U; + if (u is not null) + { + list.Add(u); + } + } +} + +private (string assemblyName, string typeName) GetType(IConfigurationSection section) +{ + var parts = section.Value.Split( + ',', + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries + ); + var assemblyName = parts[1]; + var typeName = parts[0]; + return (assemblyName, typeName); + // var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName( + // new AssemblyName(assemblyName) + // ); + // return assembly.GetType(typeName); +} } diff --git a/src/Security/Authentication.Basic/BasicAuthenticationHandler.cs b/src/Security/Authentication.Basic/BasicAuthenticationHandler.cs index 0097d59a..c2c35b70 100644 --- a/src/Security/Authentication.Basic/BasicAuthenticationHandler.cs +++ b/src/Security/Authentication.Basic/BasicAuthenticationHandler.cs @@ -13,6 +13,6 @@ ISystemClock clock ) : AuthenticationHandler(options, loggerFactory, urlEncoder, clock), ILog where TOptions : AuthenticationSchemeOptions, new() { - private ILogger _logger; - public new virtual ILogger Logger => _logger ??= loggerFactory.CreateLogger(GetType().FullName); + private ILogger _logger; +public new virtual ILogger Logger => _logger ??= loggerFactory.CreateLogger(GetType().FullName); } diff --git a/src/Security/Authentication.Basic/BasicWithUsers/BasicAuthenticationHandlerWithUsers.cs b/src/Security/Authentication.Basic/BasicWithUsers/BasicAuthenticationHandlerWithUsers.cs index 885f3f75..05cfc55e 100644 --- a/src/Security/Authentication.Basic/BasicWithUsers/BasicAuthenticationHandlerWithUsers.cs +++ b/src/Security/Authentication.Basic/BasicWithUsers/BasicAuthenticationHandlerWithUsers.cs @@ -23,52 +23,52 @@ ISystemClock clock clock ) { - private ICollection Users => Options.Users; - - protected override async Task HandleAuthenticateAsync() - { - var authHeader = Request.Headers[HReqH.Authorization.DisplayName].FirstOrDefault(); - if (authHeader == null) - { - return AuthenticateResult.NoResult(); - } - - var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader); - if ( - !authHeaderVal.Scheme.Equals( - BasicAuthenticationWithUsersDefaults.AuthenticationScheme, - OrdinalIgnoreCase - ) - ) - { - return AuthenticateResult.NoResult(); - } - - var credentialBytes = Convert.FromBase64String(authHeaderVal.Parameter); - var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':', 2); - if (credentials.Length != 2) - { - return AuthenticateResult.Fail("Invalid Basic authentication header"); - } - - var (username, password) = (credentials[0], credentials[1]); - if (!Users.Any(u => u.Username == username && u.Password == password)) - { - return AuthenticateResult.Fail("Invalid username or password"); - } - - return await Task.FromResult( - AuthenticateResult.Success( - new AuthenticationTicket( - new ClaimsPrincipal( - new ClaimsIdentity( - new[] { new Claim(ClaimTypes.Name, username) }, - BasicAuthenticationWithUsersDefaults.AuthenticationScheme - ) - ), - BasicAuthenticationWithUsersDefaults.AuthenticationScheme - ) - ) - ); - } + private ICollection Users => Options.Users; + +protected override async Task HandleAuthenticateAsync() +{ + var authHeader = Request.Headers[HReqH.Authorization.DisplayName].FirstOrDefault(); + if (authHeader == null) + { + return AuthenticateResult.NoResult(); + } + + var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader); + if ( + !authHeaderVal.Scheme.Equals( + BasicAuthenticationWithUsersDefaults.AuthenticationScheme, + OrdinalIgnoreCase + ) + ) + { + return AuthenticateResult.NoResult(); + } + + var credentialBytes = Convert.FromBase64String(authHeaderVal.Parameter); + var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':', 2); + if (credentials.Length != 2) + { + return AuthenticateResult.Fail("Invalid Basic authentication header"); + } + + var (username, password) = (credentials[0], credentials[1]); + if (!Users.Any(u => u.Username == username && u.Password == password)) + { + return AuthenticateResult.Fail("Invalid username or password"); + } + + return await Task.FromResult( + AuthenticateResult.Success( + new AuthenticationTicket( + new ClaimsPrincipal( + new ClaimsIdentity( + new[] { new Claim(ClaimTypes.Name, username) }, + BasicAuthenticationWithUsersDefaults.AuthenticationScheme + ) + ), + BasicAuthenticationWithUsersDefaults.AuthenticationScheme + ) + ) + ); +} } diff --git a/src/TagHelpers/Bootstrap/ActiveAnchorTagHelper.cs b/src/TagHelpers/Bootstrap/ActiveAnchorTagHelper.cs index aec2c6e5..8b70d386 100644 --- a/src/TagHelpers/Bootstrap/ActiveAnchorTagHelper.cs +++ b/src/TagHelpers/Bootstrap/ActiveAnchorTagHelper.cs @@ -15,80 +15,80 @@ namespace Dgmjr.AspNetCore.TagHelpers.Bootstrap; public class ActiveAnchorTagHelper(IHtmlGenerator generator) : Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper(generator) { - private bool? _isActive; - public bool IsActive - { - get => _isActive ?? ShouldBeActive(); - set => _isActive = value; - } - - public override int Order => int.MaxValue; - - public override void Process(TagHelperContext context, TagHelperOutput output) - { - // base.Process(context, output); - - if (IsActive) - { - var activeClass = output.Attributes.FirstOrDefault(a => a.Name == "class"); - if (activeClass != null) - { - output.Attributes.SetAttribute( - AttributeNames.Class, - activeClass.Value + " " + CssClasses.Active - ); - } - else - { - output.Attributes.SetAttribute(AttributeNames.Class, CssClasses.Active); - } - } - } - - private bool ShouldBeActive() - { - // Get the current page's area - var currentArea = ViewContext.RouteData.Values["area"]?.ToString(); - - // Get the current page's controller - var currentController = ViewContext.RouteData.Values["controller"]?.ToString(); - - // Get the current page's page name - var currentPage = ViewContext.RouteData.Values["page"]?.ToString(); - - // Get the current page's action - var currentAction = ViewContext.RouteData.Values["action"]?.ToString(); - - // Get the anchor's area - var anchorArea = Area; - - // Get the anchor's controller - var anchorController = Controller; - - // Get the anchor's page name - var anchorPage = Page; - - // Get the anchor's action - var anchorAction = Action; - - // Compare the current page's area, controller, page name, and action to the anchor's properties - // If they all match, return true - if ( - string.Equals(currentArea, anchorArea, OrdinalIgnoreCase) - && string.Equals(currentController, anchorController, OrdinalIgnoreCase) - && string.Equals(currentPage, anchorPage, OrdinalIgnoreCase) - && string.Equals(currentAction, anchorAction, OrdinalIgnoreCase) - ) - { - return true; - } - - if(anchorPage != null && currentPage?.StartsWith(anchorPage, OrdinalIgnoreCase) == true) - { - return true; - } - - // If any of the above comparisons fail, return false - return false; - } + private bool? _isActive; +public bool IsActive +{ + get => _isActive ?? ShouldBeActive(); + set => _isActive = value; +} + +public override int Order => int.MaxValue; + +public override void Process(TagHelperContext context, TagHelperOutput output) +{ + // base.Process(context, output); + + if (IsActive) + { + var activeClass = output.Attributes.FirstOrDefault(a => a.Name == "class"); + if (activeClass != null) + { + output.Attributes.SetAttribute( + AttributeNames.Class, + activeClass.Value + " " + CssClasses.Active + ); + } + else + { + output.Attributes.SetAttribute(AttributeNames.Class, CssClasses.Active); + } + } +} + +private bool ShouldBeActive() +{ + // Get the current page's area + var currentArea = ViewContext.RouteData.Values["area"]?.ToString(); + + // Get the current page's controller + var currentController = ViewContext.RouteData.Values["controller"]?.ToString(); + + // Get the current page's page name + var currentPage = ViewContext.RouteData.Values["page"]?.ToString(); + + // Get the current page's action + var currentAction = ViewContext.RouteData.Values["action"]?.ToString(); + + // Get the anchor's area + var anchorArea = Area; + + // Get the anchor's controller + var anchorController = Controller; + + // Get the anchor's page name + var anchorPage = Page; + + // Get the anchor's action + var anchorAction = Action; + + // Compare the current page's area, controller, page name, and action to the anchor's properties + // If they all match, return true + if ( + string.Equals(currentArea, anchorArea, OrdinalIgnoreCase) + && string.Equals(currentController, anchorController, OrdinalIgnoreCase) + && string.Equals(currentPage, anchorPage, OrdinalIgnoreCase) + && string.Equals(currentAction, anchorAction, OrdinalIgnoreCase) + ) + { + return true; + } + + if (anchorPage != null && currentPage?.StartsWith(anchorPage, OrdinalIgnoreCase) == true) + { + return true; + } + + // If any of the above comparisons fail, return false + return false; +} } diff --git a/src/TagHelpers/Bootstrap/PageElements/Footer.cs b/src/TagHelpers/Bootstrap/PageElements/Footer.cs index 9d630205..260c8261 100644 --- a/src/TagHelpers/Bootstrap/PageElements/Footer.cs +++ b/src/TagHelpers/Bootstrap/PageElements/Footer.cs @@ -55,7 +55,7 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu ); output.PreContent.AppendHtml( $$$""" -
+ < div class="{{{CssClasses.Container}}}"> """ ); if (!IsNullOrEmpty(CopyrightHolder)) @@ -71,49 +71,51 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu output.PreContent.AppendHtml( $$$""" - {{{datetime.Now.Year}}} - - """ - ); - } - if (CopyrightEndYear.HasValue && CopyrightEndYear != CopyrightStartYear) - { - output.PreContent.AppendHtml( - $$$""" - - - {{{datetime.Now.Year}}} - """ - ); - } - if (!IsNullOrEmpty(CopyrightHolderEmail)) - { - output.PreContent.AppendHtml( - $$$""" - - - {{{CopyrightHolder}}} - - """ - ); - } - else - { - output.PreContent.AppendHtml( - $$$""" - {{{CopyrightHolder}}} - """ - ); - } - if(!IsNullOrWhiteSpace(childContent.GetContent())) - { - output.PreContent.AppendHtml( - """ - - | + {{{datetime.Now.Year +} +}} """ ); } + if (CopyrightEndYear.HasValue && CopyrightEndYear != CopyrightStartYear) +{ + output.PreContent.AppendHtml( + $$$""" + + - { { { datetime.Now.Year} } } + """ + ); +} +if (!IsNullOrEmpty(CopyrightHolderEmail)) +{ + output.PreContent.AppendHtml( + $$$""" + + < a href = "mailto:{{{CopyrightHolderEmail}}}" > + { { { CopyrightHolder} } } + + """ + ); +} +else +{ + output.PreContent.AppendHtml( + $$$""" + { { { CopyrightHolder} } } + """ + ); +} +if (!IsNullOrWhiteSpace(childContent.GetContent())) +{ + output.PreContent.AppendHtml( + """ + + | + + """ + ); +} } } }