Skip to content

Commit 9e8f59a

Browse files
3.0.1
1 parent 18f3d43 commit 9e8f59a

File tree

7 files changed

+171
-11
lines changed

7 files changed

+171
-11
lines changed

samples/snglrtycrvtureofspce.Core.Samples.BasicApi/Program.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ public static void Main(string[] args)
3131

3232
// Sample endpoints
3333
app.MapGet("/", () => "Hello from snglrtycrvtureofspce.Core!")
34-
.WithName("GetRoot")
35-
.WithOpenApi();
34+
.WithName("GetRoot");
3635

3736
app.MapGet("/error/notfound", () =>
3837
{
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using Microsoft.AspNetCore.Cors.Infrastructure;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using snglrtycrvtureofspce.Core.Microservices.Core.Configurations;
4+
5+
namespace snglrtycrvtureofspce.Core.Extensions;
6+
7+
/// <summary>
8+
/// Extension methods for configuring CORS in the DI container.
9+
/// </summary>
10+
public static class CorsExtensions
11+
{
12+
/// <summary>
13+
/// Adds CORS policy configuration to the service collection.
14+
/// </summary>
15+
/// <param name="services">The service collection.</param>
16+
/// <param name="corsPolicy">The CORS policy options.</param>
17+
/// <param name="policyName">The name of the CORS policy. Defaults to "AllowAll".</param>
18+
/// <returns>The service collection.</returns>
19+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="corsPolicy"/> is null.</exception>
20+
public static IServiceCollection AddCorsPolicy(
21+
this IServiceCollection services,
22+
CorsPolicyOptions corsPolicy,
23+
string policyName = "AllowAll")
24+
{
25+
ArgumentNullException.ThrowIfNull(corsPolicy);
26+
27+
services.AddCors(options => options.AddPolicy(policyName, corsPolicyBuilder =>
28+
{
29+
ConfigureOrigins(corsPolicyBuilder, corsPolicy.AllowAnyOrigin, corsPolicy.AllowedOrigins);
30+
ConfigureMethods(corsPolicyBuilder, corsPolicy.AllowAnyMethod, corsPolicy.AllowedMethods);
31+
ConfigureHeaders(corsPolicyBuilder, corsPolicy.AllowAnyHeader, corsPolicy.AllowedHeaders);
32+
33+
if (corsPolicy.AllowCredentials)
34+
{
35+
corsPolicyBuilder.AllowCredentials();
36+
}
37+
38+
}));
39+
40+
return services;
41+
}
42+
43+
private static void ConfigureOrigins(CorsPolicyBuilder builder, bool allowAny, List<string>? allowed)
44+
{
45+
if (allowAny || allowed is not { Count: > 0 })
46+
{
47+
builder.AllowAnyOrigin();
48+
}
49+
else
50+
{
51+
builder.WithOrigins(allowed.ToArray());
52+
}
53+
}
54+
55+
private static void ConfigureMethods(CorsPolicyBuilder builder, bool allowAny, List<string>? allowed)
56+
{
57+
if (allowAny || allowed is not { Count: > 0 })
58+
{
59+
builder.AllowAnyMethod();
60+
}
61+
else
62+
{
63+
builder.WithMethods(allowed.ToArray());
64+
}
65+
}
66+
67+
private static void ConfigureHeaders(CorsPolicyBuilder builder, bool allowAny, List<string>? allowed)
68+
{
69+
if (allowAny || allowed is not { Count: > 0 })
70+
{
71+
builder.AllowAnyHeader();
72+
}
73+
else
74+
{
75+
builder.WithHeaders(allowed.ToArray());
76+
}
77+
}
78+
}

src/snglrtycrvtureofspce.Core/Extensions/ServiceCollectionExtensions.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,16 @@ public static IServiceCollection AddCore(this IServiceCollection services, param
3939
/// <returns>The service collection.</returns>
4040
public static IServiceCollection AddValidators(this IServiceCollection services, params Assembly[] assemblies)
4141
{
42-
foreach (var assembly in assemblies)
43-
{
44-
var validatorTypes = assembly.GetTypes()
42+
var validatorTypes = assemblies
43+
.SelectMany(assembly => assembly.GetTypes()
4544
.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
4645
.SelectMany(t => t.GetInterfaces()
4746
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IValidator<>))
48-
.Select(i => new { Interface = i, Implementation = t }));
47+
.Select(i => new { Interface = i, Implementation = t })));
4948

50-
foreach (var validator in validatorTypes)
51-
{
52-
services.AddTransient(validator.Interface, validator.Implementation);
53-
}
49+
foreach (var validator in validatorTypes)
50+
{
51+
services.AddTransient(validator.Interface, validator.Implementation);
5452
}
5553

5654
return services;

src/snglrtycrvtureofspce.Core/Filters/LoggingBehavior.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public async Task<TResponse> Handle(
4747

4848
try
4949
{
50-
var response = await next();
50+
var response = await next(cancellationToken);
5151

5252
stopwatch.Stop();
5353
var elapsedMs = stopwatch.ElapsedMilliseconds;

src/snglrtycrvtureofspce.Core/Filters/RequestValidationBehavior.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public async Task<TResponse> Handle(
4949
ArgumentNullException.ThrowIfNull(next);
5050

5151
if (!validators.Any())
52+
{
5253
return await next(cancellationToken);
54+
}
5355

5456
var context = new ValidationContext<TRequest>(request);
5557

@@ -63,7 +65,9 @@ public async Task<TResponse> Handle(
6365
.ToList();
6466

6567
if (failures.Count > 0)
68+
{
6669
throw new ValidationException(failures);
70+
}
6771

6872
return await next(cancellationToken);
6973
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
namespace snglrtycrvtureofspce.Core.Microservices.Core.Configurations;
2+
3+
/// <summary>
4+
/// CORS policy configuration options.
5+
/// This class defines the settings for configuring Cross-Origin Resource Sharing (CORS) policies in ASP.NET Core applications.
6+
/// </summary>
7+
public class CorsPolicyOptions
8+
{
9+
/// <summary>
10+
/// Gets or sets a value indicating whether any origin is allowed.
11+
/// When set to true, the CORS policy allows requests from any origin.
12+
/// When set to false, only origins specified in <see cref="AllowedOrigins"/> are permitted.
13+
/// </summary>
14+
/// <remarks>
15+
/// Default value is true for development convenience, but should be set to false in production with specific allowed origins.
16+
/// </remarks>
17+
public bool AllowAnyOrigin { get; set; } = true;
18+
19+
/// <summary>
20+
/// Gets or sets a value indicating whether any HTTP method is allowed.
21+
/// When set to true, the CORS policy allows all HTTP methods (GET, POST, PUT, DELETE, etc.).
22+
/// When set to false, only methods specified in <see cref="AllowedMethods"/> are permitted.
23+
/// </summary>
24+
/// <remarks>
25+
/// Default value is true. For security, consider restricting to specific methods in production.
26+
/// </remarks>
27+
public bool AllowAnyMethod { get; set; } = true;
28+
29+
/// <summary>
30+
/// Gets or sets a value indicating whether any header is allowed.
31+
/// When set to true, the CORS policy allows all request headers.
32+
/// When set to false, only headers specified in <see cref="AllowedHeaders"/> are permitted.
33+
/// </summary>
34+
/// <remarks>
35+
/// Default value is true. Common practice is to allow specific headers like "Content-Type", "Authorization", etc.
36+
/// </remarks>
37+
public bool AllowAnyHeader { get; set; } = true;
38+
39+
/// <summary>
40+
/// Gets or sets a value indicating whether credentials (cookies, authorization headers) are allowed.
41+
/// When set to true, the CORS policy allows credentials to be included in cross-origin requests.
42+
/// </summary>
43+
/// <remarks>
44+
/// This should only be enabled when necessary, as it reduces security. When enabled, <see cref="AllowAnyOrigin"/> should be false.
45+
/// </remarks>
46+
public bool AllowCredentials { get; set; }
47+
48+
/// <summary>
49+
/// Gets or sets the list of allowed origins.
50+
/// This property is used when <see cref="AllowAnyOrigin"/> is false.
51+
/// </summary>
52+
/// <example>
53+
/// <code>
54+
/// AllowedOrigins = new List&lt;string&gt; { "https://example.com", "https://api.example.com" }
55+
/// </code>
56+
/// </example>
57+
public List<string>? AllowedOrigins { get; set; }
58+
59+
/// <summary>
60+
/// Gets or sets the list of allowed HTTP methods.
61+
/// This property is used when <see cref="AllowAnyMethod"/> is false.
62+
/// </summary>
63+
/// <example>
64+
/// <code>
65+
/// AllowedMethods = new List&lt;string&gt; { "GET", "POST", "PUT" }
66+
/// </code>
67+
/// </example>
68+
public List<string>? AllowedMethods { get; set; }
69+
70+
/// <summary>
71+
/// Gets or sets the list of allowed headers.
72+
/// This property is used when <see cref="AllowAnyHeader"/> is false.
73+
/// </summary>
74+
/// <example>
75+
/// <code>
76+
/// AllowedHeaders = new List&lt;string&gt; { "Content-Type", "Authorization", "X-Custom-Header" }
77+
/// </code>
78+
/// </example>
79+
public List<string>? AllowedHeaders { get; set; }
80+
}

src/snglrtycrvtureofspce.Core/snglrtycrvtureofspce.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net10.0</TargetFramework>
5+
<LangVersion>14</LangVersion>
56
<OutputType>Library</OutputType>
67
<IsPackable>true</IsPackable>
78
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>

0 commit comments

Comments
 (0)