Skip to content

Commit

Permalink
Merge pull request #69 from AngeloDotNet/develop
Browse files Browse the repository at this point in the history
Sync Main from Develop
  • Loading branch information
AngeloDotNet authored Dec 19, 2024
2 parents fa10db6 + 1c578e3 commit 8fda24c
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 52 deletions.
44 changes: 0 additions & 44 deletions src/GSWCloudApp.Common/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,50 +245,6 @@ public static IServiceCollection ConfigureOptions(this IServiceCollection servic
return services;
}

/// <summary>
/// Configures JWT authentication for the application.
/// </summary>
/// <param name="services">The service collection to configure.</param>
/// <param name="jwtSettings">The JWT settings to use for configuration.</param>
/// <returns>The configured service collection.</returns>
[Obsolete("This method is obsolete. Use ConfigureAuthFullTokenJWT instead.", true)]
public static IServiceCollection ConfigureAuthTokenJWTShared(this IServiceCollection services, JwtOptions jwtOptions)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer("Bearer", options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtOptions.Issuer,
ValidateAudience = true,
ValidAudience = jwtOptions.Audience,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecurityKey)),
RequireExpirationTime = true,
ClockSkew = TimeSpan.Zero
};
});

services.AddScoped<IAuthorizationHandler, UserActiveHandler>();
services.AddAuthorization(options =>
{
var policyBuilder = new AuthorizationPolicyBuilder().RequireAuthenticatedUser();
policyBuilder.Requirements.Add(new UserActiveRequirement());
options.FallbackPolicy = options.DefaultPolicy = policyBuilder.Build();
});

return services;
}

/// <summary>
/// Configures full JWT authentication for the application, including Identity and authorization policies.
/// </summary>
Expand Down
29 changes: 27 additions & 2 deletions src/GSWCloudApp.Common/Routing/IEndpointRouteBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,25 @@

namespace GSWCloudApp.Common.Routing;

/// <summary>
/// Provides extension methods for mapping endpoints.
/// </summary>
public static class IEndpointRouteBuilderExtensions
{
/// <summary>
/// Maps endpoints from the calling assembly.
/// </summary>
/// <param name="endpoints">The endpoint route builder.</param>
/// <param name="predicate">An optional predicate to filter types.</param>
public static void MapEndpoints(this IEndpointRouteBuilder endpoints, Func<Type, bool>? predicate = null)
=> endpoints.MapEndpoints(Assembly.GetCallingAssembly(), predicate);

/// <summary>
/// Maps endpoints from the specified assembly.
/// </summary>
/// <param name="endpoints">The endpoint route builder.</param>
/// <param name="assembly">The assembly to scan for endpoint route handler builders.</param>
/// <param name="predicate">An optional predicate to filter types.</param>
public static void MapEndpoints(this IEndpointRouteBuilder endpoints, Assembly assembly, Func<Type, bool>? predicate = null)
{
ArgumentNullException.ThrowIfNull(endpoints);
Expand All @@ -25,13 +39,24 @@ public static void MapEndpoints(this IEndpointRouteBuilder endpoints, Assembly a
var mapEndpointsMethod = endpointRouteHandlerBuilderType.GetMethod(nameof(IEndpointRouteHandlerBuilder.MapEndpoints),
BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)!;

mapEndpointsMethod.Invoke(null, [endpoints]);
mapEndpointsMethod.Invoke(null, new object[] { endpoints });
}
}

/// <summary>
/// Maps endpoints from the assembly containing the specified type.
/// </summary>
/// <typeparam name="T">The type whose containing assembly to scan for endpoint route handler builders.</typeparam>
/// <param name="endpoints">The endpoint route builder.</param>
/// <param name="predicate">An optional predicate to filter types.</param>
public static void MapEndpointsFromAssemblyContaining<T>(this IEndpointRouteBuilder endpoints, Func<Type, bool>? predicate = null) where T : class
=> endpoints.MapEndpoints(typeof(T).Assembly, predicate);

/// <summary>
/// Maps endpoints using the specified endpoint route handler builder type.
/// </summary>
/// <typeparam name="T">The endpoint route handler builder type.</typeparam>
/// <param name="endpoints">The endpoint route builder.</param>
public static void MapEndpoints<T>(this IEndpointRouteBuilder endpoints) where T : IEndpointRouteHandlerBuilder
=> T.MapEndpoints(endpoints);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

namespace GSWCloudApp.Common.Routing;

/// <summary>
/// Defines a contract for mapping endpoints.
/// </summary>
public interface IEndpointRouteHandlerBuilder
{
/// <summary>
/// Maps endpoints using the specified endpoint route builder.
/// </summary>
/// <param name="endpoints">The endpoint route builder.</param>
public static abstract void MapEndpoints(IEndpointRouteBuilder endpoints);
}
65 changes: 63 additions & 2 deletions src/GSWCloudApp.Common/Services/GenericService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,21 @@

namespace GSWCloudApp.Common.Services;

/// <summary>
/// Provides generic service methods for handling CRUD operations.
/// </summary>
public class GenericService : IGenericService
{
/// <summary>
/// Retrieves all entities of type <typeparamref name="TEntity"/> and maps them to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <param name="cacheData">Indicates whether to cache the data.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="cacheService">The cache service.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>A list of DTOs or a NotFound result.</returns>
public async Task<Results<Ok<List<TDto>>, NotFound>> GetAllAsync<TEntity, TDto>([FromQuery] bool cacheData, DbContext dbContext, ICacheService cacheService, IMapper mapper)
where TEntity : class
where TDto : class
Expand Down Expand Up @@ -51,7 +64,17 @@ public async Task<Results<Ok<List<TDto>>, NotFound>> GetAllAsync<TEntity, TDto>(
return TypedResults.Ok(result);
}

public async Task<Results<Ok<TDto>, NotFound>> GetByIdAsync<TEntity, TDto>(Guid id, DbContext dbContext, ICacheService cacheService, IMapper mapper)
/// <summary>
/// Retrieves an entity of type <typeparamref name="TEntity"/> by its ID and maps it to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <param name="id">The ID of the entity.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="cacheService">The cache service.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>The DTO or a NotFound result.</returns>
public async Task<Results<Ok<TDto>, NotFound>> GetByIdAsync<TEntity, TDto>([FromQuery] bool cacheData, Guid id, DbContext dbContext, ICacheService cacheService, IMapper mapper)
where TEntity : class
where TDto : class
{
Expand Down Expand Up @@ -79,6 +102,16 @@ public async Task<Results<Ok<TDto>, NotFound>> GetByIdAsync<TEntity, TDto>(Guid
return TypedResults.Ok(result);
}

/// <summary>
/// Creates a new entity of type <typeparamref name="TEntity"/> from the provided DTO and maps it to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <typeparam name="TCreateDto">The type of the create DTO.</typeparam>
/// <param name="createDto">The create DTO.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>The created DTO or a BadRequest result.</returns>
public async Task<Results<Ok<TDto>, BadRequest<string>>> PostAsync<TEntity, TDto, TCreateDto>(TCreateDto createDto, DbContext dbContext, IMapper mapper)
where TEntity : class
where TDto : class
Expand All @@ -99,6 +132,17 @@ public async Task<Results<Ok<TDto>, BadRequest<string>>> PostAsync<TEntity, TDto
}
}

/// <summary>
/// Updates an existing entity of type <typeparamref name="TEntity"/> with the provided DTO and maps it to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <typeparam name="TEditDto">The type of the edit DTO.</typeparam>
/// <param name="id">The ID of the entity.</param>
/// <param name="editDto">The edit DTO.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>The updated DTO, a NotFound result, or a BadRequest result.</returns>
public async Task<Results<Ok<TDto>, NotFound, BadRequest<string>>> UpdateAsync<TEntity, TDto, TEditDto>(Guid id, TEditDto editDto, DbContext dbContext, IMapper mapper)
where TEntity : class
where TDto : class
Expand Down Expand Up @@ -126,6 +170,13 @@ public async Task<Results<Ok<TDto>, NotFound, BadRequest<string>>> UpdateAsync<T
}
}

/// <summary>
/// Deletes an entity of type <typeparamref name="TEntity"/> by its ID.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="id">The ID of the entity.</param>
/// <param name="dbContext">The database context.</param>
/// <returns>A NoContent result or a NotFound result.</returns>
public async Task<Results<NoContent, NotFound>> DeleteAsync<TEntity>(Guid id, DbContext dbContext)
where TEntity : class
{
Expand All @@ -144,6 +195,16 @@ public async Task<Results<NoContent, NotFound>> DeleteAsync<TEntity>(Guid id, Db
return TypedResults.NoContent();
}

/// <summary>
/// Filters entities of type <typeparamref name="TEntity"/> by the specified festa ID and maps them to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <param name="festaId">The festa ID.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="cacheService">The cache service.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>A list of DTOs or a NotFound result.</returns>
public async Task<Results<Ok<List<TDto>>, NotFound>> FilterByIdFestaAsync<TEntity, TDto>(Guid festaId, DbContext dbContext, ICacheService cacheService, IMapper mapper)
where TEntity : class
where TDto : class
Expand All @@ -170,4 +231,4 @@ public async Task<Results<Ok<List<TDto>>, NotFound>> FilterByIdFestaAsync<TEntit

return TypedResults.Ok(mapper.Map<List<TDto>>(entity));
}
}
}
65 changes: 63 additions & 2 deletions src/GSWCloudApp.Common/Services/IGenericService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,89 @@

namespace GSWCloudApp.Common.Services;

/// <summary>
/// Defines generic service methods for handling CRUD operations.
/// </summary>
public interface IGenericService
{
/// <summary>
/// Retrieves all entities of type <typeparamref name="TEntity"/> and maps them to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <param name="cacheData">Indicates whether to cache the data.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="cacheService">The cache service.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>A list of DTOs or a NotFound result.</returns>
Task<Results<Ok<List<TDto>>, NotFound>> GetAllAsync<TEntity, TDto>([FromQuery] bool cacheData, DbContext dbContext, ICacheService cacheService, IMapper mapper)
where TEntity : class
where TDto : class;

Task<Results<Ok<TDto>, NotFound>> GetByIdAsync<TEntity, TDto>(Guid id, DbContext dbContext, ICacheService cacheService, IMapper mapper)
/// <summary>
/// Retrieves an entity of type <typeparamref name="TEntity"/> by its ID and maps it to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <param name="id">The ID of the entity.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="cacheService">The cache service.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>The DTO or a NotFound result.</returns>
Task<Results<Ok<TDto>, NotFound>> GetByIdAsync<TEntity, TDto>([FromQuery] bool cacheData, Guid id, DbContext dbContext, ICacheService cacheService, IMapper mapper)
where TEntity : class
where TDto : class;

/// <summary>
/// Creates a new entity of type <typeparamref name="TEntity"/> from the provided DTO and maps it to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <typeparam name="TCreateDto">The type of the create DTO.</typeparam>
/// <param name="createDto">The create DTO.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>The created DTO or a BadRequest result.</returns>
Task<Results<Ok<TDto>, BadRequest<string>>> PostAsync<TEntity, TDto, TCreateDto>(TCreateDto createDto, DbContext dbContext, IMapper mapper)
where TEntity : class
where TDto : class;

/// <summary>
/// Updates an existing entity of type <typeparamref name="TEntity"/> with the provided DTO and maps it to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <typeparam name="TEditDto">The type of the edit DTO.</typeparam>
/// <param name="id">The ID of the entity.</param>
/// <param name="editDto">The edit DTO.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>The updated DTO, a NotFound result, or a BadRequest result.</returns>
Task<Results<Ok<TDto>, NotFound, BadRequest<string>>> UpdateAsync<TEntity, TDto, TEditDto>(Guid id, TEditDto editDto, DbContext dbContext, IMapper mapper)
where TEntity : class
where TDto : class;

/// <summary>
/// Deletes an entity of type <typeparamref name="TEntity"/> by its ID.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="id">The ID of the entity.</param>
/// <param name="dbContext">The database context.</param>
/// <returns>A NoContent result or a NotFound result.</returns>
Task<Results<NoContent, NotFound>> DeleteAsync<TEntity>(Guid id, DbContext dbContext)
where TEntity : class;

/// <summary>
/// Filters entities of type <typeparamref name="TEntity"/> by the specified festa ID and maps them to <typeparamref name="TDto"/>.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <typeparam name="TDto">The type of the DTO.</typeparam>
/// <param name="festaId">The festa ID.</param>
/// <param name="dbContext">The database context.</param>
/// <param name="cacheService">The cache service.</param>
/// <param name="mapper">The mapper.</param>
/// <returns>A list of DTOs or a NotFound result.</returns>
Task<Results<Ok<List<TDto>>, NotFound>> FilterByIdFestaAsync<TEntity, TDto>(Guid festaId, DbContext dbContext, ICacheService cacheService, IMapper mapper)
where TEntity : class
where TDto : class;
}
}
15 changes: 14 additions & 1 deletion src/GSWCloudApp.Common/Swagger/ConfigureSwaggerGenOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@

namespace GSWCloudApp.Common.Swagger;

/// <summary>
/// Configures the Swagger generation options.
/// </summary>
/// <param name="provider">The API version description provider.</param>
public class ConfigureSwaggerGenOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions<SwaggerGenOptions>
{
/// <summary>
/// Configures the Swagger generation options.
/// </summary>
/// <param name="options">The Swagger generation options to configure.</param>
public void Configure(SwaggerGenOptions options)
{
foreach (var description in provider.ApiVersionDescriptions)
Expand All @@ -18,6 +26,11 @@ public void Configure(SwaggerGenOptions options)
}
}

/// <summary>
/// Creates the OpenAPI information for the specified API version.
/// </summary>
/// <param name="description">The API version description.</param>
/// <returns>The OpenAPI information for the specified API version.</returns>
private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
{
var text = new StringBuilder("API endpoints that enable the use of this microservice.");
Expand Down Expand Up @@ -47,4 +60,4 @@ private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription descrip

return info;
}
}
}
10 changes: 9 additions & 1 deletion src/GSWCloudApp.Common/Swagger/SwaggerDefaultValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,19 @@

namespace GSWCloudApp.Common.Swagger;

/// <summary>
/// Sets default values for Swagger operations.
/// </summary>
public class SwaggerDefaultValues : IOperationFilter
{
/// <summary>
/// Applies the filter to the specified operation.
/// </summary>
/// <param name="operation">The OpenAPI operation.</param>
/// <param name="context">The operation filter context.</param>
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var apiDescription = context.ApiDescription;
operation.Deprecated |= apiDescription.IsDeprecated();
}
}
}

0 comments on commit 8fda24c

Please sign in to comment.