diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 85a8338..49284a2 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -22,13 +22,18 @@ jobs: with: dotnet-version: '8.0.x' - - name: Install SonarScanner - run: dotnet tool install --global dotnet-sonarscanner + - name: Install global tools (SonarScanner + ReportGenerator) + run: | + dotnet tool install --global dotnet-sonarscanner + dotnet tool install --global dotnet-reportgenerator-globaltool + + - name: Add tool path to environment + run: echo "$HOME/.dotnet/tools" >> $GITHUB_PATH - name: Restore dependencies run: dotnet restore src/Faura.sln - - name: Begin SonarCloud Analysis + - name: Begin SonarCloud analysis env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: | @@ -36,10 +41,35 @@ jobs: /k:"JosepFe_faura" \ /o:"josepfe" \ /d:sonar.login="${SONAR_TOKEN}" \ - /d:sonar.host.url="https://sonarcloud.io" + /d:sonar.host.url="https://sonarcloud.io" \ + /d:sonar.cs.opencover.reportsPaths="coverage/combined/coverage.opencover.xml" - name: Build solution - run: dotnet build src/Faura.sln --no-restore --no-incremental + run: dotnet build src/Faura.sln --no-restore --configuration Release + + - name: Run Unit Tests with Coverage (WebAPI) + run: | + mkdir -p coverage/unit + dotnet test src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj \ + --configuration Release \ + /p:CollectCoverage=true \ + /p:CoverletOutputFormat=opencover \ + /p:CoverletOutput=coverage/unit/ \ + --no-build + + - name: Merge coverage reports + run: | + mkdir -p coverage/combined + reportgenerator \ + -reports:"coverage/unit/coverage.opencover.xml" \ + -targetdir:"coverage/combined" \ + -reporttypes:Html + + - name: Upload Coverage Report Artifact + uses: actions/upload-artifact@v4 + with: + name: CoverageReport + path: coverage/combined - name: End SonarCloud Analysis env: diff --git a/.gitignore b/.gitignore index 4c071b2..8de49f6 100644 --- a/.gitignore +++ b/.gitignore @@ -150,7 +150,6 @@ AppPackages/ sql/ *.Cache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl diff --git a/src/.editorconfig b/src/.editorconfig new file mode 100644 index 0000000..ded567f --- /dev/null +++ b/src/.editorconfig @@ -0,0 +1,157 @@ +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +insert_final_newline = true +time_trailing_whitespace = true +end_of_line = lf + +[*.cs] +csharp_using_directive_placement = inside_namespace:warning +dotnet_sort_system_directives_first = true +csharp_style_expression_bodied_methods = true:warning +csharp_style_expression_bodied_constructors = true:warning +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning + + +### IDE specific rules + +# IDE0090: Use 'new(...)' +csharp_style_implicit_object_creation_when_type_is_apparent = true + +# IDE0017: Simplify object initialization +dotnet_style_object_initializer = true + +### StyleCop.Analyzers custom configuration + +# SA0001: Xml comment analysis disabled +dotnet_diagnostic.SA0001.severity = none + +# Methods should only be documented if shipped as a public API, the best documentation is the code implementation +dotnet_diagnostic.SA1516.severity = none +dotnet_diagnostic.SA1600.severity = none +dotnet_diagnostic.SA1601.severity = none +dotnet_diagnostic.SA1602.severity = none +dotnet_diagnostic.SA1611.severity = none +dotnet_diagnostic.SA1615.severity = none +dotnet_diagnostic.SA1618.severity = none +dotnet_diagnostic.SA1619.severity = none + +# SA1633: File should have header +dotnet_diagnostic.SA1633.severity = none + +# SA1101: Prefix local calls with this +dotnet_diagnostic.SA1101.severity = none + +# SX1101: Do not prefix local calls with 'this.' +dotnet_diagnostic.SX1101.severity = warning + +# SA1309: Field names should not begin with underscore +dotnet_diagnostic.SA1309.severity = none + +# SX1309: Field names should begin with underscore +dotnet_diagnostic.SX1309.severity = warning + +# SA1130: Classes should not be empty +dotnet_diagnostic.SA1130.severity = none + +# SA1400: Access modifier must be declared +dotnet_diagnostic.SA1400.severity = warning + +# SA1413: Use trailing commas in multi-line initializers +dotnet_diagnostic.SA1413.severity = warning + +# SA1503: Braces should not be omitted +dotnet_diagnostic.SA1503.severity = none + +### SonarAnalyzer.CSharp custom configuration + +# S1128: Unused "using" should be removed +dotnet_diagnostic.S1128.severity = warning + +# S2094: Classes should not be empty +dotnet_diagnostic.S2094.severity = none + +# S4487: Unread "private" fields should be removed +dotnet_diagnostic.S4487.severity = warning + +# S1172: Unused method parameters should be removed +dotnet_diagnostic.S1172.severity = warning + +#Disable S1133 for obsolete +dotnet_diagnostic.S1133.severity = suggestion + +#Disable CS0618 for obsolete +dotnet_diagnostic.CS0618.severity = suggestion +csharp_indent_labels = one_less_than_current +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = file_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_prefer_system_threading_lock = true:suggestion +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_space_around_binary_operators = before_and_after +dotnet_diagnostic.SA1010.severity = none +dotnet_diagnostic.SA1000.severity = none + +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..7d28e81 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,43 @@ + + + net8.0 + enable + enable + latest + false + en + true + Faura + Faura + git + 1.0.0 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Faura.sln b/src/Faura.sln index 6adf77b..0b0ea62 100644 --- a/src/Faura.sln +++ b/src/Faura.sln @@ -27,7 +27,22 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.Infrastructure.ApiBoo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.Infrastructure.IntegrationTesting", "Modules\Faura.Infrastructure.IntegrationTesting\Faura.Infrastructure.IntegrationTesting.csproj", "{09790598-6AD0-D698-A32D-D9A056BAF8D0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.IntegrationTest", "Templates\Faura.IntegrationTest\Faura.IntegrationTest.csproj", "{89320569-AAF8-4290-B912-699F792319F5}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + ..\.gitignore = ..\.gitignore + Directory.Build.props = Directory.Build.props + global.json = global.json + stylecop.json = stylecop.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAPI", "WebAPI", "{F1517752-590B-4773-A4D6-9E670C639523}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAPIGrpc", "WebAPIGrpc", "{F3ABDB5B-F5E0-43DE-898B-4170F6852893}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.WebAPI.UnitTests", "Templates\Faura.WebAPI.UnitTests\Faura.WebAPI.UnitTests.csproj", "{38B3C54C-1AED-42E7-A510-0734DF5A7B8F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.WebAPI.IntegrationTests", "Templates\Faura.WebAPI.IntegrationTests\Faura.WebAPI.IntegrationTests.csproj", "{71A15B05-FF1A-8D1F-0833-4F72927CEC48}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -75,10 +90,14 @@ Global {09790598-6AD0-D698-A32D-D9A056BAF8D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {09790598-6AD0-D698-A32D-D9A056BAF8D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {09790598-6AD0-D698-A32D-D9A056BAF8D0}.Release|Any CPU.Build.0 = Release|Any CPU - {89320569-AAF8-4290-B912-699F792319F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {89320569-AAF8-4290-B912-699F792319F5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89320569-AAF8-4290-B912-699F792319F5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {89320569-AAF8-4290-B912-699F792319F5}.Release|Any CPU.Build.0 = Release|Any CPU + {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Release|Any CPU.Build.0 = Release|Any CPU + {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -87,14 +106,17 @@ Global {F0757E5C-ACCD-44DD-B755-64CAFE654A7A} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} {8146A031-8E30-4F0F-940E-F77795C208F8} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} {1F34C695-2396-428D-87EF-7D3FDD9BD8C2} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} - {2B690895-0614-4013-85D8-7FC47B956C26} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26} + {2B690895-0614-4013-85D8-7FC47B956C26} = {F1517752-590B-4773-A4D6-9E670C639523} {F749C616-5B16-4A0B-9F88-D08BEAA5F27B} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} {CE7C267E-97CF-4C7F-A5D0-B8AFC30C6130} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} - {09790598-6AD0-D698-A32D-D9A056BAF8D0} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} - {89320569-AAF8-4290-B912-699F792319F5} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26} {AFC92389-71C2-BB14-10A4-CA1B415F02E9} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} - {31D599B8-9C10-410E-9ACD-0F2201C2BD4E} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26} + {31D599B8-9C10-410E-9ACD-0F2201C2BD4E} = {F3ABDB5B-F5E0-43DE-898B-4170F6852893} {93D57E51-3F79-19CF-B65F-08600B130F57} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} + {09790598-6AD0-D698-A32D-D9A056BAF8D0} = {420A3EFF-9247-407D-B58F-EC8144EB14F4} + {F1517752-590B-4773-A4D6-9E670C639523} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26} + {F3ABDB5B-F5E0-43DE-898B-4170F6852893} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26} + {38B3C54C-1AED-42E7-A510-0734DF5A7B8F} = {F1517752-590B-4773-A4D6-9E670C639523} + {71A15B05-FF1A-8D1F-0833-4F72927CEC48} = {F1517752-590B-4773-A4D6-9E670C639523} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7B487365-BA97-49F1-93FD-C12DB361C20B} diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs index 8283470..88bc600 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs @@ -1,14 +1,13 @@ -using Microsoft.Extensions.DependencyInjection; - namespace Faura.Infrastructure.ApiBootstrapper.Extensions; +using Microsoft.Extensions.DependencyInjection; + public static class ApiExtensions { /// /// Configures controllers. /// /// services. - /// public static IMvcBuilder ConfigureControllers(this IServiceCollection services) => services.AddControllers(); } diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs index 71c0402..73956eb 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs @@ -1,8 +1,8 @@ -using Faura.Configurations; -using Microsoft.Extensions.Configuration; - namespace Faura.Infrastructure.ApiBootstrapper.Extensions; +using Faura.Infrastructure.Common.Models; +using Microsoft.Extensions.Configuration; + public static class ConfigurationExtensions { public static void ConfigureUserSecrets(this IConfigurationBuilder configBuilder) diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs index 0538053..f639345 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs @@ -1,22 +1,21 @@ -using Microsoft.AspNetCore.Builder; +namespace Faura.Infrastructure.ApiBootstrapper.Extensions; + +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -namespace Faura.Infrastructure.ApiBootstrapper.Extensions; - public static class HeadersPropagationExtensions { public const string CorrelationIdHeaderKey = "x-correlation-id"; public static void AddHeadersPropagation( this WebApplicationBuilder builder, - IConfiguration config - ) => builder.Services.AddHeadersPropagation(config); + IConfiguration config) + => builder.Services.AddHeadersPropagation(config); public static IServiceCollection AddHeadersPropagation( this IServiceCollection services, - IConfiguration config - ) + IConfiguration config) { services.AddHeaderPropagation(options => { diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs index fd7cf3b..706dc27 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs @@ -1,15 +1,15 @@ -using Faura.Configurations; +namespace Faura.Infrastructure.ApiBootstrapper.Extensions; + using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey; using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth; using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.Bearer; using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2; +using Faura.Infrastructure.Common.Models; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Swashbuckle.AspNetCore.SwaggerGen; -namespace Faura.Infrastructure.ApiBootstrapper.Extensions; - public static class SwaggerExtensions { /// @@ -29,8 +29,7 @@ public static void ConfigureUseSwagger(this IApplicationBuilder app) public static IServiceCollection SetUpSwagger( this IServiceCollection services, - IConfiguration configuration - ) + IConfiguration configuration) { if (FauraEnvironment.IsProduction) { @@ -49,13 +48,10 @@ IConfiguration configuration private static SwaggerGenOptions AddSwaggerSecurityConfigurations( this SwaggerGenOptions options, - IConfiguration configuration - ) - { - return options + IConfiguration configuration) + => options .AddOAuth2Authentication(configuration) .AddBearerAuthentication(configuration) .AddBasicAuthentication(configuration) .AddApiKeyAuthentication(configuration); - } } diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs index 1089e15..b3255ad 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs @@ -1,15 +1,14 @@ -using Microsoft.AspNetCore.Builder; +namespace Faura.Infrastructure.ApiBootstrapper.Extensions; + +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -namespace Faura.Infrastructure.ApiBootstrapper.Extensions; - public static class WebApplicationBuilderExtensions { public static WebApplicationBuilder BootstrapCommonFauraServices( - this WebApplicationBuilder builder - ) + this WebApplicationBuilder builder) { builder.Services.ConfigureControllers(); diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs index fd32aaa..2091220 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs @@ -1,8 +1,8 @@ -using Faura.Infrastructure.ApiBootstrapper.Middlewares; -using Microsoft.AspNetCore.Builder; - namespace Faura.Infrastructure.ApiBootstrapper.Extensions; +using Faura.Infrastructure.ApiBootstrapper.Middlewares; +using Microsoft.AspNetCore.Builder; + public static class WebApplicationExtensions { public static WebApplication ConfigureCommonFauraWebApplication(this WebApplication app) diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj index 33e005c..69022d8 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj @@ -1,5 +1,5 @@  - + net8.0 enable @@ -17,13 +17,22 @@ - - - + + + + + + + + + **/**/*.cs + + + True @@ -34,5 +43,5 @@ \ - + diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs index 4cd4371..5a641bd 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs @@ -1,9 +1,9 @@ -using Faura.Infrastructure.ApiBootstrapper.Extensions; +namespace Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId; + +using Faura.Infrastructure.ApiBootstrapper.Extensions; using Microsoft.AspNetCore.HeaderPropagation; using Microsoft.AspNetCore.Http; -namespace Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId; - public class CorrelationIdMiddleware { private readonly RequestDelegate _next; @@ -11,14 +11,13 @@ public class CorrelationIdMiddleware public CorrelationIdMiddleware( RequestDelegate next, - HeaderPropagationValues headerPropagationValues - ) + HeaderPropagationValues headerPropagationValues) { _next = next; _headerPropagationValues = headerPropagationValues; } - public async Task InvokeAsync(HttpContext context) + public Task InvokeAsync(HttpContext context) { var correlationId = context .Request.Headers[HeadersPropagationExtensions.CorrelationIdHeaderKey] @@ -28,12 +27,10 @@ public async Task InvokeAsync(HttpContext context) correlationId = Guid.NewGuid().ToString(); context.Request.Headers.TryAdd( HeadersPropagationExtensions.CorrelationIdHeaderKey, - correlationId - ); + correlationId); _headerPropagationValues.Headers!.TryAdd( HeadersPropagationExtensions.CorrelationIdHeaderKey, - correlationId - ); + correlationId); } var responseHeader = context @@ -43,10 +40,9 @@ public async Task InvokeAsync(HttpContext context) { context.Response.Headers.TryAdd( HeadersPropagationExtensions.CorrelationIdHeaderKey, - correlationId - ); + correlationId); } - await _next(context); + return _next(context); } } diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs index 2765988..7f9504d 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs @@ -1,12 +1,10 @@ -using Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId; -using Microsoft.AspNetCore.Builder; - namespace Faura.Infrastructure.ApiBootstrapper.Middlewares; +using Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId; +using Microsoft.AspNetCore.Builder; + public static class MiddlewareConfiguration { public static void ConfigureMiddlewares(this IApplicationBuilder app) - { - app.UseMiddleware(); - } + => app.UseMiddleware(); } diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs index 988f01d..2c5aff5 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs @@ -1,16 +1,15 @@ -using Microsoft.Extensions.Configuration; +namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey; + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; -namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey; - public static class ApiKeyExtensions { public static SwaggerGenOptions AddApiKeyAuthentication( this SwaggerGenOptions options, - IConfiguration configuration - ) + IConfiguration configuration) { var apiKeyOptions = configuration .GetSection(ApiKeyOptions.SectionName) @@ -27,8 +26,7 @@ IConfiguration configuration Name = apiKeyOptions.Name, In = apiKeyOptions.In, Description = "API Key Authentication", - } - ); + }); options.AddSecurityRequirement( new OpenApiSecurityRequirement @@ -44,8 +42,7 @@ IConfiguration configuration }, new List() }, - } - ); + }); return options; } diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs index a804272..0d6cc1b 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs @@ -1,7 +1,7 @@ -using Microsoft.OpenApi.Models; - namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey; +using Microsoft.OpenApi.Models; + public class ApiKeyOptions { public const string SectionName = "Swagger:Authentication:ApiKey"; diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs index 675f674..943ce6b 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs @@ -1,16 +1,15 @@ -using Microsoft.Extensions.Configuration; +namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth; + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; -namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth; - public static class BasicAuthExtensions { public static SwaggerGenOptions AddBasicAuthentication( this SwaggerGenOptions options, - IConfiguration configuration - ) + IConfiguration configuration) { var basicAuthOptions = configuration .GetSection(BasicAuthOptions.SectionName) @@ -21,14 +20,13 @@ IConfiguration configuration // Security Definition options.AddSecurityDefinition( - basicAuthOptions.Name, + basicAuthOptions!.Name, new OpenApiSecurityScheme { Type = SecuritySchemeType.Http, Scheme = "basic", Description = "Basic Authentication", - } - ); + }); // Security Requirement options.AddSecurityRequirement( @@ -45,8 +43,7 @@ IConfiguration configuration }, new List() }, - } - ); + }); return options; } diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs index ec55c56..5ed0e2e 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth; +namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth; public class BasicAuthOptions { diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs index c88990a..5f5ff7b 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs @@ -1,16 +1,15 @@ -using Microsoft.Extensions.Configuration; +namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.Bearer; + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; -namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.Bearer; - public static class BearerExtensions { public static SwaggerGenOptions AddBearerAuthentication( this SwaggerGenOptions options, - IConfiguration configuration - ) + IConfiguration configuration) { var bearerOptions = configuration .GetSection(BearerOptions.SectionName) @@ -30,8 +29,7 @@ IConfiguration configuration BearerFormat = "JWT", In = ParameterLocation.Header, Description = "JWT Authorization header using the Bearer scheme.", - } - ); + }); // Security Requirement var requirement = new OpenApiSecurityRequirement diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs index 706b125..a328beb 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs @@ -1,16 +1,15 @@ -using Microsoft.Extensions.Configuration; +namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2; + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; -namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2; - public static class OAuth2Extensions { public static SwaggerGenOptions AddOAuth2Authentication( this SwaggerGenOptions options, - IConfiguration configuration - ) + IConfiguration configuration) { var oauth2Options = configuration .GetSection(OAuth2Options.SectionName) @@ -21,7 +20,7 @@ IConfiguration configuration // Security Definition options.AddSecurityDefinition( - oauth2Options.Name, + oauth2Options!.Name, new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, @@ -29,12 +28,11 @@ IConfiguration configuration { Implicit = new OpenApiOAuthFlow { - AuthorizationUrl = new Uri(oauth2Options.AuthenticationURL), + AuthorizationUrl = new Uri(oauth2Options.AuthenticationURL!), Scopes = oauth2Options.Scopes, }, }, - } - ); + }); // Security Requirement var requirement = new OpenApiSecurityRequirement diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs index 64ce93a..58bb9ff 100644 --- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs +++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs @@ -1,12 +1,12 @@ -namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2; +namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2; public class OAuth2Options { public const string SectionName = "Swagger:Authentication:OAuth2"; public bool Enable { get; set; } = false; - public string Name { get; set; } - public string AuthenticationURL { get; set; } + public string? Name { get; set; } + public string? AuthenticationURL { get; set; } public Dictionary Scopes { get; set; } = - new() { { "openid", "openid" }, { "profile", "profile" } }; + new () { { "openid", "openid" }, { "profile", "profile" } }; } diff --git a/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj b/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj index afd0134..969efbf 100644 --- a/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj +++ b/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj @@ -1,5 +1,5 @@  - + net8.0 enable @@ -22,6 +22,12 @@ + + + **/**/*.cs + + + True @@ -32,4 +38,5 @@ \ + diff --git a/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs b/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs index 9424115..eb82fa1 100644 --- a/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs +++ b/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs @@ -1,5 +1,4 @@ -namespace Faura.Configurations; - +namespace Faura.Infrastructure.Common.Models; public enum FauraDeploymentMode { Local, @@ -12,8 +11,8 @@ public enum FauraDeploymentMode public static class FauraEnvironment { - private static FauraDeploymentMode? _currentMode; private const string FauraEnvVariableName = "FAURA_ENVIRONMENT"; + private static FauraDeploymentMode? _currentMode; public static FauraDeploymentMode CurrentMode => _currentMode ??= DetectMode(); diff --git a/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs b/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs index d7aa150..657d159 100644 --- a/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs +++ b/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs @@ -1,10 +1,10 @@ -using System.Reflection; - namespace Faura.Infrastructure.Common.Utils; +using System.Reflection; + public static class FileUtils { - private static string? AapplicationDirectory; + private static string? applicationDirectory; public static List SearchFiles(string pattern, string baseDirectory = "") { @@ -27,16 +27,11 @@ public static List SearchFiles(string pattern, string baseDirectory = "" } public static string? GetApplicationDirectory() - { - return AapplicationDirectory ??= Path.GetDirectoryName( - Assembly.GetEntryAssembly()?.Location - ); - } + => applicationDirectory ??= Path.GetDirectoryName( + Assembly.GetEntryAssembly()?.Location); private static string ResolveDirectory(string baseDirectory) - { - return !string.IsNullOrWhiteSpace(baseDirectory) && Directory.Exists(baseDirectory) + => !string.IsNullOrWhiteSpace(baseDirectory) && Directory.Exists(baseDirectory) ? baseDirectory : Directory.GetCurrentDirectory(); - } } diff --git a/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs b/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs index 2633acd..0b53a54 100644 --- a/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs +++ b/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs @@ -1,16 +1,15 @@ -using Microsoft.Extensions.Configuration; +namespace Faura.Infrastructure.Common.Utils; + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -namespace Faura.Infrastructure.Common.Utils; - public static class OptionUtils { public static T? GetTypedOptions( this IServiceCollection services, IConfiguration configuration, - string sectionName - ) + string sectionName) where T : class, new() { if (configuration == null || string.IsNullOrWhiteSpace(sectionName)) diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs index e83571d..5ad0189 100644 --- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs +++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs @@ -1,8 +1,8 @@ -using Faura.Configurations; -using Microsoft.Extensions.Configuration; - namespace Faura.Infrastructure.GrpcBootstrapper.Extensions; +using Faura.Infrastructure.Common.Models; +using Microsoft.Extensions.Configuration; + public static class ConfigurationExtensions { public static void ConfigureUserSecrets(this IConfigurationBuilder configBuilder) diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs index 3d4cf74..11c45e7 100644 --- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs +++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs @@ -1,27 +1,19 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - namespace Faura.Infrastructure.GrpcBootstrapper.Extensions; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; + public static class HeadersPropagationExtensions { public const string CorrelationIdHeaderKey = "x-correlation-id"; public static void AddHeadersPropagation( - this WebApplicationBuilder builder, - IConfiguration config - ) => builder.Services.AddHeadersPropagation(config); + this WebApplicationBuilder builder) => builder.Services.AddHeadersPropagation(); public static IServiceCollection AddHeadersPropagation( - this IServiceCollection services, - IConfiguration config - ) + this IServiceCollection services) { - services.AddHeaderPropagation(options => - { - options.Headers.Add(CorrelationIdHeaderKey); - }); + services.AddHeaderPropagation(options => options.Headers.Add(CorrelationIdHeaderKey)); return services; } } diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs index 38a7f03..6c2f453 100644 --- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs +++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs @@ -1,23 +1,19 @@ -using Faura.Infrastructure.GrpcBootstrapper.Interceptors; +namespace Faura.Infrastructure.GrpcBootstrapper.Extensions; + +using Faura.Infrastructure.GrpcBootstrapper.Interceptors; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -namespace Faura.Infrastructure.GrpcBootstrapper.Extensions; - public static class WebApplicationBuilderExtensions { public static WebApplicationBuilder BootstrapCommonFauraServices( - this WebApplicationBuilder builder - ) + this WebApplicationBuilder builder) { - builder.Services.AddGrpc(options => - { - options.Interceptors.Add(); - }); + builder.Services.AddGrpc(options => options.Interceptors.Add()); - builder.Services.AddHeadersPropagation(builder.Configuration); + builder.Services.AddHeadersPropagation(); return builder; } diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs index 0cb7e3d..f6a8ff7 100644 --- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs +++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs @@ -1,23 +1,19 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Routing; - namespace Faura.Infrastructure.GrpcBootstrapper.Extensions; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; + public static class WebApplicationExtensions { public static IApplicationBuilder ConfigureCommonFauraWebApplication( this IApplicationBuilder app, - Action mapGrpcServices - ) + Action mapGrpcServices) { app.UseRouting(); app.UseHeaderPropagation(); - app.UseEndpoints(endpoints => - { - mapGrpcServices(endpoints); - }); + app.UseEndpoints(endpoints => mapGrpcServices(endpoints)); return app; } diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj index 5fe256f..246f0c9 100644 --- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj +++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj @@ -1,5 +1,5 @@  - + net8.0 enable @@ -18,10 +18,19 @@ - - + + + + + + + + **/**/*.cs + + + True @@ -32,5 +41,5 @@ \ - + diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs index c1339d9..7f0485f 100644 --- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs +++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs @@ -1,24 +1,21 @@ -using Grpc.Core; +namespace Faura.Infrastructure.GrpcBootstrapper.Interceptors; + +using Grpc.Core; using Grpc.Core.Interceptors; using Microsoft.AspNetCore.HeaderPropagation; -namespace Faura.Infrastructure.GrpcBootstrapper.Interceptors; - public class CorrelationIdInterceptor : Interceptor { - private readonly HeaderPropagationValues _headerPropagationValues; private const string HeaderKey = "x-correlation-id"; + private readonly HeaderPropagationValues _headerPropagationValues; public CorrelationIdInterceptor(HeaderPropagationValues headerPropagationValues) - { - _headerPropagationValues = headerPropagationValues; - } + => _headerPropagationValues = headerPropagationValues; - public override async Task UnaryServerHandler( + public override Task UnaryServerHandler( TRequest request, ServerCallContext context, - UnaryServerMethod continuation - ) + UnaryServerMethod continuation) { var correlationId = context.RequestHeaders.GetValue(HeaderKey) ?? Guid.NewGuid().ToString(); @@ -26,6 +23,6 @@ UnaryServerMethod continuation context.ResponseTrailers.Add(HeaderKey, correlationId); - return await continuation(request, context); + return continuation(request, context); } } diff --git a/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs b/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs index 06e0656..b0b6690 100644 --- a/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs +++ b/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs @@ -1,23 +1,21 @@ -using Faura.Infrastructure.Common.Utils; +namespace Faura.Infrastructure.JWT.Extensions; + +using Faura.Infrastructure.Common.Utils; using Faura.Infrastructure.JWT.Options; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; -namespace Faura.Infrastructure.JWT.Extensions; - public static class ServiceCollectionExtensions { public static IServiceCollection SetUpJwt( this IServiceCollection services, - IConfiguration configuration - ) + IConfiguration configuration) { var jwtOptions = services.GetTypedOptions( configuration, - JwtOptions.SectionName - ); + JwtOptions.SectionName); services.AddAuthorization(); services diff --git a/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj b/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj index 169a8d1..1003781 100644 --- a/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj +++ b/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj @@ -1,5 +1,5 @@  - + net8.0 enable @@ -16,9 +16,18 @@ - + + + + + + + + **/**/*.cs + + @@ -30,5 +39,5 @@ \ - + diff --git a/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs b/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs index 9ea5424..9b5827e 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.Logger.Enrichers; +namespace Faura.Infrastructure.Logger.Enrichers; using Microsoft.Extensions.Configuration; using Serilog; @@ -11,7 +11,7 @@ public static LoggerConfiguration ConfigureLogEnrichers(this LoggerConfiguration var loggingOptions = configuration.GetSection(LoggingOptions.SectionName).Get(); return loggerConfiguration - .Enrich.WithProperty("ApplicationName", loggingOptions.ApplicationName) + .Enrich.WithProperty("ApplicationName", loggingOptions!.ApplicationName) .Enrich.With(new CorrelationIdEnricher()); } } diff --git a/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs b/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs index 9671625..de88be3 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.Logger.Enrichers; +namespace Faura.Infrastructure.Logger.Enrichers; using Microsoft.AspNetCore.HeaderPropagation; using Serilog.Core; @@ -10,7 +10,10 @@ public class CorrelationIdEnricher : ILogEventEnricher private const string HeaderKey = "x-correlation-id"; private readonly HeaderPropagationValues _headerPropagationValues; - public CorrelationIdEnricher() : this(new HeaderPropagationValues()) { } + public CorrelationIdEnricher() + : this(new HeaderPropagationValues()) + { + } public CorrelationIdEnricher(HeaderPropagationValues headerPropagationValues) => _headerPropagationValues = headerPropagationValues; diff --git a/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj b/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj index 1f6de5f..fe26329 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj +++ b/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj @@ -16,16 +16,25 @@ - - + - + + + + + + + + **/**/*.cs + + + True diff --git a/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs b/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs index b694a58..b81471c 100644 --- a/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs +++ b/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs @@ -13,6 +13,7 @@ namespace Faura.Infrastructure.Logger; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Faura.Infrastructure.Logger.Options; +using Faura.Infrastructure.Logger.Outputs.Seq; public static class LoggingConfiguration { @@ -56,4 +57,4 @@ public static LoggerConfiguration ConfigureFauraLogging( return loggerConfiguration; } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs index 86457d8..e8e418f 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs @@ -1,8 +1,8 @@ -namespace Faura.Infrastructure.Logger.Options +namespace Faura.Infrastructure.Logger.Options { public class LoggingOptions { public const string SectionName = "Logging"; - public string ApplicationName { get; set; } + public string? ApplicationName { get; set; } } } diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs index daa5dc9..4474dda 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.Logger.Outputs.Console; +namespace Faura.Infrastructure.Logger.Outputs.Console; using Microsoft.Extensions.Configuration; using Serilog.Core; @@ -8,7 +8,7 @@ public static class LogConsoleExtensions { public const string BaseLogTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}"; - public static LoggerConfiguration ConfigureLogConsole(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List logEnrichers = null) + public static LoggerConfiguration ConfigureLogConsole(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List? logEnrichers = null) { var consoleOptions = configuration.GetSection(LogConsoleOptions.SectionName).Get() ?? new LogConsoleOptions(); diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs index 33e1ef5..a773ae9 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs @@ -1,9 +1,9 @@ -namespace Faura.Infrastructure.Logger.Outputs.Console; +namespace Faura.Infrastructure.Logger.Outputs.Console; public class LogConsoleOptions { public const string SectionName = "Logging:Outputs:Console"; public bool Enable { get; set; } = false; - public string LogTemplate { get; set; } + public string? LogTemplate { get; set; } } diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs index cdbd7f1..1d6759d 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.Logger.Outputs.GrayLog; +namespace Faura.Infrastructure.Logger.Outputs.GrayLog; using Serilog.Sinks.Graylog; using Serilog; @@ -8,7 +8,7 @@ public static class LogGrayLogExtensions { - public static LoggerConfiguration ConfigureLogGraylog(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List logEnrichers = null) + public static LoggerConfiguration ConfigureLogGraylog(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List? logEnrichers = null) { var graylogOptions = configuration.GetSection(LogGraylogOptions.SectionName).Get(); @@ -17,11 +17,11 @@ public static LoggerConfiguration ConfigureLogGraylog(this LoggerConfiguration l var graylogSinkConfig = new GraylogSinkOptions { HostnameOrAddress = graylogOptions.GrayLogHost, - TransportType = GetGraylogTransportTypeFromString(graylogOptions.GrayLogProtocol), - HostnameOverride = graylogOptions.GrayLogHost, + TransportType = GetGraylogTransportTypeFromString(graylogOptions.GrayLogProtocol!), + HostnameOverride = graylogOptions.GrayLogHost!, Port = graylogOptions.GrayLogPort, MaxMessageSizeInUdp = graylogOptions.MaxUdpMessageSize, - Facility = "FauraApp" + Facility = "FauraApp", }; return loggerConfiguration diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs index 6f190ad..2a40857 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs @@ -1,12 +1,12 @@ -namespace Faura.Infrastructure.Logger.Outputs.GrayLog; +namespace Faura.Infrastructure.Logger.Outputs.GrayLog; public class LogGraylogOptions { public const string SectionName = "Logging:Outputs:Graylog"; public bool Enable { get; set; } = false; - public string GrayLogHost { get; set; } + public string? GrayLogHost { get; set; } public int GrayLogPort { get; set; } - public string GrayLogProtocol { get; set; } + public string? GrayLogProtocol { get; set; } public int MaxUdpMessageSize { get; set; } } diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs index 40ac89b..8eed022 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.Logger.Outputs.GrayLog; +namespace Faura.Infrastructure.Logger.Outputs.Seq; using Serilog; using Microsoft.Extensions.Configuration; @@ -6,12 +6,12 @@ public static class LogSeqExtensions { - public static LoggerConfiguration ConfigureLogSeq(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List logEnrichers = null) + public static LoggerConfiguration ConfigureLogSeq(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List? logEnrichers = null) { var seqOptions = configuration.GetSection(LogSeqOptions.SectionName).Get() ?? new LogSeqOptions(); if (!seqOptions.Enable) return loggerConfiguration; return loggerConfiguration - .WriteTo.Seq(serverUrl: seqOptions.ServerUrl, apiKey: seqOptions.ApiKey); + .WriteTo.Seq(serverUrl: seqOptions.ServerUrl!, apiKey: seqOptions.ApiKey); } } diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs index fb908d2..95cc0d2 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs @@ -1,12 +1,11 @@ -namespace Faura.Infrastructure.Logger.Outputs.GrayLog; +namespace Faura.Infrastructure.Logger.Outputs.Seq; public class LogSeqOptions { public const string SectionName = "Logging:Outputs:Seq"; public bool Enable { get; set; } = false; - public string ServerUrl { get; set; } - public string ApplicationName { get; set; } - public string ApiKey { get; set; } - + public string? ServerUrl { get; set; } + public string? ApplicationName { get; set; } + public string? ApiKey { get; set; } } diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs index 72d494c..98cd289 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb; +namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb; using Faura.Infrastructure.Common.Utils; using Microsoft.Extensions.Configuration; @@ -15,7 +15,7 @@ public static LoggerConfiguration ConfigureLogSqLiteDb(this LoggerConfiguration if (!sqLiteDbOptions.Enable) return loggerConfiguration; return loggerConfiguration - .WriteTo.SQLite(GetSqliteDbLogFilePath(sqLiteDbOptions.LogSqLiteFile, DefaultLogSqLiteFileName)); + .WriteTo.SQLite(GetSqliteDbLogFilePath(sqLiteDbOptions.LogSqLiteFile!, DefaultLogSqLiteFileName)); } internal static string GetSqliteDbLogFilePath(string file, string defaultFileName) diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs index 2faf4fc..fc09a02 100644 --- a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs +++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs @@ -1,9 +1,9 @@ -namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb; +namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb; public class LogSqLiteDbOptions { public const string SectionName = "Logging:Outputs:SqLiteDb"; public bool Enable { get; set; } = false; - public string LogSqLiteFile { get; set; } + public string? LogSqLiteFile { get; set; } } diff --git a/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj b/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj index b6d782e..7b2785e 100644 --- a/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj +++ b/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj @@ -16,10 +16,15 @@ - + + + **/**/*.cs + + + True diff --git a/src/Modules/Faura.Infrastructure.Result/FauraError.cs b/src/Modules/Faura.Infrastructure.Result/FauraError.cs index bc58773..9e06525 100644 --- a/src/Modules/Faura.Infrastructure.Result/FauraError.cs +++ b/src/Modules/Faura.Infrastructure.Result/FauraError.cs @@ -1,20 +1,12 @@ -namespace Faura.Infrastructure.Result; +namespace Faura.Infrastructure.Result; using System.Net; -public class FauraError +public class FauraError(string code, string message, HttpStatusCode? httpStatus = null) { - public string Code { get; init; } + public string Code { get; init; } = code; - public string Message { get; init; } + public string Message { get; init; } = message; - public HttpStatusCode HttpStatus { get; private set; } - - public FauraError(string code, string message, HttpStatusCode? httpStatus = null) - { - Code = code; - Message = message; - HttpStatus = httpStatus ?? HttpStatusCode.InternalServerError; - } - -} \ No newline at end of file + public HttpStatusCode HttpStatus { get; private set; } = httpStatus ?? HttpStatusCode.InternalServerError; +} diff --git a/src/Modules/Faura.Infrastructure.Result/FauraResult.cs b/src/Modules/Faura.Infrastructure.Result/FauraResult.cs index 591825b..7f9ad6d 100644 --- a/src/Modules/Faura.Infrastructure.Result/FauraResult.cs +++ b/src/Modules/Faura.Infrastructure.Result/FauraResult.cs @@ -1,25 +1,24 @@ -namespace Faura.Infrastructure.Result; +namespace Faura.Infrastructure.Result; -using Faura.Infrastructure.Result.Helpers; -using Microsoft.AspNetCore.Mvc; using System.Net; using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Mvc; +using Faura.Infrastructure.Result.Helpers; +using System.Collections.Generic; +using System; +using System.Linq; public class FauraResult : IFauraResult { - protected FauraResult() { } + public FauraResult(T value) => Data = value; - public FauraResult(T value) + protected FauraResult() { - Data = value; } - public static implicit operator T(FauraResult result) => result.Data; - public static implicit operator FauraResult(T value) => new FauraResult(value); - [JsonInclude] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public T Data { get; init; } + public T? Data { get; init; } [JsonIgnore] public Type ValueType => typeof(T); @@ -31,78 +30,52 @@ public FauraResult(T value) [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public IEnumerable Errors { get; protected set; } = []; - public object GetData() - { - return Data; - } + public static implicit operator T(FauraResult result) => result.Data!; - public static FauraResult Success(T value) - { - return new FauraResult(value); - } + public static implicit operator FauraResult(T value) => new(value); - public static FauraResult Error(FauraError fauraError) - { - return new FauraResult() { Errors = [fauraError] }; - } + public static FauraResult Success(T value) => new (value); - public static FauraResult Error(IEnumerable fauraErrors = null) + public static FauraResult Error(FauraError fauraError) => new() { - return new FauraResult() - { - Errors = fauraErrors - }; - } + Errors = [fauraError], + }; - public void AddError(FauraError error) + public static FauraResult Error(IEnumerable? fauraErrors = null) => new() { - IEnumerable errors; - if (Errors != null) - { - errors = Errors.Append(error); - } - else - { - errors = []; - } + Errors = fauraErrors ?? [], + }; - Errors = errors; - } + public object? GetData() => Data; + + public void AddError(FauraError error) + => Errors = Errors.Append(error); public IEnumerable GetErrors() - { - return Errors; - } + => Errors; public bool ReturnedError(FauraError errorCode) - { - return Errors?.Any((myError) => myError.Code == $"{errorCode}") ?? false; - } + => Errors?.Any(e => e.Code == errorCode.Code) ?? false; public bool ReturnedError(IEnumerable errorCodes) - { - return errorCodes.Any((errorCode) => Errors?.Any((myError) => myError.Code == $"{errorCode}") ?? false); - } + => errorCodes.Any(code => Errors?.Any(e => e.Code == code.Code) ?? false); public IActionResult BuildResult(HttpStatusCode httpStatusCode = HttpStatusCode.OK) { if (IsSuccess) { - T dataAsT = Data; - if (dataAsT == null) - { + if (EqualityComparer.Default.Equals(Data!, default!)) return new NoContentResult(); - } - return new OkObjectResult(dataAsT) + return new OkObjectResult(Data) { StatusCode = (int)httpStatusCode, }; - } + return new ObjectResult(Errors) { StatusCode = Errors.ToHigherHttpStatusCode(), }; } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs b/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs index 4bb2ede..998d99c 100644 --- a/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs +++ b/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs @@ -1,6 +1,4 @@ -namespace Faura.Infrastructure.Result.Helpers; - -using Faura.Infrastructure.Result; +namespace Faura.Infrastructure.Result.Helpers; public static class FauraErrorHelper { diff --git a/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs b/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs index ccaad13..b57bad8 100644 --- a/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs +++ b/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs @@ -1,7 +1,7 @@ -namespace Faura.Infrastructure.Result; +namespace Faura.Infrastructure.Result; public interface IFauraResult { IEnumerable Errors { get; } Type ValueType { get; } - object GetData(); + object? GetData(); } diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs index 4f9575c..98c7637 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.UnitOfWork.Common; +namespace Faura.Infrastructure.UnitOfWork.Common; using Faura.Infrastructure.UnitOfWork.Enums; using Microsoft.EntityFrameworkCore; @@ -17,7 +17,8 @@ public static void ConfigureDatabase( this IServiceCollection services, string connectionString, DatabaseType databaseType, - ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) where TContext : DbContext + ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) + where TContext : DbContext { if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentException("Connection string cannot be null or empty.", nameof(connectionString)); @@ -31,7 +32,8 @@ public static async Task ConfigureDatabase( string connectionStringName, DatabaseType databaseType, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped, - bool runMigrations = false) where TContext : DbContext + bool runMigrations = false) + where TContext : DbContext { var connectionString = configuration.GetConnectionString(connectionStringName) ?? throw new ArgumentException($"Connection string '{connectionStringName}' not found or is empty."); @@ -58,7 +60,8 @@ private static void ConfigureDatabaseOptions( break; case DatabaseType.MySql: - options.UseMySql(ServerVersion.AutoDetect(connectionString), + options.UseMySql( + ServerVersion.AutoDetect(connectionString), mysqlOptions => mysqlOptions.EnableRetryOnFailure(MaxRetryCount, TimeSpan.FromSeconds(MaxRetryDelay), null)); break; @@ -75,7 +78,8 @@ private static void ConfigureDatabaseOptions( } } - private static async Task ApplyMigrations(IServiceCollection services) where TContext : DbContext + private static async Task ApplyMigrations(IServiceCollection services) + where TContext : DbContext { using var serviceProvider = services.BuildServiceProvider(); var logger = serviceProvider.GetService(); @@ -83,7 +87,7 @@ private static async Task ApplyMigrations(IServiceCollection services) if (context == null) { - logger?.LogError($"Unable to resolve {typeof(TContext).FullName}. Database migration will not be performed."); + logger?.LogError("Unable to resolve {ContextType}. Database migration will not be performed.", typeof(TContext).FullName); return; } @@ -93,8 +97,8 @@ private static async Task ApplyMigrations(IServiceCollection services) } catch (Exception ex) { - logger?.LogError(ex, "An error occurred while migrating the database."); - throw; + string contextName = typeof(TContext).FullName ?? "UnknownContext"; + logger?.LogError(ex, "An error occurred while migrating the database for context {ContextName}. See inner exception for details.", contextName); } } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs index c0ee16d..6c4c552 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs @@ -1,7 +1,7 @@ -namespace Faura.Infrastructure.UnitOfWork.Enums; +namespace Faura.Infrastructure.UnitOfWork.Enums; /// -/// Direction for sorting operations +/// Direction for sorting operations. /// public enum SortDirection { @@ -13,5 +13,5 @@ public enum SortDirection /// /// Sort in descending order /// - Descending -} \ No newline at end of file + Descending, +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs index e3ca4fe..76293dd 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs @@ -1,24 +1,18 @@ -namespace Faura.Infrastructure.UnitOfWork.Exceptions; +namespace Faura.Infrastructure.UnitOfWork.Exceptions; -using System.Runtime.Serialization; - -[Serializable] public class NullContextException : Exception { - public NullContextException() : base() - { - } - - public NullContextException(string message) : base(message) + public NullContextException() { } - public NullContextException(string message, Exception innerException) : base(message, innerException) + public NullContextException(string message) + : base(message) { } - protected NullContextException(SerializationInfo serializationInfo, StreamingContext streamingContext) - : base(serializationInfo, streamingContext) + public NullContextException(string message, Exception innerException) + : base(message, innerException) { } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs index 96adabb..26386ac 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs @@ -1,15 +1,21 @@ -namespace Faura.Infrastructure.UnitOfWork.Exceptions; +namespace Faura.Infrastructure.UnitOfWork.Exceptions; /// -/// Base exception for repository-related errors +/// Base exception for repository-related errors. /// public abstract class RepositoryException : Exception { - protected RepositoryException(string message) : base(message) + protected RepositoryException() { } - protected RepositoryException(string message, Exception innerException) : base(message, innerException) + protected RepositoryException(string message) + : base(message) { } -} \ No newline at end of file + + protected RepositoryException(string message, Exception innerException) + : base(message, innerException) + { + } +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs index 816f198..0f9313c 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs @@ -1,15 +1,21 @@ -namespace Faura.Infrastructure.UnitOfWork.Exceptions; +namespace Faura.Infrastructure.UnitOfWork.Exceptions; /// /// Exception for errors during repository operations (create, update, delete) /// public class RepositoryOperationException : RepositoryException { - public RepositoryOperationException(string message) : base(message) + public RepositoryOperationException() { } - public RepositoryOperationException(string message, Exception innerException) : base(message, innerException) + public RepositoryOperationException(string message) + : base(message) + { + } + + public RepositoryOperationException(string message, Exception innerException) + : base(message, innerException) { } } diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs index 81dabe5..51269ba 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs @@ -1,15 +1,21 @@ -namespace Faura.Infrastructure.UnitOfWork.Exceptions; +namespace Faura.Infrastructure.UnitOfWork.Exceptions; /// -/// Exception for errors during repository queries +/// Exception for errors during repository queries. /// public class RepositoryQueryException : RepositoryException { - public RepositoryQueryException(string message) : base(message) + public RepositoryQueryException() { } - public RepositoryQueryException(string message, Exception innerException) : base(message, innerException) + public RepositoryQueryException(string message) + : base(message) + { + } + + public RepositoryQueryException(string message, Exception innerException) + : base(message, innerException) { } } diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs index d7e2009..6885a3b 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs @@ -1,24 +1,18 @@ -namespace Faura.Infrastructure.UnitOfWork.Exceptions; +namespace Faura.Infrastructure.UnitOfWork.Exceptions; -using System.Runtime.Serialization; - -[Serializable] public class NullTransactionException : Exception { - public NullTransactionException() : base() - { - } - - public NullTransactionException(string message) : base(message) + public NullTransactionException() { } - public NullTransactionException(string message, Exception innerException) : base(message, innerException) + public NullTransactionException(string message) + : base(message) { } - protected NullTransactionException(SerializationInfo serializationInfo, StreamingContext streamingContext) - : base(serializationInfo, streamingContext) + public NullTransactionException(string message, Exception innerException) + : base(message, innerException) { } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj b/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj index 80c765b..367c237 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj @@ -16,14 +16,21 @@ - - - + + + + + + + **/**/*.cs + + + True diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs index 8ca1473..9a76443 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs @@ -1,42 +1,43 @@ -namespace Faura.Infrastructure.UnitOfWork.Models; +namespace Faura.Infrastructure.UnitOfWork.Models; /// -/// Represents a paginated result set +/// Represents a paginated result set. /// -public class PagedResult where T : class +public class PagedResult + where T : class { /// - /// Items in the current page + /// Gets or sets items in the current page. /// public IList Items { get; set; } = new List(); /// - /// Current page number + /// Gets or sets current page number. /// public int CurrentPage { get; set; } /// - /// Number of items per page + /// Gets or sets number of items per page. /// public int PageSize { get; set; } /// - /// Total number of items across all pages + /// Gets or sets total number of items across all pages. /// public long TotalCount { get; set; } /// - /// Total number of pages + /// Gets or sets total number of pages. /// public int TotalPages { get; set; } /// - /// Whether a previous page exists + /// Gets or sets a value indicating whether whether a previous page exists. /// public bool HasPreviousPage { get; set; } /// - /// Whether a next page exists + /// Gets or sets a value indicating whether whether a next page exists. /// public bool HasNextPage { get; set; } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs index 6a32df6..13d51ce 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs @@ -1,17 +1,18 @@ namespace Faura.Infrastructure.UnitOfWork.Projectors; -public interface IProjector where TEntity : class +public interface IProjector + where TEntity : class { /// - /// Gets a projection from the entity + /// Gets a projection from the entity. /// - /// The result type of the projection - /// The projection function - /// Optional page number for pagination - /// Optional page size for pagination - /// A task that represents the asynchronous operation, containing the projected results + /// The result type of the projection. + /// The projection function. + /// Optional page number for pagination. + /// Optional page size for pagination. + /// A task that represents the asynchronous operation, containing the projected results. Task> GetProjectionAsync( Func, IQueryable> projection, int? page = null, int? pageSize = null); -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs index 23ccead..e09f4d8 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs @@ -1,16 +1,14 @@ namespace Faura.Infrastructure.UnitOfWork.Projectors; -using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; -public class Projector : IProjector where TEntity : class +public class Projector : IProjector + where TEntity : class { private readonly DbContext _context; public Projector(DbContext context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } + => _context = context ?? throw new ArgumentNullException(nameof(context)); public async Task> GetProjectionAsync( Func, IQueryable> projection, @@ -28,4 +26,4 @@ public async Task> GetProjectionAsync( var projectionQuery = projection(query); return await projectionQuery.ToListAsync(); } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs index df2593c..bef44fe 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs @@ -1,29 +1,29 @@ -namespace Faura.Infrastructure.UnitOfWork.Repositories; +namespace Faura.Infrastructure.UnitOfWork.Repositories; using Faura.Infrastructure.UnitOfWork.Enums; using Faura.Infrastructure.UnitOfWork.Exceptions; using Faura.Infrastructure.UnitOfWork.Models; -using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using System.Linq.Expressions; /// -/// Generic repository implementation for data access operations +/// Generic repository implementation for data access operations. /// -/// The entity type this repository works with -public class EntityRepository : IEntityRepository where TEntity : class +/// The entity type this repository works with. +public class EntityRepository : IEntityRepository + where TEntity : class { private readonly DbContext _dbContext; private readonly ILogger> _logger; private readonly bool _enableTracking; /// - /// Creates a new instance of the repository + /// Initializes a new instance of the class. /// - /// Database context to use for operations - /// Logger for capturing operation information - /// Whether to enable entity tracking + /// Database context to use for operations. + /// Logger for capturing operation information. + /// Whether to enable entity tracking. public EntityRepository( DbContext dbContext, ILogger> logger, @@ -37,7 +37,7 @@ public EntityRepository( } /// - /// Base queryable for this entity type + /// Gets base queryable for this entity type. /// private IQueryable BaseQuery => GetBaseQuery(); @@ -212,35 +212,15 @@ public async Task> DeleteRangeAsync(IEnumerable en } /// - public Task GetFirstOrDefaultAsync(Expression> predicate = null) - { - try - { - return ApplyPredicate(predicate).FirstOrDefaultAsync(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error retrieving first entity of type {EntityType}", typeof(TEntity).Name); - throw new RepositoryQueryException($"Failed to retrieve first entity: {ex.Message}", ex); - } - } + public Task GetFirstOrDefaultAsync(Expression>? predicate = null) + => ApplyPredicate(predicate).FirstOrDefaultAsync(); /// - public Task GetLastOrDefaultAsync(Expression> predicate = null) - { - try - { - return ApplyPredicate(predicate).LastOrDefaultAsync(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error retrieving last entity of type {EntityType}", typeof(TEntity).Name); - throw new RepositoryQueryException($"Failed to retrieve last entity: {ex.Message}", ex); - } - } + public Task GetLastOrDefaultAsync(Expression>? predicate = null) + => ApplyPredicate(predicate).LastOrDefaultAsync(); /// - public async Task> GetAsync(Expression> predicate = null) + public async Task> GetAsync(Expression>? predicate = null) { try { @@ -274,7 +254,7 @@ public async Task> GetSortedAsync( /// public async Task> GetWithIncludesAsync( IEnumerable includes, - Expression> predicate = null) + Expression>? predicate = null) { try { @@ -292,7 +272,7 @@ public async Task> GetWithIncludesAsync( public async Task> GetPagedAsync( int page, int pageSize, - Expression> predicate = null) + Expression>? predicate = null) { try { @@ -310,7 +290,7 @@ public async Task> GetPagedWithIncludesAsync( int page, int pageSize, IEnumerable includes, - Expression> predicate = null) + Expression>? predicate = null) { try { @@ -345,7 +325,7 @@ public async Task> GetPagedSortedAsync( } /// - public Task CountAsync(Expression> predicate = null) + public Task CountAsync(Expression>? predicate = null) { try { @@ -360,12 +340,23 @@ public Task CountAsync(Expression> predicate = null) } } + private static IQueryable ApplySorting( + IQueryable query, + Expression> orderBy, + SortDirection sortDirection) + => sortDirection == SortDirection.Ascending + ? query.OrderBy(orderBy) + : query.OrderByDescending(orderBy); + + private static IQueryable ApplyIncludes( + IQueryable query, + IEnumerable includes) + => includes.Aggregate(query, (current, includePath) => current.Include(includePath)); + private IQueryable GetBaseQuery() - { - return _enableTracking + => _enableTracking ? _dbContext.Set() : _dbContext.Set().AsNoTracking(); - } private void ConfigureContextBehavior() { @@ -376,27 +367,8 @@ private void ConfigureContextBehavior() : QueryTrackingBehavior.NoTracking; } - private IQueryable ApplyPredicate(Expression> predicate) - { - return predicate != null ? BaseQuery.Where(predicate) : BaseQuery; - } - - private IQueryable ApplySorting( - IQueryable query, - Expression> orderBy, - SortDirection sortDirection) - { - return sortDirection == SortDirection.Ascending - ? query.OrderBy(orderBy) - : query.OrderByDescending(orderBy); - } - - private IQueryable ApplyIncludes( - IQueryable query, - IEnumerable includes) - { - return includes.Aggregate(query, (current, includePath) => current.Include(includePath)); - } + private IQueryable ApplyPredicate(Expression>? predicate) + => predicate != null ? BaseQuery.Where(predicate) : BaseQuery; private async Task> CreatePagedResultAsync( int page, @@ -411,7 +383,7 @@ private async Task> CreatePagedResultAsync( { CurrentPage = page, PageSize = pageSize, - TotalCount = await query.CountAsync() + TotalCount = await query.CountAsync(), }; var skip = (page - 1) * pageSize; @@ -422,15 +394,4 @@ private async Task> CreatePagedResultAsync( return result; } - - private (string Query, object[] ParameterValues) BuildStoredProcedureCommand( - string procedureName, - SqlParameter[] parameters) - { - var paramList = parameters.ToList(); - var paramPlaceholders = string.Join(", ", paramList.Select((p, i) => $"@p{i}")); - var paramValues = paramList.Select(p => p.Value).ToArray(); - - return ($"EXEC {procedureName} {paramPlaceholders}", paramValues); - } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs index afb518d..0012480 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs @@ -1,151 +1,145 @@ -namespace Faura.Infrastructure.UnitOfWork.Repositories; +namespace Faura.Infrastructure.UnitOfWork.Repositories; using Faura.Infrastructure.UnitOfWork.Enums; using Faura.Infrastructure.UnitOfWork.Models; using System.Linq.Expressions; /// -/// Repository interface for entity operations +/// Repository interface for entity operations. /// -/// Entity type -public interface IEntityRepository where TEntity : class +/// Entity type. +public interface IEntityRepository + where TEntity : class { /// - /// Creates a new entity + /// Creates a new entity. /// - /// Entity to create - /// Save options - /// Created entity + /// Entity to create. + /// Created entity. Task CreateAsync(TEntity entity, bool detach = true, bool autoSaveChanges = true); /// - /// Creates multiple entities + /// Creates multiple entities. /// - /// Entities to create - /// Save options - /// Created entities + /// Entities to create. + /// Created entities. Task> CreateRangeAsync(IEnumerable entities, bool autoSaveChanges = true); /// - /// Updates an existing entity + /// Updates an existing entity. /// - /// Entity to update - /// Save options - /// Updated entity + /// Entity to update. + /// Updated entity. Task UpdateAsync(TEntity entity, bool detach = true, bool autoSaveChanges = true); /// - /// Updates multiple entities + /// Updates multiple entities. /// - /// Entities to update - /// Save options - /// Updated entities + /// Entities to update. + /// Updated entities. Task> UpdateRangeAsync(IEnumerable entities, bool autoSaveChanges = true); /// - /// Deletes an entity + /// Deletes an entity. /// - /// Entity to delete - /// Save options - /// Deleted entity + /// Entity to delete. + /// Deleted entity. Task DeleteAsync(TEntity entity, bool detach = true, bool autoSaveChanges = true); /// - /// Deletes entities matching a predicate + /// Deletes entities matching a predicate. /// - /// Filter predicate - /// Save options - /// True if entities were deleted + /// Filter predicate. + /// True if entities were deleted. Task DeleteByPredicateAsync(Expression> predicate, bool autoSaveChanges = true); /// - /// Deletes multiple entities + /// Deletes multiple entities. /// - /// Entities to delete - /// Save options - /// Deleted entities + /// Entities to delete. + /// Deleted entities. Task> DeleteRangeAsync(IEnumerable entities, bool autoSaveChanges = true); /// - /// Gets the first entity matching the predicate or default if none + /// Gets the first entity matching the predicate or default if none. /// - /// Filter predicate - /// First matching entity or default - Task GetFirstOrDefaultAsync(Expression> predicate = null); + /// Filter predicate. + /// First matching entity or default. + Task GetFirstOrDefaultAsync(Expression>? predicate = null); /// - /// Gets the last entity matching the predicate or default if none + /// Gets the last entity matching the predicate or default if none. /// - /// Filter predicate - /// Last matching entity or default - Task GetLastOrDefaultAsync(Expression> predicate = null); + /// Filter predicate. + /// Last matching entity or default. + Task GetLastOrDefaultAsync(Expression>? predicate = null); /// - /// Gets all entities matching the predicate + /// Gets all entities matching the predicate. /// - /// Filter predicate - /// List of matching entities - Task> GetAsync(Expression> predicate = null); + /// Filter predicate. + /// List of matching entities. + Task> GetAsync(Expression>? predicate = null); /// - /// Gets sorted entities matching the predicate + /// Gets sorted entities matching the predicate. /// - /// Type of the sort key - /// Filter predicate - /// Property to sort by - /// Sort direction - /// Sorted list of matching entities + /// Type of the sort key. + /// Filter predicat. + /// Property to sort by. + /// Sort direction. + /// Sorted list of matching entities. Task> GetSortedAsync( Expression> predicate, Expression> orderBy, SortDirection sortDirection = SortDirection.Ascending); /// - /// Gets entities with included related entities + /// Gets entities with included related entities. /// - /// Properties to include - /// Filter predicate - /// List of entities with included properties + /// Properties to include. + /// Filter predicate. + /// List of entities with included properties. Task> GetWithIncludesAsync( IEnumerable includes, - Expression> predicate = null); + Expression>? predicate = null); /// - /// Gets a page of entities matching the predicate + /// Gets a page of entities matching the predicate. /// - /// Page number (1-based) - /// Page size - /// Filter predicate - /// Paged result + /// Page number (1-based). + /// Page size. + /// Filter predicate. + /// Paged result. Task> GetPagedAsync( int page, int pageSize, - Expression> predicate = null); + Expression>? predicate = null); /// - /// Gets a page of entities with included related entities + /// Gets a page of entities with included related entities. /// - /// Page number (1-based) - /// Page size - /// Properties to include - /// Filter predicate - /// Paged result with included properties + /// Page number (1-based). + /// Page size. + /// Properties to include. + /// Filter predicate. + /// Paged result with included properties. Task> GetPagedWithIncludesAsync( int page, int pageSize, IEnumerable includes, - Expression> predicate = null); + Expression>? predicate = null); /// - /// Gets a sorted page of entities matching the predicate + /// Gets a sorted page of entities matching the predicate. /// - /// Type of the sort key - /// Page number (1-based) - /// Page size - /// Filter predicate - /// Property to sort by - /// Sort direction - /// Sorted paged result + /// Type of the sort key. + /// Page number (1-based). + /// Page size. + /// Filter predicate. + /// Property to sort by. + /// Sort direction. + /// Sorted paged result. Task> GetPagedSortedAsync( int page, int pageSize, @@ -154,9 +148,9 @@ Task> GetPagedSortedAsync( SortDirection sortDirection = SortDirection.Ascending); /// - /// Counts entities matching the predicate + /// Counts entities matching the predicate. /// - /// Filter predicate - /// Number of matching entities - Task CountAsync(Expression> predicate = null); -} \ No newline at end of file + /// Filter predicate. + /// Number of matching entities. + Task CountAsync(Expression>? predicate = null); +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs index c6e370e..57eac99 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs @@ -1,16 +1,13 @@ -namespace Faura.Infrastructure.UnitOfWork.Repositories; +namespace Faura.Infrastructure.UnitOfWork.Repositories; using System.Data; -public interface IRawSqlRepository where TModel : class +public interface IRawSqlRepository + where TModel : class { /// /// This method executes a SQL query against the database using the Dapper library. /// - /// - /// - /// - /// /// /// It returns an IEnumerable of the provided object containing the results of the query. /// @@ -19,10 +16,6 @@ public interface IRawSqlRepository where TModel : class /// /// This method executes a SQL query against the database using the Dapper library. /// - /// - /// - /// - /// /// /// Returns the first result, or null if the query returns no results. /// @@ -31,12 +24,8 @@ public interface IRawSqlRepository where TModel : class /// /// This method executes a SQL query against the database using the Dapper library. /// - /// - /// - /// - /// /// /// It returns the number of affected rows. /// Task ExecuteAsync(string sql, object? parameters = null, IDbTransaction? transaction = null); -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs index ef7983d..2708613 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs @@ -1,33 +1,32 @@ -namespace Faura.Infrastructure.UnitOfWork.Repositories; +namespace Faura.Infrastructure.UnitOfWork.Repositories; using System.Data; using Dapper; using Microsoft.EntityFrameworkCore; -public class RawSqlRepository : IRawSqlRepository where TModel : class +public class RawSqlRepository : IRawSqlRepository + where TModel : class { private readonly DbContext _context; public RawSqlRepository(DbContext context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } + => _context = context ?? throw new ArgumentNullException(nameof(context)); - public async Task> QueryAsync(string sql, object? parameters = null, IDbTransaction? transaction = null) + public Task> QueryAsync(string sql, object? parameters = null, IDbTransaction? transaction = null) { var connection = _context.Database.GetDbConnection(); - return await connection.QueryAsync(sql, parameters, transaction); + return connection.QueryAsync(sql, parameters, transaction); } - public async Task QueryFirstOrDefaultAsync(string sql, object? parameters = null, IDbTransaction? transaction = null) + public Task QueryFirstOrDefaultAsync(string sql, object? parameters = null, IDbTransaction? transaction = null) { var connection = _context.Database.GetDbConnection(); - return await connection.QueryFirstOrDefaultAsync(sql, parameters, transaction); + return connection.QueryFirstOrDefaultAsync(sql, parameters, transaction); } - public async Task ExecuteAsync(string sql, object? parameters = null, IDbTransaction? transaction = null) + public Task ExecuteAsync(string sql, object? parameters = null, IDbTransaction? transaction = null) { var connection = _context.Database.GetDbConnection(); - return await connection.ExecuteAsync(sql, parameters, transaction); + return connection.ExecuteAsync(sql, parameters, transaction); } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs index 6dd42b5..4231a2d 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.UnitOfWork.UnitOfWork; +namespace Faura.Infrastructure.UnitOfWork.UnitOfWork; using System.Data; using Microsoft.EntityFrameworkCore.Storage; @@ -6,7 +6,7 @@ public interface IUnitOfWork { /// - /// Begins the transaction + /// Begins the transaction. /// Task GetDbTransaction(int secondsTimeout = 30); @@ -18,4 +18,4 @@ public interface IUnitOfWork /// Commit the transaction if is correct, else rollback. Both cases dispose. /// Task CommitTransaction(IDbTransaction transaction); -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs index abe0110..7ed260f 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs @@ -1,18 +1,17 @@ -namespace Faura.Infrastructure.UnitOfWork.UnitOfWork; +namespace Faura.Infrastructure.UnitOfWork.UnitOfWork; using System.Data; using Faura.Infrastructure.UnitOfWork.Exceptions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; -public class UnitOfWork : IUnitOfWork where TContext : DbContext +public class UnitOfWork : IUnitOfWork + where TContext : DbContext { private const int DefaultSecondsTimeout = 30; protected UnitOfWork(TContext context) - { - Context = context ?? throw new NullContextException(nameof(context)); - } + => Context = context ?? throw new NullContextException(nameof(context)); private TContext Context { get; } @@ -24,16 +23,11 @@ public async Task GetDbTransaction(int secondsTimeout = DefaultS return dbContextTransaction.GetDbTransaction(); } - public Task SaveChanges() - { - //Auditable entities - return Context.SaveChangesAsync(); - } + public Task SaveChanges() => + Context.SaveChangesAsync(); public IExecutionStrategy CreateExecutionStrategy() - { - return Context.Database.CreateExecutionStrategy(); - } + => Context.Database.CreateExecutionStrategy(); public async Task CommitTransaction(IDbTransaction transaction) { @@ -46,7 +40,7 @@ public async Task CommitTransaction(IDbTransaction transaction) transaction.Commit(); } - catch (Exception ex) + catch (Exception) { transaction.Rollback(); throw; @@ -57,4 +51,4 @@ public async Task CommitTransaction(IDbTransaction transaction) transaction.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs index 1cf2186..20b10f5 100644 --- a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs +++ b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs @@ -1,4 +1,4 @@ -namespace Faura.Infrastructure.UnitOfWork; +namespace Faura.Infrastructure.UnitOfWork; using Faura.Infrastructure.UnitOfWork.Projectors; using Faura.Infrastructure.UnitOfWork.Repositories; @@ -12,4 +12,4 @@ public static void SetupUnitOfWork(this IServiceCollection services) services.AddScoped(typeof(IRawSqlRepository<>), typeof(RawSqlRepository<>)); services.AddScoped(typeof(IProjector<>), typeof(Projector<>)); } -} \ No newline at end of file +} diff --git a/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs b/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs index 097f3e2..23997bd 100644 --- a/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs +++ b/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs @@ -1,11 +1,7 @@ -namespace Faura.Grpc.Bootstrappers; +namespace Faura.Grpc.Bootstrappers; public static class ApplicationBootstrapper { public static WebApplicationBuilder RegisterApplicationDependencies( - this WebApplicationBuilder builder - ) - { - return builder; - } + this WebApplicationBuilder builder) => builder; } diff --git a/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs b/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs index 80baf53..a5441ba 100644 --- a/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs +++ b/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs @@ -1,9 +1,9 @@ -using Faura.Grpc.Services; +namespace Faura.Grpc.Bootstrappers; + +using Faura.Grpc.Services; using Faura.Infrastructure.GrpcBootstrapper.Extensions; using Faura.Infrastructure.Logger; -namespace Faura.Grpc.Bootstrappers; - public static class GrpcBootstrapper { public static WebApplicationBuilder RegisterDependencies(this WebApplicationBuilder builder) @@ -16,10 +16,5 @@ public static WebApplicationBuilder RegisterDependencies(this WebApplicationBuil } public static Action RegisterGrpcServices() - { - return endpoints => - { - endpoints.MapGrpcService(); - }; - } + => endpoints => endpoints.MapGrpcService(); } diff --git a/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs b/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs index 104c5b8..e2d28f3 100644 --- a/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs +++ b/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs @@ -1,11 +1,10 @@ -namespace Faura.Grpc.Bootstrappers; +namespace Faura.Grpc.Bootstrappers; public static class OptionsBootstrapper { public static void RegisterOptions( this IServiceCollection services, - IConfiguration configuration - ) + IConfiguration configuration) { // Add Options here } diff --git a/src/Templates/Faura.Grpc/Faura.Grpc.csproj b/src/Templates/Faura.Grpc/Faura.Grpc.csproj index e56d51f..6651ab9 100644 --- a/src/Templates/Faura.Grpc/Faura.Grpc.csproj +++ b/src/Templates/Faura.Grpc/Faura.Grpc.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Templates/Faura.Grpc/Program.cs b/src/Templates/Faura.Grpc/Program.cs index fa44dcd..83e9bbb 100644 --- a/src/Templates/Faura.Grpc/Program.cs +++ b/src/Templates/Faura.Grpc/Program.cs @@ -10,4 +10,11 @@ app.ConfigureCommonFauraWebApplication(GrpcBootstrapper.RegisterGrpcServices()); -app.Run(); +await app.RunAsync(); + +public partial class Program +{ + protected Program() + { + } +} diff --git a/src/Templates/Faura.Grpc/Services/GreeterService.cs b/src/Templates/Faura.Grpc/Services/GreeterService.cs index a0a3bf2..87b6075 100644 --- a/src/Templates/Faura.Grpc/Services/GreeterService.cs +++ b/src/Templates/Faura.Grpc/Services/GreeterService.cs @@ -1,16 +1,13 @@ -using Faura.Infrastructure.Logger.Extensions; -using Grpc.Core; - namespace Faura.Grpc.Services; +using Faura.Infrastructure.Logger.Extensions; +using global::Grpc.Core; + public class GreeterService : Greeter.GreeterBase { private readonly ILogger _logger; - public GreeterService(ILogger logger) - { - _logger = logger; - } + public GreeterService(ILogger logger) => _logger = logger; public override Task SayHello(HelloRequest request, ServerCallContext context) { diff --git a/src/Templates/Faura.IntegrationTest/Configuration/CustomWebApplicationFactory.cs b/src/Templates/Faura.WebAPI.IntegrationTests/Configuration/CustomWebApplicationFactory.cs similarity index 100% rename from src/Templates/Faura.IntegrationTest/Configuration/CustomWebApplicationFactory.cs rename to src/Templates/Faura.WebAPI.IntegrationTests/Configuration/CustomWebApplicationFactory.cs diff --git a/src/Templates/Faura.IntegrationTest/Configuration/IntegrationTestBase.cs b/src/Templates/Faura.WebAPI.IntegrationTests/Configuration/IntegrationTestBase.cs similarity index 100% rename from src/Templates/Faura.IntegrationTest/Configuration/IntegrationTestBase.cs rename to src/Templates/Faura.WebAPI.IntegrationTests/Configuration/IntegrationTestBase.cs diff --git a/src/Templates/Faura.IntegrationTest/Faura.IntegrationTest.csproj b/src/Templates/Faura.WebAPI.IntegrationTests/Faura.WebAPI.IntegrationTests.csproj similarity index 100% rename from src/Templates/Faura.IntegrationTest/Faura.IntegrationTest.csproj rename to src/Templates/Faura.WebAPI.IntegrationTests/Faura.WebAPI.IntegrationTests.csproj diff --git a/src/Templates/Faura.IntegrationTest/Seeders/EmployeeTestDataSeeder.cs b/src/Templates/Faura.WebAPI.IntegrationTests/Seeders/EmployeeTestDataSeeder.cs similarity index 100% rename from src/Templates/Faura.IntegrationTest/Seeders/EmployeeTestDataSeeder.cs rename to src/Templates/Faura.WebAPI.IntegrationTests/Seeders/EmployeeTestDataSeeder.cs diff --git a/src/Templates/Faura.WebAPI.IntegrationTests/UseCases/EmployeeTests.cs b/src/Templates/Faura.WebAPI.IntegrationTests/UseCases/EmployeeTests.cs new file mode 100644 index 0000000..57e4215 --- /dev/null +++ b/src/Templates/Faura.WebAPI.IntegrationTests/UseCases/EmployeeTests.cs @@ -0,0 +1,92 @@ +namespace Faura.IntegrationTest.UseCases; + +using System.Net; +using System.Net.Http.Json; +using Faura.IntegrationTest.Configuration; +using Faura.WebAPI.Domain.Entities; +using Xunit; + +public class EmployeeTests : IClassFixture> +{ + private readonly HttpClient _client; + + public EmployeeTests(CustomWebApplicationFactory factory) + => _client = factory.CreateClient(); + + [Fact] + public async Task Should_Get_Employees() + { + // Act + var response = await _client.GetAsync("/Employee"); + + // Assert + response.EnsureSuccessStatusCode(); + var employees = await response.Content.ReadFromJsonAsync>(); + + Assert.NotNull(employees); + } + + [Fact] + public async Task Should_Create_Employee() + { + // Arrange + var newEmployee = new Employee("Test", "User", "test.user@example.com"); + + // Act + var response = await _client.PostAsJsonAsync("/Employee", newEmployee); + + // Assert + response.EnsureSuccessStatusCode(); + var created = await response.Content.ReadFromJsonAsync(); + + Assert.NotNull(created); + Assert.Equal(newEmployee.Email, created?.Email); + } + + [Fact] + public async Task Should_Get_Employee_By_Id() + { + // Arrange + var employee = new Employee("Get", "ById", "get.byid@example.com"); + var post = await _client.PostAsJsonAsync("/Employee", employee); + var created = await post.Content.ReadFromJsonAsync(); + + // Act + var response = await _client.GetAsync($"/Employee/{created!.Id}"); + + // Assert + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + Assert.Equal(created.Id, result?.Id); + } + + [Fact] + public async Task Should_Delete_Employee() + { + // Arrange + var employee = new Employee("To", "Delete", "to.delete@example.com"); + var post = await _client.PostAsJsonAsync("/Employee", employee); + var created = await post.Content.ReadFromJsonAsync(); + + // Act + var delete = await _client.DeleteAsync($"/Employee/{created!.Id}"); + + // Assert + Assert.Equal(HttpStatusCode.NoContent, delete.StatusCode); + + var get = await _client.GetAsync($"/Employee/{created.Id}"); + Assert.Equal(HttpStatusCode.NotFound, get.StatusCode); + } + + [Fact] + public async Task Should_Create_Two_Employees_In_Transaction() + { + // Act + var response = await _client.PostAsync("/Employee/batch", null); + + // Assert + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadAsStringAsync(); + Assert.Equal("Two employees created in transaction.", result.Trim()); + } +} diff --git a/src/Templates/Faura.IntegrationTest/appsettings.Test.json b/src/Templates/Faura.WebAPI.IntegrationTests/appsettings.Test.json similarity index 100% rename from src/Templates/Faura.IntegrationTest/appsettings.Test.json rename to src/Templates/Faura.WebAPI.IntegrationTests/appsettings.Test.json diff --git a/src/Templates/Faura.WebAPI.UnitTests/EmployeeControllerTests.cs b/src/Templates/Faura.WebAPI.UnitTests/EmployeeControllerTests.cs new file mode 100644 index 0000000..4c50a81 --- /dev/null +++ b/src/Templates/Faura.WebAPI.UnitTests/EmployeeControllerTests.cs @@ -0,0 +1,127 @@ +namespace Faura.WebAPI.Tests.Controllers; + +using System; +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using Faura.WebAPI.Controllers; +using Faura.WebAPI.Domain.Entities; +using Faura.WebAPI.Domain.Repositories; +using Faura.WebAPI.Infrastructure.Persistence; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using NSubstitute; +using Xunit; + +public class EmployeeControllerTests +{ + private readonly ILogger _logger = Substitute.For>(); + private readonly IEmployeeRepository _repository = Substitute.For(); + private readonly IEmployeeUoW _uow = Substitute.For(); + private readonly EmployeeController _controller; + + public EmployeeControllerTests() + => _controller = new EmployeeController(_logger, _repository, _uow); + + [Fact] + public async Task Get_ReturnsEmployees() + { + // Arrange + var employees = new List { new("Josep", "Ferrandis", "test@example.com") }; + _repository.GetAsync().Returns(employees); + + // Act + var result = await _controller.Get(); + + // Assert + var okResult = Assert.IsType(result); + Assert.Equal(employees, okResult.Value); + } + + [Fact] + public async Task Create_ReturnsCreatedAtAction() + { + // Arrange + var employee = new Employee("Test", "User", "test@domain.com"); + await _repository.CreateAsync(employee); + + // Act + var result = await _controller.Create(employee); + + // Assert + var created = Assert.IsType(result); + Assert.Equal(nameof(_controller.GetById), created.ActionName); + Assert.Equal(employee, created.Value); + } + + [Fact] + public async Task CreateBatch_CreatesTwoEmployeesAndCommitsTransaction() + { + // Arrange + var fakeTransaction = Substitute.For(); + _uow.GetDbTransaction(Arg.Any()).Returns(fakeTransaction); + + // Act + var result = await _controller.CreateBatch(); + + // Assert + await _repository.Received(2).CreateAsync(Arg.Is(e => + e.FirstName == "Josep" && e.LastName == "Ferrandis" && e.Email.StartsWith("josep"))); + + await _uow.Received(1).CommitTransaction(fakeTransaction); + + var okResult = Assert.IsType(result); + Assert.Equal("Two employees created in transaction.", okResult.Value); + } + + [Fact] + public async Task GetById_EmployeeExists_ReturnsOk() + { + // Arrange + var id = 1; + var employee = new Employee("A", "B", "a@b.com") { Id = id }; + _repository.GetByIdAsync(id).Returns(employee); + + // Act + var result = await _controller.GetById(id); + + // Assert + var ok = Assert.IsType(result); + Assert.Equal(employee, ok.Value); + } + + [Fact] + public async Task GetById_EmployeeNotFound_ReturnsNotFound() + { + var id = 1; + _repository.GetByIdAsync(id).Returns((Employee?)null); + + var result = await _controller.GetById(id); + + Assert.IsType(result); + } + + [Fact] + public async Task Delete_EmployeeExists_DeletesAndReturnsNoContent() + { + var id = 1; + var employee = new Employee("Del", "Ete", "del@ete.com") { Id = id }; + _repository.GetByIdAsync(id).Returns(employee); + + var result = await _controller.Delete(id); + + await _repository.Received(1).DeleteAsync(employee); + Assert.IsType(result); + } + + [Fact] + public async Task Delete_EmployeeNotFound_ReturnsNotFound() + { + var id = 1; + _repository.GetByIdAsync(id).Returns((Employee?)null); + + var result = await _controller.Delete(id); + + Assert.IsType(result); + } +} diff --git a/src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj b/src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj new file mode 100644 index 0000000..85bea97 --- /dev/null +++ b/src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + false + true + + + + + + + + + + + + diff --git a/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs b/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs index 894655b..423aeb5 100644 --- a/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs +++ b/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs @@ -1,8 +1,8 @@ -using Faura.Infrastructure.ApiBootstrapper.Extensions; +namespace Faura.WebAPI.Bootstrappers; + using Faura.Infrastructure.JWT.Extensions; using Faura.Infrastructure.Logger; - -namespace Faura.WebAPI.Bootstrappers; +using Faura.Infrastructure.ApiBootstrapper.Extensions; public static class ApiBootstrapper { diff --git a/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs b/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs index ef95385..2ae9097 100644 --- a/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs +++ b/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs @@ -1,11 +1,10 @@ -namespace Faura.WebAPI.Bootstrappers; +namespace Faura.WebAPI.Bootstrappers; public static class OptionsBootstrapper { public static void RegisterOptions( this IServiceCollection services, - IConfiguration configuration - ) + IConfiguration configuration) { // Add Options here } diff --git a/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs b/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs index 36ac673..f861528 100644 --- a/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs +++ b/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs @@ -1,7 +1,7 @@ -using System.ComponentModel.DataAnnotations.Schema; - namespace Faura.WebAPI.Domain.Entities; +using System.ComponentModel.DataAnnotations.Schema; + [Table("employee")] public class Employee { diff --git a/src/Templates/Faura.WebAPI/Domain/IEmployeeRepository.cs b/src/Templates/Faura.WebAPI/Domain/IEmployeeRepository.cs deleted file mode 100644 index e6f2c49..0000000 --- a/src/Templates/Faura.WebAPI/Domain/IEmployeeRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Faura.Infrastructure.UnitOfWork.Repositories; -using Faura.WebAPI.Domain.Entities; - -namespace Faura.WebAPI.Domain; - -public interface IEmployeeRepository : IEntityRepository { } diff --git a/src/Templates/Faura.WebAPI/Domain/Repositories/IEmployeeRepository.cs b/src/Templates/Faura.WebAPI/Domain/Repositories/IEmployeeRepository.cs new file mode 100644 index 0000000..24618aa --- /dev/null +++ b/src/Templates/Faura.WebAPI/Domain/Repositories/IEmployeeRepository.cs @@ -0,0 +1,9 @@ +namespace Faura.WebAPI.Domain.Repositories; + +using Faura.Infrastructure.UnitOfWork.Repositories; +using Faura.WebAPI.Domain.Entities; + +public interface IEmployeeRepository : IEntityRepository +{ + Task GetByIdAsync(long id); +} diff --git a/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs b/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs index 3343fc0..cdc3374 100644 --- a/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs +++ b/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs @@ -1,5 +1,7 @@ -using Faura.Infrastructure.UnitOfWork.UnitOfWork; - namespace Faura.WebAPI.Infrastructure.Persistence; -public interface IEmployeeUoW : IUnitOfWork { } +using Faura.Infrastructure.UnitOfWork.UnitOfWork; + +public interface IEmployeeUoW : IUnitOfWork +{ +} diff --git a/src/Templates/Faura.WebAPI/Infrastructure/Repositories/EmployeeRepository.cs b/src/Templates/Faura.WebAPI/Infrastructure/Repositories/EmployeeRepository.cs new file mode 100644 index 0000000..b33aa70 --- /dev/null +++ b/src/Templates/Faura.WebAPI/Infrastructure/Repositories/EmployeeRepository.cs @@ -0,0 +1,21 @@ +namespace Faura.WebAPI.Infrastructure.Repositories; + +using System.Threading.Tasks; +using Faura.Infrastructure.UnitOfWork.Repositories; +using Faura.WebAPI.Domain.Entities; +using Faura.WebAPI.Domain.Repositories; +using Faura.WebAPI.Infrastructure.Persistence; + +public class EmployeeRepository : EntityRepository, IEmployeeRepository +{ + public EmployeeRepository( + EmployeeDbContext dbContext, + ILogger logger, + bool enableTracking = false) + : base(dbContext, logger, enableTracking) + { + } + + public Task GetByIdAsync(long id) + => GetFirstOrDefaultAsync(e => e.Id == id); +} diff --git a/src/global.json b/src/global.json new file mode 100644 index 0000000..dc998b1 --- /dev/null +++ b/src/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "rollForward": "latestFeature", + "version": "8.0.300" + } +} diff --git a/src/stylecop.json b/src/stylecop.json new file mode 100644 index 0000000..2289c6a --- /dev/null +++ b/src/stylecop.json @@ -0,0 +1,11 @@ +{ + "@schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "layoutRules": { + "newlineAtEndOfFile": "require" + }, + "orderingRules": { + "blankLinesBetweenUsingGroups": "omit" + } + } +}