From 7ba35a0d172d3699e58da473f41c408ee0267376 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 13 Oct 2023 19:33:55 +0200 Subject: [PATCH 001/104] Version pre5.x --- .editorconfig | 270 ++++++++++++++++++ .env | 10 + .github/FUNDING.yml | 3 + .github/dependabot.yml | 11 + .github/workflows/build_and_test.yml | 29 +- .github/workflows/dockerhub-publish.yml | 55 ++++ .github/workflows/nuget-publish.yml | 5 +- .gitignore | 149 +++++++++- CHANGELOG.md | 24 ++ CODE_OF_CONDUCT.md | 128 +++++++++ Directory.Build.props | 27 ++ Directory.Build.targets | 5 + Makefile | 26 ++ NuGet.config | 1 - README.md | 101 +++++-- assets/buy-me-a-coffee.png | Bin 0 -> 12991 bytes assets/genocs-library-logo.png | Bin 0 -> 58074 bytes dotnet.ruleset | 164 +++++++++++ global.json | 7 + icon.png | Bin 1034 -> 19476 bytes launchSettings.json | 11 + src/Genocs.Auth/Genocs.Auth.csproj | 4 +- src/Genocs.Common/Genocs.Common.csproj | 2 +- src/Genocs.Common/Options/AppSettings.cs | 16 +- src/Genocs.Common/Types/Extensions.cs | 10 +- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 4 +- src/Genocs.Core.Demo.Worker/Program.cs | 5 +- src/Genocs.Core/Genocs.Core.csproj | 4 +- .../Genocs.Discovery.Consul.csproj | 6 +- .../Genocs.HTTP.RestEase.csproj | 13 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 4 +- .../Genocs.LoadBalancing.Fabio.csproj | 8 +- src/Genocs.Logging/Genocs.Logging.csproj | 4 +- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 6 +- .../Genocs.MessageBrokers.Outbox.csproj | 4 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 4 +- .../Genocs.MessageBrokers.csproj | 4 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 4 +- .../Genocs.Monitoring.csproj | 8 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 4 +- .../Genocs.Persistence.MongoDb.csproj | 4 +- .../Genocs.Persistence.Redis.csproj | 4 +- .../Genocs.QueryBuilder.UnitTests.csproj | 2 +- .../Genocs.QueryBuilder.csproj | 2 +- .../Genocs.Secrets.Vault.csproj | 4 +- src/Genocs.Security/Genocs.Security.csproj | 4 +- src/Genocs.Security/README.md | 3 +- .../Genocs.ServiceBusAzure.csproj | 4 +- src/Genocs.Tracing/Extensions.cs | 61 ++-- src/Genocs.Tracing/Genocs.Tracing.csproj | 12 +- .../Genocs.WebApi.CQRS.csproj | 6 +- .../Genocs.WebApi.Security.csproj | 4 +- .../Genocs.WebApi.Swagger.csproj | 4 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 4 +- .../Framework/UserMiddleware.cs | 12 +- .../Genocs.APIGateway.csproj | 18 +- .../Genocs.Identities.Application.csproj | 28 +- .../Genocs.Identities.WebApi/Program.cs | 5 +- .../Genocs.Orders.WebApi.csproj | 32 +-- .../Genocs.Products.WebApi.csproj | 32 +-- .../Genocs.SignalR.WebApi.csproj | 34 +-- stylecop.json | 12 + 63 files changed, 1191 insertions(+), 242 deletions(-) create mode 100644 .editorconfig create mode 100644 .env create mode 100644 .github/FUNDING.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/dockerhub-publish.yml create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 Directory.Build.props create mode 100644 Directory.Build.targets create mode 100644 Makefile create mode 100644 assets/buy-me-a-coffee.png create mode 100644 assets/genocs-library-logo.png create mode 100644 dotnet.ruleset create mode 100644 global.json create mode 100644 launchSettings.json create mode 100644 stylecop.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..586c5fb7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,270 @@ +root = true + +[*] +roslynator_accessibility_modifiers = explicit +roslynator_use_anonymous_function_or_method_group = anonymous_function|method_group +roslynator_enum_has_flag_style = method +roslynator_object_creation_type_style = explicit|implicit|implicit_when_type_is_obvious + +indent_style = space + +trim_trailing_whitespace = true + +insert_final_newline = false + +[*.md] +trim_trailing_whitespace = false + +[*.json] +indent_size = 2 + +[*.cs] +dotnet_sort_system_directives_first = true:warning + +csharp_style_namespace_declarations = file_scoped:warning + +csharp_style_var_for_built_in_types = false:warning + +csharp_style_var_when_type_is_apparent = true:warning + +csharp_style_var_elsewhere = true:warning + +csharp_new_line_before_members_in_anonymous_types = true:warning + +# SA1623: Property summary documentation should match accessors +dotnet_diagnostic.SA1623.severity = none + +# SA1101: Prefix local calls with this +dotnet_diagnostic.SA1101.severity = none + +# SA1642: Constructor summary documentation should begin with standard text +dotnet_diagnostic.SA1642.severity = none + +# SA1309: Field names should not begin with underscore +dotnet_diagnostic.SA1309.severity = none + +# RCS1194: Implement exception constructors. +dotnet_diagnostic.RCS1194.severity = none + +# SA1000: Keywords should be spaced correctly +dotnet_diagnostic.SA1000.severity = none + +# SA1124: Do not use regions +dotnet_diagnostic.SA1124.severity = none + +# SA1413: Use trailing comma in multi-line initializers +dotnet_diagnostic.SA1413.severity = none + +# SA1201: Elements should appear in the correct order +dotnet_diagnostic.SA1201.severity = suggestion + +# SA1638: File header file name documentation should match file name +dotnet_diagnostic.SA1638.severity = warning + +# SA1633: File should have header +dotnet_diagnostic.SA1633.severity = none + +# SA1404: Code analysis suppression should have justification +dotnet_diagnostic.SA1404.severity = none + +# SA1206: Declaration keywords should follow order +dotnet_diagnostic.SA1206.severity = none + +# CA1040: Avoid empty interfaces +dotnet_diagnostic.CA1040.severity = none + +# RCS1012: Use explicit type instead of 'var' +dotnet_diagnostic.RCS1012.severity = none + +# RCS1008: Use explicit type instead of 'var' +dotnet_diagnostic.RCS1008.severity = none + +# CA1725 +dotnet_diagnostic.CA1725.severity = none + +# RCS1009: Use explicit type instead of 'var' +dotnet_diagnostic.RCS1009.severity = none + +# SA1402: File may only contain a single type +dotnet_diagnostic.SA1402.severity = suggestion + +# CA1711 +dotnet_diagnostic.CA1711.severity = none + +# CA1720: Identifier contains type name +dotnet_diagnostic.CA1720.severity = none + +# IDE0022: Use block body for methods +dotnet_diagnostic.IDE0022.severity = none + +# SA1011: Closing square brackets should be spaced correctly +dotnet_diagnostic.SA1011.severity = none + +# CA1721 +dotnet_diagnostic.CA1721.severity = none + +# SA1313: Parameter names should begin with lower-case letter +dotnet_diagnostic.SA1313.severity = none + +# SecurityIntelliSenseCS: MS Security rules violation +dotnet_diagnostic.SecurityIntelliSenseCS.severity = suggestion + +# SA1123: Do not place regions within elements +dotnet_diagnostic.SA1123.severity = none + +# RCS1046: Add suffix 'Async' to asynchronous method name +dotnet_diagnostic.RCS1046.severity = warning + +# SA1625: Element documentation should not be copied and pasted +dotnet_diagnostic.SA1625.severity = none + +# SCS9999 +dotnet_diagnostic.SCS9999.severity = none + +# RCS1090 Add call to 'ConfigureAwait' +dotnet_diagnostic.RCS1090.severity = none + +# RCS1170 Use read-only auto-implemented property +dotnet_diagnostic.RCS1170.severity = none + +# SA1649 +dotnet_diagnostic.SA1649.severity = none + +# RCS1021 Use expression-bodied lambda. +dotnet_diagnostic.RCS1021.severity = none + +# RCS1047 Remove suffix 'Async' from non-asynchronous method name. +# dotnet_diagnostic.RCS1047.severity = silent + +# SA1600 Elements should be documented +dotnet_diagnostic.SA1600.severity = silent + +# CS1591 Missing XML comment for publicly visible type or member +dotnet_diagnostic.CS1591.severity = none + +# SA1602: Enumeration items should be documented +dotnet_diagnostic.SA1602.severity = none + +# CA1720 Identifier 'Decimal' contains type name +dotnet_diagnostic.CA1720.severity = none + +# SA1601: Partial elements should be documented +dotnet_diagnostic.SA1601.severity = silent + +# CA1711 Rename type name UserEventHandler so that it does not end in 'EventHandler' +dotnet_diagnostic.CA1711.severity = none + +# CA1307: Specify StringComparison for clarity +dotnet_diagnostic.CA1307.severity = none +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_indent_labels = one_less_than_current +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_prefer_readonly_struct = true:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_conditional_delegate_call = true:suggestion +csharp_space_around_binary_operators = before_and_after +[*.{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_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 +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf +dotnet_style_prefer_collection_expression = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_code_quality_unused_parameters = all:suggestion diff --git a/.env b/.env new file mode 100644 index 00000000..0a57f1b7 --- /dev/null +++ b/.env @@ -0,0 +1,10 @@ +# Compose supports declaring default environment variables in an environment file named .env placed in the folder docker-compose command is executed from (current working directory). +# Compose expects each line in an env file to be in VAR=VAL format. Lines beginning with # (i.e. comments) are ignored, as are blank lines. +# Note: Values present in the environment at runtime will always override those defined inside the .env file. Similarly, values passed via command-line arguments take precedence as well. + +# The IP below should be swapped to your real IP or DNS name, like 192.168.88.248, etc. if testing from remote browsers or mobile devices + +PROJECT_EXTERNAL_DNS_NAME_OR_IP=localhost + +# The docker image version +DOCKER_IMAGE_TAG=5.0.0 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..d642ac99 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms +open_collective: genocs +custom: ['https://www.buymeacoffee.com/genocs'] diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..03ec5454 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "nuget" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index ce398d56..cf3d5112 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -2,10 +2,9 @@ name: Build test and pack on: push: - branches: ["master"] - + branches: [ main ] pull_request: - branches: ["master"] + branches: [ main ] jobs: build: @@ -13,22 +12,22 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 - - name: Setup .NET - uses: actions/setup-dotnet@v2 - with: - dotnet-version: 7.0.x + - name: Setup .NET + uses: actions/setup-dotnet@v2 + with: + dotnet-version: 7.0.x - - name: Restore dependencies - run: dotnet restore + - name: Restore dependencies + run: dotnet restore - - name: Build - run: dotnet build --no-restore + - name: Build + run: dotnet build --no-restore - - name: Test - run: dotnet test --no-build --verbosity normal + - name: Test + run: dotnet test --no-build --verbosity normal - name: Pack run: dotnet pack --no-build --verbosity normal diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml new file mode 100644 index 00000000..8ae370ae --- /dev/null +++ b/.github/workflows/dockerhub-publish.yml @@ -0,0 +1,55 @@ +# This is a manually triggered dockerhub build and publish + +name: Publish to Dockerhub + +# Controls when the action will run. Workflow runs when manually triggered using the UI +# or API. +on: + workflow_dispatch: + # Inputs the workflow accepts. + inputs: + version: + # Friendly description to be shown in the UI instead of 'name' + description: "Image Version" + + # Default value if no value is explicitly provided + default: "5.0.0" + + # Input has to be provided for the workflow to run + required: true + + +jobs: + build: + name: Publish Docker Image + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v2 + with: + dotnet-version: 7.0.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build -c Debug --no-restore + + - name: Test + run: dotnet test --no-build --verbosity normal + + - name: Log in to Docker Hub + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + username: ${{secrets.DOCKER_USERNAME}} + password: ${{secrets.DOCKER_PASSWORD}} + + - name: Build and push image to Dockerhub + run: | + docker build -f webapi.dockerfile -t genocs/demo-webapi:${{github.event.inputs.version}} -t genocs/demo-webapi:latest . + docker push genocs/demo-webapi:${{github.event.inputs.version}} + docker push genocs/demo-webapi:latest diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 89c68139..2d58c4b0 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -13,7 +13,7 @@ on: description: "Packages Version" # Default value if no value is explicitly provided - default: "5.0.0-preview.4.0" + default: "5.0.0-preview.5.0" # Input has to be provided for the workflow to run required: true @@ -23,6 +23,7 @@ jobs: build: name: Update NuGet packages runs-on: ubuntu-latest + steps: - name: Checkout uses: actions/checkout@v3 @@ -42,7 +43,7 @@ jobs: run: dotnet test --no-build --verbosity normal - name: Pack - run: dotnet pack -c Debug -o out -p:Version=${{ github.event.inputs.version }} --no-build --verbosity normal + run: dotnet pack -c Debug -o out -p:PackageVersion=${{github.event.inputs.version}} --no-build --verbosity normal - name: Push packages to Nuget run: dotnet nuget push ./out/*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json --skip-duplicate --no-symbols diff --git a/.gitignore b/.gitignore index c1aafb51..65f178a7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files +*.rsuser *.suo *.user *.userosscache @@ -12,6 +13,9 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +# Mono auto generated files +mono_crash.* + # Build results [Dd]ebug/ [Dd]ebugPublic/ @@ -19,10 +23,14 @@ [Rr]eleases/ x64/ x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +[Ll]ogs/ # Visual Studio 2015/2017 cache/options directory .vs/ @@ -36,9 +44,10 @@ Generated\ Files/ [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -# NUNIT +# NUnit *.VisualState.xml TestResult.xml +nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ @@ -54,6 +63,12 @@ project.fragment.lock.json artifacts/ # **/Properties/launchSettings.json +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + # StyleCop StyleCopReport.xml @@ -61,6 +76,7 @@ StyleCopReport.xml *_i.c *_p.c *_i.h +*_h.h *.ilk *.meta *.obj @@ -77,6 +93,7 @@ StyleCopReport.xml *.tlh *.tmp *.tmp_proj +*_wpftmp.csproj *.log *.vspscc *.vssscc @@ -132,6 +149,11 @@ _TeamCity* .axoCover/* !.axoCover/settings.json +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + # Visual Studio code coverage results *.coverage *.coveragexml @@ -179,6 +201,8 @@ PublishScripts/ # NuGet Packages *.nupkg +# NuGet Symbol Packages +*.snupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. @@ -203,12 +227,14 @@ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx +*.appxbundle +*.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache -!*.[Cc]ache/ +!?*.[Cc]ache/ # Others ClientBin/ @@ -217,10 +243,11 @@ ClientBin/ *.dbmdl *.dbproj.schemaview *.jfm +*.pfx *.publishsettings orleans.codegen.cs -# Including strong name files can present a security risk +# Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk @@ -251,6 +278,9 @@ ServiceFabricBackup/ *.bim.layout *.bim_*.settings *.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ @@ -293,6 +323,9 @@ paket-files/ # CodeRush .cr/ +# CodeRush personal settings +.cr/personal + # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc @@ -316,7 +349,7 @@ __pycache__/ # OpenCover UI analysis results OpenCover/ -# Azure Stream Analytics local run output +# Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log @@ -325,7 +358,111 @@ ASALocalRun/ # NVidia Nsight GPU debugger configuration file *.nvuser -# MFractors (Xamarin productivity tool) working folder +# MFractors (Xamarin productivity tool) working folder .mfractor/ -logs/ \ No newline at end of file +logs/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# JetBrains Rider +.idea/ +*.sln.iml + +## +## Visual Studio Code +## +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..33ef4c22 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +### Changelog + +All notable changes to this project will be documented in this file. Dates are displayed in UTC. + +Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). + + +## [0.0.1](https://github.com/Genocs/telegram-integration/compare/v0.1.0...v0.1.1) (2023-06-02) + +### Features + +* + +### Bug Fixes + +* + +### Documentation + +* + +### Dependencies + +* diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..5d2f3da5 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +info@genocs.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..14757c4d --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,27 @@ + + + + $(MSBuildThisFileDirectory)dotnet.ruleset + false + false + true + $(OutputPath)$(AssemblyName).xml + true + enable + enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 00000000..fd9797bc --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,5 @@ + + + $(OutputPath)$(AssemblyName).xml + + \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..d01ff741 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +build: + dotnet build +start: + dotnet run --project ./src/Genocs.TelegramIntegration.WebApi +nuget: + nuget pack -NoDefaultExcludes -OutputDirectory nupkgs +publish: + dotnet publish --os linux --arch x64 -c Release --self-contained +publish-to-hub: + dotnet publish --os linux --arch x64 -c Release -p:ContainerRegistry=docker.io -p:ContainerImageName=genocs/telegram_integration-webapi --self-contained +tp: # terraform plan + cd terraform/environments/staging && terraform plan +ta: # terraform apply + cd terraform/environments/staging && terraform apply +td: # terraform destroy + cd terraform/environments/staging && terraform destroy +dcu: # docker-compose up : webapi + postgresql + cd docker-compose/ && docker-compose -f docker-compose.postgresql.yml up -d +dcd: # docker-compose down : webapi + postgresql + cd docker-compose/ && docker-compose -f docker-compose.postgresql.yml down +fds: # force rededeploy aws ecs service + aws ecs update-service --force-new-deployment --service dotnet-webapi --cluster genocs +gw: # git docker workflow to push docker image to the repository based on the main branch + @echo triggering github workflow to push docker image to container + @echo ensure that you have the gh-cli installed and authenticated. + gh workflow run dockerhub-publish -f push_to_docker=true \ No newline at end of file diff --git a/NuGet.config b/NuGet.config index 4dfe59d3..a552551f 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,6 @@ - diff --git a/README.md b/README.md index 7bb7c68f..608c649d 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,52 @@ -# Genocs .NET library + +[![License][license-shield]][license-url] +[![Build][build-shield]][build-url] +[![Downloads][downloads-shield]][downloads-url] +[![Contributors][contributors-shield]][contributors-url] +[![Forks][forks-shield]][forks-url] +[![Stargazers][stars-shield]][stars-url] +[![Issues][issues-shield]][issues-url] +[![Discord][discord-shield]][discord-url] +[![Gitter][gitter-shield]][gitter-url] +[![Twitter][twitter-shield]][twitter-url] +[![Twitterx][twitterx-shield]][twitterx-url] +[![LinkedIn][linkedin-shield]][linkedin-url] + +[license-shield]: https://img.shields.io/github/license/Genocs/genocs-library?color=2da44e&style=flat-square +[license-url]: https://github.com/Genocs/genocs-library/blob/main/LICENSE +[build-shield]: https://github.com/Genocs/genocs-library/actions/workflows/build_and_test.yml/badge.svg?branch=main +[build-url]: https://github.com/Genocs/genocs-library/actions/workflows/build_and_test.yml +[downloads-shield]: https://img.shields.io/nuget/dt/Genocs.Microservice.Template.svg?color=2da44e&label=downloads&logo=nuget +[downloads-url]: https://www.nuget.org/packages/Genocs.Microservice.Template +[contributors-shield]: https://img.shields.io/github/contributors/Genocs/genocs-library.svg?style=flat-square +[contributors-url]: https://github.com/Genocs/genocs-library/graphs/contributors +[forks-shield]: https://img.shields.io/github/forks/Genocs/genocs-library?style=flat-square +[forks-url]: https://github.com/Genocs/genocs-library/network/members +[stars-shield]: https://img.shields.io/github/stars/Genocs/genocs-library.svg?style=flat-square +[stars-url]: https://img.shields.io/github/stars/Genocs/genocs-library?style=flat-square +[issues-shield]: https://img.shields.io/github/issues/Genocs/genocs-library?style=flat-square +[issues-url]: https://github.com/Genocs/genocs-library/issues +[discord-shield]: https://img.shields.io/discord/1106846706512953385?color=%237289da&label=Discord&logo=discord&logoColor=%237289da&style=flat-square +[discord-url]: https://discord.com/invite/fWwArnkV +[gitter-shield]: https://img.shields.io/badge/chat-on%20gitter-blue.svg +[gitter-url]: https://gitter.im/genocs/ +[twitter-shield]: https://img.shields.io/twitter/follow/genocs?color=1DA1F2&label=Twitter&logo=Twitter&style=flat-square +[twitter-url]: https://twitter.com/genocs +[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555 +[linkedin-url]: https://www.linkedin.com/in/giovanni-emanuele-nocco-b31a5169/ +[twitterx-shield]: https://img.shields.io/twitter/url/https/twitter.com/genocs.svg?style=social +[twitterx-url]: https://twitter.com/genocs + + +

+ icon +

-[![GitHub](https://img.shields.io/github/license/Genocs/genocs-library?color=2da44e&style=flat-square)](https://github.com/Genocs/genocs-library/blob/main/LICENSE) -[![.NET build and test](https://github.com/Genocs/genocs-library/actions/workflows/build_and_test.yml/badge.svg)](https://github.com/Genocs/genocs-library/actions/workflows/build_and_test.yml) -[![NuGet](https://img.shields.io/badge/nuget-v.5.0.0-blue)](https://www.nuget.org/packages/Genocs.Core) -[![NuGet Downloads](https://img.shields.io/nuget/dt/Genocs.Core.svg)](https://www.nuget.org/packages/Genocs.Core) -[![Discord](https://img.shields.io/discord/1106846706512953385?color=%237289da&label=Discord&logo=discord&logoColor=%237289da&style=flat-square)](https://discord.com/invite/fWwArnkV) -[![Twitter](https://img.shields.io/twitter/follow/genocs?color=1DA1F2&label=Twitter&logo=Twitter&style=flat-square)](https://twitter.com/genocs) +# Genocs .NET library ---- -This repo contains a set of libraries designed by Genocs. The libraries are built using .NET standard 2.1, .NET6 and .NET7. + +This repo contains a set of libraries designed by Genocs. The libraries are built using .NET6 and .NET7. Packages are available on [NuGet Genocs](https://www.nuget.org/profiles/gioema_nocco). @@ -464,39 +501,49 @@ You can deploy Demo Application with one click in Heroku, Microsoft Azure, or Go [](https://deploy.cloud.run) + + +## License + +This project is licensed with the [MIT license](LICENSE). + +## Changelogs + +View Complete [Changelogs](https://github.com/Genocs/microservice-template/blob/main/CHANGELOGS.md). + ## Community - Discord [@genocs](https://discord.com/invite/fWwArnkV) - Facebook Page [@genocs](https://facebook.com/Genocs) - Youtube Channel [@genocs](https://youtube.com/c/genocs) -## Contributors -Submit your PR and join the list! +## Support - - - +Has this Project helped you learn something New? or Helped you at work? +Here are a few ways by which you can support. -## License +- ⭐ Leave a star! +- 🥇 Recommend this project to your colleagues. +- 🦸 Do consider endorsing me on LinkedIn for ASP.NET Core - [Connect via LinkedIn](https://www.linkedin.com/in/giovanni-emanuele-nocco-b31a5169/) +- ☕ If you want to support this project in the long run, [consider buying me a coffee](https://www.buymeacoffee.com/genocs)! + -This project is licensed with the [MIT license](LICENSE). +[![buy-me-a-coffee](https://raw.githubusercontent.com/Genocs/blazor-template/main/assets/buy-me-a-coffee.png "buy-me-a-coffee")](https://www.buymeacoffee.com/genocs) -## Support :star: +## Code Contributors -Has this project helped you learn something New? or Helped you at work? -Here are a few ways by which you can support. +This project exists thanks to all the people who contribute. [Submit your PR and join the team!](CONTRIBUTING.md) + +[![genocs contributors](https://contrib.rocks/image?repo=Genocs/blazor-template "genocs contributors")](https://github.com/genocs/blazor-template/graphs/contributors) + +## Financial Contributors -- Leave a star! :star: -- Recommend this awesome project to your colleagues. 🥇 -- Do consider endorsing me on LinkedIn for ASP.NET Core - [Connect via LinkedIn](https://www.linkedin.com/in/giovanni-emanuele-nocco-b31a5169/) 🦸 -- Or, If you want to support this project in the long run, [consider buying me a coffee](https://www.buymeacoffee.com/genocs)! ☕ +Become a financial contributor and help me sustain the project. [Support the Project!](https://opencollective.com/genocs/contribute) -
- -black-button + -## **acknowledgments** +## Acknowledgements - [devmentors](https://github.com/devmentors) - [abp](https://github.com/abpframework) \ No newline at end of file diff --git a/assets/buy-me-a-coffee.png b/assets/buy-me-a-coffee.png new file mode 100644 index 0000000000000000000000000000000000000000..02687279f645cfacd591c5db398752832c0bff2d GIT binary patch literal 12991 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/global.json b/global.json new file mode 100644 index 00000000..7cd6a1f4 --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "7.0.0", + "rollForward": "latestMajor", + "allowPrerelease": true + } +} \ No newline at end of file diff --git a/icon.png b/icon.png index 66a5cbe2d9c95b6827e11cf9dd9e7244cf632c26..3f859c6e617368eaae5fb5edb4697959b1449665 100644 GIT binary patch literal 19476 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 Cd^5xV literal 1034 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sDEfH31!Z9ZwBAX}2Ry9>jA5L~c#`DCC7dx@v7EBhlBCLslj ztgllY7#NtVJY5_^D&pSG*yw-TLF8C`j?hMxBv!LF5ksLPcla6?3I(y3xkU(Q*E_O_ zT~U?2X{->Mq%qO!`HGVrK`NV6*90DFaLWBP_w%J+KIh7WCJMc)oAmWv&eNmc@9r*t zKPO}RZT}^PV$r#VOdGC>DKijcOuM*`vrJa&-j0%cwTrxtKb>7`W-PW=_vV*EL&u+A z-n@|VXW;p>;+IFd>^t`jJ7+CA{U)bF;P14x?zeVz+5d=CwqY{(ob*BTU6sO>@0*HC zcBEY7x-Vq1OYd${X3QOnlD#J8#)1M$4c}^<4=S1PY+e5XhOJw?f0u6EZ?V(k=a!o1@_P!>{7otpUsOGL zz^W%3|8>QUr|Y`Z{2W3V%A`)^*GJ^IvY` zxQK7R+c`qprS5RE?+X*;owr_O>a?HR*tfm0uH4OMR1*^LcGhgUh~V2n9!b%EemQV= zWpi(Bn*XVHj>pjl{(oN!mmYS^>*JDq$8E(|+ug;{=|3W7} zgSCa6F2QP@vMslT#B#koPcMxZWa==jlls!y8TB|#CN8ca!K8FUS-VT`j%%-rp2Xa5 zZ++i#dXnVjX5Zz_U$xiq=D2GG$h)ZT`+vNEu_>`-*Z*m=^LbraR9?)rSL`gk^XS^S#G8)f3zn!DOqt}Vcp2-Caks1$UL6et210IxAIv)1;7Uzh`i>dP#Pk^?y81+WDYdf9lh=LmLPmD7Fj)1>2% zoWj-nhLT~;{cq9>ZhTby9WYnYWn$Z7>+ddi1FP5DC9G6#IQjh9%C_Q$Ei%Ux<_o80 zJ-P2YHzI#a)2B~CS8lG@`Mn^gR;_J^df$SW$^7T}@m&@3kK8lpTzvliRGenocs.Auth 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index a118ec23..c34bd433 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -7,7 +7,7 @@ Genocs.Common 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs diff --git a/src/Genocs.Common/Options/AppSettings.cs b/src/Genocs.Common/Options/AppSettings.cs index 014b578f..94ac5643 100644 --- a/src/Genocs.Common/Options/AppSettings.cs +++ b/src/Genocs.Common/Options/AppSettings.cs @@ -1,42 +1,42 @@ namespace Genocs.Common.Options; /// -/// The application settings +/// The application settings. /// public class AppSettings { /// - /// Default section name + /// Default section name. /// public const string Position = "App"; /// - /// Application name + /// Application name. /// public string? Name { get; set; } /// - /// Service name + /// Service name. /// public string? Service { get; set; } /// - /// The instance of the service + /// The instance of the service. /// public string? Instance { get; set; } /// - /// The application version + /// The application version. /// public string? Version { get; set; } /// - /// It defines whether the banner is shown into the console at startup time or not + /// It defines whether the banner is shown into the console at startup time or not. /// public bool DisplayBanner { get; set; } /// - /// It defines whether the application version is shown into the console at startup time or not + /// It defines whether the application version is shown into the console at startup time or not. /// public bool DisplayVersion { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Common/Types/Extensions.cs b/src/Genocs.Common/Types/Extensions.cs index ba2548ed..c8b82d9f 100644 --- a/src/Genocs.Common/Types/Extensions.cs +++ b/src/Genocs.Common/Types/Extensions.cs @@ -5,12 +5,12 @@ namespace Genocs.Common.Types; /// -/// Type extensions +/// Type extensions. /// public static class Extensions { /// - /// GetDefaultInstance + /// GetDefaultInstance. /// /// /// @@ -23,7 +23,7 @@ public static class Extensions var defaultValueCache = new Dictionary(); - if (TryGetDefaultValue(type, out var instance, defaultValueCache)) + if (TryGetDefaultValue(type, out object? instance, defaultValueCache)) { return instance; } @@ -42,7 +42,7 @@ private static object SetDefaultInstanceProperties(object instance, Dictionary - + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index ae4a0a79..5d8caffb 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index 4d2feb06..f7a7d566 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -28,12 +28,11 @@ .WriteTo.Console() .CreateLogger(); - IHost host = Host.CreateDefaultBuilder(args) .UseLogging() .ConfigureServices((hostContext, services) => { - // Run the hosted service + // Run the hosted service services.AddHostedService(); services @@ -51,7 +50,6 @@ Log.CloseAndFlush(); - static IServiceCollection ConfigureMassTransit(IServiceCollection services, IConfiguration configuration) { services.TryAddSingleton(KebabCaseEndpointNameFormatter.Instance); @@ -107,7 +105,6 @@ static void ConfigureAzureServiceBusTopic(IServiceCollection services, IConfigur var topicBus = services.BuildServiceProvider().GetRequiredService(); topicBus.Subscribe>(); - } static void ConfigureAzureServiceBusQueue(IServiceCollection services, IConfiguration configuration) diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 5a627bd2..34344ea8 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -7,7 +7,7 @@ Genocs.Core 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 9f9d2066..7a998981 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -7,7 +7,7 @@ Genocs.Discovery.Consul 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -49,8 +49,8 @@ - - + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 4f988395..f2cee3e0 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -8,7 +8,7 @@ Genocs.HTTP.RestEase 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -52,13 +52,12 @@ - - - - + + + + - - + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 43309689..d4c14dd4 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -7,7 +7,7 @@ Genocs.HTTP 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 295946a7..069f8905 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -7,7 +7,7 @@ Genocs.LoadBalancing.Fabio 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -50,9 +50,9 @@ - - - + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 04079462..ee4b9ac3 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -7,7 +7,7 @@ Genocs.Logging 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 8ef8a32e..c064cfe7 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -7,7 +7,7 @@ Genocs.MessageBrokers.Outbox.MongoDB 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,7 +48,7 @@ - - + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 06446e83..bc1249c3 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -7,7 +7,7 @@ Genocs.MessageBrokers.Outbox 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,6 +47,6 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index b3baf369..11b72e62 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -7,7 +7,7 @@ Genocs.MessageBrokers.RabbitMQ 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 4e480cd1..421ea09c 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -7,7 +7,7 @@ Genocs.MessageBrokers 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,7 +48,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 18de27a1..22eac31b 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -7,7 +7,7 @@ Genocs.Metrics 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 14e5806f..848549c3 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -7,7 +7,7 @@ Genocs.Monitoring 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -50,9 +50,9 @@ - - - + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index fe7c0b2a..3b27b3ad 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -6,7 +6,7 @@ enable false false - bf5e372b-b320-4d11-beb8-a793edae0ad4 + Genocs @@ -26,7 +26,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index dd46c1b5..c42f0e83 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -7,7 +7,7 @@ Genocs.Persistence.MongoDb 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index a9615719..23a55f69 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -7,7 +7,7 @@ Genocs.Persistence.Redis 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 0ced936b..c1bd7066 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 19628780..fb990c8f 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -7,7 +7,7 @@ Genocs.QueryBuilder 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index af1b194e..30a7377d 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -7,7 +7,7 @@ Genocs.Secrets.Vault 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index e42b67e6..a1cce305 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -7,7 +7,7 @@ Genocs.Security 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,7 +48,7 @@ - + diff --git a/src/Genocs.Security/README.md b/src/Genocs.Security/README.md index c96381ac..7f9dd01f 100644 --- a/src/Genocs.Security/README.md +++ b/src/Genocs.Security/README.md @@ -1,8 +1,7 @@ # .NET Core Base library This package contains a set of base functionalities designed by Genocs. -The libraries are built using .NET standard 2.1. - +The libraries can be used on both .NET6 and .NET7. ## Description diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 28b70d72..142a640f 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -7,7 +7,7 @@ Genocs.ServiceBusAzure 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,7 +48,7 @@ - + diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index f6328503..0345f959 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -8,22 +8,23 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using OpenTelemetry; +using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; namespace Genocs.Tracing; /// -/// The Open Telemetry extensions +/// The Open Telemetry extensions. /// public static class Extensions { /// - /// Custom settings for OpenTelemetry + /// Custom settings for OpenTelemetry. /// - /// The genocs builder - /// the builder + /// The genocs builder. + /// The builder. public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) { @@ -37,10 +38,30 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) var services = builder.Services; - // Set Custom Open telemetry services.AddOpenTelemetry().WithTracing(x => { +/* + Action appResourceBuilder = + resource => resource + .AddDetector(new ContainerResourceDetector()); + + builder.Services.AddOpenTelemetry() + .ConfigureResource(appResourceBuilder) + .WithTracing(tracerBuilder => tracerBuilder + .AddRedisInstrumentation( + cartStore.GetConnection(), + options => options.SetVerboseDatabaseStatements = true) + .AddAspNetCoreInstrumentation() + .AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation() + .AddOtlpExporter()) + .WithMetrics(meterBuilder => meterBuilder + .AddRuntimeInstrumentation() + .AddAspNetCoreInstrumentation() + .AddOtlpExporter()); +*/ + TracerProviderBuilder provider = x.SetResourceBuilder(ResourceBuilder.CreateDefault() .AddService(appOptions.Service) .AddTelemetrySdk() @@ -50,10 +71,8 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) // TODO> add flag to enable feature MongoDB.Driver.Core.Extensions.OpenTelemetry provider.AddMongoDBInstrumentation(); - var loggerOptions = builder.GetOptions(LoggerSettings.Position); - // Check for Console config if (loggerOptions.Console != null && loggerOptions.Console.Enabled) { @@ -74,20 +93,20 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) if (jaegerOptions != null && jaegerOptions.Enabled) { - provider.AddJaegerExporter(o => - { - o.AgentHost = jaegerOptions.UdpHost; - o.AgentPort = jaegerOptions.UdpPort; - o.MaxPayloadSizeInBytes = jaegerOptions.MaxPacketSize; - o.ExportProcessorType = ExportProcessorType.Batch; - o.BatchExportProcessorOptions = new BatchExportProcessorOptions - { - MaxQueueSize = 2048, - ScheduledDelayMilliseconds = 5000, - ExporterTimeoutMilliseconds = 30000, - MaxExportBatchSize = 512, - }; - }); + //provider.AddJaegerExporter(o => + //{ + // o.AgentHost = jaegerOptions.UdpHost; + // o.AgentPort = jaegerOptions.UdpPort; + // o.MaxPayloadSizeInBytes = jaegerOptions.MaxPacketSize; + // o.ExportProcessorType = ExportProcessorType.Batch; + // o.BatchExportProcessorOptions = new BatchExportProcessorOptions + // { + // MaxQueueSize = 2048, + // ScheduledDelayMilliseconds = 5000, + // ExporterTimeoutMilliseconds = 30000, + // MaxExportBatchSize = 512, + // }; + //}); } }); diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index c887dff2..bef6e970 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -7,7 +7,7 @@ Genocs.Tracing 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -50,9 +50,9 @@ - - - + + + @@ -63,8 +63,8 @@ - - + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index a808b4db..d6e36c6a 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -7,7 +7,7 @@ Genocs.WebApi.CQRS 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -50,8 +50,8 @@ - - + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 12a3702e..987a067b 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -7,7 +7,7 @@ Genocs.WebApi.Security 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 3e5ca529..9056b78e 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -7,7 +7,7 @@ Genocs.WebApi.Swagger 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 300ac44a..5c100340 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -7,7 +7,7 @@ Genocs.WebApi 10.0 true - 5.0.0-preview.4.0 + 5.0.0-preview.5.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,7 +48,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/UserMiddleware.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/UserMiddleware.cs index d2b85bb6..deb13ecb 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/UserMiddleware.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/UserMiddleware.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Authentication; +using System.Net; using System.Text; using System.Text.Json; @@ -10,7 +11,7 @@ public class UserMiddleware : IMiddleware { "POST", "PUT", "PATCH" }; - + public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var request = context.Request; @@ -26,7 +27,7 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next) return; } - var path = context.Request.Path.Value; + string? path = context.Request.Path.Value; if (path is not null && (path.Contains("sign-in") || path.Contains("sign-up"))) { await next(context); @@ -36,7 +37,8 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next) var authenticateResult = await context.AuthenticateAsync(); if (!authenticateResult.Succeeded || authenticateResult.Principal is null) { - context.Response.StatusCode = 401; + // Set the response code to 401. + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return; } @@ -47,7 +49,7 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next) content = await reader.ReadToEndAsync(); } - if(string.IsNullOrWhiteSpace(content)) + if (string.IsNullOrWhiteSpace(content)) { await next(context); return; @@ -61,7 +63,7 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next) } payload["userId"] = Guid.Parse(context.User.Identity.Name); - var json = JsonSerializer.Serialize(payload); + string json = JsonSerializer.Serialize(payload); await using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)); context.Request.Body = memoryStream; context.Request.ContentLength = json.Length; diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 29981233..46eda5f4 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -19,15 +19,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 8bc44ddb..5120883d 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -7,20 +7,20 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/apps/identity/Genocs.Identities.WebApi/Program.cs b/src/apps/identity/Genocs.Identities.WebApi/Program.cs index 8e6cb25e..1a840d1a 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Program.cs +++ b/src/apps/identity/Genocs.Identities.WebApi/Program.cs @@ -19,14 +19,12 @@ .WriteTo.Console() .CreateLogger(); - var builder = WebApplication.CreateBuilder(args); builder.Host .UseLogging() .UseVault(); - var services = builder.Services; services.AddGenocs(builder.Configuration) @@ -63,5 +61,4 @@ app.Run(); -Log.CloseAndFlush(); - +Log.CloseAndFlush(); \ No newline at end of file diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 8f7c4c0d..a92fd129 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -29,21 +29,21 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index f560c95f..d30a4e0e 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -30,22 +30,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index eec9a627..cae2889e 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -34,23 +34,23 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 00000000..95ceebe8 --- /dev/null +++ b/stylecop.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "orderingRules": { + "systemUsingDirectivesFirst": true, + "usingDirectivesPlacement": "outsideNamespace" + }, + "layoutRules": { + "newlineAtEndOfFile": "omit" + } + } +} \ No newline at end of file From 08f7ea0ef2212d92769c1aad6fd0af05c673e168 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 13 Oct 2023 21:16:45 +0200 Subject: [PATCH 002/104] Updates change log --- CHANGELOG.md | 5 ++- README.md | 18 +++++----- demo-webapi.dockerfile | 7 ---- demo-worker.dockerfile | 7 ---- src/Genocs.Auth/README.md | 14 +++++++- src/Genocs.Common/README.md | 8 ++++- .../Genocs.Core.Demo.WebApi.csproj | 2 +- .../Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Core/README.md | 8 ++++- src/Genocs.Discovery.Consul/README.md | 8 ++++- src/Genocs.HTTP.RestEase/README.md | 8 ++++- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- src/Genocs.HTTP/README.md | 8 ++++- src/Genocs.LoadBalancing.Fabio/README.md | 8 ++++- src/Genocs.Logging/README.md | 8 ++++- .../README.md | 8 ++++- src/Genocs.MessageBrokers.Outbox/README.md | 8 ++++- .../Extensions.cs | 36 +++++++++++-------- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- src/Genocs.MessageBrokers.RabbitMQ/README.md | 8 ++++- src/Genocs.MessageBrokers/README.md | 8 ++++- src/Genocs.Metrics/README.md | 8 ++++- .../Genocs.Monitoring.csproj | 4 +-- src/Genocs.Persistence.Redis/README.md | 8 ++++- src/Genocs.QueryBuilder/README.md | 8 ++++- src/Genocs.Secrets.Vault/README.md | 8 ++++- src/Genocs.Security/README.md | 8 ++++- src/Genocs.ServiceBusAzure/README.md | 8 ++++- src/Genocs.Tracing.Jaeger.RabbitMQ/README.md | 8 ++++- src/Genocs.Tracing/Genocs.Tracing.csproj | 8 ++--- src/Genocs.Tracing/README.md | 8 ++++- src/Genocs.WebApi.CQRS/README.md | 8 ++++- src/Genocs.WebApi.Security/README.md | 8 ++++- src/Genocs.WebApi.Swagger/README.md | 8 ++++- src/Genocs.WebApi/README.md | 8 ++++- src/apps/apigateway.dockerfile | 7 ---- src/apps/identity-webapi.dockerfile | 7 ---- src/apps/order-webapi.dockerfile | 7 ---- src/apps/product-webapi.dockerfile | 8 +---- 39 files changed, 219 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33ef4c22..45949c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,10 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). ### Features -* +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme ### Bug Fixes diff --git a/README.md b/README.md index 608c649d..d1c8a6be 100644 --- a/README.md +++ b/README.md @@ -83,37 +83,37 @@ docker-compose -f ./containers/infrastructure-elk.yml --project-name genocs-infr docker-compose -f ./containers/infrastructure-ml.yml --project-name genocs-infrastructure up -d ``` -`infrastructure-bare.yml` allows to install the basic infrastructure components. Basic componens are the [RabbitMQ](https://rabbitmq.com), [Redis](https://redis.io), [Mongo](https://mongodb.com), [Postgres](https://www.postgresql.org/). +`infrastructure-bare.yml` allows to install the basic infrastructure components. Basic components are the [RabbitMQ](https://rabbitmq.com), [Redis](https://redis.io), [Mongo](https://mongodb.com), [Postgres](https://www.postgresql.org/). - [rabbitmq](http://localhost:15672/) -- redis -- mongo -- postgresql +- Redis +- MongoDb +- PostgreSQL `infrastructure-monitoring.yml` allows to install the monitoring infrastructure components. Inside the file you can find: -- prometheus -- grafana +- Prometheus +- Grafana - influxdb -- jaeager +- jaeger - seq `infrastructure-scaling.yml` allows to install the scaling infrastructure components. Inside the file you can find: -- fabio +- Fabio - consul `infrastructure-security.yml` allows to install the security infrastructure components. Inside the file you can find: -- vault (hashicorp) +- vault (Hashicorp) The script below allows to setup the infrastructure components. This means that you can find all the containers inside the same network. diff --git a/demo-webapi.dockerfile b/demo-webapi.dockerfile index dea4fa6c..8ad8f855 100644 --- a/demo-webapi.dockerfile +++ b/demo-webapi.dockerfile @@ -1,18 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. - -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim #FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env -#FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env -# FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build-env #FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env WORKDIR /src diff --git a/demo-worker.dockerfile b/demo-worker.dockerfile index fa4bd415..80a9bb69 100644 --- a/demo-worker.dockerfile +++ b/demo-worker.dockerfile @@ -1,18 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. - -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim #FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env -#FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env -# FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build-env #FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env WORKDIR /src diff --git a/src/Genocs.Auth/README.md b/src/Genocs.Auth/README.md index a840446a..637423d1 100644 --- a/src/Genocs.Auth/README.md +++ b/src/Genocs.Auth/README.md @@ -37,7 +37,19 @@ Following are the project settings needed to enable monitoring ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-24] 5.0.0 diff --git a/src/Genocs.Common/README.md b/src/Genocs.Common/README.md index 36aac719..e13b098e 100644 --- a/src/Genocs.Common/README.md +++ b/src/Genocs.Common/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-24] 5.0.0 diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 41790cf1..2db4d0c1 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 5c94816b..ac73bf64 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Genocs.Core/README.md b/src/Genocs.Core/README.md index d99be2c9..4d083c6c 100644 --- a/src/Genocs.Core/README.md +++ b/src/Genocs.Core/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Discovery.Consul/README.md b/src/Genocs.Discovery.Consul/README.md index 945bb03b..a9b80e9f 100644 --- a/src/Genocs.Discovery.Consul/README.md +++ b/src/Genocs.Discovery.Consul/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.HTTP.RestEase/README.md b/src/Genocs.HTTP.RestEase/README.md index 945bb03b..a9b80e9f 100644 --- a/src/Genocs.HTTP.RestEase/README.md +++ b/src/Genocs.HTTP.RestEase/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index d4c14dd4..a6de5746 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -52,7 +52,7 @@ - + diff --git a/src/Genocs.HTTP/README.md b/src/Genocs.HTTP/README.md index 53efd407..d3afafc4 100644 --- a/src/Genocs.HTTP/README.md +++ b/src/Genocs.HTTP/README.md @@ -33,7 +33,13 @@ Following are the project settings needed to enable monitoring ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.LoadBalancing.Fabio/README.md b/src/Genocs.LoadBalancing.Fabio/README.md index 945bb03b..a9b80e9f 100644 --- a/src/Genocs.LoadBalancing.Fabio/README.md +++ b/src/Genocs.LoadBalancing.Fabio/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Logging/README.md b/src/Genocs.Logging/README.md index 4fd1372a..e2424fce 100644 --- a/src/Genocs.Logging/README.md +++ b/src/Genocs.Logging/README.md @@ -22,7 +22,13 @@ Following are the project settings needed to enable monitoring ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md b/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.MessageBrokers.Outbox/README.md b/src/Genocs.MessageBrokers.Outbox/README.md index 301959bb..c7408fe7 100644 --- a/src/Genocs.MessageBrokers.Outbox/README.md +++ b/src/Genocs.MessageBrokers.Outbox/README.md @@ -26,7 +26,13 @@ Following are the project settings needed to enable monitoring ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs index 48a2158c..e34149aa 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs @@ -17,9 +17,8 @@ namespace Genocs.MessageBrokers.RabbitMQ; - /// -/// RabbitMQ support helper +/// RabbitMQ support helper. /// public static class Extensions { @@ -27,7 +26,7 @@ public static class Extensions private const string RegistryName = "messageBrokers.rabbitmq"; /// - /// AddRabbitMq extension method + /// AddRabbitMq extension method. /// /// /// @@ -35,10 +34,13 @@ public static class Extensions /// /// /// - /// - public static IGenocsBuilder AddRabbitMq(this IGenocsBuilder builder, string sectionName = SectionName, - Func? plugins = null, - Action? connectionFactoryConfigurator = null, IRabbitMqSerializer? serializer = null) + /// Raised when configuration is incorrect. + public static IGenocsBuilder AddRabbitMq( + this IGenocsBuilder builder, + string sectionName = SectionName, + Func? plugins = null, + Action? connectionFactoryConfigurator = null, + IRabbitMqSerializer? serializer = null) { if (string.IsNullOrWhiteSpace(sectionName)) { @@ -57,7 +59,6 @@ public static IGenocsBuilder AddRabbitMq(this IGenocsBuilder builder, string sec throw new ArgumentException("RabbitMQ hostnames are not specified.", nameof(options.HostNames)); } - ILogger logger; using (var serviceProvider = builder.Services.BuildServiceProvider()) { @@ -129,8 +130,10 @@ public static IGenocsBuilder AddRabbitMq(this IGenocsBuilder builder, string sec return builder; } - private static void ConfigureSsl(ConnectionFactory connectionFactory, RabbitMQOptions options, - ILogger logger) + private static void ConfigureSsl( + ConnectionFactory connectionFactory, + RabbitMQOptions options, + ILogger logger) { if (options.Ssl is null || string.IsNullOrWhiteSpace(options.Ssl.ServerName)) { @@ -138,8 +141,10 @@ private static void ConfigureSsl(ConnectionFactory connectionFactory, RabbitMQOp return; } - connectionFactory.Ssl = new SslOption(options.Ssl.ServerName, options.Ssl.CertificatePath, - options.Ssl.Enabled); + connectionFactory.Ssl = new SslOption( + options.Ssl.ServerName, + options.Ssl.CertificatePath, + options.Ssl.Enabled); logger.LogDebug($"RabbitMQ SSL is: {(options.Ssl.Enabled ? "enabled" : "disabled")}, " + $"server: '{options.Ssl.ServerName}', client certificate: '{options.Ssl.CertificatePath}', " + @@ -180,12 +185,13 @@ private static void ConfigureSsl(ConnectionFactory connectionFactory, RabbitMQOp logger.LogDebug("Received X509 certificate chain statuses: " + $"{string.Join(", ", statuses.Select(x => x.Status))}"); - var isValid = statuses.All(chainStatus => chainStatus.Status == X509ChainStatusFlags.NoError + bool isValid = statuses.All(chainStatus => chainStatus.Status == X509ChainStatusFlags.NoError || ignoredStatuses.Contains(chainStatus.Status)); if (!isValid) { - logger.LogError(string.Join(Environment.NewLine, - statuses.Select(s => $"{s.Status} - {s.StatusInformation}"))); + logger.LogError(string.Join( + Environment.NewLine, + statuses.Select(s => $"{s.Status} - {s.StatusInformation}"))); } return isValid; diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 11b72e62..c4d7a3fb 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -52,7 +52,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/README.md b/src/Genocs.MessageBrokers.RabbitMQ/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/README.md +++ b/src/Genocs.MessageBrokers.RabbitMQ/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.MessageBrokers/README.md b/src/Genocs.MessageBrokers/README.md index bc2fb3cb..da894335 100644 --- a/src/Genocs.MessageBrokers/README.md +++ b/src/Genocs.MessageBrokers/README.md @@ -33,7 +33,13 @@ Following are the project settings needed to enable monitoring ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Metrics/README.md b/src/Genocs.Metrics/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.Metrics/README.md +++ b/src/Genocs.Metrics/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 848549c3..e60f1141 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -57,9 +57,9 @@ - + - + diff --git a/src/Genocs.Persistence.Redis/README.md b/src/Genocs.Persistence.Redis/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.Persistence.Redis/README.md +++ b/src/Genocs.Persistence.Redis/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.QueryBuilder/README.md b/src/Genocs.QueryBuilder/README.md index 945bb03b..a9b80e9f 100644 --- a/src/Genocs.QueryBuilder/README.md +++ b/src/Genocs.QueryBuilder/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Secrets.Vault/README.md b/src/Genocs.Secrets.Vault/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.Secrets.Vault/README.md +++ b/src/Genocs.Secrets.Vault/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Security/README.md b/src/Genocs.Security/README.md index 7f9dd01f..5212a012 100644 --- a/src/Genocs.Security/README.md +++ b/src/Genocs.Security/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.ServiceBusAzure/README.md b/src/Genocs.ServiceBusAzure/README.md index 9d913aa8..d4ae6e0b 100644 --- a/src/Genocs.ServiceBusAzure/README.md +++ b/src/Genocs.ServiceBusAzure/README.md @@ -33,7 +33,13 @@ Following are the project settings needed to enable monitoring ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md b/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md index 945bb03b..a9b80e9f 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md @@ -15,7 +15,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index bef6e970..380db2c3 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -60,11 +60,11 @@ - + - - - + + + diff --git a/src/Genocs.Tracing/README.md b/src/Genocs.Tracing/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.Tracing/README.md +++ b/src/Genocs.Tracing/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.WebApi.CQRS/README.md b/src/Genocs.WebApi.CQRS/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.WebApi.CQRS/README.md +++ b/src/Genocs.WebApi.CQRS/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.WebApi.Security/README.md b/src/Genocs.WebApi.Security/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.WebApi.Security/README.md +++ b/src/Genocs.WebApi.Security/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.WebApi.Swagger/README.md b/src/Genocs.WebApi.Swagger/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.WebApi.Swagger/README.md +++ b/src/Genocs.WebApi.Swagger/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/Genocs.WebApi/README.md b/src/Genocs.WebApi/README.md index c96381ac..783a9116 100644 --- a/src/Genocs.WebApi/README.md +++ b/src/Genocs.WebApi/README.md @@ -16,7 +16,13 @@ Please check the GitHub repository getting more info. ## Release notes -### [2023-03-12] 5.0.0-preview.5.0 +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 - Implemented MongoDB repository interfaces ### [2023-03-12] 5.0.0 diff --git a/src/apps/apigateway.dockerfile b/src/apps/apigateway.dockerfile index 9d96bc30..37b9b1e0 100644 --- a/src/apps/apigateway.dockerfile +++ b/src/apps/apigateway.dockerfile @@ -1,18 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. - -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim #FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env -#FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env -# FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build-env #FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env WORKDIR /src diff --git a/src/apps/identity-webapi.dockerfile b/src/apps/identity-webapi.dockerfile index d7525095..cba04136 100644 --- a/src/apps/identity-webapi.dockerfile +++ b/src/apps/identity-webapi.dockerfile @@ -1,18 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. - -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim #FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env -#FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env -# FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build-env #FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env WORKDIR /src diff --git a/src/apps/order-webapi.dockerfile b/src/apps/order-webapi.dockerfile index 4ae55469..45881ddb 100644 --- a/src/apps/order-webapi.dockerfile +++ b/src/apps/order-webapi.dockerfile @@ -1,18 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. - -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim #FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env -#FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env -# FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build-env #FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env WORKDIR /src diff --git a/src/apps/product-webapi.dockerfile b/src/apps/product-webapi.dockerfile index c54eb404..b9860e42 100644 --- a/src/apps/product-webapi.dockerfile +++ b/src/apps/product-webapi.dockerfile @@ -1,18 +1,12 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. - -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim #FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env -#FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env -# FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build-env + #FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env WORKDIR /src From 32f4e2c8831d2fb2ccc0b17831469c012c43fa99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 19:31:51 +0000 Subject: [PATCH 003/104] Bump Serilog.Sinks.ElasticSearch from 8.4.1 to 9.0.3 Bumps [Serilog.Sinks.ElasticSearch](https://github.com/serilog-contrib/serilog-sinks-elasticsearch) from 8.4.1 to 9.0.3. - [Release notes](https://github.com/serilog-contrib/serilog-sinks-elasticsearch/releases) - [Changelog](https://github.com/serilog-contrib/serilog-sinks-elasticsearch/blob/dev/CHANGES.md) - [Commits](https://github.com/serilog-contrib/serilog-sinks-elasticsearch/commits/v9.0.3) --- updated-dependencies: - dependency-name: Serilog.Sinks.ElasticSearch dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- src/Genocs.Logging/Genocs.Logging.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index ee4b9ac3..8d56f4ad 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -1,4 +1,4 @@ - + net6.0;net7.0 @@ -54,7 +54,7 @@ - + From ac2c429ef128772b7eedee17dfdf8ff4d4c08d8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 19:35:48 +0000 Subject: [PATCH 004/104] Bump Serilog.Sinks.Seq from 5.1.0 to 5.2.3 Bumps [Serilog.Sinks.Seq](https://github.com/serilog/serilog-sinks-seq) from 5.1.0 to 5.2.3. - [Release notes](https://github.com/serilog/serilog-sinks-seq/releases) - [Commits](https://github.com/serilog/serilog-sinks-seq/compare/v5.1.0...v5.2.3) --- updated-dependencies: - dependency-name: Serilog.Sinks.Seq dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 8d56f4ad..f50c1aa9 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -57,7 +57,7 @@ - + From 6f527c7324c6097ca287a3c1a1bcff592af081ea Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 13 Oct 2023 21:47:50 +0200 Subject: [PATCH 005/104] Fix workflow --- .github/workflows/build_and_test.yml | 38 +++++++++++++------------ .github/workflows/dockerhub-publish.yml | 15 ++++++---- .github/workflows/manual.yml | 8 +++--- .github/workflows/nuget-publish.yml | 4 +-- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index cf3d5112..50b58032 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -1,4 +1,6 @@ -name: Build test and pack +# This is a manually triggered dockerhub build and publish + +name: Publish to Dockerhub on: push: @@ -12,22 +14,22 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v2 - with: - dotnet-version: 7.0.x - - - name: Restore dependencies - run: dotnet restore - - - name: Build - run: dotnet build --no-restore - - - name: Test - run: dotnet test --no-build --verbosity normal - + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 7.0.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build -c Debug --no-restore + + - name: Test + run: dotnet test --no-build --verbosity normal + - name: Pack run: dotnet pack --no-build --verbosity normal diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml index 8ae370ae..3dd29382 100644 --- a/.github/workflows/dockerhub-publish.yml +++ b/.github/workflows/dockerhub-publish.yml @@ -27,22 +27,25 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - + - name: Setup .NET - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: 7.0.x - + - name: Restore dependencies run: dotnet restore - + - name: Build run: dotnet build -c Debug --no-restore - + - name: Test run: dotnet test --no-build --verbosity normal + + - name: Pack + run: dotnet pack --no-build --verbosity normal - - name: Log in to Docker Hub + - name: Docker Hub Log in uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a with: username: ${{secrets.DOCKER_USERNAME}} diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 47ebde80..99a3c53a 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -29,7 +29,7 @@ jobs: steps: # Runs a single command using the runners shell - name: Send greeting - run: echo "Hello ${{ github.event.inputs.name }}" + run: echo "Hello ${{github.event.inputs.name}}" - name: Print Run Number run: echo "Hello $env:GITHUB_RUN_NUMBER" @@ -38,10 +38,10 @@ jobs: run: echo "Hello $env:GITHUB_RUN_ATTEMPT" - name: Output Run ID - run: echo ${{ github.run_id }} + run: echo ${{github.run_id}} - name: Output Run Number - run: echo ${{ github.run_number }} + run: echo ${{github.run_number}} - name: Output Run Attempt - run: echo ${{ github.run_attempt }} + run: echo ${{github.run_attempt}} diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 2d58c4b0..f872f6a2 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -26,10 +26,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v3 with: dotnet-version: 7.0.x From aa542848efc453e7f298f5dd02e466d5a42c7791 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 23 Nov 2023 22:49:37 +0100 Subject: [PATCH 006/104] removed templates and updated packages --- src/Genocs.Auth/Genocs.Auth.csproj | 7 + src/Genocs.Common/Genocs.Common.csproj | 7 + .../Genocs.Core.Demo.Contracts.csproj | 8 + .../Genocs.Core.Demo.Domain.csproj | 7 + .../Genocs.Core.Demo.Infrastructure.csproj | 7 + .../Genocs.Core.Demo.WebApi.csproj | 9 +- .../Genocs.Core.Demo.Worker.csproj | 12 +- .../Genocs.Core.UnitTests.csproj | 10 +- src/Genocs.Core/Genocs.Core.csproj | 7 + .../Genocs.Discovery.Consul.csproj | 7 + .../Genocs.HTTP.RestEase.csproj | 7 + src/Genocs.HTTP/Genocs.HTTP.csproj | 9 +- .../Genocs.LoadBalancing.Fabio.csproj | 7 + src/Genocs.Logging/Genocs.Logging.csproj | 6 + ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 7 + .../Genocs.MessageBrokers.Outbox.csproj | 7 + .../Genocs.MessageBrokers.RabbitMQ.csproj | 11 +- .../Genocs.MessageBrokers.csproj | 7 + src/Genocs.Metrics/Genocs.Metrics.csproj | 7 + .../Genocs.Monitoring.csproj | 7 + ...enocs.Persistence.MongoDB.UnitTests.csproj | 13 +- .../Genocs.Persistence.MongoDb.csproj | 7 + .../Genocs.Persistence.Redis.csproj | 7 + .../InMemoryBasicDynamicQueriesUnitTests.cs | 57 +- .../InMemoryDynamicQueriesUnitTests.cs | 32 +- .../SqlServerDynamicQueriesUnitTests.cs | 133 +- .../Genocs.QueryBuilder.UnitTests.csproj | 13 +- .../Models/Customer.cs | 9 +- .../Models/Order.cs | 42 +- .../Models/TreeNode.cs | 5 +- .../Models/User.cs | 4 +- .../Genocs.QueryBuilder.csproj | 7 + .../Genocs.Secrets.Vault.csproj | 7 + src/Genocs.Security/Genocs.Security.csproj | 7 + .../Genocs.ServiceBusAzure.UnitTests.csproj | 10 +- .../Genocs.ServiceBusAzure.csproj | 7 + src/Genocs.Tracing/Genocs.Tracing.csproj | 7 + .../Genocs.WebApi.CQRS.csproj | 7 + .../Genocs.WebApi.Security.csproj | 7 + .../Genocs.WebApi.Swagger.csproj | 7 + src/Genocs.WebApi/Genocs.WebApi.csproj | 7 + .../Genocs.APIGateway.csproj | 9 +- .../Genocs.Identities.Application.csproj | 8 + .../Genocs.Identities.WebApi.csproj | 7 + .../Genocs.Orders.WebApi.csproj | 7 + .../Genocs.Products.WebApi.csproj | 7 + .../Genocs.SignalR.WebApi.csproj | 8 + templates/README.md | 30 - templates/WebApiTemplate.nuspec | 70 - templates/icon.png | Bin 1034 -> 0 bytes templates/nuget.exe | Bin 6512008 -> 0 bytes templates/template/.dockerignore | 25 - templates/template/.editorconfig | 191 --- templates/template/.env | 7 - .../template/.template.config/template.json | 59 - templates/template/.travis.yml | 20 - templates/template/Genocs.Template.sln | 61 - templates/template/NuGet.config | 8 - templates/template/README.md | 1493 ----------------- templates/template/api-workbench.rest | 19 - templates/template/docker-compose.dcproj | 18 - .../template/docker-compose.override.yml | 20 - templates/template/docker-compose.yml | 8 - .../Genocs.Template-kubernetes-ingress.yaml | 24 - .../Genocs.Template-kubernetes-webapi.yaml | 44 - .../Genocs.Template-kubernetes-worker.yaml | 44 - .../pipelines/azure-pipeline-build.yml | 40 - .../pipelines/azure-pipeline-docker-acr.yml | 64 - .../pipelines/azure-pipeline-docker.yml | 64 - .../template/pipelines/azure-pipeline.yml | 126 -- templates/template/scripts/build.sh | 9 - templates/template/scripts/test.sh | 2 - .../Genocs.Template.AcceptanceTests.csproj | 26 - .../Commands/CreateUser.cs | 24 - .../Commands/Handlers/CreateUserHandler.cs | 63 - .../Commands/Handlers/LockUserHandler.cs | 35 - .../Handlers/RevokeAccessTokenHandler.cs | 17 - .../Handlers/RevokeRefreshTokenHandler.cs | 27 - .../Commands/Handlers/SignInHandler.cs | 72 - .../Commands/Handlers/UnlockUserHandler.cs | 34 - .../Handlers/UseRefreshTokenHandler.cs | 54 - .../Commands/LockUser.cs | 13 - .../Commands/RevokeAccessToken.cs | 13 - .../Commands/RevokeRefreshToken.cs | 13 - .../Commands/SignIn.cs | 16 - .../Commands/UnlockUser.cs | 13 - .../Commands/UseRefreshToken.cs | 14 - .../ContractAttribute.cs | 6 - .../CorrelationContext.cs | 21 - .../CorrelationIdFactory.cs | 78 - .../DTO/AuthDto.cs | 11 - .../DTO/PagedDto.cs | 16 - .../DTO/UserDetailsDto.cs | 12 - .../DTO/UserDto.cs | 9 - .../LoggingCommandHandlerDecorator.cs | 36 - .../LoggingEventHandlerDecorator.cs | 36 - .../OutboxCommandHandlerDecorator.cs | 35 - .../Decorators/OutboxEventHandlerDecorator.cs | 36 - .../Domain/Entities/AggregateId.cs | 50 - .../Domain/Entities/AggregateRoot.cs | 16 - .../Domain/Entities/RefreshToken.cs | 37 - .../Domain/Entities/Role.cs | 19 - .../Domain/Entities/User.cs | 70 - .../Domain/Exceptions/DomainException.cs | 8 - .../Domain/Exceptions/EmailInUseException.cs | 11 - .../Exceptions/EmptyRefreshTokenException.cs | 8 - .../Exceptions/InvalidAggregateIdException.cs | 8 - .../Exceptions/InvalidCredentialsException.cs | 11 - .../Exceptions/InvalidEmailException.cs | 8 - .../Domain/Exceptions/InvalidNameException.cs | 8 - .../Exceptions/InvalidPasswordException.cs | 8 - .../InvalidRefreshTokenException.cs | 8 - .../Domain/Exceptions/InvalidRoleException.cs | 8 - .../Domain/Exceptions/NameInUseException.cs | 11 - .../RevokedRefreshTokenException.cs | 8 - .../Domain/Exceptions/UserLockedException.cs | 11 - .../Repositories/IRefreshTokenRepository.cs | 10 - .../Domain/Repositories/IUserRepository.cs | 12 - .../Events/SignedIn.cs | 13 - .../Events/UserCreated.cs | 17 - .../Events/UserLocked.cs | 13 - .../Events/UserUnlocked.cs | 13 - .../Exceptions/AppException.cs | 8 - .../Exceptions/ExceptionToMessageMapper.cs | 9 - .../Exceptions/ExceptionToResponseMapper.cs | 37 - .../Exceptions/Extensions.cs | 9 - .../Exceptions/UserNotFoundException.cs | 11 - .../Genocs.Template.Application/Extensions.cs | 128 -- .../Genocs.Template.Application.csproj | 25 - .../Logging/LogContextMiddleware.cs | 24 - .../Mongo/Documents/RefreshTokenDocument.cs | 28 - .../Mongo/Documents/UserDocument.cs | 34 - .../Mongo/Extensions.cs | 33 - .../Queries/Handlers/BrowseUsersHandler.cs | 46 - .../Mongo/Queries/Handlers/GetUserHandler.cs | 35 - .../Repositories/RefreshTokenRepository.cs | 28 - .../Mongo/Repositories/UserRepository.cs | 50 - .../Queries/BrowseUsers.cs | 9 - .../Queries/GetUser.cs | 9 - .../Services/IJwtProvider.cs | 12 - .../Services/IMessageBroker.cs | 8 - .../Services/IPasswordService.cs | 7 - .../Services/IRng.cs | 6 - .../Services/ITokenStorage.cs | 9 - .../Services/JwtProvider.cs | 29 - .../Services/MessageBroker.cs | 84 - .../Services/PasswordService.cs | 19 - .../Services/Rng.cs | 20 - .../Services/TokenStorage.cs | 23 - .../Genocs.Template.IntegrationTests.csproj | 21 - .../Genocs.Template.UnitTests.csproj | 23 - .../Genocs.Template.WebApi.csproj | 30 - .../src/Genocs.Template.WebApi/Program.cs | 65 - .../Properties/launchSettings.json | 27 - .../appsettings.Docker.json | 20 - .../Genocs.Template.WebApi/appsettings.json | 241 --- .../certs/localhost.cer | 19 - .../certs/localhost.key | 30 - .../certs/localhost.pem | 56 - .../certs/localhost.pfx | Bin 2381 -> 0 bytes templates/template/webapi.dockerfile | 25 - 161 files changed, 461 insertions(+), 4995 deletions(-) delete mode 100644 templates/README.md delete mode 100644 templates/WebApiTemplate.nuspec delete mode 100644 templates/icon.png delete mode 100644 templates/nuget.exe delete mode 100644 templates/template/.dockerignore delete mode 100644 templates/template/.editorconfig delete mode 100644 templates/template/.env delete mode 100644 templates/template/.template.config/template.json delete mode 100644 templates/template/.travis.yml delete mode 100644 templates/template/Genocs.Template.sln delete mode 100644 templates/template/NuGet.config delete mode 100644 templates/template/README.md delete mode 100644 templates/template/api-workbench.rest delete mode 100644 templates/template/docker-compose.dcproj delete mode 100644 templates/template/docker-compose.override.yml delete mode 100644 templates/template/docker-compose.yml delete mode 100644 templates/template/k8s/Genocs.Template-kubernetes-ingress.yaml delete mode 100644 templates/template/k8s/Genocs.Template-kubernetes-webapi.yaml delete mode 100644 templates/template/k8s/Genocs.Template-kubernetes-worker.yaml delete mode 100644 templates/template/pipelines/azure-pipeline-build.yml delete mode 100644 templates/template/pipelines/azure-pipeline-docker-acr.yml delete mode 100644 templates/template/pipelines/azure-pipeline-docker.yml delete mode 100644 templates/template/pipelines/azure-pipeline.yml delete mode 100644 templates/template/scripts/build.sh delete mode 100644 templates/template/scripts/test.sh delete mode 100644 templates/template/src/Genocs.Template.AcceptanceTests/Genocs.Template.AcceptanceTests.csproj delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/CreateUser.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/Handlers/CreateUserHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/Handlers/LockUserHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeAccessTokenHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeRefreshTokenHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/Handlers/SignInHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/Handlers/UnlockUserHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/Handlers/UseRefreshTokenHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/LockUser.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/RevokeAccessToken.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/RevokeRefreshToken.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/SignIn.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/UnlockUser.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Commands/UseRefreshToken.cs delete mode 100644 templates/template/src/Genocs.Template.Application/ContractAttribute.cs delete mode 100644 templates/template/src/Genocs.Template.Application/CorrelationContext.cs delete mode 100644 templates/template/src/Genocs.Template.Application/CorrelationIdFactory.cs delete mode 100644 templates/template/src/Genocs.Template.Application/DTO/AuthDto.cs delete mode 100644 templates/template/src/Genocs.Template.Application/DTO/PagedDto.cs delete mode 100644 templates/template/src/Genocs.Template.Application/DTO/UserDetailsDto.cs delete mode 100644 templates/template/src/Genocs.Template.Application/DTO/UserDto.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Decorators/LoggingCommandHandlerDecorator.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Decorators/LoggingEventHandlerDecorator.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Decorators/OutboxCommandHandlerDecorator.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Decorators/OutboxEventHandlerDecorator.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateId.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateRoot.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Entities/RefreshToken.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Entities/Role.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Entities/User.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/DomainException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmailInUseException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmptyRefreshTokenException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidAggregateIdException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidCredentialsException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidEmailException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidNameException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidPasswordException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRefreshTokenException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRoleException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/NameInUseException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/RevokedRefreshTokenException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Exceptions/UserLockedException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Repositories/IRefreshTokenRepository.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Domain/Repositories/IUserRepository.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Events/SignedIn.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Events/UserCreated.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Events/UserLocked.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Events/UserUnlocked.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Exceptions/AppException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToMessageMapper.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToResponseMapper.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Exceptions/Extensions.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Exceptions/UserNotFoundException.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Extensions.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Genocs.Template.Application.csproj delete mode 100644 templates/template/src/Genocs.Template.Application/Logging/LogContextMiddleware.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Mongo/Documents/RefreshTokenDocument.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Mongo/Documents/UserDocument.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Mongo/Extensions.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/BrowseUsersHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/GetUserHandler.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Mongo/Repositories/RefreshTokenRepository.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Mongo/Repositories/UserRepository.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Queries/BrowseUsers.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Queries/GetUser.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/IJwtProvider.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/IMessageBroker.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/IPasswordService.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/IRng.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/ITokenStorage.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/JwtProvider.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/MessageBroker.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/PasswordService.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/Rng.cs delete mode 100644 templates/template/src/Genocs.Template.Application/Services/TokenStorage.cs delete mode 100644 templates/template/src/Genocs.Template.IntegrationTests/Genocs.Template.IntegrationTests.csproj delete mode 100644 templates/template/src/Genocs.Template.UnitTests/Genocs.Template.UnitTests.csproj delete mode 100644 templates/template/src/Genocs.Template.WebApi/Genocs.Template.WebApi.csproj delete mode 100644 templates/template/src/Genocs.Template.WebApi/Program.cs delete mode 100644 templates/template/src/Genocs.Template.WebApi/Properties/launchSettings.json delete mode 100644 templates/template/src/Genocs.Template.WebApi/appsettings.Docker.json delete mode 100644 templates/template/src/Genocs.Template.WebApi/appsettings.json delete mode 100644 templates/template/src/Genocs.Template.WebApi/certs/localhost.cer delete mode 100644 templates/template/src/Genocs.Template.WebApi/certs/localhost.key delete mode 100644 templates/template/src/Genocs.Template.WebApi/certs/localhost.pem delete mode 100644 templates/template/src/Genocs.Template.WebApi/certs/localhost.pfx delete mode 100644 templates/template/webapi.dockerfile diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 31d284e3..75a32975 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -64,4 +64,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index c34bd433..53b44aea 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -42,4 +42,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 4ca5d9bd..0f133816 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -18,4 +18,12 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 5d8caffb..30ad925d 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -18,4 +18,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj index d32391db..10e58d89 100644 --- a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj +++ b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj @@ -8,4 +8,11 @@ false + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 2db4d0c1..a2f08cea 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -12,7 +12,7 @@ - + @@ -26,4 +26,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index ac73bf64..c2a64f4f 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -12,7 +12,7 @@ - + @@ -22,7 +22,7 @@ - + @@ -32,5 +32,13 @@ + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 1603b78b..e446d286 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -9,8 +9,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -19,5 +19,11 @@ all + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 34344ea8..43d2c5cd 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -74,6 +74,13 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 7a998981..a605130f 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -57,4 +57,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index f2cee3e0..b041a3a4 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -61,4 +61,11 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index a6de5746..d5617735 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -52,7 +52,14 @@ - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 069f8905..fc03c875 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -55,4 +55,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 8d56f4ad..94960513 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -63,5 +63,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index c064cfe7..22bd7d33 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -51,4 +51,11 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index bc1249c3..f05af59a 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -49,4 +49,11 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index c4d7a3fb..c46d5eb6 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -52,8 +52,15 @@ - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 421ea09c..32660229 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -51,4 +51,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 22eac31b..be872115 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -83,4 +83,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index e60f1141..411d4946 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -62,4 +62,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 3b27b3ad..231034fd 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -12,9 +12,9 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -33,4 +33,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index c42f0e83..5a602a9e 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -55,4 +55,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 23a55f69..0e9b0452 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -54,4 +54,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryBasicDynamicQueriesUnitTests.cs b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryBasicDynamicQueriesUnitTests.cs index f907b62d..d43c5e49 100644 --- a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryBasicDynamicQueriesUnitTests.cs +++ b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryBasicDynamicQueriesUnitTests.cs @@ -11,48 +11,53 @@ public void InMemoryLinqTest() { var liCust = new List(); - Customer oCust = new Customer(001, 123000, "Devesh", "Ghaziabad", + Customer oCust = new Customer(001, "Devesh", "Ghaziabad", "250301", "9891586890", "devesh.akgec@gmail.com", "Genpact", "3123000"); liCust.Add(oCust); - oCust = new Customer(002, 123001, "NIKHIL", "NOIDA", "250201", + oCust = new Customer(002, "NIKHIL", "NOIDA", "250201", "xxx9892224", "devesh.akgec@gmail.com", "X-vainat", "4123001"); liCust.Add(oCust); - oCust = new Customer(003, 123002, "Shruti", "NOIDA", "25001", + oCust = new Customer(003, "Shruti", "NOIDA", "25001", "xxx0002345", "devesh.akgec@gmail.com", "Genpact", "5123002"); liCust.Add(oCust); - oCust = new Customer(004, 123003, "RAJ", "DELHI", "2500133", + oCust = new Customer(004, "RAJ", "DELHI", "2500133", "xxx9898907", "devesh.akgec@gmail.com", "HCL", "6123003"); liCust.Add(oCust); - oCust = new Customer(005, 123004, "Shubham", "Patna", "250013", + oCust = new Customer(005, "Shubham", "Patna", "250013", "x222333xx3", "devesh.akgec@gmail.com", "Genpact", "6123004"); liCust.Add(oCust); - - //order data + // Order data var liOrder = new List(); - Order oOrder = new Order(123000, "Noika Lumia", "7000", "2"); - liOrder.Add(oOrder); - oOrder = new Order(123001, "Moto G", "17000", "1"); - liOrder.Add(oOrder); - oOrder = new Order(123002, "Intext Mobile", "7000", "1"); - liOrder.Add(oOrder); - oOrder = new Order(123001, "Celkom GX898", "2500", "1"); - liOrder.Add(oOrder); - oOrder = new Order(123001, "Micromax", "1000", "10"); - liOrder.Add(oOrder); - oOrder = new Order(222, "NOIKA Asha", "2500", "1"); - liOrder.Add(oOrder); - oOrder = new Order(22212, "Iphone", "1000", "10"); - liOrder.Add(oOrder); + Order order = new Order(123000, 003); + order.Products.Add(new Product("Noika Lumia", "Noika Lumia", 150)); + order.Products.Add(new Product("Moto G", "Moto G", 2500)); + order.Products.Add(new Product("Intext Mobile", "Intext Mobile", 7000)); + liOrder.Add(order); + + //Order oOrder = new Order(123000, "Noika Lumia", "7000", "2"); + //liOrder.Add(oOrder); + //oOrder = new Order(123001, "Moto G", "17000", "1"); + //liOrder.Add(oOrder); + //oOrder = new Order(123002, "Intext Mobile", "7000", "1"); + //liOrder.Add(oOrder); + //oOrder = new Order(123001, "Celkom GX898", "2500", "1"); + //liOrder.Add(oOrder); + //oOrder = new Order(123001, "Micromax", "1000", "10"); + //liOrder.Add(oOrder); + //oOrder = new Order(222, "NOIKA Asha", "2500", "1"); + //liOrder.Add(oOrder); + //oOrder = new Order(22212, "Iphone", "1000", "10"); + //liOrder.Add(oOrder); // Query Sintax - var result = (from T1 in liCust - join T2 in liOrder - on T1.OrderId equals T2.OrderId + var result = (from c in liCust + join o in liOrder + on c.CustomerId equals o.CustomerId select new { - T1, - T2 + c, + o }).AsQueryable(); string selectStatement = "Where(x => x.OrderId = 123001)"; diff --git a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs index c38e417f..46be433b 100644 --- a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs +++ b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs @@ -20,19 +20,36 @@ public class InMemoryDynamicQueriesUnitTests { private async Task> GetUsers() { - List users = new List(); + List users = new List + { + new User { Id = 1, FirstName = "Giovanni", LastName = "Nocco", Age = 53, IsActive = true }, + new User { Id = 2, FirstName = "Giulio", LastName = "Nocco", Age = 19, IsActive = true }, + new User { Id = 3, FirstName = "Vittoria", LastName = "Nocco", Age = 17, IsActive = false }, + new User { Id = 4, FirstName = "Emanuele", LastName = "Nocco", Age = 54, IsActive = true, DateOfBirth = DateTime.Parse("1968-10-24"), Childs = 4 } + }; - users.Add(new User { Id = 1, FirstName = "Giovanni", LastName = "Nocco", Age = 53, IsActive = true }); - users.Add(new User { Id = 2, FirstName = "Giulio", LastName = "Nocco", Age = 19, IsActive = true }); - users.Add(new User { Id = 3, FirstName = "Vittoria", LastName = "Nocco", Age = 17, IsActive = false }); - users.Add(new User { Id = 4, FirstName = "Emanuele", LastName = "Nocco", Age = 54, IsActive = true, DateOfBirth = DateTime.Parse("1968-10-24"), Childrens = 4 }); + Address address = new Address { City = "Milano" }; + + users.Add(new User { Id = 5, FirstName = "Joshua", LastName = "Nocco", Age = 61, IsActive = true, DateOfBirth = DateTime.Parse("1965-10-24"), Childs = 2, Address = address }); + + return await Task.Run(() => users); + } + private async Task> GetOrders() + { + List orders = new List + { + new Order(1, 1), + new Order(2, 2), + new Order(3, 1), + new Order(4, 2) + }; Address address = new Address { City = "Milano" }; - users.Add(new User { Id = 5, FirstName = "Joshua", LastName = "Nocco", Age = 61, IsActive = true, DateOfBirth = DateTime.Parse("1965-10-24"), Childrens = 2, Address = address }); + // users.Add(new User { Id = 5, FirstName = "Joshua", LastName = "Nocco", Age = 61, IsActive = true, DateOfBirth = DateTime.Parse("1965-10-24"), Childs = 2, Address = address }); - return await Task.Run(() => users); + return await Task.Run(() => orders); } [Fact] @@ -41,7 +58,6 @@ public async Task MultipleUnwindTestAsync() var result = await GetUsers(); } - [Fact] public async Task ApplyAndOrOperatorToAStringTest() { diff --git a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/SqlServerDynamicQueriesUnitTests.cs b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/SqlServerDynamicQueriesUnitTests.cs index aee4364a..d10f703a 100644 --- a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/SqlServerDynamicQueriesUnitTests.cs +++ b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/SqlServerDynamicQueriesUnitTests.cs @@ -1,69 +1,72 @@ -namespace Genocs.QueryBuilder.UnitTests.DynamicQuery; - -public class SqlServerDynamicQueriesUnitTests -{ - //private async Task> GetUnwindItems() - //{ - // IMongoCollection promotionWallets = TestHelper.GetPromotionWalletCollection(); - - // var aggregates = await promotionWallets - // .Aggregate() - // //.Unwind(x => x.CreditCards, new AggregateUnwindOptions { IncludeArrayIndex = "CreditCardsCount", PreserveNullAndEmptyArrays = true }) - // //.Unwind(x => x.FidelityCards, new AggregateUnwindOptions { IncludeArrayIndex = "FidelityCardsCount", PreserveNullAndEmptyArrays = true }) - // //.Unwind(x => x.PartnerAccounts, new AggregateUnwindOptions { IncludeArrayIndex = "PartnerAccountsCount", PreserveNullAndEmptyArrays = true }) - // //.Unwind(x => x.Transactions, new AggregateUnwindOptions { IncludeArrayIndex = "TransactionsCount", PreserveNullAndEmptyArrays = true }) - // //.Unwind(x => x["Bs.Cs"]) - // //.Group(new BsonDocument { { "_id", "$Bs.Cs.Name" }, { "total", new BsonDocument("$sum", "$Bs.Cs.Amount") } }) - // //.Sort(new BsonDocument("total", -1)) - // .ToListAsync(); - - // List result = new List(); - - // foreach (var aggregate in aggregates) - // { - // var tmp = new UnwindPromotionWallet(aggregate.MemberId, - // aggregate.MobileNumber, - // aggregate.MobilePrefix, - // aggregate.Email, - // aggregate.MobileLanguage, - // aggregate.CountryOfResidence, - // aggregate.Currency, - // aggregate.SignIn, - // //aggregate.Membership, - // aggregate.CreatedAt, - // aggregate.UpdatedAt); - - // tmp.CreditCards = aggregate.CreditCards.FirstOrDefault(); - - // result.Add(tmp); - // } - - // return result; - //} - - //[Fact] - //public async Task MultipleUnwindTestAsync() - //{ - // await Task.CompletedTask; - // //var result = await GetUnwindItems(); - //} - - - //[Fact] - //public async Task ApplyAndOrOperatorToAStringTest() - //{ - // await Task.CompletedTask; - - // //var unwindedItems = await GetUnwindItems(); - - // //QueryItem queryItem = new QueryItem(propertyName: "MemberId", propertyValue: "UK9I1LONH or (HRNX5XOFA or MRNXFXOFA)"); +using MongoDB.Driver; +using Xunit; - // //IQueryable unwindedItemsQuery = unwindedItems.AsQueryable(); - // //unwindedItemsQuery = unwindedItemsQuery.Where(DynamicQueryBuilder.BuildAdvancedSearchExpressionTree(queryItem, "UnwindPromotionWallet")); +namespace Genocs.QueryBuilder.UnitTests.DynamicQuery; - // //var result = unwindedItemsQuery.ToList(); - // //Assert.NotEmpty(result); - //} +//public class SqlServerDynamicQueriesUnitTests +//{ +// private async Task> GetUnwindItems() +// { +// IMongoCollection promotionWallets = TestHelper.GetPromotionWalletCollection(); + +// var aggregates = await promotionWallets +// .Aggregate() +// .Unwind(x => x.CreditCards, new AggregateUnwindOptions { IncludeArrayIndex = "CreditCardsCount", PreserveNullAndEmptyArrays = true }) +// .Unwind(x => x.FidelityCards, new AggregateUnwindOptions { IncludeArrayIndex = "FidelityCardsCount", PreserveNullAndEmptyArrays = true }) +// .Unwind(x => x.PartnerAccounts, new AggregateUnwindOptions { IncludeArrayIndex = "PartnerAccountsCount", PreserveNullAndEmptyArrays = true }) +// .Unwind(x => x.Transactions, new AggregateUnwindOptions { IncludeArrayIndex = "TransactionsCount", PreserveNullAndEmptyArrays = true }) +// .Unwind(x => x["Bs.Cs"]) +// .Group(new BsonDocument { { "_id", "$Bs.Cs.Name" }, { "total", new BsonDocument("$sum", "$Bs.Cs.Amount") } }) +// .Sort(new BsonDocument("total", -1)) +// .ToListAsync(); + +// List result = new List(); + +// foreach (var aggregate in aggregates) +// { +// var tmp = new UnwindPromotionWallet(aggregate.MemberId, +// aggregate.MobileNumber, +// aggregate.MobilePrefix, +// aggregate.Email, +// aggregate.MobileLanguage, +// aggregate.CountryOfResidence, +// aggregate.Currency, +// aggregate.SignIn, +// //aggregate.Membership, +// aggregate.CreatedAt, +// aggregate.UpdatedAt); + +// tmp.CreditCards = aggregate.CreditCards.FirstOrDefault(); + +// result.Add(tmp); +// } + +// return result; +// } + +// [Fact] +// public async Task MultipleUnwindTestAsync() +// { +// await Task.CompletedTask; +// //var result = await GetUnwindItems(); +// } + + +// [Fact] +// public async Task ApplyAndOrOperatorToAStringTest() +// { +// await Task.CompletedTask; + +// var unwindedItems = await GetUnwindItems(); + +// QueryItem queryItem = new QueryItem(propertyName: "MemberId", propertyValue: "UK9I1LONH or (HRNX5XOFA or MRNXFXOFA)"); + +// IQueryable unwindedItemsQuery = unwindedItems.AsQueryable(); +// unwindedItemsQuery = unwindedItemsQuery.Where(DynamicQueryBuilder.BuildAdvancedSearchExpressionTree(queryItem, "UnwindPromotionWallet")); + +// //var result = unwindedItemsQuery.ToList(); +// //Assert.NotEmpty(result); +// } //[Fact] //public async Task ApplyEqualOperatorToNullableIntReturnItemsTest() @@ -153,4 +156,4 @@ public class SqlServerDynamicQueriesUnitTests // //var result = unwindedItemsQuery.ToList(); // //Assert.NotEmpty(result); //} -} \ No newline at end of file +//} \ No newline at end of file diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index c1bd7066..64e44bb9 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -15,10 +15,10 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -31,4 +31,11 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.QueryBuilder.UnitTests/Models/Customer.cs b/src/Genocs.QueryBuilder.UnitTests/Models/Customer.cs index be80ca5b..e394db39 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Models/Customer.cs +++ b/src/Genocs.QueryBuilder.UnitTests/Models/Customer.cs @@ -2,8 +2,7 @@ namespace Genocs.QueryBuilder.UnitTests.Models; public class Customer { - public int CustomerID { get; set; } - public int OrderId { get; set; } + public int CustomerId { get; set; } public string? CustomerName { get; set; } public string? CustomerAddress { get; set; } public string? CustomerPinCode { get; set; } @@ -13,7 +12,6 @@ public class Customer public string? LocationCode { get; set; } public Customer(int custid, - int orderid, string custname, string cusAddress, string custtPin, @@ -22,8 +20,7 @@ public Customer(int custid, string custOffice, string locCode) { - CustomerID = custid; - OrderId = orderid; + CustomerId = custid; CustomerName = custname; CustomerAddress = cusAddress; CustomerPinCode = custtPin; @@ -31,7 +28,5 @@ public Customer(int custid, CustomerEmail = custEmail; CustomerOffice = custOffice; LocationCode = locCode; - } - } diff --git a/src/Genocs.QueryBuilder.UnitTests/Models/Order.cs b/src/Genocs.QueryBuilder.UnitTests/Models/Order.cs index 4eb180ac..022b9fa5 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Models/Order.cs +++ b/src/Genocs.QueryBuilder.UnitTests/Models/Order.cs @@ -3,15 +3,41 @@ namespace Genocs.QueryBuilder.UnitTests.Models; public class Order { public int OrderId { get; set; } - public string ProductName { get; set; } - public string ProductCost { get; set; } - public string ProductQunatity { get; set; } + public int CustomerId { get; } + public List Products { get; set; } - public Order(int orderid, string pName, string pCost, string Pquant) + public Order(int orderId, int customerId) { - OrderId = orderid; - ProductCost = pCost; - ProductQunatity = Pquant; - ProductName = pName; + + OrderId = orderId; + CustomerId = customerId; + Products = new List(); + } + + public Order(int orderId, int customerId, string pName, string pCost, int cost) + : this(orderId, customerId) + { + Products.Add(new Product(pName, pCost, cost)); + } + + public void AddProduct(string pName, string pCost, int cost) + { + if (Products == null) Products = new List(); + Products.Add(new Product(pName, pCost, cost)); } } + +public class Product +{ + public Product(string sKU, string? description, int cost) + { + SKU = sKU; + Description = description; + Cost = cost; + } + + public string SKU { get; set; } = default!; + public string? Description { get; set; } + public int Cost { get; set; } + +} diff --git a/src/Genocs.QueryBuilder.UnitTests/Models/TreeNode.cs b/src/Genocs.QueryBuilder.UnitTests/Models/TreeNode.cs index f6f2fb68..117fee41 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Models/TreeNode.cs +++ b/src/Genocs.QueryBuilder.UnitTests/Models/TreeNode.cs @@ -1,13 +1,12 @@ namespace Genocs.QueryBuilder.UnitTests.Models; -class TreeNode +internal class TreeNode { public string? Name { get; set; } public List? ChildNodes { get; set; } - public int OwnderId { get; set; } + public int OrderId { get; set; } public bool Valid { get; set; } - public bool FindDescendant() { if (ChildNodes != null && ChildNodes.Any()) diff --git a/src/Genocs.QueryBuilder.UnitTests/Models/User.cs b/src/Genocs.QueryBuilder.UnitTests/Models/User.cs index 74af36e6..01968b43 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Models/User.cs +++ b/src/Genocs.QueryBuilder.UnitTests/Models/User.cs @@ -9,9 +9,9 @@ public class User public int Age { get; set; } /// - /// This is used as nullable to check the builder + /// This is used as nullable to check the builder. /// - public int? Childrens { get; set; } + public int? Childs { get; set; } public DateTime DateOfBirth { get; set; } public bool IsActive { get; set; } public string? MobileNumber { get; set; } diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index fb990c8f..05d77bb8 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -42,4 +42,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 30a7377d..28c03a82 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -55,4 +55,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index a1cce305..20ff53c7 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -51,4 +51,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index da901de6..e57f1d6e 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -9,8 +9,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -19,5 +19,11 @@ all + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 142a640f..3d1c3707 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -55,6 +55,13 @@ + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 380db2c3..883d19f0 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -67,4 +67,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index d6e36c6a..0038d4a9 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -54,4 +54,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 987a067b..17675bac 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -56,6 +56,13 @@ + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 9056b78e..ca65c0cd 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -58,4 +58,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 5c100340..16ea95c1 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -58,6 +58,13 @@ + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 46eda5f4..45aaa59a 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -31,7 +31,7 @@ - + @@ -49,4 +49,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 5120883d..8c8aa249 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -39,6 +39,14 @@ + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj index a5eff4b5..bc4c5329 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj +++ b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj @@ -26,5 +26,12 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index a92fd129..df5837db 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -46,4 +46,11 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index d30a4e0e..f4cab645 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -53,4 +53,11 @@ + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index cae2889e..53fd8644 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -53,4 +53,12 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/templates/README.md b/templates/README.md deleted file mode 100644 index a2b1b571..00000000 --- a/templates/README.md +++ /dev/null @@ -1,30 +0,0 @@ -Genocs Library Template -=== - -This folder contains the templates to be used to implement an entire solution. - - -``` cmd -# Pack template with nuget -nuget pack WebApiTemplate.nuspec -NoDefaultExcludes -OutputDirectory .\nuget - - -# Get the template list -dotnet new list - -# Install with local nuget package -dotnet new install .\nuget\Genocs.ServiceTemplate.5.0.0.nupkg - -# Uninstall local nuget package -dotnet new --uninstall .\nuget\Genocs.ServiceTemplate.5.0.0.nupkg - -# Some uninstall commands -dotnet new uninstall Genocs.ServiceTemplate -dotnet new uninstall Genocs.CleanArchitecture -dotnet new uninstall Genocs.CleanArchitectureTemplate - -dotnet new uninstall Genocs.MicroserviceTemplate - -# Create a new WebApi called 'CommanyName.ServiceName' inside the folder folder -dotnet new gnx-webapi -n CommanyName.ServiceName -o folder -``` \ No newline at end of file diff --git a/templates/WebApiTemplate.nuspec b/templates/WebApiTemplate.nuspec deleted file mode 100644 index ceb176ff..00000000 --- a/templates/WebApiTemplate.nuspec +++ /dev/null @@ -1,70 +0,0 @@ - - - - Genocs.ServiceTemplate - 5.0.0 - Nocco Giovanni Emanuele - [Genocs] Nocco Giovanni Emanuele - https://github.com/Genocs/genocs-library - - MIT - icon.png - false - The service template by Genocs - - A .NET template that can be used in accordance with Genocs Library. - - -Install the package: -dotnet new -i Genocs.ServiceTemplate::5.0.0 - -The full clean project: -$ dotnet new gnx-service - - -- Relesase 5.0.0: - New version aligned to the library - -- Clean Architecture Principles Documentation -- .NET Core 7.0 -- Swashbuckle 5 -- Enterprice Service Bus - - - architecture - boilerplate - clean-architecture - clean-code - ddd - ddd-architecture - design-patterns - docker - domain-driven-design - dotnet - dotnetcore - dotnet-core - dotnet-cli - dotnet-new - dotnet-template - generator - layered - masstransit - microservice - microservices - rabbitmq - solid - solid-principles - templating - webapi - - en-US - - - - - - - - - - diff --git a/templates/icon.png b/templates/icon.png deleted file mode 100644 index 66a5cbe2d9c95b6827e11cf9dd9e7244cf632c26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1034 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%0A$C%$C{w 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 z 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

q3-{sF4Ph|pP-~wwklh}p2lziwJ+g8{I>tY{< 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

EW|-(lCvzs9T* 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%0D&!ZuUBsR%FiPm$SRH3XD(#9d2pgh!Er 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᝱-`tNh=zUeFSaMlc*P71cV7UO_$tRoI?(kRc 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

V0 za{*YZ;BXq)rve*krlk_dkB-`7cx;f{Kp@{a^VK=86>**+N)JhKE+Z&JlO6Si*e;tZ zdG9rT$j9zQI3CfTDUN#RsJW6k1fO&nu8jaQfUq5VUgunXCmp5h(R6I*nyS&%>=VWV z=zOH!**%*N@wKRJKz^pg)J-csr7Tkk;@IYnS$K6PDW=?o3#4H7f$!hPn zKXMqPs22>zTpXsX&|qRH=_dek)~*3LNw8Oqn6}Ok(uP#;aANGzajWEzC$A@VxYX_m>&&UaoA3VA6nXuTwjZvn1d(mLRz zsUdw(ZX{av&eq``7>6jYpB?y$TQPPTbw?8aReM#AOt*kBs|24#L>E`#5i&d<{FU25 zZq#N$bNV_|8kEdw;{|jRi^!3tihbgA(^)+?kUbEPK3buxgaYBy_~v#Tjs|v-2sWU) zr-)bc;ii}IA4c6~qj`xN9wi?Q4|0yTa05BZt1-x=Bv}-I>>3tR0l5|v=hKjq2~~Xf z0W`~3<7JxSX`wyH{2YBQ{{B5W*yUQ3yT$?pw9xo^H6s)19lpJAJmXW)9sQ_J`64v3 zD^_?nj^aOgtwPa{OUM}{jBC)@Mu!g;5>L80q=A&E4skc>jg>0X)uKvg+pafO;TBbE zR5Bm0KJf9|o;Y8!xi&MjQ-Od(iN&v~%Ms{ebFGs+Dg8@w4g>0r?pEwF1l?T4QMoj9 zIphwJTZ+P(oUE_KEOfLfMTtS{Pj<+p)F*D_I%>>SNdaKeFmaq?GrQhR?go8Z`Ov&d zu?PPq)@q`9^h*XRxCq=OGV0^D!1V9Oxbg4;&J-Ybx7U0Q<|g09midVxqZbau1}L;= zgU^_QC+Da8$_XQlrgjM&eMXrNpt?f~i;aiS)s_TZ>#AdMqR+)>Iv{;H5+c~5r0O5g z%|=~ssN@{IZhCn9rQ3Odwc3#^y%wHTN>SjuBKAS?8Z$Zb81!OucOG)Ismk*LFoV`BTH__ zl=6;!yV&sM!JW%arOpA6dA*#b;|d`n1+cn}R3^aCJggmGj)Z4KREJ4dT30C25g z*8yZ-!=(W0TEkrd>s`b90MbQvH^|&%--1rI5u$>7?OA+#^tViBatciZ8Xro-xW`2*l;U#$z(sW0D9SSBoT5TN z)25J@8zO?0oS@h>=x&=@Qm3l!6ezhn-tX>M39CkirzP4FO=ww&e(}S08_SW55NzXd5W+CHS_qYT> z!n@;;*?hfzLtMn63zdDN(Ly9RdSH}xC}E6_$11jRI=Ulh5j3%7r5+9R3f4=|)Rrn8 zlej06vuqi!H_s&PR5Z3Fq~6$TByc`%hh!1Dj+~7ko#T}09u{xes5|j)e!LeQ{kq}J z?cgpZpp>5U^wUOTJ|Z+->mucfzN^$p%~b&BqsVi@*V5-x2cXQq`W+e-cGSq5Qqa8s zYbAxL_bYu)@=$LInjgXtxQtLzQq+R7>gh6o zJ#BY@TWi5FifRiCiYPyopZv z?8HEey6xsB2Ma>TaHGWJP^4;3kR6;?GWfew&TWA>cBsU7JO!c7lW3C*lEx7LP@)cr zboR)e*rJ$55{{r~0R)X9094u)K*UIzbzV@f0aRgjP?VBXRE%UYNZ{N8ys8kS>$p=D z03-n*WNbi(qTC&rQy{}o+3D~~XS;Jm#)rA$Tsp~n`wWBT%Rc%H(9=1XQKL_Ta!wgz z(QQ)Kx_L`AGP60yLg^!u??_)6oC}KlB-$8G)yHNeC{NCgjU%*4Mw;$Y3iJ3|2l57h zjLZ&%jFG!zd<3Lq_Kw-4L-|N-|Lo26Xv4W^2=*gm%Lu=>yo}m{6cIGQ!kE*o=!Erj zchafp-gGiN!8ZUNKsT(X)6IKqAh)?1kJ9`+aof3rOh&QXBe{!YS+{9Pp!D7}_2 z3ITFT`ye@U#;0UL47a4j%&mVf0hlwsKNuBv$;9(M41hhKn|d%4@L9Q?ZMZV*xmA2bOl%E9!V{!64uiCLvS4(r?=lRGY3&`?+E3U0Or@f)MY$( znEw4c=+Z7n5@A(9P3bfp#GYedXXzj5qq@Iy0-gFUti$$`M_ES#T)Df8caONg^R9R< zpr-(6ySv5>ROgCZATRFMU%TiG6 zIC5+UeCzJy#_T3^oZ$W-bF^ki4B8xg)++N%{#yWm(4l&)wJvGssezeKp=ApT7UFUX z@W>5D-?Nz@P6q&NfZPCd4+#&Jc0h?%P#5$BzX58Abc0Rjt| z4Fr5+uoBge7l6_c#Oh%HfN9$`0Gx>T>c~d`1j1$q#176z&TZTe7!PkO7Z4uEFo4q_ zNXuQxw`RPP%Z6J6z&7L_RfZ3g4W-|hAu`S}t~5000&$1aS#X?`3am1Hwe=V*vO5Oj z5VRR+$hSA(!x(Vvt__$lo5}UqG|YDbReEMNccga)<0fKCD_A_vNVt*4+R}SgAYo z$vp)CW4%$kOl|FrsGJObP8+YIbD_7h3NkR1MU^5^cN`briSXTXb&@V7A0U+)f{*%; zaq6&lWF#?)?i0M-sn(;Odl0$CpFg>i0El>0T#R9+5GAU7Vd*yjFd!3yY=O=J#W?)- zHq{qEUoi3-_qWVTN*FZU<@LvE@(G?*2e)9r7uU(IvjvUdI3{D#s#mcIGht-CBDpl zcncjfSX~NMX|zfGOp(J4z&ypEF=1*JR+GDx%tZDohJujSYne+%P;PX?0ALO-Z(Ge$ zVSN0jCMHW{qOeU(Akw;F^OcP$-@-s+OqOaJVpj`|hML;$Y1)QBNCYBOr)G$(+-M%g6P8OZfQAWPII>Fr?tB|ETUYB%tZ%KnnN!h#WgM-L5sJxJU@YaV(nsD3NS8sxt7n)ru^n)jp?lA4+QaoRO{Nd)r#A(EMWB| zUf94850^QNNQ}u^P2hOE_s?f#^L>qYEDY#KCQbN~ts9!~@RhZVFx^J$ZPjoD?BO?O z%)^^!3sIE8+QhPmV!rHvx@HR#cx68tsd}WZP=&YqXToAmxh% z8v{$yzN`Zd!p6iSW2iI{M1_|zpg0Nva4D^~b@8$rG8d5=lHo#^v!8i(i-;w~tln`F* zR4x$2qCp6TTI~Li1kIA7_Os4%CDeyQ{CLo;E?n<7D|Z1jX{oL75Wk?W^%+=gPE%-! z5M~rm5ZSh5M?0}!TH+uImk_f|1R8`OYu#Y82q)kO_G?Uqq@q}?CJG4*GN1>fp%hxI z)=(i|X||R(aVj2@n}x@rMSTSTjY7Dgd?Cn%e_ApZ%0lTr>lGcv%`zn*^h{KH~v1Aks9*adPLUo}yDw9Bl zOEnj(0bMABd<#)m(qda6&Hd_h^P6X3A3~X|RT>HfxmY*bqChF0s0IiQ&*@tny%wAk zYl%fbi1k*#bdfJ1Y7XYBdJ%r{t2x&Z8=81d2xW^`@ETj%?uj_s0w_CBAztMpc%^)e za8WGYC@GAmpUVV)fSrXVbVQc*a3S6)JgXe)2anS!vZsJQ6;eyg+aH6s89&PXX&3bT^qsJ|gY7GW$Ep}x!1PP@nlw5`OQ%pl1o}QBpSguZpr5mLd_L=X`I&0 zA__KHjZhPwN$9gIAXnNp5eyB%IvZKrhm23FA`q!ZIqD>y?8KAPQ*1*jD@tXJ>}s*Dzt|nfsjaf!68EfjBNYb_7JDD^X}6%e(6vC&qX|kGA<#iJ zSm=}})UP!G-~3_zLVw|z5G!C@OZ2EBnLbzoG#8b;fjEmb(bgfr^%9`pJjz)%n5hL1Hz*N^`11u(}GK^6?3hD(l1eH@>tF0H4QM*TOUp|qx;(E<~43>9M}uv9xT|l zN!VUMG7*6t0m}!FEe(U6Q4SN|x1<>=3$kY|{!cuVt|pCwv9`4ssL@y3kj9{L*GIGM z3}B_a670-I6v&Ii&wv?~4|xXjg4PN7MzsTy(g=aGAX<1;lhqJAab~4dR;b4#3Ka?i zEEV5;CCCQ7sX(R#t3v>!fpHVeU@k%cW=496lo#Msv#86kfOLd9A8uH=Ge^EL3tBbN zSD_k%m8O&#XKBfiP$Me3Rtv|2I-C@RSq+D8^O^`6W%c*g`pt7S0$bjO*X(wi`tH^D zG8wqUG4h*0Yzz-}7cOQj*%BvlD3PSh^_#2qut=0)8(1O@Yr6z;25x2`i zA)ACdsg^C@VKjaQgF70Ez+y_E{8kdmwZ)fO5@-@@xV{PR%ff4Ef|WZj&=_dj1QFv{ zKC>&Q(Dh3x6NqL{C^(x1T7|TS?htAqw3yY@!U8L?{3Lln0cu&)h6+M_M;P`mj3KN5 z#H_>voMP_>kS5TWMDfosNdjlZ_5dU${O0r-bdYS5*iBfA_ec@R)}Szbn1GK(#RLHw z>33Vj!-hCa0crz5uolZz;{|Km;DJ?;ioizZcC)Nuo2_im7($s`MIo&G@kVf%r8vnaFX&|1E{fwyMu1{mE*1gMl59)` zF@W&qARNJ!)ffq^QJG8y!?Ap2(SlRJ--#reP#m?bZr#uv2yR{@MIR-dB{))06%f`G zTY`1vUQNVOo3G@GfqBS*t!wFsBG3ZG(6*MkK{%fn0_GrrLzFV$BU->Gr-sI^YP%f> z+T85-os2?UXS-wd=x z16a%rth+bG(fooTp|LoDsNBxjk%2}8qa0IAL@uzFVr`(!P)FJvsImJ-u?`NcDYF^I z!X`Q!x;(_$2&HJPuMAyaL`K$@1QJ+ZY9|C|=$>0#MfD8QfU{_pz=uOPjG;bd34jv> zdEPcbAB#g=?tQtyA>cc$oTLE@$N*IY0Ydc^7Q*@(23?>Da#=6n`y1}5Vmp&Hj5Sglv{lYlSxdSpfU4KjDk3^dUXZb^ zMhqmilMt0sXGuB=wI&SHSP*^)Oc^Xr-`QC}a3$ps5ooIZ)f`P2y8Hs6oNzO2kTq?$ z`vivws+(i=RzgHH27L9ASdEm-aF{JcOxN4hbFkji4WD}7-E?H`rcJS6DgwYP{9S+| z6|MpNdaoc@CLo*__fW3(M`^USi6!^*R#VDksGTA?2r2^CB4Xs5fHY*R8j9KmO{jDY$k9-N{jqsoc`VVGP72E{ zYKtn^LX03P27@wmSPTZI>;qK?-NR5TV=nNaYa6g7rAH>QlJmXKardB{A5O~Qh0YSWDohGfP`>9*G8+dxOcXQMy_`ZA`PfGf25$}m1o2&sJT z2x#nOE^yQ<2-iXRDuI!bl6{E~-Xt27yk%%wTCOF{;~jeNun@#C7+fiO&vd3W-;&dX z?h|IAG%(>TA21c3dfL|_W!VW70Kov%6g(Xv3x!R|;3kL|2{)qhnYAh!!L9uXwgW3S zg2~oK(nV%LnN(N+)EEOG1QNh~Hc<(QF#tJ7zqucYH3-xiY#wO;(>IiJHhm|Bq9Ix? z#7au_l+W_?BqyykGnQ9uFV}&mjKMp{p8m3FRX!&mtI!c^BaJ>-H!ME@7X201IqhS<<{C$2HT;B*C1)5d5R z@kYcYU;wtH+tv!v+xjqEP0Y`4)>TS##sX~d0s5z0a*TWRd&-c2dmK;%iyp&ZNoQ*I zO2I~jNe3HhBMuZa>@cw<;J1{oUNKHUL=e)Df_`&SIf7#FnP7k8z-sfAmi)q8gfI8rO@N@7$3PV<(iMdMpkXcs3#8oGtL3Y8#@c zVrrdvxg^ICQ+W0xjA55P0!blBot0^ZKb^oqqYDQG%N1h=J;i46n}gNv5|WP#1R7hu z3*{0|kg*L|&U0XftZ>Cfp*NE)kXK;@Q+8v()un>%Gb&(CgDTb z%Dp8-tosOBY7@U%l&!Vx@;RJE-y96@N&xYjM`!l6dls2vsxueU4$Y=zT-#CgL=Xy& zt2t(-h;!N&xy=kT0fb$lb>q>J>^K%|pyI=5$>=Tjn03gsRwc2lbtSQ2YjSA^=smMi zi|w@NEX+UU8mlposE~zDz1-04K1Jqe??l0t#J{6?Dw&Gr&CGTXp(OI{ZkDM>Z~hUi z0b6$}r6gkDesdc9MxGucX9wpCjzS{L~$A^P*umfi$+-v3DEV0}>56U`|#O5L_Q49hB0+aM2L-?WRCb z<8d5u3Tg%#YZ0*ND<;D%Ba*i!L#TqhlXEnoD1`KGeHcza1j}fhg}_p?#R#hz0z%(% zTQ7oE)T|-K79ASNePgLkF$*ytU_`S6t}#wgm?g$ocLS2dV9ymUV-88RLK(Y?+gxxP z&Y0+vh&c)EomOgBWX%wx(=4@)g|qy8Y$-u8i?&!Hn3g!BZM4iJm?u0eCq9UEaZ&A# ze&1B;QK2u)69u&d`em_#In93GY?p&ChNwwlSGa=wI7D^%SFsSkc%m5A}Mr<|;aO|@=-+35F~=T@hq(5-f00-%Hu zDCWX=g*;sWQo@=^DWZ~18~z$XF~>)=sp`%!Y~(MmKcM~uW4M5huPEPP(U7vvMiwQ`b07=NQG?xQ!g!*G7{ zVzb;@M1WXgIk!rFd%R66_6R8vX~j7lq!!N{!pLchTCRehiwGsY0^vBT*%23 zHh&|T9JzWpR&@kO(3LI=qZ3Ax_W%x|*3o5fN)e(JXRWsE$=24lu&H%DPAMfx6v4TYq7ykZ(5nni_0AD4G$&h}hx2Afd@_@Zx=-jCaR_JonB0RPFI1%P zVc;ixe+Yd9XA!LA-n4ItwR49E8^h7TY?F-R$T{RoHAa|hi%cgWg=H3!ICF6)0yYNIrV8TihaZ zFS;65{0Gzx!5?5i=ohB7L|WFVy$X=;PtcvdZptuT+*vAu8+ zBgB(Q3N2-^H@5yNm?|>w&dHQga@a>(|1E5}kh|DYj_x&3EGc&eLciF@LW&?MHiQE$ z8UbR@h+_}!D|=1VF@4xqAaugDCZoSHjEwLhvRT4N3v+VDxf?~MJ;L?Pk+#c(XJZA8 z0#J-Hm$wl~kFD$DVR1T~nGqnil6CHa@HZ1Cfsn1?ybS6$x0zWLjSDYFu`}_9m_b=W zFSUo-f6Mv~#uinluZ(sfMnlFGcWfXB)kbW)r^xJQ8#3H*?&z1*g$JOA%KQb@PecpM zlN~)F54=PqNM=qU#ab#YFpNrbwDJ^-5J^o2!q}|fF64_qEyt5)ewjRO6XvKRDpI~; z94U&RDyq7}Q|7sq->g#SnbKtpsiYuz^Ty6;-#|?TLCatUlYeENBCIg$@L8LW-yAYq ziov8BUARKj)3~ixztC9W{L@sdy{IxJH zOrU;x6|$mW?aA|jP66$XEH;nw)S4>veKSxd(5*+t}Tqc!T_4gNEZoZOAvd<_CypW>yDG4 z{N~{mnvEboE;2{W6PYv4N}&)uCe$MBz6_RCX4vR1bz36I4)d*x!;!Zc9qw8;Y(*T^ zq1$-1Mq;*|T_VxgZw6IoYk|RGOdYW-Q5u5kI46j}2Qx8*2}E*YODKZU8dMyFV{9CZ zZ$|ieqabpq#c$TAQ6!4HcMxkPh4VaXY#BywVdM(FfN%qaN)bLnFy&-#2AoKw^mfhu zj*Oy%MG=6DM^3y_a^?}1zvI~a^uYwv9;#d+>7mLGaXPw$7Y}qN#To#)!_EMZoyE|# z4Dh6VbBoI@Y2c((aw|eQSt$e(1T(xG5IEndC>N?M(83hWfXe}})7!AK?ac}KCdRYX zD)kq#R**Yv1v#1aGEGYmTPqbrwtPr*&9x8#zgeh(QAwX!7SQ&P#%eu0X`i_}A{snd z>)Cmft^EdU+f6ymGPZX45$2D1;QYB~k_UWmU2rWO5_5m|Fa1x}F50Y@*KE>mYX{ci zvD!4;7ffZO=MXJhSbips#OGtcGkH&l#%yRY5}0@^1UXR9r_fh0mMlkcB9W3duaw+= zU)C!g(5n`+fI(m-@E#bn>)`3x?wgQ@=+;@8gA%Xv%ITUl;_w&72U6k$+e z256)NW7?NOMu>0&#MKT*HsHeZK!_FRqLef*kQ+hbxUXj+oKYfAGm!ECUqhbp*CGHT zkh4EYAyg8J!#GBm0pEbF`pFe!*g4iFj-v zw05l}&3a{1JC_oid?vZ*()fb;D2%EiUjaT{29r{{{1mZT4NGWzaf+ZqXSL`h$ zcHxFTMD`&6V9*o>tvJ5I!pZA`IMfB_C6RU(hzFS-(voJPfe1u_?5;Fb8B(>DSxga; z3G#?q8Y@NI%Hqa>+-jM`tvoJYL0POMR2N7^lG7H~MsQ|i$g z$jF__6~#cdSQCdtWI8i$Q5P|J%u~OLZP`oINLC;MA{E>#!Q0dhi*@3OhjmVCZz$`? z#08tj8JApZ7+be|yvZ~S;~M-#D$_he_v2!=xWSXK|5Xu!D~G$NO^MoAJQA+S_f?1D z33!qdNAfbEzcAl76?+?^b|Nw%p#C9#%Tw5wwI_$tRk6lUbYjhzF@aIFqec%KH)3R{ zaO}8#nS;s8aBB3*P;w6-^$mXbr@Xj?|NlDggyqXe7A`;c*nt<_^|^V;df(1VZfHF2 zvcliKeA(B=aaV*k{`rcJQ#br*)3yt*te6p45ia}cs+0eA;??JDoqP2y)myGPYQGm& z=3h~8-PXM8u7B{89ydPpw(rI#|1oG)W7*nO@zL8>4|{sY>g1-SH~H%KTl49Dqt|@Y zG~?#=GtXQ1X8NbMoiO0`+kW##>rXE{;)B~Sojmi7bMLFZaUViPv%MM!b$N>evesul;MVo5hdgF$xctl)M%;eF zi!Y7(!;8OsyVpy5EFS+-Y5JR&#xxhba{bF|UU}!VK7UM2Ui#{nXFT=lnz}{XPN=(c z+n{S^zWL4P-@G~b+uqwJUN`YClRvojtxxK&d+ULz=3lR@TJY|m^Y49c%cqaMH?{DJ zzqS7Tl=uI6{8{h6c5(9kn#Z4be?Z}3A3k*OCm-H+^-&*vwC;BwmACfYQ9oeHj)UuG z?)cIS?>OT1pX_*I^3EMAYmJZZ{KG{bfAW0fljZL=eRAsX$3Hz}`q!U+7oPNwK0m(V zvqxs!^4W@?-}S{liDf%){qFF8zW>EN{~UGyx_@;)<*e`O4!y+u%QeUBHN4xjy}o?; z`n}HS*|c|J<~w_j_{W@m+GY>!7QFn-Zr%Ib*sX2*L)~6K;+1{pOEE2V|AF1k z-@o6CnjZZYE$(sW*Vi5Ri+IIBhhDJd(61hzarpG-*7dr2W1x5Ks&&2N-S6&w@%$lu zE;#gyK6`Dw^~gsjZ9eMDg63l$eC_IE4r+Pin1R89V|#wS-FM+5U;A!(>&m|OHayXH z+vM;1E+24d|3TaK9x!ZD$-w81{CMCm-Z^aW_Mcra_>l>B4f*KUeNMRcz@7OU9(}Rk z`XW@9#UhV(RiSJDYor-SPbLqDRiSujuxM z`tiSvj-K#A%Z5qQ&YE!I%4z#d-g5i3lb^b)XYq_Rg;SQjG_>Tw-m6M~@ZRAwULBr4 zbI_I7&y1b)>CA!EBWG0)sGk*TxO~>8lbUAFJ9qKy_b&M3oF{v}J?F!oAIv%ZvHVjm zyZ4n-=9R6kc=wDmDof)Hrw_T};Q3FSo?dYEy+2#9`L+!U-kw)>_LA;z1RnY7vCt8< z2iJeRVRrp@vuYdOKjr*}i_crzFuv`i@TwbvjiF~IMZVZs+Vq1%uaB7r-5fi0^~vY_ zX>;J5?+QOW=kfV3$6wtVZW%bGId= zm+g7f#%14pHu(H4ha1Li2O35VswYqNXpX&7_!3}Y$eMC>rb_!BA> zEXL0Zcnm#($`XG>J3soqhG!V3>|+@J=z+SM5OzE9-DBu~HpI%5gA8Ll-cnu-*uepY zaSW;h^hY`G1>+3k4ZPI-`q6mv3WZX7pxrCzJD`tYZ0?44oPftq@I?RTM;XR6pJDtI zFAAT7em?`uMHpva{C?CiXp3=g-peq~!x$f+?_}Wia$m#veJ{g!@kq=8Rf69_pDzK6 zfBGGPC($tOuh6yvV^2bx^D*{HjCT{}F#vPD6V*9t3k;)=&oDm3n8ko`Pj$RIh}#AA4Q+Df%D#2Q`X3hgHFZ3zY^hu)aSCxB&k!%bDaoYXu;f%#@xDLtNM3 z;~NvWg9g_E?|k633H(qC`n&+#-b0@PtU(?=I}miN1b&ZUZ~PHB{1tGY#MrL`R!u2t zWXQ)_)ti2N=u&^d4YW2!7aJ`2#|PZxqvEVG62<@8FFy~oj494rm+Eyw_akpr07TGy zJX3z3`ReU_V&ENdE?&`dKmRyKJmSX3)tvX+6UI>JF3I$?~dvZG?_=-<%H_+W|Ds4b+*UyE0V?R!A%3?Vf^q33N85Q3JTFpb<0@=%Q6+ zcXx4~FLghQDqpU5Bm7eU(a_@qgnYY@mAJWJa>e%o^YnMm!rP4XCHaQ%Y&0CyUPHco zs~*|Cz9XpWG2PeEaF!eDG{E39hhM!5-scM$3Y{5XJC5jm2RIL#Oe?nT z0CYcmtr%TB`*$9?&CHHR_HJ(O<$LDj2&XL2LjYIg21j&jL3U1#ETrlc>YGfx0%}4c zj`nt!wZ0YNat+l>($1rVHR$T|c6BOM6ocJMjl0okUhYQODbFd?i5=5qO@Z$ka-VWq z>dD;@eqR7#R@xqTc3?qbJ}^vL5YQX|_sW-qaSK3Y5Ym~B{-`E-BZ_q(rjlB}?F=TI z4&RK->`w6NaoatiEv9rdsobDcp|e_msmKk6Z=g~H5g-1y78^l-NK)d&9m(2boNyBR zb0ffx%nf!HCgQH>$HCHbiYDr;=+ zDY#WcrgFH)+gX1i)V+s^0ZB(CCM*8*hQXk1H*T)kXp#ic8U&5&bBLoU=&B*juKFDH zG5wftLWQMOd2%{^kqh z3q)08zDiERhUL1F9$BKw$U5)JlPxx5nEc$skQ7`FRY5Ii6!h>2X?@bt64UEMxEEp; zx@#;ag-$KlnvW!h1&iwsmCH(Fe?Uh~*Xz=X^vL!w^;hUNU7w#@o9i_fmE4{IOw{|q z@_Bd3)l1+=X!29XAv-WhLUK_GlM5Oz0Z4UjjMUra+<3L<#23z`wUMbV#alVA{H|sZ*zd(^LwJ{5Ttv zp*9=@KTs14%I5Gs^Is_}dui)VLC5K!LlSBg&uqgr(pXJb3}gdV4d7^Tm=S!`oM0lx zI&>^^uMj;Xz9Q}2qiU^44XL8_&7e%Ygz+>$YFfu3C1>rn<;gE@Yd;U3=mZ@by%dDB zi@B}IDdblv1f(D$dGxW>(sA=8F*Yk*=GsjU02gfo=%Cc^08tc9-l#4h-d}y6_-^0NOrj4}{LIZp)+({C~~7+chu? zfF*Z$0PH6mT!7Vfj2EmTv(9Yyp_}G=%5F68C_xp0-J9SwbSZSR7P~a!N9q>G$1N86 zMB46s5v|ayAa>&O_IeQmhcnzHi=%Uudqh>7G-TDUaUN^uZd5MM9PCsw)gt_mOGDTp z{1?k!k#{1--2gnq4fr&$PX(IIv^`)|-Gm!%D8e{{+|vkxe#PMNmPu z4_;(P0u> zaNl5LI`hLM{wqm?yi8V$uGd6u`@PSc0V~qV-OB^5Q$P=sf6rL}B*(2ElBrl&9yubH zZ7YQ2kZi_Khr2PwwDp@p$F`8(TY*fyZQnQFqKlpjI!nFQqh7nY|6P^)?(SmO_(~2PS7@W|oXY z(KVkD4lCE@@UtiiO}zLEW-ndNy+GHi=tFdpYDi0r8pX^$G#%Q&H_)jM-V)bO6R|y@ zZB=HT16`Ll`0$oEK!Vr3`OYuH&SK?5S@YT*D+Uev+HU7|fGHuSQD#KJY*nw0OoP%(fXHFY|#9p2)Tly^A3Oma+*K@>13IsQV!)& zDG?IY?d%z|2J28}hs9n)0JqL+=_*WNzqwTNo-kMWv+)FgVl-vkY~0`j@;WI zuCKwAN(l(NoHl?3%5H;+LfHCy5{A#yYvJFdS})Y@eo3Q(?4cl~d0}Q?_UD(IbVL!C zJCL1g46>uc=U{DJFtawuPqOc8F?^6FdzO-#WNc}qX2J;l6!R|opg;UbMXWOPs;6ViFd*F?DDIF}#d;=8 z8nx(p0NSco-8(3&T8XY&?d_Dcw_egeFwK$una0*cn;`L_;nQ{el+k(L{S2TJIhKtU3sn|r-we18CdN}WkKQv@a-I>MN99*c7bL3&{45(SkSG8@y`#3>jY zkYNrM%+xY-c+q(m06`!SfG!LwfFP}sI_cjThZX9zI`%%4n%0Gxn5fY^v3D>V;6XNL zgPR%CQVa`xcJ*PEX1E2Qf#7UVs@NPDe}gks<;i-(22Ec81@XQz5MzRVP61B;ZFg7=zCcPn}&KlC<_wk zC}B3UnAT>&n{jo9#+oj;H_vekfC8Cn>x#}-iPK|nnk&enG@x$tRTt2e01M2jGFZ8o zUImb98_~V74;eNuP4#B94<#i0Y*WASoI%5ld5MCIFDhTcdNKuLF0b|G04QJ%OQ_0* zR(@9G6aen2)hYxuJ7}vhB=D7XH!$j0AH>i=srzQ}Y@90$e7rrpoVDj;aNr^B!FIM* zbhsX~AbA3yqh=v%35znj!disBWu=!@cRT>PZ71F|hZ8VZ4&CTIfpACb4S>v8HxRKs z+p6?V&2~7R7o*Dy+t*U_=?zdmHGC8Xjp%Do*qIgGxD-Ic#F<7v(t%vM7qY4MI)-n{ z7PxdM=_!(!x(>$;n{ED!qU#z%J1~7zr;_$^uZwOf3{Oo!d*s)FmJ95PAin{~$C}86 zA(~P;Av(AYgwFEnVq=_P+;uLLfQ*+NEk;)jJPaT2YxA$WV#7a&ffM^Pus7|v6G%o- zBh!i)Rw(oq(P!cH{)`a4=V*i~0W zogwM^6`bV&A6a?!>ELI$F{7o>hBhEkcD&}oy6Ox>x_T@{dg4@gE;Mnc7?4mh?RUa~S^CGSv!)6M%<9&UFV znlKRRN5z&7{~{IF+rSP9MA`)DBA9?>&{)a?2=X+6Y;KxHC+!Iu=xG3hJVUVPwt;Wv zn43C8Zya?GPXWd3-cW>F0b>3qqxpwQ~- zGifEFI8CN~3xLyl2P{8>Xpaw_@>4(-w?DLfJT1)re9sAeXe0?{XO{j<$21$oK|nFX z{*^te`B~WLw5?D!YPpp)8|dbmAW<7JKZ{Dd8q#xsv{$P!k=j~O4dw6G1tqzt55-sB zqvp~#JQV4WNl9-@k808c09$@63d{;7qm(a9E6xK@uX<|&nUoEjh)l%%Mfq%<@EFWF zJk_L(?#Z7E1aLY`*OUI2H0+~+4RF5S$07C-RfoZelWEY)z07Nvd4mcnE-nrntxP3Djg%Yin^ol3NgnBq9? z)n}FVfzF}qZ_JRGa2r<=4emVC!dWcvgc*%B1zF4P?TMHy`*lplDVWAHk?(E7b1>o9 z^_#HhTn6CUzJTXoe%T`~I=A&_HlEI4WfnbK`V4@F^)*{qeY}C;6NC+NUYKpH@N6je z;dR4|Ux{HbV7hAaorzLkM&&vgq1)`pEL`(!pPGP;6qHo`(f0K3qY_z@oLAcAsdD;*k0JK3G(X=iM<#m z?o#H4Ta!ls#jxH`*xq6VhR^G5c=(x)ka7r9=k+o_k=l}91H|J(U>3Y`;)XpRep|r& zOk#(hlzcWgTikM^xXgOs%8n@*XRBCi?KLeZJ z(V?~gY=KeNXy0-!31{1(uo=jlg&L{(I}kRlA42ALT!u#VDNs#ZKUASB9C#Qa0pK@ZWjPY|RI9Y%ev6iDj91O&xqKN4q3m8~b z9HNL*a5~&b2+t;NFtdWHi({3fE&R47LAiI9a!vqHnXZaOl1K`45&{IjpWvz7il|I- zuLlA=hKzfzGqD=ndsBlORy%N4>0&$!%4ZpCa6?T^tUZ%kUTW*P8}DGbwGD|P-fc;j zI&fWS3^!A?#c~-uT^O4^f96a+#9D}DJ^WwM%jDwjc#g&`MZ8tepI~XGkct6W0l>xB z(HSor-cT>o;pQ6LyPd^NgHwbiyat!^XTjr?xY?!^FFcoW=~xGDPQ&$BUI7n|9f2Fc z@E308S?b|eU9qKJ0hh4F-6Q~T<4wuS6_;Y#R3;7baNlaaz)Oj8eBn+lK&>+Eah(Bh zOwq5{!6zkU;F5fY4`0LuW*K0QyLC-odlq7oF|=RZ5>+ORqk%iqmRSswi(&1!ZoiR34=+LEaT6o#P!xbu5J`tJ zCrE8>TOuWv=<8_QZ8EG2l3(sYusPf!DAolHGq8#!RaUM=p_cQKEvP6~Pko2#i8H{x zeOTZ~_yW?*b>nj57>6iU@JF}}-_Aw9^g|>bE?u256&jR-9(Za^vE}NSNoA){Z#+6* z?DUd#wQ?Jo|0;8xI1?YKuqFXZxW%0-?`Y0T6!2JU6P`hB#V=wol-Q(V(d&x*esRwo zIox~fYyI*PUW0}ml>3QTqiB#%C)AHTP(q5;RGe}M?!_*6NeC@9l#D5YUj@yDQU|OC zJ_=-rAleVpLmXm^gG!|n zt)A#4#09dHkEa+-74QmltuX)Nssm5ev?~mFXWYx8u_p|Zng`53(WMSDqz6^c;guZPchkE=(#SpxRgW45_1s!rzguP z9n5LFf}j-`TpaBOx>@MCJGnUSUg;V{ACbY0o`rULOc*NgavJhj8AGfQ!sV=qHiS7` zkOuGK`8rcP0x^IOXg1;E@)~6`u%TGfq?s*^u{I2a`}5Mctr5sn{0KY=ek2Jc1H`6$%0v=Y`!1%@cG z0>(Vv1zOV(fY!v|bK4VHgp|0Op^hcMZpC3Q*3#Y4n$P+yXv!CGt9u|ihDaV9UbuT z^p7eUbSUqzJXmSYa0YlD6iG>`C zs;w|dUu%4#`?uh@$bwqT^+A=xTnaSv668cSoyWry?YP4~?(Wx@%Eo!it@}N>mg+aRb??L?$(CWchGPX1r#J4OE?w4MNh=sPf=^J ztFuZ59;>Q!MC%6*gkOe=nD5k;q~U$^$3f&0f5SNF`%M%~J_=ul1IOxVlKqF2)r*cb zcGjNA;WB+QV}~ihlg(gSu+ErG_a4?>6Ux~Ht1kL!1nhsgmt_*C{E=n@VvvfQa8#p7 ziJ2}t6<2a?66{ASxMF5BI+`)-cYn137ot{a zBqI{&d_$1J2&@pLO0>fH4$sRY2`Qk;bG3)}C2{!VSadyol6)+r7?Wy`P*hA@fo|=pn^W(M8cF`5_TNtaKuH zA!0d5kIm_1rXH)Qt82>_l3tyM2YpJ&`~eM*%Gp}N{0!xd|L6o2lj+g;2CO#ZJH|)q z#*pzrtuSrgytyrP^P6YJ-60K}K;8KZ&MtvVC|Ii^H2W`ccV3vY7Gq5Clw((SsQdX} z@JlcWVVhx5`8=$bDx6%LNPEciu=p^$8^?GF&5mfJj?OAwlt3T!Bn;@5%Fvb~isDo# zfK@SQb5TRd?Gs%ot>yw5c%2zBT+`^QPax}P}zgh?8#mmnp;J*7w}vltS=s$ge0Mm zYeVT>RPv$z`_qV@k5U`t`o6It1`;R8X9EyVBoTvR9RE>Hj8}l!VNP;D#p$^F&BH)= zY;q}+O)<9>hKD?c@09*R;0^*4RxsM^{fZ8hD7O)E99;_m^H;3$ zuh>#uAi`g%?xmk>Dj$bu2+Y9TQi2?z76~kd-0ujX(Vvh6kD~P_U>q~aKt35JAx01g zoViYOo9H$q)%O=bM-j0FQ6K|NdAd9&oX%%+rqwS^1HpPC3c6v{>SW(I5U9>PR09d_ zu$~CZ{fSZrpHkH(7E;aZI_{prMX|#3vORZzS#W$Ua~r4B$sFc77$?M`3qxR5P+_Q# zgoje0$fPVMX62_ElJv?dl?AYs;AL2rsOB+Vlvuez=wlJq?M@4DA4##*%@0cg@W?l4 z=#OerO4A@RL~%<2tK7*`Erl+`Pj;;B)|gr=NmAKbh}Bm5*`=vS9S@9;jxSTWqkg(H zS3>0*&ll3eQ-11;x5f~~z#Wt^NF`L!I@3!hlHHvW$T1g#nx9R^-I%G)jX}Fxcezoe zA4M@~xpQN|5U820_(D;xPW9R805lwxNIPC_d+2nrn}MaWZ8OBn4MmC|ZF2Dg1X>uI z-E&>Co$BEaM8=CpD~@$lD69sI%n^0JA>J}iq}x8yU!KsPp{lmiijrcB*Dtr@?kuIt zVb`S0R-rn&M`F~*bl5?f;KQ&YPMA`e3F}a925vK!%`e7VuQ{Y3MR_^^1^+CTdf-q_ zGFhMLR!dxLjJrG9rKn7#9Ghrj4w9fz0s!y8(|alvteXNy=ZONa*@Zkp*f%B|;`=vc z1LHf?vnoi(T}Ye4hg^5hy1GjRu+cdzDUzhJ@-?rO5;QQksUH zsUx5r@bA#ikV|+$5iF^VvI;HJEH)P=Q_9G`RdR#}AyutgrlLBm81=1st6sM6M$!<= zV0;IQW+CE+q+N!BpF|jB83_;!lGWaWGHRz@lqVwGm_;nC^a;1b*ad?p!;g3+iu!Rh2ZJ*j>k0e&*(HvGE3DMgsON4UPyY^ zh;DH!_tyA{>eQ1xcpyCPUg07Mh_Q>5E+8Wh8$7xvN54R(B54t(Djk&8zsmN|ol`8r zc9X7N3*0c*yFxk-B!VDNs*tUWO?JR_pd-}s($b#mm|n--fxfE(iEJ^BFg@3#QXAbh zCMAg!3Le;Hp{<0gL=bnkF{Ibzc`3Y|JhZU@6+oWa#a@*XM>{ z^+Vl(R7UmB;ozM+m;%rxx(@h3qJZXuR}j(N;Z{})-*TXf>dbsQdHRO@86p*H&R zJbp5l2#)r5jIsE3^dXVT^8gFDI}_%Jni%#X<*Qg2SdFMlk*hitF)D0V#oe=Ah?KrS z>|VM|zU`xluUhwNMfB|O>e#oyRwHLIgiSYc;0ix6u8l!y$q(g}qzR*y5IK}4GC*$h zK)&;Tg_tr5RBRcw!ZMW!vk|>{rNiW@YO!B zS)7l;VJhuJ%oxT7Mm8-w%syHu*m0pZRwlZRy9JGY@&O(&PIV=^imZCrB*CxXV~2;t zXjc;2sFDMmht?LltWo6vX7%mwFItDTxV%gtWhi;GdH8R7ii%KF(#XKk5#z527o9Ec?rVTm1i@4| z^hlEd zU8X8!D8)mFNlBXuBPXd|BmQA_hhfFa8~N3!uW;%psE+L(a(O@RhLq=;!zm_T7nVjF zy1`D*VUem!MGAN?B*Z!D&4CikcxnU=4-u_=IVucUnZcwggS1x+u<<}=n?yi$ZcOim z#odwqNx+1$keh+X!-iJ zXG*16$Vj+qxC%(tObC@DM%jpZ#?+kviR!ueq^>KH!Si#i9=8`*^p@*kzAcj#P4y24 zshtQTO!(>@M3|tZTBGuRxL#FFN4gjaCHn1TgWu^L467O}`WR}W`)wC!)Imn{Jyadf z4cwHML?6MY0>yP44MJUDf_dt|rr+R0MXC1%C9O?mR1*RrPxl|x31IC8Rk6%hhEX8H z1GakYitX;9$|4M%SXV|X1j;Y0r=%K4f%1jLa8KU%xcyg}$8gS=XQHII(~Sz+9gjw( z%mW>Mk_Cna)iYiMw$2?d$s0|Akfi`o!s+nPXefALvVxi}5R}em#5Vg$i894p3iAe#a2fs#+8Q}Pz;2hEm*hTO z!Q9`U!(xp^T+UD2`-WzyWR1vPw9eD?)==DSxqA(%H@4H5T^UiOuXNZdT<>nkD%ahLndA_qHZ0DEx(`d( zh6%{GKg75Bd^R>E0)-`W(7(ad(!NWeVI|=Q2cf(!JXQ|!+5DOe$C2q$2`w@qRY~D{ zRl!6!X%RisSw)4pDb$Z$ptUX&H)8@{wpwZaU$vN_M@XYwo&JD<2m7if3uzK@cQ4ty z&>m}fz+rs4G|`@QN7(r{-I3nc>M-~Pmnh#FLr0`{2qo2yPIP)soMpGDChlD@db2lP+)(4_`iRHiz zOo0M&CF-<0x{5ef(T+CvZ+p>m8ZmI_9qs>C1wY+wQjrad47I%6Ua2j?YQVq4aH?x5 z_aB39ymg@6(yd^u#4H>$(&r1+Rsfq(R|T7`IFI3{2O&8)0N@{bko<&|CR}%LlmNXH zoId9kib_gQD0ytA_!~{CsiMw1VU6L`+<~cS5Qq*e_(`oC-<*XaF^aKbfB_Vd_vsH)fH$Vq zAwkM(WAFUXmi*Fudls=PSK?P#6?r@%kw9NQw4@H@ehj@1il&bL3<13!&R{M`WHTwf zAbgPzrzYlMF(5-5lFDh~?&jeE<1TkoHl7sY+^J+(FgPgDB95*fM|WmXUJ4uY6F*JO=uWJs)t_wp4n zV^3A@d`o8sI~J5km=KD5!_N^p-W|31A~hW2988j&qZb_FOs z64u3)U5M7xHLG<3wVyt_7#%c#S}qZ9}|3qmqBss}`NbAxGKHaF6n*$N58^cJz+}z$?jd zE#u^um}Zd1i{3P-&ZL1^Z`H-)?gz@GWQ0G95`sEcr$kesAt}91aFdE4$G4>vrJ~ft zd2k=cm&tDR^*Z^je1{)l2?;23aMj<%h6GM26jB{M*Y#YLNweFcHgfzO_1Jv%1v{9e zPzV_=FSUB8K2V3$1`Q24IayOTJKx~7B}&<@#%0ND2^B0V9$~-vJ*GG|Ok}B)lbqa^ z&3ykGi#Vl=6Eyldp5r|<$J&GLt#*10z|{RVG?CD~$9J&gI|oWXL8r>LMapbQv#%^R zZ5%XkFY*a#&A_C!tq|DX6Ib8*ip}TuNpOG&UpDn!9p<);T{W^r+Ur16xJZ+z|Ih7y zY=iJ9Cx*cr35eVIMx?$O=O=*f7WgIiv}DNc{!c+$MEOav@VNVsvKt>uLg$QdcG{QG zI*s(JH=!behG!tyn!#Ytk~+0GD)S;7JU9I~T5Zf>^RLL@zb!Y)L zq)xYW^yOQW_u`2+;3sNz*if88s5LrKP@9##`J0iZlku_Wf;$f82B%?-@U^1R?|w`4 z(Cbc=aA*YE4cS)ZVJ(B;z652CvnIR=#+PsqqY=({YECT$CBGQv0-v8e-5sthzRd-W z^Vr(=?r|N*xe$M{E!|*p2lfW!>ompSU(FuQfa6Yvj$$&8uPe6J>T}uSNAdE3_=wur z6ga0+!5hzms5l~08=G6g$=u{&UiZ8_&gPD9J?Nms=;Y`z2ONChC~w5rgZC+)3^6X# z;py31ysiyE)R*|f|ID4#!2f+-v;WGKqeiSeanHf0-~5sL?VDnse*1fi_xjF=ho1S) z=gwYdd%yY1+3%IUcg{U8o_22Y^u&3Y*`J+%*gp=v;DpEKU+}{PYcJew(*FN&2eK!Bijkk`z z@}{+){raY{`#*ov-)?&F<_+FH@5i@3^1UD5`&j)?&YBck^W=9w{rNe&@A!+E7i@C- zg0l~}{iT;y-tLXv^3K%8f4TGcvo8MiimeyjwME@8?_Rh?{XNOoUb^q1hc@Wh`IglW zoV@UbhfXbQ`ta3v-~aH7r|MgP9=ch{Y>!|x~V^Z4&u=5?$cRdeCmTUI`}_LX-J zc_cIK!biTU`PQRb)Zg*wp-Waie&(dRA76cb;fb0H-+5y3FGl}y+QU!M5yon9G#$@o_%zIE|y@24+$?e;0|-_D)4==C9|-1^4a5AJEw%Uj5Y$U%dJ8Prn%bi);V2+2O~1)wbQY-B&N%W5baH z8aMppnM*f3VatwaTF=G?#K zU+28N!F>>}?j_cU1SH3vT_F4N{^sGQw4ZVEHSLEyI5o5Cd#T0VqZ6_pf7;aX zt?e$&yIWtGKjQMkPWbZ!i4(pW@%9P7UHDAlxyLd~1|Q-q{Z(eiWtYrf)qT<4JD%vB z*LLC|&o4je+}D45(#q%4E55PYZ&rNy;m}jo?%+79x58VXc&PLFZ5-!jyytNm9zWUe z8;&!-#&J%9pU7|TIDa1IILq+oNxXYi#G875!ninKpU1NqlQ(vpe-6a+<#2YN;+$zxi7+e-^V%zVXZd~cAO+0 zAlo_SIB#RlNx-r7W{%T=vG?M$HsJaY&kEhQkK^35spDJ=`XAp8KA!Y%>Z$IHJ;}y;E#*(U*dOv!MvYr;y7o5 z&dYX!EP#6(@bg2=ch+8xlg1+zdx4Jk@b4Ai|9RlidBA@v)^rT!z8fkD>krY~du z0{Aou^tV8sXJO3=%zZG%bOXl=7}tckUfI)eJ{}2qfp-n~{eysc5quqp&%OIv!JPY}c z-`sHy2kytf#~Z-sM?u#QG5T~A{E9l?{mz`Nm)#Q=PEI_N(W`f@LR{ss8b0)Baz z?-v$iy+yR&q>wFmSmw`V&#kxKNoqL1c^TChP0KYBfcpPir9lZY%GFXB! z-^biHV4gAH)i}sGp!s(2?jw9whrc^Eg04Zo#$mpn0arKRpTJtj zLl>4{?Ym=b10btzd_EJhJQM5R7X0|q1?}L$#h|+ubln4eNP<64g0?pRQwJH;;CEYr zk1e3@Uf9N;K*QgF_kPU%0&ul9;i)lsDMMc>%lpFZi*UhfXUrtr{hC(y;L6)9e5{QR zH1esf$+#JomvZyo^*I>V=bhU-h7&AW2Vw*cky^2Y-bq#!yY@Ao!u z(Vl}Dd9QZCf8>D|6&Ib$0XjFlV0#fRwdFO#?I65hJg~;Qo#n1vxtZP^)q?AA(^x8> znBdbrp7S)2)|g1cC7Kt44}*l_<}h;!pT*6_3-wQ*rh)Cof0mC8)hd`#SZa6FxL>C=wM*JJ$u6a%u*Ryhz@2 zegISrCi94@JZ6Q#L#~jgx3a1IBM@1NB#0Oj3J8-@V~OE{l+d@uzO3a(t+}E8z%p?OeR(iL7Xcnn*Itdo=RUgl}5oj%oiK5kPww3K2fLXPt zfHA$J2h|KVjbL*$Fh-cFMUe0@`>@8Hq~eL>?uP=%%DxE1SAy)fphC?sS#~vm=b1C= zH{Lx};1!jbv8ZI>T0-EFl4p)8Gz*A$e1M38oumH6*F)v~w?~0^n2GpE#M5RBn-NsN zX4o5wmdg+`L7?7+>$Np+fAoBY>4ZSsxzy7nlYq7$Cd+W`@1w~N_1F}`1sFa#3=e$` z*FJ~nyNty3NuU`-++jX%Yc4;NLg^z69oxU5dN#fKqO%v8XS>?K=4z7oc%-&KdQ3aD zT7;kZkP)+Tll?yh*o6Lpk?G72qpyB`16{I-{X>xfE7D5Ab zVqtmYhza~{D}>~bY{n?Zh$*J6-xNBwh4gj-+3fX0HWzf3zy>mdV$v+QV*TlxhXu0f z5h8mM$a)ousRT47COK3P+Bmt$sQ4w2?AzNSrzxOLXBRX+XZAMG*4uETSPD%_>Ymw{ znI+@fKsX~DR<6zAXHgWIc%4CWNhhKy+pFk9bdqZDopX5;o0)xRI<$e?fh=Qyi<%XU7*tY*+pmDA zCPdT?Pe28vA`%q~DI!c^W29COW-oaG_5jA}K~cle`j=Iqk_;yQC_=8F=(GViAg2igkWQ94uWHjQUby*=LvuX%5H;+LfHEI4-B8D*TTQe{+`|al12rEz}~bpFU$tam_^vS^Ve5r>1iMwS9y`5$U;r0uRYSy3G>@!&i>f?ZT?RXEK;Qg zml>8qMdv7>RViBeLi(s1t*Uwn~td5`4^qt_OoPYqU|5AQb1tHaNQA9mf`t8YsheY&_>nb zcR*>d-9%ZP?XLnTNJ2!!>~v{&Qtq&~#jygFI#W}aA~5;T5yqTz6$S=D&(0+ZNEPjD z;vNhR$S?;B=IHREv&#C}jQa27z2R!N=okH^q@t&Y79rKWX3+nK1*JF!KV26&Lo z+2Cfz^c@Tfe0KF=m1ejVpn>3QQ1X8cjK9H|s?uw{VUu$H2%sR|R|cXG^;_XXhEy4@ zMaN=oF@(wOprUg%h6k?C#9n#0Bn6uB^y2pefx&drDEtx00aVv0)+Ld zwxlmG{1R8IVflF5BW5tME|$WwiaA0vK1nH_F`t>LSkZ}~DQl~wUgT^W{uJU&)hYxuJ7{?f36f^J8yI!0r(8`0OG=#he>0W?gUY4jr<$fbKBn|haH__l0; zONWx4B8jP=#IKue{)?jXSOxPw?ZEU=ol4rv?M=F=Fg(2tv`2m&Xt}_y2=egR~P34c-Og50y189v>07A@NM{bUz>m36&wDqV&KI74D3xihT!n# z2x??n5yJ|F-h!I|1<=kuLAkb^2cTL4vC&dc-I-{6O1B#)!Chya+W;_50GQE8SBpQ> z4rK3ik;->kFdz3rSR@PC)PgSOP9SK|n?$yHR6gycxhc{kDrNvF=TRVPS{Fp5NYc6} zs*7<>c0^@V^pXrz>}0Y@z(^^X&B9S&UEe_SfS?NqJm(Yu)K>>6B1MokRAoM_=`T2E zWHUlKL(=stI8Ot7WaZhXgP-BXjGny_!MWso39t$42DVHk20U>qdvYg^t|};dW||@S zE6ur-IxNB*BSdxR7#K=rYC@+?HZpY=kHzh88_A;sAk>eFEgk+vNYa^Tanm&mK57%Bi{S4wSku)2f;>$io13Q5Nqd3@`YV7z zo*`It+d#}*&q!|^bq|{yjC!*-6ya8Yn16WAOn%mfgLPa(NePsbdq>HYvo+1$i%j3X~Ri=s7!T$Ml2{CUc&G(y$!cTY>r$B zP-u1anY2i?v(`z=!vLJtJ7D=4M0$ ziqn8%hW#shR`av4(P>*@n=&?TWqlv$=9(Z;8!23g9ek=;i3MS)c3R)dE!}n2o)mszDr0jG6jx&Ez zK3gX|26GNiH7TQe^8W$?I31?zN&ib4tcM98fvW);!C=B&DnV1JEm%K6(NP_ZZL{Sl zx_|%%P#u9?K~zebR|5sa)?XBoY96l^-sSWF7!s%sOq(qyyXd?OKt$u}fb-GsoeSQJ z+ha$AwK<7~Q5p@z1ZsSU#!JTJXIE#g_NNI+YS*yK@$+BO^WSoL&JQMle zCVU?gj$OYAi_RASuI&rhJUzMRq<+lS0>Q8{i=Hi=0N`PL&Bj_ls*fWve1fn+c9+=w z3eSdeA6~a*_>~w21J*m-&lKZ9R~IPaQ4}oCSdNA5lsOQj-iJFEAR`D;#4p2LBHEGO zI-?$>L5m!oYlnvX2|)W+2C_ZZR~T3uHmdBC*~A!K!PS#tp&@`-_tTLuX$TK?5J9=K zl@7@LKr}@9U$S{*=NpUQ=)z;=u_-X;-UpM1%y4+jD}^n8O06B@;Q?#XflXZ?na~>& zdofJhrOXYtCRYN*u-;JE-eL`g&+Bb?_?eE75;t{TFY^;wCr1ZlYbg@@O6Hs2m37b~`Nq9uWoBO$N5Is0l)PSh!pRp!#Y+QeyJJ znnZ}nn1zZH7I3cud|VWqVLcc59z?bIA8G6-0ur9XsRVZCNl_7#ECDSeo6xu|r=U`! z^L7lK869d1z!n&FjrJ|)l8Ts_wj5UNtEQp>uzm=c-*Fi_CHpZ@O2Ng~;^CLedlOeuJ{YzqSm`ED->AVJU9g*a&kX3gU! z9sG}X2m15iW>vYd2fx78K{5%RMFgEWlEcgUlbN2|_(Lw1?<(YRVPhhj#|^`AciwCR zDB-WKgxlguUHJm10!&*bkz1a?{m7jfDb!0k$Nu zqJo;3OW~b9gYgEGIVs*W&g0EMjLIf>U06|(ikUl#t))yh6?YGp;fWM(DZ`S$oK9TE zl_+Ge5R*c#7q^mu4o|UMeX1zJ1w!V)xI02q0MhlULB3iIZ%{Hv%Ux3k1rWG(kykq9 zAXh~-X4G)@Gy*t00L;fuC}k+`{>}u^WO7N&mRT-P1+Oz-%z(uir3Qg)WTs;vAaex8 zjj4Lp;EnpET9dj`Itk!FVfP-VtfYaY2$8VBc8%Ys`VGl zMdnKUeJu$*9t6ja$D6e=nZqKPR+r7Y-^b%L$;FAZHxK6Tbv5Do_g4HO)-7*&MScsi zwAq4zwA8mEZd-NunXtSZsDL9QQ#1~l8lO=}gFF3~+v7lqSFHy_Y~k;Q>EGh1 zwf}S;Lp9VS!{Vm4!0TmZDnatGk|b=9uRefk)8lD{Rq8J$n(~(5D*7cbFDQ0~w+zyC z2Y?C-bz8i#4kXvPdNr5y4v}w zaT9K__opB-+`yNlih!y%+-izPm~e3>jB6S1wlnPp=v%XS&}Z5s9JG4vI_|D=qe`UJ z6sDq?VGykN;+wlt9}trfZUlf8-jahNV35Q`XaQmfB5=f_lp=<(?g?-(DoCnZRmq@y zfkIQUj^S9|rS%!rlt&co@*Rw?e|XG6f-ISX$dyUui@4;jD3@&F0?T4|M{7P?jLR?L z?%YVw)C@>@t$>Xs$XFo>F@$cVfUDc_q{U*+Yj`zqSEUVcci3!YPJG`-IW=**;9}1; z9Uk%ks*yNv=>N=wgfaXw^sNdrVo(Mn=`9&1=;M{%6l3jtCV?&~lSW{}<9__W^e1}h z38Wgw_|)W*C67LV0YI-2LXF4pxvxSx8tIQYHDv9@GO0MVhfzLX=vjlXty$Pn9AOL`)$B-g zm*7&0dARdfvgbC?C%L1sR4}R7vxZiaFXC$13{oMF!jHSFzb^7LemEfCGQLJC(_z|G zgf$!KuD2|aMAif=MsBw70NzA-Y)w4YLdV7AKzR@-zJIYM3{4=I&g67D(2!r6%jOfv zn0JTw()ytUZ=~vRcZt?UcojGlcyg7JDs`ao10^(+KF4$g%0vykH1>?jN+1Nt9zF&I zOM?2>^Xn`wz(giU-PDl>Wl9S!;Z@NlRf0#!)1i5~P=Jd?x+s+BNUpS~o|bxI)Bvb{ zI`#4m5wQffCgY_#mF$6x(8aS735FLvFy2pcy46_ab(BBSGegt#__*6_@GFr6!~ASq z4>q51g`3hDBo+vXRUniLnh`9B#g91V^~8sl(~Z?JJR)Lvv5H|%D+N-0um3RUFtCuokap4Igeq-i)k%Xda=M@iMSucf{f65?@D69=x>z=qp= zH^3@2hcIiUydtN3Tr%Izw=$uX;tuI{aA`R1v`$L;9CE8x)vd5G`Yfd}hQcze()Lu* z?ji3-U88F1jyyyw^D8&j;1$~wt(mMO>qa)^KL$xw_=y#hDK9k(cWxs@bS8kFZXn+& zxtX`DGuyK!iBKA=Lu^QTbsp@qgpA$~KAMO!QW?8>jW&v|u2Q*%hWtXs4?b2Z32EyF z$BhzEe3h!zgwFZRGh@@{&70ez?FhH%TYA)zFM;~Gh5QmE4&Yf)=~3K0g_`O&NQB3lE5EVZx7)VHoM-`u<@EtwZsBzFnNtSf2gp1?xq`~}3tqsm8 zVip`Q{h-4Tcc&f&*AS$(CX28HsF<`zl(K<^l~^kd%B`IpBsdXXTZsJ8L&Iq?T6Y*M zv(h(Rf3N{CLzkf8ergrTEkcbKMe;pni)uiji-W3@ZKnm9B9sS@MU+yRJZwX0K3xHx zw}WT*GaT(0efwxnbR%#fBV}r=+FVR)l*U4Du`(zt5^#8YwxC2mExS{`Ca^EnK``S6 zP!t6VY$FHXt(et8f>9zjFmF;33%!_-Xq}AtT{;!Vbhv=9!w^7{IT&>eWY4+SSVLXu zsc6I&lgj&|78iGq3V7~&@X(!gbY`-CUI&~iaLxw@fkRt*-DI}5FgNpdRa}K4io4@s zOyFoInp}P+1)Aw4Rfi);j`e~RfjZWr`!+d9)xzEy%ps7QJznM0k@?WUlht*WAXKG$ zDn;-O5q5-+eVc%CN~Yv{45b2Ct!NKQ`4Y011jt&{h&B4gFZp2@E0r5W!$|l3ge~PI zt7@!@L@=)o2ZM1RI123jg=Xm!s`ipdQ#3}~sc&9K>jg4|v5sIb&%h}yAEq#;GURtUf!Su|_WfO#=ykbhBRZ5MiEDrd$b2M&xZx9Iwou6Kf?w zZHFKVa+qnCAWrqXX6(TD==d_saR;ZR}Y+=}6QGo%qX%Zp~x7z>uf(8#QFj*`M%_FcYZNn z@0*BXY%w+tP2bo_F&asode|O6$WrTcOA^1~WcaHyTY?KI%D@S+g>`kwEcZ=Liq$3g ze|1^DgMxo#j~%#~RW&QEHluw|7i;t6yTRx&g*MucXN28zU2#2d2S(!yK}7nk#?VXEWuoe-bPW27cZ^EnjOq>c)GA)oMtM|=(k+Vz01**OtteS^gkY|! zG})hDNkR;SwQkBoJ`8UfcL$egEW#fOfh@O(P)1N^mHI9*d{ekQxDym~93qaBSt`v? z<%6{{A^cV`gPv&69pgJfLaB1$fwKi+Fb&I##N7j@ux^D7=%q#DfoU0jI?*p6olw)Q z!`-pLBlQDK)FuM23|US|={?>MX2+b#AsAHeCcz->mx&vG8>p9Luwm45n=1T^*rDw1 z`E@Z_VpFgi&$8r#pLCRj0x%o1c78NkIFYTVWRghe@Nz2J379wTPJ!r+0?sV35q{A? z((44%^H3u6T5||#DvZ+0<6R$inj5?{{j6qkxD-7VU9hU189lHZvJ9`ErOWyVx_(i6 zSA0EFrMb*eu`Wnbc5YRYg~ypa)$4~XTm7D(a}syARBjq<5!qtbShYm(ljus2I%5Lx zyA5xVU~?$YM!Ztj#H1exD5wMkbs%il4~P(q&Fn&=XU%dY0Zpk|c3j?{8-k?|^x- zU-%igMIzwv4ifr>svyy2h%X0NBh&e=JQ~m<44qF^+Tq)5I-Y$>u>Dx??nrs-pfjX6 z)XyB;?ffyc6JNRF?o$6>RQoU}6NC)*6HS))F|}Eu#1E=#WotwcNulW0w~{WsdLlL% zz9W-|zQbm~fLvw?Fcz6LXSkPs%53d!IFrtvFwp3LkTy{m!%0GbUyFk}!)>fMFV+l) zmTyII=OIDH`~^>!JruT0tyZ@4 z>i<^K#CeVa_gLt4q2I-X(P+dd*^`Az`!je=NjW4*^LB^-Q5n5>AFZ-}4KQjtoE17g zw60z|{Nmz#r~`bPEGUb_ymXHCK?4Y}sJhwWX54+|`W}L_a598?1{HAq$0{W^X!WyqXm%nC7QkcH!eq=?$&dmc04E*FUzp6mtQxpJv07Oxj#dYNl$Y>5 z4l?ozGf4$p?;bR-Tyof0^+S|wkcafhUV^fj;qx(l9*=IKm!=&g>F17mMS!WKLWe%Z zT3N2{g$JooWoHk0s**154mA;x7Zv#ccH(8;ehsa_vYn!UnqStkEiPdv%P-PVGl}5n zTTXXpS8>ktHEK&8!=ad5i74&=f`i_7rq_-BHYhRuv>^~BQ@>y37kWiB9ExoT)WfhO zY68-V4ElZ`7jy=BhS;Er=1^=Xac~4p`UVJ)(Ds^U9Q4WJt!`!06>=2hmqRcn+zf)d zRb6U1L_qF{Yo%QG>U|_qddZNK(>8H}a2wN}y$-}FqM2Aad=V2vB_=;x39>|K+F;WP zEWxg2h6yQ~GT;x|glL~s%;=Z&6D?HR#tdbGFH)^X>;dG&{@4{$$2=5=5ZwIszGR0X zOOe8B#!(D`*$QK!tq{VYy^atWFdtSqG>`3>jVU77uUZK~JLODSqyRL{DwT#d9lz~_ zkW$Qa;K99~YjPfY2nRJT!-hak1qXWtx(5NTuU^-aGgxitofb*hv9M_!Xq003Z4Slb zKzOyW1U7h8!xxOs^Hc^!SS-Oaqo;>=|8UH)*$OKX(vF2_7~^%1H>~g^cQDj29-A4o z9xyxR3HM}ruBnXvyDpT9Tlx!0E~94fu7T1~CZ9p1dKOs6}rahKn+hGL01aD%wex!p|6mSAkI>@S!=; z4>9)1<0<`+Tc1b{Gbu4Vp;0Aj{?hz<*QCGD9O1eAWI@=3f}JXWV$WxYRS~c%S78yY zg5Y$pvRZH~NQJr~P=AL_HxDpc^Hegc4t0D4^RS(S1MdonPB$QBo%%8mXVN+JYIz=; z!~`({qk5kekqoDDQGB!ipy@*`o6V#X)W?KG{eCS)0sEVJEo!^G_`_Bh4;Ru!izDdF+-Ii|rgzibbJaC<39V7?(a&dR3 zDotXXMYO^xxMX^MATfNPI^3Z(F3A0%Js2Y!J8a{9{TOQ+k)1&8q?9yd&sLmY-qlXg znVQb?=uzx64+`k>v2lvoVZcB?H>A^-?l!`shzi{qhHG1Yd^D-A15KYgwNDejdZ8MB zpfpe>EG~_yOcinXxn~wQ?Bzhicx#zbW-FD*@;T{k{QL?+%^?nX7agpZJLz z48n5lfU9>;^7US|V38-P&2j@(xUD0atH@D8_rp$Y44b)(5-=uA#II@~zIS-X!-0cJ zs$4d)M4cE>q^sZb+=ipYXw}~5+78K_SZOD*!tsTBQ0CFn{|*_eBtNtWmA|NM3K(nA z>$%nXiiApFAd)^TGO#Z>NCrs-$b5&TA_n}oK6z482lKCqyXUavFawUi*K2ULsKk{l zG3F!J4|++gl-Qg`9&a3W#9^GsAs0+FVnvM(S>f?g!?Pfkvo{xa|5j$m`k0GBP)HB^ z{kkbxm7KZ%eL67GE-tC#e$NvBvW!mIkJ@(|JQJJ_ayP_PF)h`KGdh}acgH#MMJ#pN zDQqXYvlsA-2(%F2Jj6olc*YQ4Taa|S^0yTl5M6P?Kb5aRj$AV(U+Bu$xQD_PgMHxO zyn;Dv4Z}_i4Kmy^M$qM#S19Z@YujDzGU`*pM!-`di4TR|*RBdF|C_Gd#WsOoO7*{bRYQxY4O z(s2JvA9kA47&69G13%#Ti)9i7K^j>p1a29Sar&k|XyCm3bH5Ny6c;<<6r0R$a zq4$R<^%c`{awzmFs?!gl`;dXqmjYWQ6+(oMa9CAXL7o_VXNP7UxHPmhI`JJ>oS;Aq znQJSrKZ`oA4$r}fD=p*epV*&8PdqN1*p!0g9{!s3(d%;Vk8QDIZH2nF)QJu}^oXv$ zfDI+TmZ)QXrm~~*3Yd1UJ-R=9&!Aj2>oqXj|9ofp+%q-@{7?L^7{NMhr{I4tSW!%= zm6H*7=cou3Y?xrw{7F2aMQ6yAgr^7mFRaMs8=^w52xp*$8f-~$R=Z-ux`|dLk=jKd zu`&)`=<(P;KLnCf5tF44Pyy0Ev8`54h1CsOq+}6~FdD$>8|2j>`HlH3+4s=plTGQF7h=X^-60YI{JxX74B7_O!Iu?LQS#Ias)96fu{BBo&PNXCMR+XG6m`aa`A>baqf+;J|X+IXB&m#I?gjTy-i2vA+;c+5v zBoRg6s{QK%=%!S%WO$jPTNiA%$xgcF3OS_|8jAskBs0Yw3?K$b*icleD7$waPd|A) zJqCrqw-eFRh5z6;ckq2ySs7S{0q`LvKmB|+2vOz^d|+{$4$a?k&G(`@p!ZOG2z{E5 z6%HH|zq+QJGMOW(s!|{H!tL{obxee7V|7g|#*6M&Q-lD;SZKXF6OK;GUTK^mj_G6d z>WD)UXKVaZ@iZ@1P7IRG9!|bw6U%ks4u12f&;&sO8s(dpSSQobP%CSL(?~K)Jcg|v z`cY)%*hKq>S!D;j20DG31E*rO_+m4$R9^s;mj8VPzh;Duc(^l!&NfyPXYs(?Pj6nT zsDR(gH=pT&y=Cf~qN-&hN5OEFL9i2vbDYwAQp?I9mavWQPcFyPaivIu*OtImVk1$( zYG^rd7tp;5-y3mL^f|uv;%_Qj$Q%+R2g<=g_W9XrhEj5m8^2*YLG>-LJinC+{fs4` zTFdaYN9<`6A&(uNst))-Rq&B+gi&!pk?J1e;I2C5CGslrLK!hzyWa}p){6x0Q2hU( zmA_4c+Vzqz(Md?zvPB=8l%EH}dXQgs$RSU6i2f0h@(-FSRSn&f4l}p7uu#Lx;oqS- zsaOf=2FXaTqK(I<srbxJ+p+wicLc~ApOQVrtL6V3&I&|Fe_xH|VoHX|6tYroc zB-U2q;a#y%E=S#p;q$^^gpwcDik?EE#f-%ijs$U-ShH`z1;ZLgAPiJPL3XPz`+NO@Km53iqg^WtgeHcwBSmzn+9`G@`E&l{r?=YYVquARu#s)c=-X3ynA`qJtuuXmfrM=4>lch#XB9-ue@o-$=ANz zeckH)2VKAVS1m%R$@x71L|KzMmu{BSA_tT%Bv-^&}n0dh_w=X#RfZJbs zY31$S*e&l&ZTy!zk3Z|;U$5AD(Op~A{qpXGTh!l^eC?(CE_!H#o}F)5{lLi!UwG)$ z!ln;jefRwjzj*q7zgzV03x9XrIXnD*;y#c6zGYs=+EFzZuDxaDgKJ-T_mD?2(=L4E ztD0{;x<&mRj~=>Y<>O~gy8H3f=NF!+x$vDQ7XM=OA4h)i_dh1iI`+u}uiyWvr$_(c zsh|CI$EP<~cF5CB-CsU^P-p$Kmp*gFvwuHw=RcJup7h)&$2|Pp6>Upj+`sL{7l&Lp zdqWzxICmlGkpZ;{NU2d5c~ja>}i5to`8LH>Qj@`yW03 zbNHKI?04Lo&!5rtX6tY7dvnl;?cct0oA=*deZg+;ymRgE-kIC8_q*vqli%GYJ>%U^ z+|0YXyl~aK_f7ot-HVdWdpG{!^!MKXWA^=(uXntE#K_-%u9T=0etyYTKPfbCz1^v6xBKkZ(|4Hm#I-wK@SDU=$yL|xRM_m6oz7S| zZ0A$A`*`OKAG>VIq1xNhrGDapaUi}41QwQ_Xhvu@7oW3eJda zcRyA4%#(Y^SJzIDfB%hD!#iGCHDbZ*+mAf?@?VW!_2wpHny0Kh=+n*}$G-c=mGyTW z^Yi-a+tY{qEH`G{TT9kVXgqG*p%*o7JaO&y7f*cn<}D{pzhcDX6;BUuxMQbPP2YNB zhw0Cater9B+)HQVr+zSF@Pbh@7Ys_z^xDswdC%02Sx29^Y}Om6{%OwrTmE&<+grXh z=cs#Y5C6`s&mMmC?8}>9KjxU0rb7Es!_MAj;eAJSFS_8?A1!)d^_oS0J$m*xmv8n` z;;zr`^>#^alYVc_tn^nilkIOFeoFfpCtuTk$b(ZetG<_7>^(Xm`|+nu9pBpS(!9I% zmH8tsKkS4*Kae=#s}XOX@Y{vY6rOu5vt;lg&eC6Hc3gJJ{8il-?Y-lP-g#{&9`gM1 zlg@qpwp5MlCZpLl)r{OyP4Zq0K^_Kx%CVUDv5f1ZpxP7%*X{R!jZfPKCmmkn?1IR6}omz3e`KE-GE0{)wDE0ec& zoI~*1!R5f68ss>8?2lVWw{Vmn6K4Z4?peSN+Szd)7=WAkK*v>h zr{|;H9H%knIM?C1gA)MvBj8+$c{ah%yX}FonD@#J9p_}s@fKhwg0^S&cAVeu=r~X9 ziZyKOIIjWb6X4>1_SprOTw>naFt!x<5p#Smh;NwaEMvhZ=5I#S^aZ1DSFd6tZ zVN37?e4GWE55kyTacTJo@a_SOy#w^D#>-O${Bbe)S9Oq2XdD%{o1#oWz zetwAg&f3dy(zp?PFVOKG{=EYHKMy=Q5BN{Tn)sT+-GKQfXx<1ieHrr?z^6%|zXkF< z3u{hb?t?L=8#rFTxF*c?%ASt%@kq!EylcSk9|X*c;Ojtq_HEF659Ycb>v#-u%wgOq zSo3GVu_I)C#(2mSGC3GLSp)s}0pxrY=y()k27~5*;qUiB|IabzS;&9<=8khXa6bk< z-T*#73c7xX`LBWOhCl|Zz~|>6lWV|-srda+;2Qw>%muH2%6SwrdKoxQ#hT7L*m3T} z-!mbHrJ#Kj;PLI0W1mwWN^FTj@;@XNz|$AG4bK*LU0 z$NRwL4#1pP=fi-%4E*^i*7X_a+#B?s4}P2m_-!%A<5>Id;Qg17!4i!5KIXmw^Nazn z#zB^If$sz0T?qbd1Hw-O&9{ShAK|k){N1q;bPf774)gsCxVi!V1lBqpy08Rm-yLfk z09ke8^O=z4nOOg};K!FPXa^522Hmxw>mKMs68w1*w7mhCI>?{~zuO9YYyo}u!Z!W{ z8vX{n_harCfUC6$uO7+u+xnJPUR`Y8$q8ONVCOC*y+5 z+4ziCK+nOrMqJ#<8%nz!u-};+-d?Qln>DZPG@m7t&&%&IPm+S@jJ#^tywG=!x|WmI zWriD(ykNZE!)s>c+D>`N#~j5w*3(!j@BQQ}BA)X%AgwWx zhD$W>CO#MvikrjCCFr}I`G#>T@bV$Kl#>F;#A+bnh1BLn*L)zNU@hw$AhF2fm9i91 z%D;P8B>p~z?Q73v595o$ycK>wXxWh71~!8y9hieRr5=mHy<*kZqhE@FGfk|a+El*c zT$95KcsXPAW_LP-k(CjePZ?-M*B80&4%?iuE?}ni@`Va&1h4p}7`mN#Kv!>~Be_X@ zNSl!N59E$;+sO32&Q}6_OcY$+-PMH82C^;TOvo z87_x99o}nA-N=CsQYzf?0Ny7hTuu&VQ4UV@`nvKPfNFAIi>i)FKV3NxL8rMong*rP z^sXuVi#pRCxxiXzqD2-!Hy6w|&2vCIsybR;dThSY7jo!f09w9=AB7CIuYRhZ9< zic5$}y&y3kr?ydu+Y)`+3L$H3^(B}gqC7a990j&7eKt*>6p(ctU@-lB!Fe6PmbuZm zW?@JdnAWa%oDN>C5>wOfmF$RI!y=lX_8RS*or_L*=lO{MwzP9yfGMYD(8xQjJ?9Oe zYA~5cROK-%3?6bNHNBNh?e<7|EJYGTj0pvBgV$km=5j}HIshwBz~>Drxw`6Hc?gIm zM3+KW7ro`a`uhf-1BK-T^%~8quzw_?5R zt;ml`PYp~5*fe{6W;AccOmwR9#-H}vypvwv2rmzIh*tj+$Sl`q(@+_iu#j5BsZ!47 z$if#?r%1n6LBmS|h;LR%wox7~8kmDx+K%d%t| zQ1iW%qH`HaBTLonz(6(NJ20HB06)iPDx{)$34pUr39&-T!?>b0s%1rPNQkzLL8o{{ zXG@fmR@4bu$yJ-h2ld6w_PYT(&ZedSLdimcYR=QF$x!O6H~~rJi_UF8U_~B#ZjFG( zr&HQ$*7Pw@Sq5OE($XhGtJ4!hX>NHCnwkzAWHn8mmSS6%jzqHoZfQmoT-1pg=v8?~ z=l?+yz_OFxP>?^NzM7fIL8$+&^ltsoEK=n(lMG4~Z@&VqWie5-n$5Pd-2^bJ_7pIt zcdRrugH0p&13*TYszs2+_#?3;tZ^r)cp|y`7U))3SrCDWpxu6!Ce#d*Whns9GiTJ# zO?yg_i^|McRI+d_A@E3vKF2RMmO`FRq0qggw zi2QR5A7aKO>Rq^ATk{5@Uo=d|A#vwYPZJXXZ9$Bb;o9FvlOO7_DTME0_~bA=^fg@j z9HQ?s64xhyW)N|Q`Mj;U{7ed^k1%v>|Ay+>^y-Vwo@hqxY6F|AX~oCtNqFirJ*J&n zEyB-yxsF-6$^IV$Oug>jHyD}D{4n|eA-i4^we9yla|W!CEJL2$W>{qM?>TWGId1)s zOvS?T$Pu}0TOlNeWHW}2aW1BqwtiFS*cQ@z7Ld(eKV)-3XUVr9ib=EJXX{VjJS>n+ zj}X}_K-Q~JOeLTxG0CBV(8kF{Htx1SFLU4C7CB7;bvh$3aAt1OS+5BZVYx~Hsfa|yLW&4a#IRaDj2|*GnVlO(4=O(g^C72m0Wc&4kdT@N5zNp$ zyh=wO$am_v_~$S%%wF<2*k2f{2Sp7>>z}+LPX?2J6d_kobbbinfSe`}Kss6G zkO$&XL*_ni57wc~4vWp0gVo_{_F&y^k$1-z`^u+ZW8WlZXl;3Grx}TOLj+_yfCO4g zht0MhXVIF&hI$ygwYuyJuu+;@)0Jpga)^b{NoSR_rUBTpm;u0mQ}h_j{sf?$Q=gc` z^);AMDFI=Zv(es$vfE&y5VrpAf#LJ?TKKow-?O`4(x@PN*qfH-g_(ibpC4q>5k*|? zKpyIC_#CXQ3ue{^`APOYy9POlCVQ5Wnq+Kgq-MehDZGo$^B6iN97=!1f`qmqvSU!7 zOD6Y3^wjVsR9+kHV|W6a8GV7;RQw2t0!6bC+2X+ak(gV1)n;rN2Bg~qwV#uobC@)0 z9sMpqTlK1Y2c@Hw=&IG;PFZ{FC0&bYj_l7gwkFyHi4UcSC5z;zjLv@n@_=hLh`oF} zY1@83KUOoSl!H;sB5d9H>#MU=4}{|?FH#g)sOj{zM>;xTe!I+B4Ft{q34%qc)ZjA1 zQmE)W3$!XlD_>~;=vt)GT@&SyL4F=lj*?xz^4eMV{wlFx4v>wgyliRzCgE?QTUp-$ zkijdnrDpdIbOk5RkD89C-1!%sdx6%Fp^3JCyxMYbRl53zpt20d0j(j!b*HObhGzk# z!FCg6b+-Q)KtU3sn|r-we6IpPrOwn8rU*h-Axv%u z;hp1QhS`|dD-V~XKr^0R{CprVn9k6wGgGc9ryMkM3T90#(9B6Z=Xrn!sg}f44NlKq z9dHwzWC;LUuqJ6w3)w=Z9inxIz6pSV2DYdgh7M8yD-}a010WDU6dtZP^tNsspZvrQ0QLPWZF9H!{6$m?Y63k?o>4cDk5R#C|J|W96lY}Ke z?CI{AX_%QFx_gogdr(#ZStTGMf-FHn;qQiQLO?VZP}x^eP?7DzWnVyNKx7sN6aS{!`cqe<~mG?B-S;-eOZnHxL_2q#%Nc3y-Jim0TZKmz)Un{zUmD6 z8>Tr(iZ=Vx%GtDcQkRWr-dKmU#YTA5G1@?hpd$AU4cmv zahO6?Rn5N6BIvwU!MM*DFmqL>lJxSdi)PBYr*i@JkS_u( zH&}`Re;&XmxWJ8hr%F=S46c$u`q{;3+^^iF5yMD$InknbHQPKAAMfSUueV~s{~`>W zx;_K@l8zSvWHcqRO(DY!h1PZeiAP5(_PIYbsuzGUdj45CoNL zOqe7S7|}>oi~pt`5KIZij)t`vKe498Bw5g=6rf@U05c2{zIar=?PaJb+#@JP0GZ$n z0GhQSfQXTVb#YJ&#({K|LD5RmQL&QAA^|<6L^eB&2kH8sv|C-6=I zPr_JAB`;`y=m!{gkeRLPJDn@C7(rgJQY`l95=aqx93=3-K2~d>E*jS@YGBR`*BJ%j#2XY;N zjI9iWf>C|qWL#q&QF&q|>#*xYsDI_*ezoC1421Ymu%*Jk3_&^rEgrhk5g8SviQw;Z z*i!+Mz)yFQPfb_pq&z_dJrmQwPdhDsY#?fGR-`qKn}_ECVnJUZ>`{QIzrANB|27v2 zj9)7TJK-Yuw7x-d=PXUjg&3-&VCMSYQvv4i&kx4bUCQyi1q(put5Z+PZss^U6Kp<7 ziA?ngGqE8%d`Ao)-xqwJ#qP)irb4Q#uVh$ijI{|`(wI1>?}_Di5dHDiC|?U;N&iFN z##6)m&%??6NF)(vWtR4gIxR7eyU~FFG1rIcuj+ng3!T0ewkl=gQC2O$HM&#cI^up7 z=Xf=sodDXW*0?}@si+3>mJI<(Dw<32mCvZT^|t|Xf{RICTaQc9_$e_v7N5)vCZ{6> zBaW*usZY6eC%Krtjfs=oUzD%b4T~Ypvl0or4p2si?lG;uq~Tu;oB@fTGqFCnQd#gu zfB_!W!T35`4&n&_fJv?nz|SBm1^4<#p!#I$Y&qJ+U@RuW z8&{vW81>#psJobbdgXF32LlL9e{~>-VH#@;ls1|G3E_6EKnN?o!{6Mu0boMBYFF;9;}w+yfm3gA4JMC{Pc}sc zma-@bg1Svy{)I^st4)#=lNZ*+LrlXe6daqtO`nAw$EVY+cg4O3QEmNkv)2;<5${r8 zjNwfoTGX5>(p(P!L(4I!ROp;I2Z!JBp*{nAhEdk2-&wWmBBCkkvd!8@G@tG6u>Sj2kV}Xl$#S;St>sH#8Mgk=L%4= z0E5aDho<#g06aDhnD()tWYyH+Y<-pZ(taE?w}PmPVU>7G{4-4s6@X`FncxOYDw9>w zRw7C9s)vJ+uh%YCs_mouJOG5_>W|9fiP{36bwW3mcDzy}ZwKMsKs@G@K04Kw1Dd{noabU5FZ6rtw=E{xnSm^#H<3EHLS=Nj>hP{*(7^R1A68a zrC({Lrl*9a(|DKHpu9YrPGoBE;vwGAVZ+uengu7rW^Yc)ZkUhrV)axvFzQ*pb`5&p z@Lf;YbXN^t^--Hb$5-HwAAu-=V-7lftvxf{&gIk_U2X0b@eFucVZ`Ttfb-CK`VAp& zKZ|#IT2%LRg3sZlUM!u$<4(!2Wgf5wD&2+L+BKyV8gv#dZhS$H4a@{33@MT=>2|OI z&lRP*(BTfl*RJVUyM|oB`(YYY7Y5q3R-^@bh;Wl=WQj%Xn)h5O&rgkaCt<&MpdU2n zdUlq(OqF?P3JJVB)l_F@zv~ryyVC7wDxo+HR5NSWbg%tcseImiurKLCz__A%9~eZ@-PQ*j5PA;Do7I$z-lEt*UUXdAL9KeyyS+* z`PhdY6jEqmv!ZFqa7lCb+BNB1Yc6}NtLV}s9xu?@eX1F{uMt%^{!uBh_R54&yYQ!> zD;ZWD8%2i}Q8-I@v$X^5fsal==j)5bY$^6@JU@069-_nJR*+jf6sM)+SS4VfV=HV2 z-m`g`8r z(v?(rG}sb&mE|ZI4#AU%?CP0gZ$YS>Hj2>J2p0O5&4ii*Ic=t#k7#fVH;qtO!-MWZ z*g{V-%o+f8s=%Vf;#!?*D;k0_eK5UHPuhzbEha_%NM;TBYJWMx{5lyf`+UndEwN;c z5lL5^Ui7(HQ}vZo{>GtLe(kOFG?9gc{^C6|^vlU=!73h{E48x;uIhoS-hLJ*l4wnJ6tlHx z=AAF_iO3p9Ed&`@@f=>7SIF_fQRPEmqUl1w`XV<_gs*`fC&NoZS87B_OE8$Zz`60q1{+f<|Ha~MiXC58fUv8yggkxJYA{$GzG#_CwO=zdlpLANmr%(W}>;b zvnAi5DKkqwwT~t#;6)D4*zqB~$Uln8B>AvB9j?4MoGVfr=?Q9z>Y>bVu6BZybtX)FKQEsFd$5W4C31GYM!zl8WpUro>=CK-x=Bn!=p596*b*JAW^TJlG%Q$SVWsL2rHIL!-k?&9%!#RxNFCcM}2$5 z9fLnKl*OLha`wtm^oQ_-Bi*%>cYq=o&7)s&)(<k%pKu(HiJb&l5z~pq(upy?9cV6gT98oPoZuh04l+xn4wyNEy1JWtd}>9F3zcA#b_E@n$<9D~jMt_vS;HN7Nwv$o3FZ{)v1{ zb|s!zSE2_iuHI7@9TpkWvNt2YqN^jH$|S?xl(ngxMX+;?*w`GN1lI{sIuD-Ue@5W& zqZsfWN6J;~nQqVbz!Dh8;3X{dHJMzigiH95mZzg9#~&aMcp|hbxAuA{v+Ev{;jG25 zX?V4oiBM5YdLf^|1MReXe7+T=;H&xgg?N!3!$lEO73;&obTqnIonubo!VO#;FQhgo zGl{>r5=M$-3syEkk#>0c-RH2$vl%HgmF;C3=uGhXtXkV{QYGU-wV9%gWVmgX+mPAH z$-5g4Cjyd2n3gD$&p~XKBNtFHOpy{+MgwEYWEoy)K}LVs%zQworJn-5i=0!F?^ep1UCBNdR1VdCD4ng#f(bn-{6guZMuegm z!yF=wm+TpRz?p&_p0K+3!s8^v>GR4nR}3=Dt7P03H_c1TS+uCJSt}7(Kvx*KH z3weqN${tD@9T`f7Ipaq&HK+>ZI@~lyIaN9dm2zlj0?tJvL4s`0at6AT(kKG$?&vAz zR9vWmv)NEGoUj<~HdcR$*lWdHWI?n+RYVXkV5T8NRJzfkR8BP^l?j*Dt~qM$mFVUT zp)CgyQB`6qAdw7fG13+}OcVqYToLZ~zBCWQ?1e1_bd;vxF)TJlL8WDm#X!P9flwgf zfpUrE`JST5vX4zH$)UkhN1_@1&2xB-A66YA%!->Rd}i%!gxv}gZLFrKk1|Zyriz7u zGUOSl3%cRL;;Ydlvr2M74do>8L_FAzIGQa*=pCUtEG?mwkWL|5FyhTBg6~Ku)lR;Q z+zIt01r}uq^m#-f5F0~?UYh^{DlIZ)yvmloNOR{VZ$zE|fsN|5lR!-lv2Ic7WLQ3~ zaezQ!#Nx;Fs9-o5&eoBw6yQ|V3lw2R<1lT!St$DGpC-BB~5fcb(akOEQ@c ze#8p3aKz~zS|(K>l9*{TQWS-->_kWXE&vQMPEwEg=(Ng3-Kzb_7V_U*ll!IW6yaZ>pefZ z=SndAo-6OUEj(`{Q!>!hvIQHqK#$?WT^~Z$MI}I8%_Qae91jVg&_a2l+MxU!Lnu&dq(1fI*!+ zoW4Y!tsjOO9>XS883!HsZ&6j`sY`WGuG~003r#ADuPO>1gAP1H)&odbV>l0{`r(Bm z13)31ww?nMv!tL)cZe-gopf9bn`70|s1rWcq@y9UYQz=`8P;pWzG`Kbm>9y8G{sR4Bnu;=TN@8hUUAiL+19p6(F3ta|;|T?S=s04_%~i5b zjzPlQ_`>udK2|MSoHz>VoMwT|YInLgs*pva7S_;5X>SbJUD>+m*Wsxlf+`pynmKM- z$&wZ&M?fPhC51poUOP}>5brDjWvm8eDN?JpUmGV2YpWf}aPqtwZM${JQhRkDp~$^~ zKFZhPkRaEUONJvWh_3`Vh-DPSECpDExphIlF5m4aNo2B&|3b9|F0U2FxrCw=YdZ|n zXq%z}9D_tvi9yMYDYFWrK*6X0jaWe!chWlFS3|%Dby$P*OP(ir`VrNM_g$}GA2V=b?mNNwwBuslcT**M@9g`FD|M5py^d2zl7-LKsVK&a*?JA)uWitPOeIPtFbzj} z7DhhZy_is(fxkJP4R0yYfP9zJ1qe;&z?eSH3Tn6 zBCr~!JjWy-tBHev5mF+wk6|=(ZgXU#99C4uSF6L&5jY_I2vsbZ7j zY!NyF2|^T_GqWYCOvg>gr7bwwJE*_0h@$=Y%!OS6pkH2bBl2kZWY{!MZC%w6;HzQ< z3gurUxKg^*p6Y^+?2jWS!!47Z{R8c)Ay`@n=(K>=B~yeO;E*l>iefkgSRtFHCu}X; zqPsuX5098$x+6XlMgaVo)BiA8O2zAp{ADp?9VDG1q`H}MCZu8jm7KZ=shk!e2t&Z@ zdG~Ts-@}cey5~w9g)V3DqL}MsLrc&Asm%C#Ie`SfoJyZ}h#18o#;_5|!=Us=MWSTW zTuX^K03kztFQ!q^aMan+m!4I~>FN@qQV3LHrhBARL7_S>mbwJ(BpXb&a%~mFnKTjq=s`13R7r7dgF&XI2($v5qXy~Ebl@k-rjXHP*koAh z*Gh83a_(T{_48ZGY$f(%A(XATcUWCv(C3td11k%VVkj$wNQo7l%(7mH7MF-=6@iIR zIjHvuqo%QtZ^iydQ@;*EFNPbBMuvy`t^#6?LQn>FNKBx%hU$`aa> zW3)~~My1mmuWB;7$fV+tmD9EB!CW04*-C|W5y!%#!AS~*0;)043g#tE@^Ne?&@LpGb$B>>L z8D%tHDN(x-ZHga{kXQElLos1$3@}*k@v`LnIg`cH-6K_HW+@32vp$8Wj*+OlT-hml zn_>eBcyy0iyMYhwo3_eIFDl|gKPfjfw7G#B7=@I;8H{Wfr=Tgh1TGRw^AsIOCRP9R z4VWN;Q*Kf9cOz;VoHSF#z7>zI;p~)8ulOO0z@5?Yw!P}73f#Q)1OX+r8eJYiV`?T! zH3#HVwHo|$9|_0peMx4v@HfeDM{@`jt5t^!U4y7}5;oh|d9m&IDu515oUuY&>p7z2 z@e2o7I~{U{NJ1YAID+C-|Dv<9v5h>^Ld1#EJFOk>rK=!}|M21w6&|Q<;EFodaPE{x zahrQk6qB?v0z?;0anJON1lNxU4sM1v$k#}agqSNvyb@7l45Nz48>2u_3b$l}HEek< z#e&-Ka4k%QQ92UGxio7v$GI{gA#Zg35%H$2m_dF^?YO}M4ASXrH|o9kF;jyt#^em& z9QZgj#jv$&GB|Yu537hKCAI%!lzX|0&Qx2fh%bY9yC`axrQ#FFfcesoe~a@!WE+E< zV+Cu6T>5rVIMR;scgla+yVL40Asj`qP(dVF5bubS#V02@2T5TmoeV>6h@#$HhyZEYz zR32$-c-NJNhX?9R(h?HzxwrXP^s9p%;(ZW(fh_v^1CWTW7r(D=x3g6<$_q5}< ziJtJ8P#mfADTK&6Je?tQsTz)2r#>*yYQHOto2cXZUKr~=l2qZpFoYl39$(eA|oWv|S)M_8g_wV%hrr~~jD zH1sa0kF-M!MMzk5P*)CBYNhr8wXT2xBPSeNFQMROaDs8HtzH%qi-F7neE*f#p^?fK z@jY1FE?=_#gJFl|B)DE9Cr8k{fQfPtLQyM&$?z*PuzS{bu>WvCz5bzoUWB(DENQm2 z2hKeJ)?4*HMXzyRQ}e*iuW%Dh-CFi+1Q}vL9O~zRIvADGj}|#uRO0pM#u3g_)i-q* z`6C4*NbL-aIEC9ai#WQmMYz5EGKyQ&bsG1Aog+m63g4i=bD~oMWdh8xuntC%+D*5_ z+z1}qzG)+{~Q zF71$hFs#7f$ftU;gNQY{Fpg`>QPmrA-h-Ry%Cnh^a_Y*LP9X+GBlXQoogmozZ6Pnk zN2yhmldAJM4P+paJYH2bA4&*|!nk<7_-VZ*CWVwXQ|I1`>l^v)1$8xCY5@2qgnXw) zCF`)hF<8lP8Yq>?Vr9??|MPMsGc_@k(7cdWJZtVRok)i9qQ4zM@M;dM)5DZ zo8675=a(hSZ~~9MxE3WeX6*3TScIt{s`uS=GjyM3=RVo`;xe{5`s%wBw%mzTm)dga z;v>{)XB~5^@GC09sl&}z{A2h`^DRYntx|taQT^;jIrQf?$CoSC(e9O?(P!_7>x$mD z>$O#t+ayb|-Vx#6uIa{^Hor=wk9wG=rSMG-1Q2wgQPw;|gtaVHsxPA2ls&di-Hzw! zaYw{>bJIj$7@!BAIIpJi*ZFLjfOmY=F_U^lfyisgzsZ)p{eui9BU;vEXaY4CA{sqP zq46@IupX?uqPnAm)7Df6zo!Sk72U?CRzRF-KOxTuV|o6?G)WhwoRb!F>%i3r97M&c znL#oi_NBl29oZgz<<`W?x|j+8W`eSVa7UzC^dtxc(R_I)+y^y8`!0ss zs{zAPA<;aYFlngx{^lZeiwg;rJ!p~dq+umo`r^SnK0yr5Z$CosQAFCuxy?Z^u;~KJHEsiI;s1*(f6!*6%w<- zM-^xJQ%wA!bf^viXlFr%V zW%l`d`5L)gE6A=)^I8k)sp2g7X&Mck>P?rvEdZ?;`%Brr+ zA;Zx(Tu?WSgpvsfzSw}E?c3@C5CEAQO4{*tgkL5jDI1}$~3`KmWzq88`0?&OrAC5f+Uhom})+OqDn3Nrg%!u z3SIXDy!013VU`bG52GTNcj3L^DR6`zopW~g=&!VCDf7(CK8gt5S52IVQ&)E)SEG+a z&Ip&tmr9i5Hh0Bflwc{Dw84#KvM3d(@B^li6h?r8b1Le!Ll4bP^QAND95g9<5Cjx< z-czWgFH0{7f``_p(cFt0o}J02tWGGRpPI5Md_5Ber3h2ek!z_<=sipx z%P*-XN7p8%gAriN~U6xb(R3d+)c;*zD*D z`wb~yOwPp3>do2GMnLKl{NaBZ>u2zP9}OP4YSq}$tB%{F<{LM>8=kf%@xf`|IeO1C zM*sG)Gd>FTJS%(0U(R}?=R0TL`OGQjG&Q8o%`N!w+Xw#hfb))dXz_VhELnH{uA4o4 zLG4*}7dwzj}7<4^P?om1|C)I``V+Zdr2eBNyL#?Jw6oaNUrv z+;RQQ<1Syb?!#ZNnK1IHHGf-k-whkRdhU;Ie&9Ply6d5dKR&ZQapS|^`rwwccN_S# zdFOrk=S$Ao`{&O-yXxoJ30vKo+4L{B9(Cr0zdm7`Ww&in_siRtZZYxB^b614eZg-x zTD#LtSKoW$(x-oWa$&Rkue|-9`=9y7*M7I`-{=4ChiC8b`>8|z@cZUPo$JO9K7ZX! ztL|I({OkKakehS<1D_85=7U>I{KbO@EMN79)9Y{l!`0s|{BiL4ul@1ppN;#|n2-Pd zr_`B8JiN~}BOiHm+GMU($J^_2@>c(d)I7k)lH{M$K;mi=Sc zNjJZ=?yb9Cnm+ohf3E$XgI@mlYe&BP)TyPHTYhu*%R@(R|LU#VzWM6a=k5C1Yghg5 zwZ^rBUT+&Z?e%Tj=Dz-Zn0tNar@#OD-BUk!{epDx#`XX8jW^!>Q^%XD{?Ym7!DD{& z)>r3z^wy`jDR1xey|doAt>KDy&i&C1?`>K<;e#tb-QnYx-}}kO<9>G4zcxSU$WL3h zJ1zX{`MYmCX28si-+%1ljgQ%?bCcrSzi+b7+Y2|nZ~mwOnKO?Vu=!4x47l(4TL(P7 z^W$GWY}%!p9s0=uU)g%VNnaV#(6Z%_6)U&A{-cYw{&Asco9#|sx7~-oZrEYYAFmpC z-W{nO)2pxAv9S3~JD$39#7-w~_uft$KXm0Tw@`y+LaJv=CRb!|iPvX@qm>U@6n=q3Nye$0uN{%YLnm%lu| zY5J;tKj0)Wc8#C(%JLhh%sg_^0T;~Nbn3cmE}VM*4O`VW ze0TJ;6CNEk;}<)wp7qU_c4&BVOzqrZ=UhBDKl`n@HA}|MTQan5Ubg+rd3Vn4oPXGH zE9bv-@)Ha1+3LlGuWt3q!b9(>J?M;^A3x}@1(!DcDIM>9Fst*M+g+Rwx4Arj@TCVH^XGe0$9y{a)nk6M^s&N|59OBE>>sT7Rc_$Q zix#i$y z2Eh&J!f*o2dIv3C?j8~ZYc>mltAPI>wu6l) z{+k3r9lC0~vv&~mj6zR2&~3_Apb6+WA2{!eF}t8u!D!I#UX1+(@VR<;5ESqy#Q0C} zyT4%F_rDwjrvuMRb_6c~dt1=+9jtfeoN$RKaA-GjHfYf7S?)xk05w&4EP1w&A{*P!<=V8 z*DdkcX~6eRtaT6e@eugfg>ffg&mRKDK=At1$>1q?vL9%2Bjn?I;Pdx^$AcJC1DyYb zzuyG@w_wcU;Q!>W1i?Xo{SfGQE$I9p@VWx){{Xxj1|F;iou33xegHbm#_xv%-T?5Y z5wrrR;6d={Ilwp>dpdW&Ah;EO&jTM;0Qa%r`%%E_VXQw8G}#lh8wFkrz-Qk8{-;A; z?!v!+2D&tZURkVnIB>cEIP8dhya`z00IZ39-jDg0fIdILzCHw=gMjb1L61`~|EpNz z57_%|p#3M{!E%hb3~OJDb;g5MlfcVHzz8m&70KDqO=kvhJ)3N`rf*zlQz#TNW5O~)DuR9?RY0&3k z;Pw*c)PV z{sjFI#2~)nVm!&}zQw#yy{O8UPHi)lVsI^{Hri*J+3TE-)wToiLSP@~<_p2{;woEM zWV}($cvQ6wTji6jYyguDo&(UqE>OEg_gU%vz@el&%-w={mYeOTTL72stTMq-m@>86 z6pOC=M)@qY6?a>!0mMU(uK|-i8U1XsaQqbv+sj|eAI4_Se9*rZQZ}rwflZ)^dGY=z z4DJ)EdD;F)7&y;`YQ?7V>+}Yl2JnI_#vkQ>69C6l2IzL7FoJI0;GF~AoVy{@TC;O2h?`ft<1Yk{hcQjWr`onr z^$_=2!3qpItooqJl;;*&)&8VKm^?B}J>|B{`}bM=dl-z_tiHf=0^2EyItieK03Nq5 z#o!wNRYpj=9sh-E$_87x5>uhpPuB+%Zif#zmro~n^V0l>05z?@O;rbFx{jvdbegJz znW03Q)-{8lC^NmWx5ou1YGeU;bHi*$e?P#Etqzv&RlDsKEro``p?J22A6WwXFZuh@ zD#Yg-)6ez|#O*8YgAlVN@^k`R)`aR?a9u>Xb9gO2*?+IwRefSW(shEs(yHii1Pq?K zQMu-0NC`x1S2S*m8jktRGQN$e9@3oZ@6mshy9md)5+KRIcQD!0lMR_nJ~aVHK1ZGn z79m!d;S!Ia%6*n~9`c$vt(A}M*#P7Tk^rJlD1aJ#b)PGj8-gtm(Nw^IohjI-f<0*6 zj>FZdvIu~t#J5tyW_qC1H1}+}NA#<=rnm?oJR@knL_@$UF zF+JVc+(UYy40nwi+kT9kP7Y(^MKv61s!0Q309p)`oxnz(P{uqco7@q2p1J2A~O3?}A?_uOe# zk-fyaOiShfbP1-T7;KId&J#7?F;EQH!iTFBVCUFjL^7I#FmZv)A!bNy=@8dZ!z)rl zT(qwYCd4ZSD*@8;I+m2&wHwP*UfgK^V@#doW8?Q_lDL>^O@dNh#R!PsDFzde3VWW% zU)!*b%4b5_YT9%XKzRz_gEHJFL965Q69Dln2vyBE4wBj=O1^d(PxKt7dy)~KF5*N9 z%vNcEbOjQ3Pfz*+;mfNVnS2Z|UU>J}z${bgbQ&b+frMp)2`C468WRU=$m|Q-S(xVK zo-&Q$9WAIKu&V^OV9ID$v^d4KM7KF^z49j#yZ<*Pc~KB26@k0&u&rdcB%6!!$s%_} z(~sWY0PqMG@FDQ0O&B&e z%79(B_iqdz=K3Ydo!zf5d1Fw28DRnfG3Sy`6HQL^8L?D`8+#uQekjK-6K=-vY1TdT zH{949f-gCN>ze>Gl(20)?@KN}lSFA-)Q2Xl-%zuf*?loM0F!s|C%d~j1s{(w8c2)j zhgQq*Z^nm=%3bn5h-p*SZyJft_%MzC(vuVspVDscjf&UQ^#hRuDcY2PNw;*mMF#)b zU@3qc`PqQX1`c_|h$;N-3xvdwEXL3Mb;tBy(i9rqpgvOgxWZ~{$0NJarP0mr1x`UH3a9&>neYv$G zMN_C!lJ_jY%1jv-?v6^49ab*Q_Omz$gS?5LxuvH7u20rma1v@TYLjN?jO?xIPzP8M zPI5vUf`8K|kmUiRtFkiF0%?eQbkKk)N;x@Yx)OL63Pc@5QM(n*nd{JLFe2y;?#495 z#7fhAQLhfV+ks08$Vsgp9mN?tfxftr^A->6zTh4ZR12pMw|U?@bbL zF?NEaYi&S+5n2`v1-TEl806+>U~s|=wrHkj*-6(Hr7z9L9vD@hiC|mbcZt5Q~;kBSGxP5 z#bCA~6Ur%d)L;j>{sxmPJpfn=R$y8r?EW+n2w#5B!SF?9FZ|oB@A=g)DO8X=)DkIP zxDlBD`SmUyalqvUWcUyV?fCG8*jou|)(ZYf^nC+{4>f4dS6q{btqq}>5F!W0(2MVe zbGPw!D03GkB-9Pz9d(jJNj+gbC43e#uQ`|+SpuIJ{Y~|;cocvlLGuCm>?mTF)~dFD z%|YECXzZNSoNdr(Wc2%(+G2Ly_f#56@vcVf{gAbqo0yahzTSuk`~^ znTK-#*5ToX<5kYX(*e>Uy9=^9*{{N+C?0YCB ztpsUjphoM&5?zvaASzFHBc}Nn7P%XL6?a&r6^_T$h;jZ@(tjb8e?~A{h1cf5CKG%Q zlOlg#c@mjuI!?b`ZMb0_leMG4OdbazJQ?YzjSIcC*<(|5f zfo4p>sEG-hyGS;88PlUsOMI%CPRm|>Vgfg7qKVDela!|gZ9&s_(WXLw2qs1n*sO9G z8c3N~DH%E&6Cwu0C)j+|XwthFeo<)TsC>L{5p!7BBuh4}q8>KklZ>JnCubRn+mg_!9-tam0LLF|6$XZSKL8NMcC^ONN`KmK$&?pZ{(Pn>IIh)!rNtKOg-dKmU#Yph7{5pkG8RaUg}yCR#64uU<5SlNkg1ucmok*)NrfpNn+6GJ1R_Gwj# zGrV^h*?50=IcdL&%Wjc{^auOVS~1{$+=OH{rjDJDsKq8_eulLSbxW4)7|FWwcs3>` z{lJ^*a0~{^r5h91*b}Yv7*uFBY>McfuT|!x=4^mV(B#?jwd8!}0JH#RKY~G{`x_L$ zQt$~TjSyoR|HwFUsb0vT-n4yi=Z__DsZi2Vq_Omg_;r&{e-U(+MHu%P17@!3RFYnv zb&_jC!s9`Z$iV1_v) z^2KAi!hw26`$vCElnph7dj!P@AQM~;K(jUk5HXUlE)HtRc#y6#C|XH6DpoRCB%r61 z$Yz^;LAw4YEdqcN0Az!GFkxc#2}OhmQiiHbha=W^I#-ms1&a|<^(zFYVfvWLt2cn2 z_F%@WJ`?_`C-@nrP1&$%D^*~?8@Kvm9&QU)VU)iz<&N}~;#@{u7GaEGL462NQ!8U* zjW)^1&|NGRkH38&r|kz1P#FjXqx!^w6JaGQPpo7eUc>OcDi8Oo4Lk0y#E*h475-%i z(iv#+(3OtJs31)Qf1ksiCSVfy=}z*g=_;L+C#awcF%A5*)8fYlqUL5rTI0BR_#r?n z=nI5B3J~?T_srzq=0bt-YsKJkfSlGhNba1aY1UpuB?U9r|4zdF^20wr7*lsC$FqP1 zp!3zKCx;p4I6D(OiU|;z>Jw&SLw5KJ7(TwQ;XaGqk*{Maq`LY_hNWbuOSIa_sMqv8 zvHT9AKi(SU5`ZQB4}BX?4f8+015^5xNFvP2tavby10Ten0b;KID}Pn@Gh68NwNMUf zd6e}wz%{y4;yU7f7Uy_1pd+UAqctv2Un;7B%x(xsQqf$BuY5+$t$z<7C%BmOwe`3p zJ%Y(_qt!)_8B9(IAHSg?r^ z{Ur_mYTyi*Upf;v7Gb%7&ea?sA#Vm4;87inue0Tq#T5Vm1*i_d&mbxV%{Kr9*tWhP zB-A`gZM+ox9+P1?s!yiQmZMz^Uc^LrYXP z0wjbpvM0Yo^a?N_V)@OB4t3sXS-VNnByeZ4@D=~Bi%y*bVi1MU@ zF#wT_gJ62bbj+4h7J`xH9IgdZMsrFLzqF@B6g6{nMmcB$E^>LU9TM_WOxmmRB;Rs9 zi-EPaQ03puCdBv-dS^gG?F2v375`x`b`U_hv6TwQ_W)>^)W78L$d5Oc!O+RgM(*?- z44&HeVA7Bg4zGD-aOBUNu^sH;1#99_4C-cre|-V*H^abP(p-Bq*#QtE`U2rwi`5vu zsITGnGvgs8;WKf)tWTgm=kEsKNp>>t4za>wszl55cLRj5;ye7!;c{d!AzrmB_tx=> z%7GwmZ?GRGkB(0^MFy6#=u!lAo4A~fNfWD0k`$8{)|jAB6?$U{+#{GiDL$QUy({)T zh-&NKGkZM&5b-Yc#TeccqD9TAs!shJ6mH8gs8r~D97E^Dhx!cg8Ae&7e#^b2BBCkk zvd!9WY(N3vvjJp$$8DHe!d(D0^|OJprtnVy(zGE!{LS0#Qnal@`wPG>DhEpiHlbFz zIiZ!M;*(D-mC=8$03{2MA_meltpn#GK#K#WeJm(hHFY>!UnRb@AAiEcGEo=9DnXn0 zXUZ%UfM;i!VB&!lL`}4nNK(A&;UM_^gsh6K2+Bpb69B@|^=)mro~|~udu1nVblEV? zGEyCUdkZh_luCKLbAxAP)f+kCaJ-XOXj6UX@^~i`Z=Ch4y#ltXfz9e^6C#dZm3mFYX$Vc;M+myU#;ipXL-ggz&dNM z*RSRg$DU#e%Lx=b7N5f_Z;4a}@9UHbIX+m1uA+Fiu54P$?pD3hh*mYaS!=EZVDW&E zyKC+atG4C}cy23?m(KA1FCGfRB=m03u<=+wK9cABh!`lvEdwsz22u#};U7HOTRSg$ z@dvcX;kh2$6&;HZPKr-HEyv&J$ksqw;Vn44Qj8r*Ls{aOQ#41Dvpk-LQ|%D(h7sQL zN@S&xB?yS&>N$UR7TPdWLD(UQ5&-TMOXi)~S@o21IH?K*tlX96j&qt+F^pyQ0aa!f z&=@I?N2Rp6oeGE zz}-$JC5ju~6l!K##Sx8elsC5)!Ng=sv!HM-_(dX{z+0Z#QtY?f6B>@9HFsAQ&tBsn z=(}sB34Nu|#TreXu=7L;FJi0Cy)hWWGFi0eNJEF&G@km6RvHB5nX6=Y=sd`0S8E>P zNoz(k)!|74A2`FaiG1iw!Rb?`l=_-CCP#w%pg22tXhR8fwS^UJ2TRmo*oE2iAg$ea zZ`Kn5^=V#NFT-4A$tk~DLh>L72$nCVb1)9cupMHe?4%N`zFmpm-VG`P~TfTlAs-{3|&UrIs0ybcGDYby-7VIm|#F<`InPa4jvpP9*5m zC!w6-7amQ+W+20S#I1l0b|{h6uiU|xh%37}tgs8Mop|IA55vM~i9a;l%HzFOyhohp zQ*S_5*>b!Ui6_+PL9{p)56+d^+3R-}>5Hj3_H0tVposppsg7c{7SG@D6Sk32l4%qU zn$?1*&C@_QYqeQ91E_s6yn+t|#wE)rF&oTl=gw^yJE0{;F*=1uH{oT_)xy_?M1_uQ z5(OxYM7s<=WDPpH3P^oXvS}xWotCCtpXNi}!&fY5R{dEuon}$_(=g^bNlY2+aM%e+U8Vu**RBMK)V!-5)BwAjwKl^kUo*$RcOLl z(o{tu3|z62uq2)`COCcox9*y6Pc5BYC&M&2ros&|KM{*KgAakK_sa3oU<%JW;;qFl zU#IE(n%a(T6zWOD@ zDb7CfI;2x3#^MDLRNj@uj}s>x;n{Y`o_?3QGmjP{#db&j@Dj4Omc`tLq1a@!Zc??* zxHjCtNpQZobPuSF{tyfk1V8m|EIhjQ4Nwz2|C#M<>FC8vx?lv%-t3+n29Q|F5XEwV zNV+i7!!Yb9_-2y=xKVgEyez(!KdM z=Mgn%mefScGgPFIrQamxI6i7i)# zqDIM&3SDR|x)2FeFf>rXLaqma0&vy7A(j|nLQ$(rSQTV4f zX}}b7;0Yg9&qDz8V6`rUAzDirJ_KAQhm1Ro6gs%tltWGT`nOv1g{Yt`^MxY9P&QZ5 zL$xVv1e@4kz~OY4Vze*p6GJ1TO&QpLjH%7{&q!NbGl3rBUd&=eS^+Ch_CctE-i)Ok^G|wzC2XF>{{2SStYKZnSV#j*=V4SRa)3u;p2_hA`fS&+ z_|aibE$xBQy0#vC2rnxtW%q;-tgVL)36y}@xK9P0ooGRZ_R|RR07lSBCT8S{wDnLX z%z_<+gvCNZhJV@2d~^fjJk!83-`&k;@9}Q8Ds}Xr)pED!33}Av@m^}DYIc;))@32i zJt=ID>RJUwcuHiZ`9hb@l6|s4VVPM}$%9EFhku$Xkfg;;^Ad9wEoyAm3dP3n-WHox zx12_lHR!Kt5m+Khh9`#SaV#At=#!72Oo0@f=4EF-);?-kn=} zE9ptIBc+kNv9f%xA1OPX6h4)Tjw_UEWdl(e0=gu_I8--4t(gprvWd1FxD6l&3IUC^eUu_uFwqRx z0~#U>UXm;Jz(_QgdNR3ut%(3Zlon7IJnvb13&^e13dDjUAbU}zL$Ssv5TP9!86305 zKu>II3XOabDByFjQ6>Splncq?RxE;d_Las$kND8N=!1G8AIe>(y#U>nO~YC#0!4a3 zcG;AT4h&5@(0G;70^iJ>4bp~yI|ctnfkNcNEkosv(nN@L=h5c8r9~10Z5Op~(F#n| zB~;RZq*LHTdT;QHf>(=LGF(djDY+(z&>35m2WiEkx@wf}q5YS#Fp-(4o7R)-$S50X zN|M-t!5s1rO$Ap<%5+%^&kdVOkr@njT9RQE)F-uM#oeNjFVMK!WR)_+mrjO5HAE|` zO1L3Q#M)R2)u+Xj(=5_jg`x!90zq-72lAXMbkLc5Mn|Scjv8uQV;v z(w0U>1C~GupfA{88ZYWI*b-qZ=9d>zs)H&%HDW7NLoW}Aqo{Xy^G5xZlQfQM4HM}f z(ujJD+JLHkqr^tzt2}w7;k1Fs7PCm%cnl!3frRV@QevxxG{vgg6d8pGcq43*63wn2 ziaFYBq?RLc#E*m@1#UTb_qJ5J7d<A$$X)0lo?nIYc!|gl5aCEF`eNe2%8oVHjXh&S2T-?#D;ai zC6aO3CyTYpyBPk-@yp~zazro+ITHLNgK&~{l-L1y&86n~e{7O2a5+MSt`wqa)Oe2w z_v~jnjwy73QB%m8BeMhJkFk7MzagWOiCLZfJ=m#Tx01Z%+<4BV#1 zl9%YIHm?kxW1!RQ(LyJNk$X+o|FEdg>e00+sl@(4!O4|JX|wDX_S!n~Ev)T0(}!1{ z&P5oPxkE=+AF7t==xM8iWpIE`=zE3|?x+Iqp;b*uEMc{hJP;xoDIvy1?MQT0F{zlC z1dU7_uQahvh<1EJ_Rq?tDm>$3u8zOZr5%D$lz~$cOY7>=9obX?pVX!Ke|2of#~(V5 z*m84P5}p&%4%&i#RCzGEAL})~ehr;Z52JG+E5@q!1GA>Wdyz$$uY8)Om;!DTs@bVh zQSQhUdYk`8IJ2yz!8BRn@e@5(-sJ`mGPjkS5-ZqY zhW4T~UHQ6vxAH8G9Rj+LQ?)a+^)iV+-6J+hGc0FUl89BTjPKpgq+C=Fr*nbjOolZx zi-;s5RpvVAq@;YZMUCyPh8QDkj51=s@(Q%bI;LZC3IQQfU477p9S#M}r;_32R_G((a9VVkZ3XnEQAF~0i+GYC z6%e=ux^cH$;}#>-o=`Rukz-yF1(tMCMI?75FhQ^$ZX6<}@kfMKTh3(F$;8Q_xl0iD z-_(u{Okrd~)*)lZxgnPT0nqMtRyLb4>>D{FqBAzA&W@cbf;q)k20kgx4ToX7!*vsT z{x}NM3kS_+b=kTq2^UNOKrMTJ=t+v`Y$Pj@HL2gY=?3#2v+Lck)j&$LjE$+r%* z3|o0L-d0K6sCnJl5^p^qlp^tT0lJE>Qf3d8B%rsrt=v z^KhwMxgxGpu(YBN1k_Zg9P2=&%tTj&6h*--LfuF8$Wydb0hVT)J!Nq5v66?{%=!N@ zxX_R!jvEX5D6506ioC1i2)+>^e}@z(BrEBB$ooi&lQG3N`9m^XumnjTYEaqMR`>}N z0hM7#wuL++w;X~UrLwea5Y$MY@rgMHAsRX$8*X$^*?mv6F#(-Mb3Ep%z{Q84=S(VycGqEUwwk~$>Na~*reF7a=e)6pJ2#$afzw-O?@Njddt zRcDyoTvz3)n$BdnM@1NB{={&?qB5@2#b~|MmnkfE%K3;+jah7y4?}0?`d7s{4aCM& z&4eW+Kx8ue+YePwU%DIVf+97mQ4$>@!^xEf8zS_#XcCs+L7QutsT0G!T`I`V`Xj<| zfTpwtl;}o}Px0aZFWKqA^QeafCF|M>yWUk<%S8*o6IgGXaTfC#XnZT982BNSO54$m z6%{|Q!vrG|NGqOd`HwCgi2T?wZot& z0+P$SH`%(W^Eu5moj_ehh+1rPy6r&Q(}Bi8(Fg-?(QE{^ay5y5$w4+UShhNf8ZO6z^dWS#oRG6?}Oq6Ws8%Ku8#Xy_wm*W!*MzO!#HOphd0ab2@% zX1}9Jj7%0N=$Zxc0LM1qIEvgJ7t3EPLKF&na>bqV(hBZ3uwpvC`ZVR+7{(Rytg$O^ z!qlKE3m-hD8Ofm({K~heOMmWpDN$@QY70jrDI}4J1TtbTN{w(TQr@JZAt8yv9hrwP zo<0$ccu^w6bz0s>Q28Ph1vQrg9Fpn`lU_=dX1JuDZqCcf0i4O3RT!njEkHX2O%!I5phS2$P;rtsKsQ0! za#hARM5wJ0N|}*5oKt}~aEl7E$?#O>A10P`at4uc8VoN)_+N{DS2$=0j~PnvcAA_T zMwNd_>%KTynbC|UzHx(Y&mwFl77T{}j@~Py|L_R9I8(W#^ zB0g1FwNK?)!YbU!+z|d&zLH>~`?!!i8a71nG@Lg|xS${+`8FPG+v5^MGzbzHUpQZs zFhv6z2lAX#^l_viBvKFKlcbgcLv1V(H6PUEg%)*LS_W!Iofcj`VSt14b#)Vmm{dJ#LP(;?y8!MDV(ZUxxGWB{AeM%fWLC zJts^xY!M;-&%%6AvsX`ckjJ-mSi{JN!^{w=mf7uT>4${NQC3)^xDT5FJFCkslHNmN zoM{uo+WKx@>2fp*_bFlCQ#jp9#U@V-za7%TdFi7ZcKcw>p^+SRD|;sFHn=EtR2K)R zO8SlpE@k%M#=klS2Ln@ZxvAwT+=bJ5Ak4S|#draV$>R6K@Tcn~sY1X15D`7g#4P@K z2agbV6bm`K>+o;FnK%CoOm4kUqME+ybbhrY^JQ-|25COju>ro*N} zNdd;y6tPHPMF9tdb5S*(>wo&U;GWX_bKTft+P3-bfNTv9NT0yhHtbp?nb)=|j z*Z6)2f+)oYJ6Y0B_Z!gieK7}!@~~=}2n4>vS7yGIdVy?0YHRR${m=xAqzz(Ig@I1T z_9UQ4I_>p94JH|Gw@~rU2{>S^$5|>^DT?A+9Ld@$AijAc-)2SNwBLqILz1K~J@d=V z<2PigGjHsM%#)j9SnWVN%Q8y19A}irZ89nnb}bAc>kef+hg7PYS$>oa=ERN@%h?IK zbVL0pk*=Uw8R_Z5aYh;{e0=3yxJz5^e9on#UCZjAVbZQ{Wn?fUW3bX)_$gVO*U8D@ zWCj1_oSF2f=tg}#PfQ1E&(7zu<7h9wHCnTKlpQ+NF684nPuNL5MhJu~KrRjIPt?&{ zq$Qr8td0ZjrNIT57ykj=QRQOHjkvzOc+hJj0yprY4nIe61U`d`9@0m zEU~ziY=&NhscLo6f@Sw@$C6+smq3onFQ#SW8`?rGnp9P+kE)gsqU7R=*V`-1=)t{g zRBbW7uM6mg`9MH_%UzBU)(dY%UYy zFjTL68KZKi&QD_a$`PwI%N<@5<3>ZHiyyk6#1%y=6Z(!ja(a~eSwoD(zQ3#OgBcP! z1k+V-Rn;~dSR7qi(gb5r=6>fK-vCCj9A6y3p*Js90iZEgIsI@0ehKnXD9ks0!hKZ< zz&(<7a~cC6swhYIL{AqdE$cFS-E*x#hGR_ux8D=rieCOZ%9v(}CEs_b75a4`}_XEf&9sikwR?x{_GOR;P zS(~V9MiDQCv&?KU+!}ni$$JTz^-sV9ZxSn=ct5u zD}Waout&zoz}7jWfo#u=ZBu2Ws7!m6U44&7Rulf)lOA=h`C62WR?s|Sw-`x9^o{D9 zsS>dOBHIf#dJpxZp&cDZph6dA->uw z*JdOKw%-cT#c#@k$r0-oM2e|U|NKbtvgZFsE9u+JfN-Hm&s$mIm$qp( z2madXhg(9~)Cr0V7+dLUxL~AwX^ZA6=O}_PyuS*e-7aG&Vy^cfv!ke`Pc}ohx|IBa z_mu{UsemmohsDZr7-NkR3Z$eB=h29e00B9!x_t@<>qSxe`<*bdZ5v=jB7bc4!yZVH zF1lV&(ah{ky)#0uA}^b5z>&gU(z+Rcrq0>Uv^6JvQC3vW-MzI+64c`oNI}_a*iGmT z?Kk7gh(LKmKI=%=PEuJ9J{2no&@3%DRzYrbDHc`U!co*Z49m=2!6OHA&{_8=01=Vh0zLxV56_!n<(dC9FWCN8<>?P05r zUhsp}h4If^y7vRGUs}5J_{$P)n|=4K&BlNCwa$ji*UUZfs^@xtc=gDk*IfOpXV?Dl zl$~F>=Jcs^uRZRTCD%T3@vYbXa@_;h4f)C)*WWzu@-^!|{Pmg%BcEFHw>9_Ou+gjM z{^;fhzVoBI9-8>$GwTyKKK!i@ZaI6mfj^sf-j{#Aex9AM)vcLL|8nb5 zXI}X06Si4)+ZJ`dynX2w6YosF@a)|e{C1ELfZxW&X@Jb1wJ zRew0W{`Nmy{q4dZ2cQ4iACLaoxIc~g`0sy8oq5E=`&={fkw?e<*CRiDap0pHt=#|7 zS-qb;x^MTy$1i^DyO00z^5R{@mw2dH0j&rv7`! z=OuLuCKjz)$d+wTs!FXwxQEr-?nY;>+grT*LQyU`>)?U z^@Gz&&gu6XC%AKmcY zro|IJxbo8-K7RSVpL{&-XIK4e^Mj83v~|1F!oQxs`^IAi%-s0>$1dLZn5{ZDDbD@- zCi}d-aMSzdj~b9U^N0bP?{vw4`<}mbz|%WF{^i4_UAoz!pB(U&tp}X+l_3o+TMk*V za?9&Kx@hYk7n-)&?&NjbefaB!9p?P;s)6U-k=il6`l=lZo8PqKsY^%fbnYj zSMGBAlzVr5zpi`tUp#f*?%OQCZTFf?-5y)L`+VY*+dfKM@xnQSZf?JO&@)p%9kgob z>3a=(W|N_NPnl8k$6em2`SIVkAO8GxCl9}E(hVbC+hfy_7jFGQ?TxoTQuo-ygOXR* zHY6{5Y4xbi=U0zj@{jGuoOtQ4#;tz&%j27-uiE#6?tv3t|I@08w;g`V#B18y_WxZvJfQwh!;h?wsDX z?Ts7fw|zP<-Tv}HC$*n?;t$&Qzi)PK^>;EyXCIu>@!kisI={Ky#rbfX%ku|cdf+jC zzBhHur=wpz<~K_pD?Is7Zh6iA!HQqy2Clql@#@|S1`Rwedv5D-`#*K;@#p;GH^;Af zs_ld??Rv)vpS&~tq;)$4!PQ%%!R1~-@YJ?Ja05C^oPstW8-FPX77q@B<6$TA+Xum) zM+Cu2{CPMT1V!|#djjKt4Qb5S)lLUcua{!0oX?LGb&5LGTEAm2dpjAb0_D z-UlrHXUNWYE*0zkAB=6n+EXy*B&>Y_*1HV*7>d1KUlRoBx**so5d^Pd&3eGtX7eEE z#Mry=Su0?@gI+mz4+(-bn+3sD!2b{1!NwE+O@g3qUwpoI5cG^fi#yP5%2uEW=r|uZ z?~5_Jpu@vx(C%K0{RQy3dUy~N@F&FhPw>0HVBPn>90aEW&r5a$F93U6(DNOvcP6?U zx1qhkp1|V`{CooFe=cZrF5sVxJspm|X$nb>m*Yww3K zy@2sF#?8W7&+icg?~MV!K)V_E{e7784CuNgK06Kg-ifvD!9E@WAGTsId=Gs7KJa)DV`_l&zwq~)!2cGEc^v$o{FNX$2(TXl9j^tQ9|T@k zVErF}cf-Jg)u8i};K>g_huQf3aKIY?{xpJC02Mq49z6#bCu2|N?iU2N;_rFj!wTR& z7JNSncs-2u2ZAPhf_9_8ivjrT8^Hf`$je>$_s>9=X3#5(^$rJ47XXJHv5z+aD;$6| zvCsQ4{}RyWC)n4Az;h7r{Wj=v3g&+mYy1Iw-wm|?1Uy)dF_&TOYq8FF&}tHR*$8-V z0q#=JZ(AUK3UK~8X!kBYtHa-&n?TkeUz4!jPXVhJ^Z$swPKGQj$KH3t-UfhIz4&|{ zczHVZ&t~GEguop%xDa^P0=G1`)gYmnqLC0p`cNcWy3E=QIz`X}+ zKMhzdv(P_F9&$JD{qhlP|8-Z;Iv8J%2Tj}5Ip%VxKm5pG;?~k%G6aF^~!mJw8rM_GI)c&cg94 zF>Eh?Eq~ZNY@GcC{(^zS`Wnbr@y!GL!y)Q@LNyQV=P+=d3)PBE<;U_3It}0jSB&=v z_z3`xsSMC9^yVrd7Hzk52{RgZlP7}Pdb+A zE>_qtw`HE=&*I-_!?4ck3p^*ZC_^B$;N!^)0X%MBiou@&s*I3!JN|>)l#MPBm6!^( zHixH(Oz`mLGrB#T}C$H1+xP1U|+noC##B7N?)xq6PsJ;c) zMU*>->*ACB=fhpqCkCcn4efj(7y)POsT-ARzS7e)oCImy7WF@qx4}&pz5=FtNOP*c zN1uJgz`maUFHH8Nb3-PRPffs)xMhQth#h9Q#3QJ3pJkngJZ?^FRLnY!v!ISYWM#J56I7w?xa2cX#+qP$balK|lvL9<8KF^@tB z=miC4kn}P1O$(`DOfQ>Xl5n&aEiv*P1)ztx$Zsf6S67NL;5i0s)q%4~!V1U(o4K$% z$uihf{;OAs9D7%mVr>;ni+S5~hGKCd;_ce%%a9aghv}}G2?inH^o+E>X^F)A9#SqN znlarIIWanEh_!71z|gX&y`5piYnbTydf!@AYZ|c+;`llK{#KK{6Csg?~Cb9bon{$<__F^O-Z4= ziV=`dz8KsI0G{XZ*EXyxf)*yEt)@-GkU4t_;Da*UCqb*@(*_`(1)-`L6(gys^3)Vx zyC^C2L|0?FCmHeSB2JXRY?Y2oXCguN^rSBkzP!4T$qvY|z3}d{fmx=~X$Bdzdf6Zk zu%5=m!5T9A!u9~BdAX-dV|d40+z{ARf)6ldv@2SiVmq|k9JgK>AV~ryqLSoAL7Y?s z?tX(KD;X}yZo}k7?uw>yc~C<8W~&j|c<3`Ykg+n<3j4*yk%(>*#gv5zHBff+( z5QZCj9}j*g$1W32!SHG8Kit?Hf-gCN>+=9Jl(20)?@KN}lSFCz1UR^UL(OVt_r+je zOy0$x?Cz!qACEB_NQ>!*R?F~jroxQMUGo18)26K7G!mWhVH*FHph3EpE*%8hw08(ah+M}9USv$3%}Vnj-#FAx$#vKT|dco&wK^Vya#zRlvh`Cz!J z&jzd!c=mt{BnH`JNH7r~KO=sNut63*EU+E`>ys(25Kxtv6H`EFyh%kC?yd!pz53eZ z95tysco+lc^)=9!TRT!Tg(@X^&jPH>4yQK{L8ZtJE0<>bSsa8x-bB#c(qa^s`y{Oe zC!t0GlcdozBYUel)PWxWSdtUk5d53Ag)9#kU6qxY7R&&UA`JUqFhwaRr%YD@&q9Hy zgD7gZqB(ONIt@kyy+JE#*oujjrum{?9mq`pvYSEI7zM)T4ylf>V894>fGNh9{ZQ#` zr?Kr&FrVQMr{5sONF5(7N>CfC5NCBq&DS1b7FA)tX`ake-QA z3jaS1D$#pT_&Inn{{9Ch46_p?U26k^jL@>^Z%7;1r8hsP21%?LY~7f@t3k1b z*_3DqjdX`H)>HtW7o%`o5>bj4gV~BqD5q3C&Rino`WsBH^Z;NfI2_X=VfUwrHu&;; z28J&(d*R=1eb29cNuh$|VQrdm1y4QrFP4rM!TGgFknB*}D<&i~48l9=Buz4@C#Q(Mfg`<_Ze zDc;qHy&tmnRZHT*{UPhKj4z2kLSjS7Vu>R8DZO(7CyNo){3-tS{h;j#OjEv^PNjSr z*(}U9mB0QfOP2!Rq{^EVK^APfwe(1x(#E$dgRODw-t>6@EK{ilw`o(MV$cMzDnu*a z==$NcOoh8H$X@}ZiX+NFvdUMUJDb{HB@+BMfQ_!aZ7KhzVMF3aS+n-`XyumF{Mv!Z z;G~hQYlzB?e=#^0U>zR1VAqdUpH|0f{Qy+vVLeXm9Ug8tUgbQz79bt6yCAER{TWP( zf)G>O>nq|LvX2g(DJcvQ71PL?e!U52d7)AnkN(v`(xY{20@tXwIMRMof=lSY)%S5397o zmvEaWVw^vfBDN5FnGwuZ;k7xi$pj-YDRP{ZC($P`9ONm-an*(!)-hQ-8qB0mF9sWp zchts(UU|3#1+Fa^2LKMy8KaoUlzZw@2AVMiqb4S3?jqUXEKH9=E%B*lIxTzkiMP8G zo3STS%uE$DeHU#i^x?ja1U9Q2h6YmhTPYbj6cZu_#3$H%)i~xqWB5g(5ySHFzD3Mo zVUsM`w2Co86F$i(nlYZ4tw_-g2FukX4Oky$mKr#9<0mS<#sK5F9fw#^Jre zWtg~!5i2{a6JZfPi>&oLgOicQLH`U=73>HF~GXZ;|wdVn-&}`Tg z(LG6 zV+mX;l(ZCS{Q4ODy2+=%2s*D-Fzz!3jL{X1R3+(c03ezv>z>X6*h9Vuu-qW83cA2I zsz=$v1un{BFr^U^TqS|@vx{Rfd6!0zgoLMacr~g>a9c7y)F0JppLe zh5#Z)G<4h&1;K*)7eI}!42o8gj*68`776GnC9-*Z21wWcq(uNw0)TArFHD$NeFENDY-dxBqM+LR5Owo(NKym2dM za#LniWt6`%<&N}~;#@{u7GaEGL2Wi0ic%RHYqTX?x7�b31^Htqg>MQGMbGb6_Pa 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�UPvY;HP*p@OT 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

wwV?$0{+w101adL@k8FJWqfAGEwXJ?DaQEu7v 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 z

~)w%BMfV|G(IswFx~H^T-ERuX<#FV@dCTprOVLMSbc5j|X?pV7|9my6Y6I!Lic zvYBkf8KzgFz1^f{RO*Y(9NiU%uZmeOLfOGDeS6aaDY$G&>`o0i87iZxzMQNj%FIY%>e*gT9ELa>{k0}K$7mrCbP=HoQ zCGj3Z`j{}YND&BC8lmyizKn3UAwkS=8awhV147 zQ&dGf%0--D#5G5iuzwD(8}q%^SaY8dO>99x;}*nhM`g)oH7X%yz$hVZ{Hj3RR=b_B!s@o07k65X+V8e}zuWZvZrk^} zjo-PRv;ThIB~F239PgKp~&x~)I#w*Ii&`onJP54){D z?6&@}+xo+9>kqrFKkT;tu-kgdpB5z^bzA?a+xkb{)<5dD{?TKp4du2YD-C%&FEJZ7 z4yj2;c>LA&^-7bN4`t(M?Hhb0X^GECvC~&t);3~anDix!gwfq{E1&eM!8FikFb#yt zi@oWG)i?9X7Lm5)tWe#{cnXYk1??oZ((4ICFLyKCa;OWFcS{6uzDo!vmsyj++Jhav zI>J@M7uNA@JhAP#?QV@a_I5Sxu$8%HmO|PQ`fkI8`sA{+eN9SZOJ@=xcG9R#SBWuK zzC6-x-BZaD^u21QCv#l3sB(v`QR;l640b%53|KbFp_gZ$-AzvE zeylgQpW~f*+F|H9$PqNd(*!%i*PGeJMEd^mWw|YI&t@p+#D@Y2XQjy}yvp4m)OOZl zY&>ALm>jR)ZRYcn)u*qs+vXJedf4P(y+P1<7!P;=j+5`R24q|UuDPH6e+lAPov>_i5IWILNKYRj0yMa zYRJi{I~?c>(b#V<;S45=-v;4au5(0mA<%wgiDuPu>Z(C8v`lw)!>^Y=aI$|377C&< z+3TcFq>5$MXvZ5gQ?BVJmtfSh*)4W(Wd5@yZT)6_0^4KRAj@L(%)l#SsE%kbi6lV3 zuckNh2;t+}v`u4A^^7HvMlb2g0!%lN`ryLoiBX!^HTKM#u(Yd1%1JS6(R2B0egiykh0dSqKvrHnB6em2JrUi8IdUuG!q31!Pj6i6fK z$K!HBKpr(4Tri!NKxS%eo_xXq%JTcVnk&vEX&!S_@So2W>ytQ#^dtNEixShg0>lg- zVcA^G?=TpYwltMvhQVlktK)|Fr4ksie$xoezU8AjI~N2+6`$f%qY)DL+{Eey<;Z1NSDG?VRijUO_CP+sUix97P(FE^j`=P0e~^JRl=?DGnn1 zIfW!65g;er$0wW_;$%`fRh|GF^Moh$vjuKIli;l;>N?xoDV|D!pklAFm||k6>6Ghht+0Hi>h|l0<&pWtwR&J9S$i zNZYJ%Wmk(hBU9E*{P^Km00@uE*$*|#f3h^ap^l>DB=o@_VM8#CU&tCm3Ae`l%f1S-Q z^j3}_=Ey)8TT<~C7b0N`5qZhv_F)A_$CU4J1sE{l{(O z1^y{cQ}D#7XNfQN=64(;sYbsKiQwRH0Od0&R+*K2bP4$(G>yQ^xjmxt|0#R_Cbx1N zTTq{9qpP}ic3;HAM5JAIS5DhykJD8>Z~t*9Q_4)0m6AqM+Rpy;?;HT+B>_;fFuZlyw~_@3pzy1$k3ge{|46xi`+ikW4~SeM12)IkWB~Cp}u-KF7-E?6l(R~ z{#JS+jgO&TJaQ`t@gY@!hNCBmkIn@mxR*A`=+IUVsCslI>EX}NPQavPmjHGS2vyg! z`L6#!6D}`-W~?@E1mKRt{^7bjZ_sfsXV}Sr*TTkb&+F&I?CpAs76RS@+h@FoJo$8K z?0kU4G<<&q6HA{+&m{d1TlNceYJj@VEtu25a*0vp6VueLdirrGzawe#2JLy&UFiIp)V4*{jT8 zCMt~|yx@$RnPFfjTH|~DiiQ=+z%O(h{4f;80}SxXjR?vQ#pEYC8Ue`6Q&#AuT-SG~HkgI5T}-%C@WHBR1z;fVPj zYrl|kWpd~YX0P@bjx4|2@Cg9n2ldEXzuM#A=7>_o@OOi;mo%=Fkt-b(!x-_^_J>{e z9foG`h=AOq#d^0m@E<<7d<{z;M&2A*wKqp%H%AeHYSEvX8ze6}jVdv^TFm}f!GF`6 z+)GCxyFu38Zkpn(r}IQ=ijntUa~9*IzI;yoEYAn30|mN&x>)*em8Mx%Npk9u|3EZZ?^2G)vcg!RjRK^mXJT1p>ANqd~D{lhaqSf%a6 zn{W7OSs=x(rOmCiMdhv!c6u#GBl$agY^|fPIxfl$LgnP@F527J#dycYujJ#iEtCi0 z0kR9|P1s3T_sBFC1<<1E<}G?i{yBZm&TAT$*vyihQf7bTkX6eZFKw;<&cQu4+L+O! z;_x1C%KnDEyPUx-Dfy9$@;K`MGuH&|Ji0egrAS^qAGdGO&OcJ^Vo}og@=2S(1$3rP zdG+?K@4`tkRFw1pUPAP&N55c#-de!x!>`+??Za||UftgCEh^y)EFBNJfHlE-=TItNL4H=rc}d;7M_U$nzcKVc{sfL9;A%QZy^2psMs- zd_|24UaP5S{l>xMH1S^Ijmb@`>xoDtIJ>#qqEkkb2v1D#kK3J=@#)}aLP5-mXOO1K z=(5>*U43Q^%uI#qa!tozmL7~YMmV4YAbmM{Q2thcBi9?sDaY`P*^SBp>i&EI&B!HZ z+CWOdOb7Woz^6t~kt8y!Szl9Vjj!}Z{ESa?@V9voBi1pt_D;WTb(|_~`#Pf(bhY-Bl;>gzh3=}8D73Ge*X3U{ag8o{VaqfYu2=VvS3AtL6EQv??V^z zIm^kz(yv>J?`5@`pSygIJp}PJ+3CSVtaxL1TQ=o&V9FYW$Rc_h8fsJL#Dutd22MX% zmc3Ni=#_CLf3sDG8UFQW9o3`cGqU|CF}qqL-&|v)FLm(E+S7+iwMlrRA4BCOO)q9w zTAk2?iH8o?6(9Y(D`DRzB7B8lFM3`yjOc-Hj))*VK%sBe^Bq%La9JC+VYJOpX1&bb z_$HXItLE1X3a3JQ9#k?mzl;XUpneiSGpxNgoCADQl#U7{F;+ttgK-WY$M{A4EnASt z3p1RssU5$jR#^Pf&iLo@7We;QeuQnl#%lCqIoX5R$ZyLd0-;}9)my{uWdlo?XPZq{ zXObXT>l*gWkpT~9$auZd#dB_kukac*ZN(%y-8D$c=%AyMU*TgxcW4%AoAh1fvby_$ z880t@$Qjz#Z_B2=mivf9Wv?JRLBN>sf=q0ao7kuCI2z<-@J^gTP>d|1tC8^;Tnk>W zrf4x!ay@?$YY}D*x^y==7lvWmvsJJEgZ4?H;AgwC~<`#ugtXY+;2;h zvXP$JJgV#p<7Mg^^E96@MWCT)bun*_FBrj5SMmZ_vW9@Q9K$%9cz=y@QnWyFN=4|2 z>P1>dR9sIfuAZlER0N9DKdzu1PkyTCtE7v|L)8On27}?v-3;%nJ|B0A>5mSmAcz^` zP88>0imOJDu8s*wy@2$UN_h2|o42OQOB-CqFT$06{lyty*G$L_Fml0w>n3kOPzmXo zS)i7qUyf-v2Tm|am~=XnpoErDi@#%N4^OrHMD7&d=IZA4wT9iN7$QP|f^mm2y3g#% zRTp@J<=z*|@uK<#2i)Qba|kjhQfc`DbG`Gw{Y_>}(2?;>#i(W!gmZqOuY{RL#49ZL zQK$XkaUrgcDbIglwFCA0>nDr|M4giZ3fFr3y}Gu*fBgh+klq^3{k&xw0m9CR+sO-B zE6;aDcp1*X)taAEJw9sZXfH0l8saswxssgs0f`Yj>C>EZXLI>2pNy6iQ8{F@2I9nD zc>TD%`#QZl&x8lC+I-w1zNO8%cs@3jjJ?!sHb~qb+(GB+Sg8;sF(Ss}Taq^lsvf=a+}3#Yhm z9#@#>Ru56@hGxg`kt8%CCsv=b^ovvAl~~zP>ihu;-&jEAI`eSl$$y7~@Z7!4Xiw;#%q zNt{Zjp?5e-EFE{J+gnnjP7BG6r(CW+-VTi&q@%#}4>{we8*RP|PwreA>E9S6)6__L zXKVFQy)f0WrZ z_mXf_3c#DjDoTMqu$J+ikw>s!ed7=W=Q6lc2DTudS!1+#1d45G34%%RkfpwQZh0{} zBcdp_=3A>Bp%6DR`<0%~JicjS8Z#|OM?oNoJR!SHriPixgz&7~8W)g%triuBo8mGO z66&tnef--NCUkqc{#QiwXUPoW%;jN;mKh%9S}He^dbXG+e}K0kwk(h6lVc=TQ!_Wr zeU2sCwovERoN*&kjefnxqT$0=m=rx5>9=bMf?Q~&mhh{J2(_-1%JUzhE&duZV z5qVA06ZRDV|){?HgDJ5zZ|l-SdlPmD|#lp(u={ek2^o13Qc2J6nBC01gKLF5TohF6y9 zvhvRKekI~p3ar)FCKJ+jT%QC*e19}e{Kc6;>AngsnHrK)tE;1R$Ask%bl6PP`s>gC z*8=f{_3HL+cDH}oVOSsq^ToIMZe<5w@eQ?Q5&aJDij!3$X5V<5VSbrmyG0ZBzyMr= zXX0Np0Gnl|X36_)kH`(4eT82p4F+BUqwOW;3uM}gwOG1x7_AlD=@0Qu4>O?151XxK zj2fuqY|f9`;)P($*c^cFFw%Nw+n;9JpJ&^@&X!1dGmpi7%E*?%0;a~G@z^0v6*|1D zkyv?y{qneHcHV3!^?Lt+DF}@^u+hV`39=$^FD$#lFzk7QXaFKNb=DS-%_%^cH$jd7 zGFK#@W2fI(<_w_3#ZlWH5LPOO2xn_6w=XeDk-}N@qcqr{r$|EAtXvKc1br}}a5gV% zq}6>opf}W!zFcVqGsL$#@Z4{=Yl@@C)I(fC2zol)J|j=5^r% zxWd#bSbsF=f+ zIeFDN-aubPDZ@(?x%;wAuPO=IdF$r|qTf%qTbSno3s#ZDCW^eqDsV*j7lkXk4t-T_ z25jStxo(@Q9y$GH)-I^g%mw{9K+Ne^L` zgcXtCO5YiMkOuI1UpWCrDcKS_f-Oh#GWXQ{k|yxa`JQX$#We0DmH9g(w5S8nlQ}*# z88CyoU2;&@2-&S?OU!w`<{%p{GBsxH!D03+YbyE8l=7gZ3Yum<>@kM_dQUn~(e;N? zBv1M%{{8GhRx$A1>x|j#4$bfOiLZK?HCBp;-@vfZf>hCBl8_bj@B`yJ*d&~w6*C3a zYlaYJdtB(qw6JfY*hQI}lLz67Ycv7WI64<(oUwiU46QPnh)TEO_8HBwJOL7b1w7i_ zjPXVc4ZhBawe|&79Unh$-)pPGTiRoC5Gc565wCn8LGrEior=y^#?4DPA{8S%!eYaj}}?; zlQ9gLnc~DX`;2G^R@5Ki?Au9i*Gd3btRLN zyXRYku?{Z>{>5?}n9G8}EL0sy#}(If&GkEIpyB=?a)z+5{6MbAchs!w`#0Fx<)u6< zIu_~kS!dK&sLwpR$1Wb&)PwaOwGCB^i7?lj4|`;FB87Oy8X}73A9+e<>Mmq!0_%`r zmoibtr{7ot>>IT5dW;&q+!2?|G9FyvCbK83Mp1;{3zC#MrDR@_{kwaQFBY zPl;xrJm!z5b&a(`;kDVFtq!&Pie@%J=w3LrW}b$HUBv6CBR5=C8wr@CHEQx+D6i?x z^;Tjpb2_&5j_BU7TuQ1YI>|ZcEtD^q#Tzpa;Nzg#Dg6sP6~pA=sBlM69}Vi^@NKoZ=p2mz*KmU;r@Ome8S@A z3#}CUyV+rXXW7^b`te8))ZA>CJH0nHjqty1(~s)XmgPV~ix|inQ+9Hfswcq^?Ju%0 zwh#OF3^Ze4!0homg!53*QBUD5Qk63KHDA{=@BsDq^EXMFK1ll60egQu&1d@00WFj) z_gcu01Ds={OeUM=xZs8z6JlN|Ycua+>Yf5LUa zoWkq~D;CEDHf2+%qAN6_*gNqJhf8P?UYF67CIW@xMRB<$1wp3QN}QxZny1xaau2#o zO!tOMRpLITz^2H|zDTg{Tha8w)|*SYXqg&?$G}k*yhBVs&7MHjsus@I8bC**kC7Zk zI?SDy(V$iXxI8jcVVBOaK!DQ9C?f9R3|*2WfzE`d$b!{&f@9NS~()+hk zMZ}-gF5YU|f~zCYv@T{ZT+xSp{NS`LFh*YBR|)M2(`a?Lm{gj!d$i0lVP4bdwdl!%3HoPuGEjsv9=WW#le*q`M~s$`3jhD_LzU#NR=5%{88) zuqUkAR8xSCwa-Gn5}a0a4%P7x=s;5>Dy&@cBYf-UQ znCGKEqN*{!&G_Y{b1hN5n%)7cJ35_FH4YC>?@{X%Z(VFd;(pWV7=ymycnRvV2UD+5 z4`540UM=8(qr=VXR>qne&eUN4LyIk!rUvh0&k4;;cSUo6SP_o(s(4~k=F|w63R0aw zgd;K3gimF+&?nrR3)dJT-9RkdKB~QZVGNz)}Z_>;Fkd z+0|tB^r6rL?cw7K+sK?ii(YJ;okq1(@}`=(;%I(@eZV#k=x)(+KWI}A0VRGqN4hz? ztNgYbidmX}bzmdRG%@sj63dr|=Tli#H}BFE&Q~;dl8>!FIhv9#Zux_eQ(NgInrvKV z^PSaM#nAoi8aZ%?(lVmbZvN~SmXeE*P%HpHv(u}8p_640_|EaIV9A`5j*ZX zE^n>Z;)gl(~+74f_Rs-$)1AfC zymke4es!xQ@(xv=5kLrvGX{xZ2^vpV(1`?VFr<-?Mo6X?EU4{Dr7fMxU@Lq_nF*{3 ztO&ztpWGKCR7sEA?xxY@=^RYFWP1#wvEt;w6o7rw9SJZ=gZA{u?n*Lhpo5j`V5|PkW?U&dI##G2bL5`$%&R)QG$`Kg`QxECvy`>4NAtz5r=ggE0@M7Cv` z0Bq6AH-i>kV2PM$75X?}J+Iy#y(VWW{;=dUj?6G4R|qJ@Y#%w5`=(CIN_O9WVgf|Q z8@Qy_YqUfnh|mTnT7TQx>)~~9x|O~|TmZ{%kdV=rawW+0g)?Bc)IKUB=O34gH)X#l z7_Ee{RTFHZFo1@nMqH(o1D+#R=z~1zr8*hNURbe%r7p}i+mf#^ z!>$Ot5Be`W@>jkgo>LrHXu+x*jns5fDj;fVHBh|1jrcjugeHiKt)T6FY2@|&4oFSbH9A3vfs2ASl(9NT=GBu(`uZOw5K9NhQI?7+9t#7^h1*+t6{_1`pNV z3>6#K(Ytq7)~R*brD0XBDOUBK^A@0Rv9xXhmn-In9Eb-r6lNCXiK1L{!wAyn)YmT2 zROLr+Yz8CR6BDQw1Upq@s!IQ)$0A$(%u1ciFv=zDaXu9@r{Be3t??!8m&yF{z_(%@ z#%q(Zrgm^nUUvm3wk%gK2mERoLLeCBNky)|+DA|i0m&3xMEDsMLk13$S;G_7=~6r! zd_s1J!k$g&*5*m)cbmEK(hr-&gka`V=7P(q@-$9b@<8B*Cl$n0WX3EG`Ehl-l6WxP zd$jlnr()(o=U(~d)7*Wf0*QHYU)1zE(|?aH=YZT#>35`~k-(7J*5UFB+BZcPbu;B-b z=E&F)uEI1;JCb`#<*=$E8nH9X_dlTS$m5Aq!d{`)IX=^LH5=+M1J0akw7i%^w1o5< z%)mUtkPh~*)FqAs;C64LsstEw-nR#SnqW&AC5t=cshX6FoeIM-KrM`b8XUB;jLJ2uEu}QP98JUk~+Nu z5zx{?$EZj;M{+g7@-k#2J@9IEhX-9ag2Y+t3K8E#K9zViW$e$G1C!CzJDk^bC-$P+ zDV6GB7BH8@F{?5q?Wc6;V!P-uC9@5UgX}%2pFO0HD(;{iI+MmipcS(JN^BfMK6;hc zk_5qJFAgZ3uU@5W?D!rV%vCqh@rk&J|07pxfoMmjVtBV{M5MMw(wgT zZ)y@BVxvqL6s9aiQ2eeLDn1@hq{T$vA~Z^OLr?^`ERSP02USWCTYs@Gj&lz(^B{lf zA{ntyE~t@pN`3JiW)d*+=JXWT(XqbDuAW>OAtNYp_T-mU6EumRx7W-+FsniV!VQQk z9;6Mmya>+0^KoGEx9nwK-YuDdgfIbXycPVPDftTn+>!w>d)(rT#rC+tnkxSMj;PKZzBh?15BpWdP?GOaDl`Xas7vTw zxS|1}3&~^QBm5)}!az78M99w94#0YYsaFvq^iVl@zMmZ>WPuE%Uzm$hk7QtrWJ1m} zAwU8L^>Yza2ns`f2wxrbQCIj&%l=`HrGIjDb?c==z^F=A(`)+HWGE$*rmU6VT%uO} z6*kU8Yl2xlSn)?1I;IH8dubD7hKZv!Z6df;^IponG1ix~6#`0IRnEEIOlN76W8IR4 z2cTm#BMW_BRokx z_TzO4@G__^feh)@e!S61DwrDA;E-x`Vnu`&#-R#UU?T3^g+ma^XL=Get@{>>U5bI+ z==Js7awUOvexuYm&0W(n3X6!oeHD>*7B98Iy8kW~BX0-wquWPRPh*Ofub>C$p>S!C zRVG!m<1aZ4W+a@C@ zCR7Hy$a_p^!Y=95qZh)`4R;Q!4Ym!!TSM=)!!A{*7TB{OCeKuJ(MrYoBQuvWwy6(S zUltxkd2g=kLG)fW5^Du9UnRVt`aR>>kdTSkFaEGSKw6`?3~19ZO2gbgU(d3&Fu_}N zTi-h>51AfV>N$lVY01n)72kEb0$&Rws=00_GKDRm@mh-IkGlO6ZLj3S(oA82tj34Z zqSV+{Q&02r{nRv64(iy3#300J&LJ#TYdH+w+I^WEDxE;lnQE#W zRZrxANIgGQB}oCb*)&ghgBGb&5zBF|aYiNzVHSr5Q9_S0lO=u+>vM5t;exLhQg_T? zWF&aY-MP8w1#bd}hm(HjSy)N=pwl6GLmg~SZ>-0Vl-L=(GEB#z!ZU`-L>{I#tYJM^ z#E6E8L6utNO6^8DpHSOxX1pFt%Tz_NQL051o90ORUY;qhV~#~VrQ9xDOQrRmQd^`? zv4@zty;>JUW~!h(Y`q2RO`y#w>DxRgj;UqBTkcTmG@2^*Wej;+?H3pwDWcFC#n(-c zNZ=h;$f}CL1-*HUNT!FhmzGzWa6Y14qTG~4a+`4-z-Kmw^8W5(&&3U{-wZ&Tr z8ZOY%ueUpn#->(_W{=c9Sk|Zd^t0U~vcx4!g1-D|{wKm*m<-2XnU7+Zp<4_xpa2)S zn0%=Y*3`3KfqR8HTm6A7FYzlyVa{@X@yT=qD`7s-taH7e zRtUTtL7WC`<^9wdgo9*9U+poOZH_*v>X|P2AN&zDXECgR*~-F%Ez6ys@?2p1}TgX8{ye z3iiR{%gBZnQg_7iF+feW663ga3YZpSdM$}h)CWf#sbw=piy4Ven75O5SEt(1j7S@Y z>h@MDI80pI)a!fh(8JW5Q?JhNTMcU=cAPo^-k$*Rd8$XQ)wRdtw^%qWDC-*0qRcQ7 z#yl4%y=1!@K-@40U7NHl!kxCGJc|%524Sa`dBkVWbSS5^ye zVj!02_X+7HoM}Q|ypoK}Qcz>$^&+MJ#xT9E`(wPRZd7I76_|g^9#&>nu54JS5iipZ znx~aMN)0-{nTlkjz#V5ekv7N9q@^b)#38OT`@Xy_9W~OL&`p${SuC=&G|ZtxwV~I7 zF)eceOUpn;K`xcnP6t2|9j&%NSN5LO`H>|tT$_Q*%l>zzvDUSTdM$02?M08=ji#`1 z_o5+dm7cmaJq9V9n6EL;`a_eJ@ccG&$(KQTtoX!*lG5=t_oCPxr)XOJ>5Em58XdV$r^#yZjaM3HB+)!H=4bn+NBuigTS+v*29l)AoP+_~=v4#IX#YU!!o{;`ubUMMX zCT((!J;MR7;Z>n|npl^aEVO37mi%XJcitf94mHR4Q5K3bh^`N*;-zYEd9oyjHbqiR z*o6SYTn~p(b<}ExQ>_C#h}ACdI$~4PfvH^hOiN>V(oGeMEb%1F z`Oy~P)Na2|7eQ;oNT5c%?B|{tHcI73cIRk1utp0`sb*v2=t(cb&xOM=MMf1Gz%fBT z{f)jan>CrwljcD}5qLzz9;AX`XA1pp!Y8it*0~mTNY67_qF%K#DU1;g@d(iu zepTNXaethR&VbGw{0&4-=lnJ&>qXp8$nDGw_@Y*J$g8Kr52o;6}(K%Ii8- zWIL#<*0Ed(oR-YezJP9|HlqN3JiQBc;0(lIILL^a{iG+3DOOCX^RYF9g*A&KCQcwVSss#y zTiU59g#%IG`M%J7Km9yzkzV?Yr9Qj?4zQz&S*!RHjLooRKuZBDK%dOHWX|erYZK26 z+3>XDdt--q%Zje;6IWDl>P|w!D5bYQqxxTTxrD{a_238}M(joWYxtA@*g$odH~zcq z#zJ>dD~UW@8RdX+NlxKCp+odpmQXK4}$mHUF z_Q;r~rog@>?Q!JrgjGKu$_xn{ei?2|JtuTxferz9-~D!NhE~CevsbobLSX{!xpWCL ztQN%z3iVa)kyFmM!dx-)R;~G}tjHRNqL7-2a(Ish# z)i$^C*UF)_8>*#-Z7QVRR9#4nstSVCMGdNcxMwGWrD#|Yr?kc^O%ws z95mHAlKL|BJ*;6tYanhX3}A_w%{^waL66MksVh1|_EhsM?nX!QKUhHru9qg3^p z^<|fzdS*5-oNCtrB%PuadVVt^8Sa!+slwT{42|viu64LGyXQ)E+*C3^Olb!lNy#{% z_$gG8wXGnjzAO@D(HNuOET`h-;L79vzsoKNSJ+~vK%Df%%QYoj>{8$fmG%Z7!jLuw zvky#z&<;)v8t(iO15|zD6;_tXH7hf<1Gtm)&}qVW0>F&ixtR4)5A8XNiqY0di&+hW z`;Q1YlJsNJx*ic-trRY7ATmu#YE#8!=rAiw0%Z@kKtJbhs1M9{6c3&bV97{Vl6BZ% zzu^GieU*(%EpG?4mFA14SmvuZ_p7Z_X+5NyEMzE8;+vR(f7EIuDW>I=QYSv&BV9%7 z7op`sHkw>p<7UI*awu=wyu|Ov6(%QYK5Xq)F|oQqF`94$(VEiIb~Z&;HLZiScQEGV zwRF?vPwf^rGHCm-u~V4v$8NREHt4X|5wt8Za2{b< zYfu_eBNNwQKf|tE*1w@*mHa&OQcG>PV;DiI0{e@_6iBTtArmL)Az@IjAGg!(zlT>CymO=h?>D?SF|&#wecZ^YVm!ovejL& zbvBbur7fJ_9iA3<`tgN(Xilm({LMGTC*{DvmdZ;Lwv-JNbPQ7+SK0CbVIS(A6Zlg7 zWe|=jZp2qXD!vqkUJi?kr{f#;WOC7|?2WaQlG$kkB0g6Qvnk1+;f85mI4hUD-3vT zcdW7rW@~LQ#j(In*{CLHFfiB`{>!2s)}ExeG{S0sAMVj%%-6bSDKs$0c0z}*>VS!T z;4xuPa8Y&1_gjpirwCC|lTv|jo_Ooh3F9;4tN^Hj=5MLxiB>&gcb6nAc&yy%L=&=f ze=bDr&~cV;b_!x1bSrE{H+l|jR%Yd(X>6#y*vd8yV(f&h^6?3==>pnR&C@~U;6~Mz ze*d7K(x$m@`Zg}$b=lG+x! zb1)E+R!t<}qZoP9{SO~YzPF(M@%14mp;C8J6H--7MkFt`m8}dqqcNQz$}Jypr}=!? zAm0PAqemnQLpNea@Xd;~@bPPso@~tki+S4h#pYN}TKx9cn!jDM5$(oIl>mF}@W1{(!Hc;yk>BG*yf5Hg+Z=CA)7$26shJWOw+NBtJ?^ zzTsXw_!#d_H7Wv+ubKKoWzBXVf3;(Tv_Wt=+!$|wHI{c$x!9)jMbX3}-X(8d3hv*^ zR#FQDexM+GAXWF>t^B*j1L5x2Y{gJL&}Y57ZH^Y-Umy2tlj2WabGDQBhi}H;-}Hc4 zC%5G%0}pr=>b3MBW-*_(RP(}AQXhEGF5C*y)rBGe52c8cC2P6 zvzKgzrNYUXcn_W;9m89U%HgAGDkOUE?e}Yp{~z#9a_~EvYb-EBFK&ll8RPj>x7U{* zd=Ia4RBors$Qcvh4ELetink=M#%^2Z(mCbQe30vDb+<>`eJ7s{!^SYoAYaRDJ;qw- zdO0)1x`?LkX~%YIi4<0(G;vq`sgmlpMc7mW=~z$!&$6amYId1d;+!WGgdww$gZGk> z8>vNI1F$Wh19)s3RS;8K2Bgw*wYJoy(v#BDxW-r5=v2&08vB$`gn5&V)ebrBc(8b> zzkidf$)|#cqHR?9S6{e3iX3Xi{mg9(B!)&Gg$m>9_}MKM(!eSDfocQ`o_#<3i)vha zXYhZug!Poxi#CMjovjsBh!^IHc+~J+b7lNil_448hQX)V?)LMIHEi-6ckcKRQB2v# z3yZ+@1T08Jt81-?RhL5EH5@EXUZZ;Pc^G9yfB|2JfExtU#|s<}i0ZfN3;H7r*y?(H zsW@#(PlPcv zN3sAz{wNt`5h>z+Xn-_y$VY4zVl2Ntv-epr%t>dO%Aefmk~N6onam@Lh^E>!or1`h z@TI;kHG{Wn-h(v-ZY7&bv`_jK4{iJmLCbwO@PzBdA3smO>ve%>%d|Y`*T=#wR234X znSugRTP1f&?umSH_|{Y$T$;1dP(`g090ZU){vuP<-k;CLw7O>Bja?0hs=MduBDFO z)vsYw1HY0R*h#B{HNXfcA|G2ODYiO0jy4;qyD&Lz;4!7a{!mSpnI0%6Jl@Q(+0VG2L8(*t1af>7(qj& zVYZ%RkaOe)*0E8q5Z-JqxTqnlDq|<=F}GDJm#PwyjBzDV5Zrp2UFNo1oK%)2qV`7W z_kLvGh%AmhHv7;Wz_EcB=IkUlj^iaf9(sPdw-V)(6|bMsPG|`darm2W3_n>XXsw+< zTuF1)(P7aSqeH6$FHEv711+ zL@aH3kA*B~mcD^=Jof!tm@VV|___mpH>qJN$M>!)!zB3mwCc)6<|f{e6D-VP7Nr^+riNSzihMH=D68 z@Wm*SOxVkd$*(`Pp)fy|a}>02w9&GSpG@{+^1wPp8S!u$3A58CX+9g;C9d7U+K?u~ zjYKuhJtJ5qoA;n%Q|}TjlY;3bOrteaYjfY-!^;$Ac|eP|aEh}NDv#9_R&r!Yv))x~ zhEG(55f_jxn$2tLya-N`qg|cK#M=m^XjmmD=c?>FF@uvLRO|K$@{^%iQ!#>YdeYz&`DCh;X%8WzjgEHok`JMj#t1bzll*8X!S$|bOD*6HQIXSjts!r>6c!)xS~ z*uF_J&P0{tu$WT?Z!mztPubmy0RXuLJW}g3xg{7DZWTSt@X9K&zKAhMQ<;Jmm<8#l zhqy|DBTMm^L>v5kv*wJUYNIM@FhH#I1BXNSFej=F(<)63-Mj{OVTHG1jS(ABt^IYG zzuJ2}S?|PH28rR5z-K~x&Ut3U+BF{?dx>wjd5swmtgoJrk7;0o1uEIzm&tO46qq;0 zWf;Uf?^m4Zklzgn^(uC5WnxtkeLi=H$rbyCNpbO63Fup((=JV1*p41uw ztH9TG%!i}fhcOaoCm3Br41>w(I?uz+nsk{po`Ok*>;z1)2pVY93(epJ>13%xG%KPo zBr+oH0EqEHopM40^oe?97W12insyWgS#$~c1z)Z*V6H0K;cms|BiKRX^i{lm4&C>b z_*6V$s|s}LHnLLYlhzGf$aYXG75N@!K9!<5$KJT`mNcTGhc?+MIsZHxSG|`TU~d|D zM1QZl-y%_HSw3+r-qo~PjBBqEog_I;?s|Fb*YN1+31QPu_GNT-G3dKySQm6~1vRTL zJv5Cnsbh`ZtyavUu65rR(r4CC3e{+YRvQ%!y`u#DsS_ z@6b2W`gqDMs;e^-j+bB^*Vw}pZ8T^tVS}QD$M4AS-aV+l#L)CV|M)D!u19G!ekmy) zSWbX7GUZ5`VF`~2Z!mP*XJ&<`Lp%;GDqIMj!iGSdSx%(wO1{#ZpJeg8`!#polT8g(K2O{8 zV1h_z@8 zogq8SOhya{&;H5c5axf^ZjzPh0~#CM)kQje>4dfiaVx&*KejI5MjuoC+-pE+xmFl? z>zYh!;xtL-id(;pVLF*oyRErK3Ls|0(B>}Xb21iQuq(2GlRH}@`@n5t@Bs}FiN*qd z`6V-|N7mkdTGB^k=AlfnE~@2xkVz~mp8FTj^!@}b%yodetQkk{gkGG>8Ylu^&z^!= zQ9JDI@N?WJ0wApqkJhfyDe#9*>4{Jy7=C@c(vJ<0ji%>nK|ANP1Zz%zu zcc_Z!J@}bbbQ=iZ-@W{|{rkV|3~>+SA=I_B)Y13TgTUV_&s4yvL~bMBIbi>VAtpZ* zi|JKaZY)XE2#?I*Fu{?9La@^fTWGGxKCo$){)IhfC5h8|W@Yv!+|PtgtA%q=12$jF z@*Iu}Q5`=syH~osZn~f}RZ2fLn3j5oUDCxIu*HTP|7^#9wd23a7P1R?wpgRL{Q+Ol z>f@qxZ8lGC9UUA74F}n=4RW;9p(;c3SY$@E zs*|C`@7QO`m*VXo@CXm@coRJlUx7ibM*^oF>X*Wg+iTrhfEIt`#=O(psExf=(}6`Cis((jnDl0rt#08TP9sqSKJ!l75r~w}$`9VI0qqUX4w%*ns9+$)^s~ zCb$qwM|64&7fIT0x@aY6|Hzz+vBv1#Ae6) zCq$1Ks~}PM##G4X-XkY83jQE0Z;QuxI_uWtbf!+)eGO6Bp zkb8Lc@aSbqnqEHoFfM=R7#pr1E@86|GGl|T@Bj}8hWe&X;M6w=`;pAdrl3M-=#;>3@;gmaZx_HVEOn3)XPBy znrjU2W%cLF?Ebq7Ec@VU84lS<;U0sm2dT!WR~YYW7Y&!3gI+XvGTzjI%?&Ca6o908 zcxxsx+pXYoqgo+v$7U-3*Q1x$J-@xCNVifm=l2N|m7nO>KfLX)M0}}qK zW1$}>!UF862$K|ijOBt}fIa9QQEjAZ9_>(CeEm%?L4Q^M#T_#DON%4|{sH4lJ@mJ+ z=Dl9gj*m#3yKyd$lu1|04hMr5e9un0IXSezD%=EoA!<4MpV{#ND-F;#%kDqYRPE;I zDlsNkUSz@$?I~hzld5=8QL{Y<_erBtpC2A)U-*$9)XJY`U*Nd%*Uwn-r+Ydxh5@%q zo=*COU(np{SCWTc%B9|4=~rK8@ba&?qc!?F`S*9G!rbVja(99NqpJys$vBQ$<5_mO znZJY<*lBzPS+F9rH|^pBb{*_6P*K>(*ZgNYme;Z0%@j|OMhjfe_~XV(|HjpwjO0r7 z<5k~G6I-9!wGr3;^S^e5!>lGxST$7d3b5ufLYwjpf&*7$Vl~=w#*NyIC#YK&D4Mg- z?KDQY8OB?>m*LEXvT!wo%cb3VE34U1r;uKzRcMCMx&$QAhFGBdwSLN^#+YXAIpJQ} zE-NKkVP6ilkBJu3LUXEnkj=1m5t4tnU>277%SX{#U_@elVW4Yh9_AIrl ze}gT5FgmD9@oS>|TQn$Ku&>XEGbLU%(}yo%5**4_cNkAXe7VNmEGmf)%IkbyNxVme z;x_~2D%ep+{a>y%qZ@!v$ZI?Q8P+Ai3X4Ue@ozTHnCY8N3bc!sw`ObMcBPCC-*fbukrbz$Ky;}IlHP*Ruo{5i+?!TD{my9=bd4aQde-`2bcQl z2}ZFVnEjO)fSHXB8PFBcFzxfx+-|XcM7uOJKij=|K3)jzDi`4}W+4?1t=E#nL#c}V zfk6WU(WOk@Myn{C7Flp=HEYst;{b_xb1V~B(zf|R+(2`_THsj{QM`PUi!^JbYk-@t zh92Yzx}DYE{d`jmjn|Xp$;wf?>*gPH){?zCXIy|fLqmkLk9Yj~gYIsNMi28t*FIKH zRU-t5Y&Iyf#KG%3qte5fDwbp>h=K3a?Ukmre8Ce_N!IE%z1M6iRg=lF&|^)fwO!t! zxtx@j9?x!UhS(i_xx+k;FFE>>18a$N?Rt$bi{-N`!Q722!N|##;Ja(Cv4m3)Oq z(%);h{_0DPx2^;M16Oj~*R#~nYrAb%A2;9U1X`U9uL7Z}#uGx5X2(K}vd2P={>MTM zC1at6rLj;$+*qjLaxB!)dqQYpd@R%$!C0uVi@uw0tDaeaMgEHqh0aYEN)}UVyCFNp zbyQYbJc$0VwIh>gt)>=DHd2Zjizr16|D~v5yA(CtmZFBqQq=HPiW-(`(Zoq9Y8WU* zjlP2imZ;pi{_2XE#$0i$xd_#I7obU#9%?k|p+>VFYBcPjM$;Z@H145B^B!s#2++iY zhZ;sa)G!k}AJcmPTFqx*)qMg^+K*tP{|Gh=M6lr?f(;81YFe2g&CF~Ee498)rKOu5K0r6R|ai5ycRa!h&1F{NRE2@5%< zB;;7&AZni_QSVmjG_Ivy*HRj^ETuueQW`WXr9r1s8nh{;L61@zG^nLscTyU(CZ$1N z7DzetmRCxn-WtT|ZbH2NDiU;9k)X$l1YK4n=(8e0rxgi$tw_-Agn0c{Bc?>3g;|VIH$0}Ie!(-$*XYAT!nMmCOGA+!Z~3T&egiYl5iRM4EDf|4JkpkZZD>;A~}B@#L? z6Rq{9`F16M@FyCQ1a6;Z{mh%X|IKx7F)<^vxS^iTgYj*gL*BukkfVx zIjz?$jz;CB%!H{z%%Yj zHyem6K+0MJM#?5I;j4lfSryEfs$fP_1v8E+m=RRLjGYQ*)J$N)O9eAhDwr{1{c0ej z^ta6ZXj(2|dBP$c6-(GCSVl&{GA;_1QBkmriGpQB6fEPRU>OY+OIRpaMnb{J!S#k& zLy|4ibR2E5uS@|eoCd(|gL33ct=IK7W$SpCkyP<1?CQ^~h}6wf=rP>2IT!XYK9?3T zMrjjclvXiDX%}OZmN7#ijzo~ zaS{nTP9kB*NhB;eiG(R9k+9_@B4bV>Va-WI<}BaUs$E~*TZV^n3D>7&J?kfA1OH>$ zXbEH4XcJ@EXdPqOXeVRYXfb2iXgg!sXhkPvgFTI9qh*a{qm8{SE6~Q~Rg$gPo%apT zgm}}bNHCOwM6)PJG=hRe$_o++E=Z)aAd$R+M5-zhh$%>jsaRw!6^j(6Vv)~OERvgwMW$1+NP8|8Y#%d+Jws_oCw+Tor zp#wetEf`pDz{qt2MurlX2>0BBx1^qa6`>IAJ^y@q|Z_ zz;_UdbO({hb`XhV2a(8i5Q$U=k;rrqi9|<{z;h6ZGzXCZ%T2f{P+YJPzYU&}JK;IA z6(7)A@d2k59}rsc0h<*cP+9Q-j};$~IN>>i6(7)7@d0;vL{XS8LCrX-bZ|;sJv-;E zzysO}JYcQB1JVjS;Hu$~A-?h_$e0KctZG5luve&Z*dmk=8`dmTs} zFS!=1;QX~{2Ir+{2j`_|2Qej8qQ169L`HQdl(o&Q|y`V zp^okj>N##9M{El@He1M1*g}rC7II{@kYlKY94#HxbJ0SMfEIFE_Zw$4v`yiOmdvTt z)6pRv8!gh4(IAeC260q0h-0Eb91#uTcxVtuLxVULTBIkTK^zAS;wT8IwXM1X=(U~+ zbjnWzdJdw1qaq48MxuZtCJH!yqJX0*3OKf+fFmst=(&pmj>0J5nDoPomPn6z9uvHy zG2%Uo0e2(@+;JFiM`6Gng8_F02Hf!%a7SOnd-ekE$P0MJT^U;h;tG(m)_{?+2~7B^ zU`AF2Go~t-(Nw{VqY7pORWM_xf*CavnDA1;jFbvyjM(rY5K@K}9LhC)masfwk&cQb zY!oabqhJ{q1<*+H&jTsP_(-bfejw$nU?3&-z^`KP zQ}s_sV}Fe;ruU6Q$$hydbO@A6-irsjYOiG`Y1_$t(FM1%E0}ID*OZ94Wu?b>_Ln=D zQdYsjyMvRM_ZmDr{6Y6*gL%3LAwrg_EwP!bVL~AvI)M_gI@!c57@~ zkFye@!%L*F!>MjxIlh~;3FoD#_VZHY;k*=yIWI+~&P$QH^HSvUycEg3KniT1mm>Y= zr4oDKZtN$F!NHj&M3G48V&d?0b=fdM}dj?nM&Py-32i7fI+2B9Ut^ zk`V1hBFjyO-m87ge1jyU_o(N)Lj%<<8d+}9NN|frZd)|c+M3<_3vuF6;*Xmf$H0tu7xDiHF7W>&|~W|0U*>oB3PV{%`|2U25O@Yfp~M3fv^MUWhtMvxrZN01yE zNst^`N{}3yOOPDeOpqKJPLv#3Pmmm%P>_svG~Qvmx1^z5VoRrFee-fcHrUfxHd@qJ zHrmu!Hd@tKHrmx#Hd@wLHrm!$Hd@yS*9geNkA@hB51k1`qOpYWBR z^0^1kcY~!|_ju&F!xN5MJma^;Gj3ZvV$aeacN+Xll+DOhD+dwW@TP_#PEtiY-mdizh%jKfQ<#N&F za=B=8xm+~5fn2bm?$!ULx}9vy>dM9!{7| zL_D=oBybx%Ic};{OyNOWbI1!3WCqj|$OenCP2u1D_q0|ESAo+++ybIdVgW%Yvj8uYT7VZyEx-$<7T|?a3-Cgz1$d#<0=!Ua0YNCU056nUfEOwj zVD7fG$u)tE4RQul#s{D>orA`33KnKlurQi}g~=2w45naVE(Hr?DOi}wL1QQd3o|Jw zj65G64eV-STC8l0AaF5&$V3ha4>=?(R#)YF|xbX7c)=m}3G9OH?Eqdbvt zoF@{F^hCn3o=7;_6A8zACeah0NI2#b2}ivj3ALPi%yXLH9itKN`3$&YGvJQPfIB7w z?syEiV=>^4!+<*mBi{2DaK~Q2GwvpzXKFg-!~&$OHDIJ{0u#O}n2}Y%jHwD{G*vL; zsDc?m70lSFU`EXZCcIQIBc*~FBQ{D6HK~kVC1T*nny^Sm#S%6OmXT4gjEjP0R1_>@ zqF@;j1AH&n^?qHHrmHfHnEnWY_uI+GWBh~ex4tfj#Dgi`?_4b z-!3wMlguCI$47Tg*^QO0a&I9M;_a*=!Kw-pZKxp8VhR%Nqae{53KF?5NMyPok=Kd@ z77G$ND@bJM;h0@PH@HK_+wdK1p*OuM;VYGLgI}6KRYxkO_sD6uPQs~|$vE{g8K+(* zSZ!cgG|Dym&rKwGLcgsZE$U}hm%^Ihn&M7o1WWIKpN zvV%zEI*3H7gGgjLh(w~JNZ>h$M4E%hfaMat$SAf^^$BRid>N0&YA(-J;hgaT57;j7 zfawAcST68@;Q|lXE%1QZ0uNZNaL#Cf2W%ENV{*yyj%>DZvpinyR{vPOBy(>kFk$jE zew>}e!R0BOWS+vw<|&+Xp2ErJDV&6!!pZ0egWd0ryrFv-&Fl4g`49TnlBQA@;kjf$; zOs*a_=4!oO?vJbc)g7YIZ!v?h-0$|QO}7!>O)C6xemH#J?z=5?Mv}+JX6|X0OWp80 z<=p4(=&~SBi2pW!>QZJ0qR+Q~F7J*fga=PojK6*2U+0I%tM$WnzdAlX4bFSNlF6W} z{loLqa&yEs6w4jos=dzp=k;;5TQ3{+r*gk-PhJL5?1{g@1uV=tKpE=B0`;fea{tfy zeghL|AG0olg95kvm%$5v__o}Chek$ZnCZ0_Zf-lcXqC7`<-Q+kZ`E}$0jSR=*esOr5zih(ufUFX~Bl5G+#qh+O9FmhHHpQt2IQW z$?8zdqCL&~R_ZjKa22ir8P8ZE6L^ak{slan46}ir&BHx)*Q6}0zl!+D)Wg`DkCbA!8BKJ`yGM~r<-lI%p zJ<24U)B7*xagBYDumSYv<&P6Ryo?u4pOM+c`TO9kU@4cJ6>aB&vl45%;H<>HE;uW( zxC_ooZ194!605x6ti(<)I4iN-OU{b6e8E|Xbzg8+wD-@r&aJ0=1jz-wQ(b_sVnpFo!`|03lC>lY?>c5#QZB5FgIh@l<0K#W#&UQEpB zyqMV0c`-4h^I~F2=f%X7&WnjHofi{hxAaZO(#5s?6r_%tc4s)E##Q#pq`BuatySP(>mf2-KVu%em&;(pWqz{5$~A@ zxT7QBj+1~pVgl~i3Am#u;Etz&JF+6)GZt`1TfiN6(pyil`>85*fM?Bv9c2#e`RYMO zRu4L+deG6-gN~yfbOiOFW2XllH4f}~=|M+I4`z&1ch(VN|84m@^XsB4iLcuZ;3PuiOn6X@NUJSd36n|sA-hTgmbHvHV<>J$J z+YLnWQ{c>OyDu`OV$EFCU@kE|t!anzCvGm5&b_5q^&WXD^x-=dbM^r~EqB|)3M0L4 z1}wee&2s;3b+^3UES5jcUbm|?`MZmVaXR~bx4=AYk|Z|*q*k2(kHbsKnv>y~tXM;k zHERg6Y7Ifwts%(DH3V6^h9Ilg7)1RVf~;UekTt9Wnajv8j;vRA$E!P;@;!q`e&RJC z<7moc&ZzkhePGkbviA>=9y32s*DCnTb zw1*wZ4)*-^aGF)prpY99}O1BXfe-3g9REIEO0P&rat1))t;ePWayNr zBkY8z=Wi?;=p2g%cE_TD?6GLzek>YHVJsRfV=NjB<%FoWo3Usxqp@hPs+;+JmwwdQ zk^`d!MFD3wLBLy!7YH`u1%hRGfnX0_AXtGH2;6&tz_=F(JO=^Kt``WLdV$E~a(&-= z&OMVom@pXxJd<7^FzEy$lTIKq=>#H^P9QSr1R|48ATsF$B9mSqFzEy$lTIKqDOnt2 zE*2sy4+pm5X0*L09P!9o zD&xq@WITh3OrSB530x*JfzU)Iu$ssOY7?2jZz2;&&SX5(iAEG_`L6@K|7Joa{DI~s6@f877Gi3eR=bP9|+w%SdRPk z1{>?F7PCgekgN56IbXbp{Gr7)JL$LW5xY2jTP>DyG6(*jw{|L}y8@{YN#QY(gvkd< z+IT3WQHMfWaVVtOhC-B?+t8Y}BGV`ZIUtgO?Em33+M-1%(Dd_gR6t#U`iuyk~HDE3i6fA)6!yjkFc95Ag8L8^8HqTUQaRr26W)${;V zbq_$*`2bYK4?xxa08|P_pztsNm5c#sj2yN)9kkj%y~qBL^M@t%7E22kDI!Ev|`!)`r)q0?PB3^EXY z+M$u#7i9K&zg#fma=t!%LHX@!fy1V-6G+c0g=!ql?q^Ijk@-~|E`ULY{y z1p+f(ATZ8ud~>&4FBhh{9HH(~ zM6{P7s=o|T4Q7byFhf*}8KQd35Y=Rcs4i1Pw3#8Q&kTtgNFr~ z(}1W<1EMYsh^jOoYSMtHNCToC3lP+3K-8iEL5XT_3k&5(T?X8#)Z<>W4i5@;c+j)M zgSs6awC?bre1``P93H6fxM#%Sff$G9{7e%#1A;n%jG-Ptd>dN13=L@d2wA);7$~7*N67$nn*7q4+50b}AuL*;^?3%R9%Oq){mr2rAFO#Iv zUM5NFy-bp3e3>Ne`9et;_GOZ^@XI78Q}1~%=98FUF^yhiXhA_NHydG8QK`vJ@vaG7~R0un{LVG7u*gt%KVo79j~!wq{mClh>OaJ|Z)Q zg0b{xhBn5-&Nv+Gjl#j+7#!@4z`>q;2Yb>T?8$bpC)vY}TnBqn9Xyfwc8*?X@p+2? z7wG&n-z>IIB$GkqpFbLJmQrG!THoi{Mvt08f+hkT+Oc+2?{B1g!c5%t1{*A{aVxu| zbzI!waKWz(sezOoA&Xg+rYn>;R+C}F>q)F&aIY_uvBYammJ+eaOd>YfNW>-siP&Tv z5t~dS!Kz(EY%+?7O%_ow%}sb)5)%p)Hi|&n3n%`hPY`_?gD^Dv4%~0g2dr{!8iovN zcpSim${en>KZPekQ+VPug(q55cw#n%CvsDG;x~mSigUQKoWc{)DLiovm}w~gdDw1H zN8y@ozt=5T%BX=!0&Q@wQ4mw2Gskpm_Ra=>Ie4w$UQ z0h7HrV6qekOg7?x$vQkx?ZN?*ML1xxh0^Ad?@+C+dDry7eXo4Uj)o;MbI_ocf*dZ@ zI=gVwNT+Z^N_O#vnhb6T%HW2k3~tEE;D)jcZiq|aiM|YONX+1g%HKEhTPAPHR?&>K*CdiRHpz*&H>Py0wgvCNNE8$)_U{fxZFs< zAuavo8T*z$ykFj9>O~goGc>{a%+8t%vR^-Lu`ZvR3J!{uo%9T8J@bo6g&jb`QGP*T zDTjoo91^B-NVv)&VJnA(uK`5Ha!5GKAz=*=yHw;~z`HJ4)Vx+Gtvb&TB`QH!C(^4G zg~xM>z9Ul99g(8#h!kZ>}H?F*pHu7Emh3q*Bo zfoQBP5Jj~GqMx=v)Y2A+HrfJFLRY|dZwus=+XDZlXf7J~5Z;v~{mY`nz3oB9JNBlR zXNXEh5OgzuXcGg7+8RJq+W?~e1`riFfT+;{MAeQU=y(88*#n4Lzuv6M1pb$|%Ow_@ zY>xBQ2BUy701P7V3QNYVjrNT;8y?t+pO*K_{Sp(UxPZh2PD=@+mr5Qly(aj+?3$$i zGD%v)Ws)?G%Oq(lmr2reE|a7sT_#Dxx=<2!c9|s2?lMWW!q!4yUXSo^K5y*;?m`|; zEGH51CKE-1tpt&1BtaxvM-Yi-5k#Ur1d(V6K_ps05Q)@Bk-&KniDU-ELcS<7A+$c8(K&0 zM67QqG3nG!2Et>D8J{q)o#6>1D;k|Jw5QPtL(3YSFtoAJ2}5feoiMb!(FsEf9Gx(< z#o-Afs~nv$w9nBACoEN>FI@D3#C)`W;&HpK%Z%S5HBR=Foo3gD{LoBu`LUIz@+XWm zl|Nylsr(5OP32EmXexigKvVe>_L<6`Fwb0mY@Mn63FA!VqivS(A5&G#_MAmp*bg!L zC3bP#+`YIK*3K$xx~v&4-)W9k1JFYafNCJ zu29K#h03Te6xv*&a^nh>04Ze5ro1wLw|cSTsuDe(v?0fhBILNyfgCrlFUQTB%W?D4 za@@SH95=73$J1NNar1(5+`OBvbN*w#eqQR7pi%3~+jmZ|`u-7{bP=#dF9B?{Kji#)m(T|lhS}7%yF07={fR*sQ-(m9$iy(Y?hu}84+28l;L9u8eKLgNlcouXs zIEzXeK-AU%qS^)!^*4a1$N@x+4j`&_1VP6Gh{_&7QR@f#H8*8Ss6DR<7d2O#N%{}w_F9I2dWu6P-WPGzP}ylE8Bs-r5)&tl>>PfJJ83s19@V6+jd=cO!*>TxWdld z&seE^INU#@)<#?>x-tZzpx>U6QTuv+_qaSI@b~rhcD^=`<#1N~*W+=Q36&`~P3Pvm zo$jXA-N{S9m6thMCiptB4(DZ9d6wX+dwD&=L_8Psu3t=75ZZpliz53+a52Kj!w3@&G$RpT zCffdjL`B`8+|m@g!Y>%`+-{KuVVR0;3e?q6YXAG2TPFFx#VUL~)}(()ir#M5sMG2O zTaJWPbxoowS#~ycNmu%yk%1wi_F&)44(F*wj8WRe5EZK!qGA_AR4ikNifs&0v5p}s z_Ax}oLdGasl3kCFU#ye=jRiCLE5$Xi_u>A2b%!q7l&T{Y z@dAd3X!I0%oSi_S4JaLnrJ+YI*6F(_DF_gj+M=3n9 zl)@8FIb4}a;fbphCR^67S;$55+vvQE%7v%FIZ}Cs7#JF1q-TVYn-NB0Mi^NcVWeb) zk&h8ZGKLtK7-6Jgge4rHsvvn@G9xtoc7FGj8?CuZ48$^q#-hiIuNwIqT{WR|B$}{0 z5>3b+i6-2SL=#gOi6)jY5={(cC>rf%B$}AfNb~}$(ycEJW>n|QpqIYH#=;qAP0gQi z-s0RD7Z{#9;{yA0XIx;0?u-kp(VcODQMxlOuuXTy1t#jxIB%)$j0+6boe}Mpoe@Xm z)6C`d;q~Ku^8gpGZxByNCiZ$-+S}?$>0qa)q@#_Vl8*LyN;=x+Dd}jJr=+7zo|2CC zcuG3j;z{XXho_{Y4W5#|%>FPqyxasQ;R~&>JK+*TY)`nz7Ml|;GsotH%Pg`v;WDFa zPPoi2n-eZG&E|y5tg|`cG6QW-xX4DE6D~8;=7eae=HkC!ZCgAABpJgA3BpJNvy+*Bxd175_|9>i6MBA!~(oXLVXa4oO_XkY%elk zxvUX(p42r@FW89R22aVI@SNF-4`{9UfYXW(2(9>l&594GtoVS(iVsMf@SMSl59q7- zfVbp0XY%ddh;F z=qW35qNgm$i=MD1Cwj`FoM^NvYi6{wetvqI?|pTJwisq3@1i3TrOHiE*I@1mx~sX%S9W><)W1g9;FywA+<8y6wsv&35IDUc2%}t6h1c)2_VHXkR|*vny}3*_AiC?3dBK zeq7#teYO1|yWVK)#spe%zcEjM%?GhTrR49O0vrA3XE&xk5~z#}1SV<*0ux6Afr+ev zz{J`>V4`mzF!4ALmd9(0QDL8o{J_KNR8r}!T9iigHgRZYg5JW1%#UiA)jy6;i1{2uk% z?@_P*9`*X~QBOdRdIoybQ{Yg?L63S8depJNy>yW}r|l6MHGbHoEDm7;Dz^8W<;B9- z5IPRe0#}2xNYnr#O9O}$4IuI}fJn{&A~OSsw2UBdGJr_P03sWJ%Fc|t<^G7V)!lZF z1k)q;<3EiS4#ww0LZ~<;p^Ti6Fk((f7(XW@jHVM3#?}c5BkhEQad$$(C_E*hOrDT1 zLQhDvypl%qI)9yi;};f$=F02<@31Y!77`zDF`G<0Bd4oZF_Fx2K;(;F6*J6F%15FDZPxU1RH8TEX}X>l_jC|Nkpn ztmo2emv-WEd9|vG<;}t_mN#p=Sl%q}VtKQ|i{;HCFP1m!yjb2W^>TT&+Kc7Qf-jbj z)@IWzg!nZ7Ir>CT&iJp><)_F=g8s;hKXp^U;qdA_G4wiUIIvU|A>BRo@TNjKD za_?l7^r~kBgu!WQ2(J)SmM=Log9!=(?c(k9B;?bB+ zibu;jDIU%2w0N+&lj6|;Pl{h+jj}t0EXcEOCehnFYnbU-7uo3O%=6|tIP(I_&Ck5V zi1RZqvFH5EOH4aI^Aao1&%DIo^D{58{rt>Js=?sQ3u;7u<|UOQKl6fm!tKG9i|frL zwWF22q)s^bvo)cYKX3n?`~_Cu$zNdWo%{tB-pOBJ*PZ+Y*4)WoV8fmK1(w^(pSRae z{sJrQ7UW$q8JzIe`mDr*Lw00vFCs;2C$nEbr&oCP_Ivr5`=Jd?|~&*U;2$mB9x$mBAcNaYgS$mB8`$>hvdDpsrL!^`Q&+mosGLr;(cBuz<&n|49+#~nF_q03?dt^85yy*b27BFGcsajXJo{}IvLpk z6XqrR=iy)M*7wNyJM=`o++>fRmjCmNXgT_wa}tStG!|U011WDIsZ_9$Oe$JQCKc@@ zlZuv-Nkv=9q@uNCQqf*Asc12&RIr&$Dq2k@mDo+R2W~PoGM`^o2Yx)$+e|4=45fj* zbxcq&i3&wKs8A%oLXq(bMVc!Vxvfwnv_g@^2@2FzDDqXINYWemVyRcUl_ol$5U=uz z1dSIYD!d?3-vx>4E=bgNL87t?5_MgWsOpLYO&268x*$={He;ymp=%a9EYZ2gz2+Sr z^xxx=g&vPw^mt^X$0IL29@**f$Wf0+rW_vl>hZ{0k4Nt4@sys(QP)BVa}M^z^>E;= zgClJn99iq&NLmL+&N?_!*1?gn4vvKNaNw(hBV8Swu(f?ZKi)C%)tnEVb?QBl-%_EB z!I5C#av&I4%>@&FbHRk^TrlB07fjgC1rs~S1rv+-KdikCb6ZD_F3caas~S6#Nv3LQ zs$|(tn6V|VB`4W^>z0-lk8EC3q=tvGt+{po`};ijYVt#W@E8|{x|>{jYgx< zZN!FbOdyV>q>b2+mo{Qca!g2uliV&G=yR__L9*YFov}y+tRV#sYcbwoEnYjU#a@TC zIO?z#6CKv#o5NbH3Rr_X4r?*QVPhV=?LN>S4b#zZ2D})-8*{dWGvrMJXT+m1&X`wY zoH5VFIAh+8amG9xpbWCB6Wn>C-EGbi%V|kgv981k4=16v?Fvk)!g*hch zzS((Dlv;?B(lmkG7N|DzgiJM&r^Kp>JSAC8`V zoszK@?v#wRaHnLfg*zo9k>jLZ!kOR`BwSh1tLXI#g zH-<1REQT;GA%-w57KSh_3x+T)0ERHlbwikDwIfXO*AS+eY6xRazT2$+dDqcJGT1m3 zK!bx7aLBz39C0oI$6QOmF~<^c%&i0*b1DJHTuQ((hZ1nioeUgtCIQD>Nx&(N=p<_L zL_w2W32>V)4xZqQfv0$5;3@7Hc#1y;p5l;!r+8%GDJ~g!icb!n;FN)NX>f3e(%|9{rNPM|N`sq2lmFwOX%7C<>W4Fpdof#l{CQ200n6b?=Sg?Cdx;o1~X z_%#I-PE7%YN0UHuX9_5MnF0`*BQm7sLV^rfkRSv4C&+;K z2{NF3f(*!>AOo5w$bjG(Qd2uY2Bc09(%GM!M^>HBNR7bA4b4-*Q; zeu2fOe9Z*B;?FcrVbdfIW{3}T3MVsd3Mcb!3MaF03MX@N3MVsk3Mcb*3MaF75+`wa z3MVsr3McdYJP)%*!Dx^Kb~uyc@zY&xWwft064& zXb8)^8Nm`yhOo?wA#BJ4D#;O%t+1x977oZNg+qEu;gFD0IHaHy4oN44Lz+q9kXTYU zq>>g6$RmYAx=7)WAa(Nv(WDQ7a!2 z)XGQnwDJ)-y?jVbD<2Wl%7?V{h~|ozUO1v=0@UOzfB`)NFeGRIh7=9JkfZ?^(lh`= zq6T0{)c_31S^xvO24G0o0A$MY$@_ih0&IzL+%jkZD@sow6pFVI66Ko+nFCFP%!wvK z=13DEbEb)qIn+eRoN6LujgUB z%Xd-^gYPh0>G~iJi2M)^DgFSCkpBT3;l%?u!k7negi8j<%3Sd~G3(xZ6S+@wkOF;&cmX#P253kn1g^5${__ zlMw7~r&a@ni@FqlIh&Lq-1H4Ir7~oCH!~kznECzU!k}<%W6pjJjqkb zxXr}?w^S*#SA0)bEy zAkwQ160)^HLcKOfh}Z@RE!!X=X&WSzZG(is6Cl#L4H9y9vR|LZzWO*VUXC%%c*8irb;UTu za>Y2rZ^byoY{fXlX~j6iX2m$fW5qbcV8b}TUBx)WTE(dNdUv~C$VrCN|^Rk6dv9g7bImx5g z{Ay-Q&LN=UU;|jVHwGrojewbJBVgv(2$;Dw0%lH)fSF4pVCK*Wn7K0sCeDn2nJXh; z=7=SIF~f(c^ImV4#hPh@EAC996dp~XBu-7BWPVMcWUfu1WZq4nWDZWCWIj%yWNuEN zWS&l;B+gEtWd2T|WG=tj@^wVKQR)|Z-)x~#ixLg^yG?(0d%NB7VnDZlxx)pjFWY4H zwh+(GV;aBi-`}m)h?m=cj56d|L{jG4eR}xR?YS|ilB_1UNL34*B&q?<($oNFNos(z z6g9wEf*Rl~Jq>V{oCY{cO$(ePrUA~<(g0^kdD|_P#SPKFTtH(lgO}$Wo~Yfgu72%y z{c2k_1B3F4i(^<};Ru%aH-u&84PlvcLs(|p5SDp1gk^>eVVPS)SZ37-miRP;WhM<_ znL`7ZTf$R3a`+*hB%Dd!6r5=u1A{^kV zA{=0;Ax!gA5e_g@5h_mJ-@MLH{`U>-m$GIJO)iOoU8EI9`ev+x{5%<^*(F^kYa#4JSz5wjp2M9i{u z7%_>{LBuRk2N7$bnwA`2Jz{Y<)T$#tT9Q(Q$4OMF@JPvu3XhersPI@xiwcjGxTx@0 z$%_h)mB6U*SV@cukCn($;gOOV6&@?0QQ@(YDof*|#8em2Y|tDMYR7(@fExBArBksV zE1HV^Sh-Z}#|oulKUN|Y`?2Dv*pHP(#eS?H8ulZlP_Z8?f{HyMe=k?vy6j_<01049 z13IuNOa^Srjshn{MS&BNp}+}2P~ZgL6*$3W1x|2PffGzLV4G(OoM4dx$q@^??`QK5 z8$4=`E5hA|9)y0zh^)20o59FzJY;@>_TYg!Uwy!@0qhN4AMWU)`0e9r4-zh}y4mlq zUtPRCK0SYV_V)Gh#r*8_^7!Wc>cidkuID{}Nrc=$dbU^|@Atda`@4Oohq&X0Ug9SD z`eL`(^w-U5@R*RdfEyCch_Rki5N8&Vb@Tdt8mcNU|+W62-M!*{=I0>I@$G>v-;qC_E_mg-R zTO=sn+#efW-#`>b#@AH`3FASYZo$*l5?tu_yF0#E-DuI$dG#;8G6TVZt{w69YO}hz zyE%mVhz|*Y@^&OS_vtpit@ZU$=^2s(ZxF(Ib;r0hf5Ui8fv6Ca!j9wMS4NE&o8`B3 zAT#1yD%hasB1jFs#6S%3bgLQM9!H?4#P_Ith94xU)zD5JF`mI_zP-ldMsvGvtG6L} z@^?OBEE)aaK&WyM{B*O})A4_(<$`(s5lZkNY9u1RSnNJ@`%@e^9UjG&*K{5&?Pr_y z{qZf1jJy79(_9^be477C)XHxQJmw_HB@d1Le81S=^=$oK2mejTr`uPnO*h|MZy&BU zrF%`sQ*}#vyYaL)jNh00i^Yf8*`|vr@TS{w0JGnASUUMB9hO>K+5)Mc>6fJf9m|^q zuTSaUQH|}L-rc;HRoj|k*_&;@+VhAYFrz(L@}Z7PLEumntb3IT9g6ns1AD%`(v^hY zf4o_`4h8={bYEvbFM3f<0*MgiI%Ty(bMfmBe6Qu68{{eX*Ru%;3vjhz#CtaDMf9 zwd5CeU-vJtfYSV!#qj5h3*67FJ^2LG{=9R-dgz_p9T`M2HbzVB|?*+tjyXI^mpb=A+DI_EHSFlt+km9D1s62*G<=%GJNO+GKD^xpQyC98kI$;LxVq|RrUX7~Fojv_C%#0)?Y$#Y2I;zKuk zzS^nmD3OC1TA2FM0=)jV{c?J@UeEX44NO}67gh$dN_9Iisj8Cbx1WK8_#|)wGw;K_ zpw>l`xL7Fn3o0`{IcH>&j)%Vk`f9tq{duujl8A!o8Y2olgt6PpJ9@K|#fGPU{8tnN zjQ0Fd@hc5d@Nf-oF?)^NP2CQDZM?&``j<=_>DBY4&PXpYvWNZGh3)a5z5m~^T=3qO zG#o9AKIv@7X&QanL{Uw5vflR4y|;JBl%{9guVJ>XZr6AaaD(m0e)b=C+kFSo-OYHj z?_zb+{nvKWMQ<#`xA&#w<$Al=*F{89x%3IQ_zM3n&cj8Fgy-_b@|Qy5n_)@QS-hJ) zL(&=i^WvX(pyvJ_yQfwcyKp&SYA^k=jnbQ+W?d0zBai`zob6JE>43kb4wEY{LG z7!%*+{f0(9-t89mZ?@a@jQg3t{8_X!2&LN9#8C9J@KrdR*Msw`k2ul}6=YIug$hLP z3o_%h`?3eww%7ZkU;6FlXwLs~J>f!glopnU5o5g(nY0vG{MZGW+lh{UM*&#hgP6v7~)7JHN*c`R1qq`=dEEf>&^ zK~s1ctJ2D?TTihlO;9ID~=1nvu;eqac4-hwfxD1V$l2z%NNoU!mKNFl5+6QKd1 zT?#qyxmmSKF?-%!truL!MSJ942^GN}7SaYBmWf{m3m4ShZnIcFySs+om~n=HIs3(K z&*}4Z_WXW>1q*3Gm)%bt1XHJzEgMFa^KP-b`uK9a_<*XW{pIUncp;NiCKBrkJYh*{04z1!NIKf=nyl4LnW2uQZQSLl-t3=fG440o5Vy*D2slXkq zMoXHj@=ZGGrT*Qj$BNBK-@umo`4kTU`GNrx&+SL>w_PfqTky&%jT(h+{s9zT9|@p7WrJ4`mL1F$ zJm~IR23<_5621$8%0Ovn7A{hnSEiAwGE8d9e^pk-4DoO?=nR*aw}gl!fJQHXPjn z{o6qyoHAbjhs{1>f+Xn<@{K-o}cL5y@wvj(Uy)`!x^fb<7n$w{B(Cv(4?)!AN zn6hSOmX8~M=XdY>Zm&nHvUaNhDjvO=xCwdimz;dCQSh1Kcax#t!lr(=TS1|7zhQR2 zyInCUX)#0K>6PNq8s}KC_&V~!257yn_R8S0#-H7+_QW%j-0AQSXt^LRH`us^@ZI;& zeQ^AV7i7PBzoJV-mT@*9ggNfj=!Q*sb+-mhb^rV99{!x|9hUa_221m@vqfCn6Cs+@ zcgyx5?{_yFb7g~(!{2Fx|8uv#h2Z02#B!zwui~0BZ>ls48qs4#_cQDl?&XCNU<~iE zeV`p;D6-qPztt=I(r;aaTf)H7gvn>S#_S~)Y1-hUmX0@@Egk+#t5_E18FsTgXm>~t z()O^Fx}UIX`KZQ(mB606UVY$4anz9B?S9kkPu43Od9G87Z!m(z2i)}fvVn&T#)1`O z6eSQ@oGFkoL?&&xf`iFEY)FSUACS zp1r-JDS{8h%Nsyi&bZ0IuyEIF`D%3qzZQ&vbzR!STG-n;3Th}LvGRh)YC5qEETgyE z6$zjWB6a(V?YYFx4+_nv%Hf-IDtp4e(a$kmWWed+2uspES;M-Ttf<*_k|3zcph}{D zRE&ny-7NiWU5jfiHNdWf>M}1u)&7p3^cj?;1sdYpDnt0&9>(As7}K)B{={)$66s+w zBIUHeRJL}iLsj}pmue-@^Mb}`a$2i89{Dd!Q?LqWUQ_`aiigCh`5zb>+=ci5qW6rE zUHC`tFvL9tGD(z;_>gGmjAXEEAI!l*^?C@)=Id|JC?hntAIv9oHAcYD_0R~Piv>5$ z8n`87eE`OuMm5|y&$|!1t~{fX~aKN|fm(1!k7juX`N zF@pGDO|z@2!|b*WIi=7Yw_2iI-A7K11s!J1fnwStjymcO(hWoz2pt1B0=0pLRYwWb zB{&4+Uc^imr9>_#R8eG{+&qCmo0KAugv!uue3V|xM6?0Iv7{3OmZzss zh>5F`#{SA*G7xM`{o|cyQ{_0EmL<}@nZw{5q(Iq-RE(rPzQ7D}OzEy$_6T|4lt!?? z8mFhS^XY%y?{Bd!g+(vZLjJ-i%r$Z+N9#6W`ktE_C#g?6>54=`?9)!R+{bHdVX#Eq zguSBX$}=o1>-E{rOcgO1)7qqke$JofKt#W*~N3@vuY_Um(1awO+ir&nq5xuKM zot0>ZQuXW$!-QeXXmZDa~D9|=UeNei%^oD!fVX#(L%j1ie zHWbSWkjBg-LWc5T?!Uy1d>mxJIX}SOB5oRN2FlsBM-G{;$Ka%kFbsI|&1i~h07Ixs z=wTdg0&9#iy-l^D8Mqo2VoOy0`E+Uw#gvNC5d(X_t$R`9z~JVAsTv=el?ptK_{BtA zYZ=zDvdzYgz~UloZ6L&m!BWvch`t?VU|`l}LD2;yF|>g8v@#A3qL^*;o|UPrUuRW~ zkEdJ88|T)m)%$uFQ;4<6Wdk#03aS8g`RWQ{6Ekmj1ym2(bnG0zRV(SA1ibwO< zDlO%Z$=b7>r7j}kUE1z-qfsGHS8*o7G`M2g3i@v(@t z6fm7W-%yZoP!4CmK{!8Qe2Z^U50jsDROLP$>2qjGW zR=pZE_;|)fnlejA`H}aFq>0XMt0j?aV1^jF`X(wpC|?*U>vof&{{H6e*)LpJcpir3 zRwT&h`+Q@AX_k^t+q=C49AlXleHs!#UD_yP9hrpnRhi3^H9{|7K1xd4+Hf;Vlr)X2 zH8uX5^&P?`dNtb);9Yb#w=E>PKrx;Vmuh3$qJ(q*6+8hf7ZVAigC4oX%r>WOh7|oV zM8M8-C7v;DDQp~f9!M*8wCrZv#n!n*_qkTQze2VtY?WzNNJ-4)`)7AIx83rcegj=4 zA9grgw0(u(ip=C5RTGJCgF?cEjk_jp)IMB>@m1A;0p=plU5R44cNe5Wc>jG}_;&t0 zm)mw7bbQ^b2}IkH9Zq;|1f=F4eBkD6X%(s}OAz$o^NXcaN93x-4?_Fz;J3j#ptHt) z%TOE@Qz8j~mtvQCc1`!b;PPMxJ%t_5uB;1ukp?vDLhx1b^@`LGX7w|Q4IUx?A%jK2 z=*fT`sMqkN)&PdhFuZFR*~M1qJXpjy%({lz*j5PXE4z*{vUz*zjrOO*(#861fG^=gv$M?HUkkH^*B^(-(otAC&yB$qa}{=~0?eM>c8Ga57uAct;ib++4xGPDIczrvOeouRp8ib<{WPb-PjDGNqbEQ<`8QJ4DaA!mNFrkriw zt`O7L_u^teM} zi0&lXDC&Ok-A2NBj#$ub+~FJne6kI?saS+U0hU^=7xG`RQx|@PT zT-CVdn}s@vO6*m_iQ5!xzSRg$m8L*x^-L}LvZVKqfI zZn{Uxy87JnlBTt&#xT+Ze9(YRg)~L$>IOIYA5_L3+HF4geyf4KJAR{QN`Wyz_^)o~ zhiN8~Xd=#z*7_hxEyNjqFGi2axOvA?^$J{ec~uK`DYBX;6+*rxU|6ZCsvZZB4K&+TX7oG6EDNF-(GOR`&X8NP!_{mbJZvrRx<}*F*_if`wF4yqToRy~SJ#YO zp~|?lC4NvSi?w=4Wz*5mY6Mfvb6Qp+(*w9qle(7tvH&DzBPYPky3! zNyR2Xt+1S*-CN*oKoRANb{N)FxdlSw2N?QZj?(1lJ;1ztWeb9rS^q{ZIXXjF(baCH zfu0A@{Ma}K*Jw()*KQb7scC;lIQyE!GS!gPRYB91^*aqLbuz6}=?aC47wfLryDf z6NeKr<%69Ks3v`Ved`R3PEkNa=u`@7|e<*yf4XXn4; z4}9$1*V*xVEY-MULn64162}p+H+l)4_({Sgb{8KP8yrjUKHbGOu<~Jr`iOj!uTd6o z%r3V#{D`5^^J4S)SKJdEm`GaMt3}Fy2(`JDJaD2?RH`yeN-cFa7~K^(*zfe1%EXC} z7t28j?}>6+)@6WDrngRnz znfnpn&EsE&xR{hvD$LpwKQ7ejetWfDJ7L@)k#I>yfvJ5Wt}!VSeaT70!*D(FlIbKs zwDy%t;10Wq*|Ymw)Rv>6h*C@@Wt541kpSxd)rI)^iWjNSm4>Bd5QMjUpPY+n6^Xgb zi0a15G+<*C=bsl)DwuQ|8bJ1?=90v<$KAas$;5brnQ0RrV8s$*d+}u(V?KwU47%KX zzpt?+m05$k{B>su;=}PaOPwjg8|LYjyAJY{yXVyhQD@aMV#DSX^*Ff@S-HJbVGkx^ z`B)MTUGQdQRv4I^fz$i8K?k+((y-J@$Q(G{zv>VlbhhaPHd73C!$2$Yh}}U3e5R|w zyOCNh-Pqx1)fcM-Zyhu1!5yELDYd7a#3M4y*4~q*1G`ea# zl{*HfcQ{RY6M0!y zOpjKyWpsmRS1UE&3&xG*6UVLUB^BL@DC8Lwm|d4H5{-SVZrW237IZO-yQQeG9y)zf zvHtS2oFI>t<*cG(=n2$+hJ^~J5U?msZP`>x-CBwD`T9;KeS(V~lJEe?v&O@cG7NiJ zZJ{F=ne9OiBEI1ZkzW#?2PEx(p(zFuO=R`*lkBhxo^|^#9i)8(;8lT3y^l5qCR<_* ze1%1X`f?gFwm)J#R00g~gr#g@o-eSv?>hDJ^Zsn#BcPfrTk=L&H`BOv2C88HwcXq^ z4}~n6Qp6NI6cCBex~36UN?-)7z-fq5Y&xOyqY#TCD?q#4y$3@QPUXXjTXz_;$tiE( zF9RQ2bll6uxhe0tYS`Wsyma2G9YcpIWI7~`sPx##s?f$Bt;FY_$=bMBCkUpyp;IOE zlNrvQA3cy62BYHS6|Io;4Gd6>mdq5PrIM5ZejOvzoy2G2&&@pwxb9L=w`8wSNrfK%A)1O|kT zA#VrTP=5`w#_*l`7+j3N92gVOvRf5WPGC*5VxmHD-MGg{P}!Neaf{yMP6H$i9?12Y z5q@$n9{Uv>IM+qkS0bC1-rquMLoRUK82F}l_A`!R;9>CH@ax3}N>CCNU^Bdax$q0U z5-^E%>5l7#h94vJ_zgpkWhI0&R5#IBFZGZ34rg;iL!7{-+uoRRFxj(T{Alc!Axen0 z^S^NPA0OZ28@8Bg2+yVkhpdqA?=*_KA@&qTyU67ySJ0k2?8h)?j772@GIYKegfo0G z!d~k#PB(XA^Jb4sF}PRz6>dMR-e-5p7#b6K3{vNbm-E&xBZ6AZIc(IJ1GK53n#oNK zVbRnOpiM!m$;z;tZ&v$raTn#*8sKQK0UNY=0X9qSPjac*Y=tpyxdKPyygp}+ra_|# zk{e6K+K7Iru~veCazkTiG&TllgFK45+J2C9FJmf>q0!(Nqz%He^Y-G5ZW?$s^57~! zG*gw@H*(2@QKxQ3oQol#B~5_eJ}&n2Yg=eixhuatBcJ6wXT}pfn@Z~JlEcK=+r_Hy zWHWTOIbpnrAbR~P&lDjTmZ2noaaEyARvReq_U}H?118ySdFCh~Pn1u5j(I)Jkf%bT z3F6V;GT__^8l~?7$qlSMI;kK&@xdHO^}~jNwa$Vjp`_q$>(<*_T2Ik9@8QTk;caKS zSv*3(rYp`)OnHAm&U6toYMxno8-WC4>CfMro`)iYqXu_HBwj&IzG)ANpGSy*nMM)D zhr;nBw^XqFGQiCjG#a;JV(vf=$>c$8%{*_U4sXjKz!$k@aBg?SIAkVda=|!TFa1wf zQ3=WghJ*PTr$#UU^oQe1S3Lrg?MbY#B9_(?sq4E7S)H&8y_K(|-v}NP+9}=|D7Q+^ zZZ3^qi|^Zv58?R8gBBtnF4U!3KE8~K6(u4Y!Aeth0TTZ7vwtuIF8q$WU%z8AJiUYZ z6C|nI!JE&^K5)tLVvpSM(G5fTk?wFHK&29%o>c z0KEas68?^_uMH36)k2;t^H7d$prM6G^Ug#*8njuT`m-yvUSbIFgT`8Gg9s}@XDrR$ zqp^*R{W`YRfWhb_KB?mJQOz|;`c4TmpD;6Zfw9grXNP_ow2po)Xtif+) zYn0;yEhm|vH*mPCBIfn&TvF(un5l&E?Nuud%PlKQg2$qvwWS6`0v$)&6@EwyIb!vE zv@ImiD7GR-lolE`O)*B_LLNYW!^=s~XK1fY*Uz7VYIqQmc*_Mm8`(#*FT(Emwu{31} zpMmA~!rJHC?yHEKvjjL4yUVlB7HaI*&}7hV?c!q3Xv0orZ9yr9W`l$pvjXFx?OYfX zBzcQLCwzh{2Z=R;J1)W>-{J^p1zW+Ilba&4krzz4or>jq8PL@4hw>HYC>0R8dA+*QJ4cLw6cndRSufC&q#1` zB~g7%N@OfkSr6g`;Si!_lFd;^@u5O;HWOHFsuCB4k4kbzH zbQd&iVS{Ex096A$f)v2&&8EdX#JZm^$8A_R0(IwNwQ+UD)P?W{&{q)c%$KmeG~ow* z{qRNN=Dl}fQ)Fa63=xWHAA?7>h(RmC@o9+6=V3k70AhCC!m(LuL**Cwjapm?hMOtRm5p(Tpo{3)hqZ2{^?ry z2t*j=s=ECw$i^9~CMnF_0xlowMshe)!}3#?8)RLN&z#^kg-pxako=3>Y6J^hM&j%* zmxbfAY!|@Mb4;xsKKmE~cSYS!)~ngb*NVA%ElZH)L2{Np0?|<>8&%={!$uAL` ze(3%!@N*GjQzu3%9x#OjVz-&BS6}_p#*}G9+eju+^*(hP-S`X-*$w^_t0}w)Fd`(4 z`Ph)hjuv*dCThm_$^#;ZCFFLECyLLyW3*Sjf9uD3yxZi*Bgkor)fCysH{26kpfjfY zanZn4^BVBm{AHAwx1xb-5bi(ixYE^n{nHIZCxAg!(|Dl=Hc=_nW>$to1`IE>9wjy! z@nGH60xr!tax>01*j##iQCWD(lJVPWy?%zR#V7wVY=rPUfeJYeQ@8F%pRzZ+c_}!+nE8R-%X*@`VT+?h1JH$_}tU)T^ ztNH*zg0m9y3VPFMUWj8ubbzGiRmJj9ztkmz4A%0hTZgxYv?nPkX~O z(FM^5iHQJ{)YA#+p@M9XyvNv#B?Cme@PA%4E>X%yXyHJ9hws+3Y1pnDz~@a9)3 zMw4k1rkz7S6Nx)mV*NH~uoK+lfR3|%ZSFuZj*OG@$h_tr#370yV(fVQw zQ{Demd))Gy`~C@EDXzBg5IS|RjN$ZXhsDoRsFYuCkl!ULX!s{|44Q;zP8_hbFc9Rz zjf3qndw5iCZg4B#qxMkY`3nt&u$m(`xU+2bYh zc*lh4^o4H48upTRo3%RVOyOeWv9tUMIt0p5guy!G-~Mq*&*)49iTSvU&Ow*n+;x6V zpwE3Qp}361PUBp<(-;jkBEB%@Oj_!D)=s1AZabCI;nU<)KR*cb|B# zV}}dG%14_{mU>3KmV@szkkUUs4<`wgxaB*#)m373qD4J2DfgmGlIaxLnXE?;h8B^W z1SpeXIr(@2yx87m-wK_;qCB9aRy^m_5yOEBN0#^>!hWtk$*4KiVSHTf! zar-5dFpo~49VAJci>A@ge4*x0)1ZEmv(U$}lLbE6z0N zZ=KDW_iGBrY^ev3cxy+T5F%C{f+DX3U^#q-_nvq{5DTDN@|gPOYrRigP# zu>4+Tmh#m#JhN~Cc8ePn7q5c)T3zRO(>YrScL&9<85whoE;(U^GsmP;njUy$GiY$% z&_RA>%>8Zg6=B$ko{3+y9S~a%p_XM@m4qf^umO!!l1kwP5}~f;0z~C|MMDGct1QSN z5Uw)IEJBHdOq#k7H^V?+P0gO!;RTc&E|}xdGF2$E0X9ES?oWGQKf;t%1G_XZ*P@8Y zS9Jy9MLEc9zqjSr3rBNQL(jUUxV)|Bn`B6xezh;l_XSp zVyyCx@!~Eb!Bi`#wx4r5vGlch0Q5FYVA?JC_ZSq8Atac@dYtsGgDlI_Gg$1#Y413T z{cunBBZ%J;vo(EH_)w*6||a+3u9*kIb{`Q)Vl#?O`8U zt6Q}JT@{mecA7T^43@buLQM#)_ITv6%;90%HDuJdTMETdkBbBng|BABXCyGwYZMn- z6D#X~3=i_v7#P8@30EHjbz!Cpzh+oty2)0rWubeE2X4^ZGaMvvz%)nWSPcboG*n7t z;gfsBa={29sOiyQvHDQM?v15JU1^N@$L8IQg@8iXi^6fJnY$T=g*?8bx{g{VbK%kY zK5)^e``?;2$su6Nc&PD>>`B=;oNF_(#+1ceETDtXc6XB8$QC>I?#Zezt7BC{>kP+% zDJC1&Cm#+D+wPz@+*q-=ukBK^2+%6(CD!OI_F4Rb(igxE?8$PzN4Yq&}9w7UsBONJd`jy;<;!w5mYj z0z(jr9~{NNHR6jea~35+hnjDvwJnKssaa7KwJZD=zKG#rJi12odHE^ZO202KW7@aW zjjcNWMQm{pVpdX(S{Pgr012q(c9r?KZC#T3o4xUgZ^YT3ynPuaWPs6`=Kc}o z30k;)C+?q~gD0*o!87KgrqL`fMR>GU&^F{c_$b@8-e+TfjJLd*T~eOLp;ZqP6Spk! z1?L;2F8zpG>uCJI7mi_tsq)%HEqF^_0_JRtiNTv@^s1tu>i+uM7bE5h!D%;-2o z6Jfc9G|DQCoj-GrmET1%moit;Y$77iY{2TPfxG)0f#uKc`Cm>uIDQ+=goA9CWkV|ne)9yUuYF!|#)#eo z&2SjhJfJ@=?TD4e)xdHFM16@AVRq7X4?5-4H{n~p<91_wlqWs}BhU?_Fs=f@^Y{$D zP60$Lp=lpGUo{yN(#8(Bh9#!SLQ^Mj@)B(#-61yu!R(ho*iW=el4J9eOM?sc z6$;cniNu;GT~B*d>iU*NPbA7T0$~@|?&s0fLGWS9{N>N=KYUv97|Hq`0v^i5BaIM~ zxwzWbFsQdXOa%>9V$i1L<7a3Z^*s}FVZ({DDW-%{70qGE?t(uVg0XO4f|;v=cOgj# ze9Q%+kD-{!>jG*t@)Ldc{rT^#-W;{xJaIIOgu+>;oH=5=CJ>&y4buMe>O)-2R3&A> zao&g(@`%-oj6<>L+Mu~lszvkk?)DSjfj5VxN^VmmdjL^yX-#x*-)49}CAxQ_4=_>!?77osG{;B0vTfTbYpQ$; zlPqAj!;7=aGN`GMlqjah;5zSYGMc+g+qN>@4jc2PAxRd0{my(mu)@2q&^%S;DX2DJ zor`dk?R!!4{uixD5F!b)(3Vy6WF`nw#HFk;CVL=dGOZ0G4 znV@KyAQq5%*yd+qhjI5l0k@HjF~SsOFbj@iaN{=joxmb}>Z6GM?Q3j=X@kMDgxrps zshTs0Aa!~3FR@E6V{uPXLgMss`BX0t*y_Nouyiq~ZM0`(i>oL*4!Q^l=^j`t(4TPchP| zjY)$Xzdq$jgm~jSx$7D;+L4vvX=IO)JJ4ZN5BlO2HjjG+Ki*CD0_-%h5R-}F z4W$hI|He~Zn-8+D!+FjQktKGdXJNcmVVoNSlbmd1J!?%w=SB;5_#2{z3A(k!tFjUW zk9dCHJR1h=0o+3OD|!LN$$$h=hp}Qaz0?m1rV%|~eZXG5kTjap^*Gehaw%(a97e)! zL1HlRGr4{2xYVJh_qaZ!Juhl^7Gr&A=@zj8Zb|RJG*><#18=W3Bn5@;z}SNiUK`;%K`24VmiT4*1Ml z6+CB#DPj=q?NJqAWFv!tbrAkv$fvks4KSK*56x0-Z&a;4NvDxp7N0$$Lo_1RfN@AiE zZ=6LWBsC;e(yt@8mHPHe>~?PG^kT zf9i64x$4$SDt!?P)vB{6S!g6)?;KVtLa!5(#3&|`<=PSqFd7fi z&G7^v$Agc-wsXGG7P+gwdEf2Mt}i~W=$rbK3OfE~)XBw1Jamk45vv>e|3H77W}IDf zTyQJn0a_3;I|$D<(e^{Auyy{$ms|%e7(LFeZ4@K8ehg$1VzJPVULbu}_la3(C^}m_ z#>Iu#|Bmx_0*1{wX{@(_=MsG1EE{8t+1GAP$gWj~4ZiW)K+T42G=b#7Em_XVa`|kd zU(5*7BdC`I@hwtA?U;u}nNLQaZLk(!f!8a|^G${$cm2>?;a&ra1CWOrT>`~=w6KG^ zEQsUVl9bakEiU~`moxYoK4XG2A1c+g+BRC6hEVaJF92s4R>SWH|#4f451JJun)|6uM$eQP_;U;U>9nH3{ToF_P(-b|I} z_Zdnx+GaXzo*u=JWC^e{yJ~Ht=xj+~sJX$b0dq~m!4wRBI4F!?ULw2@OV@YusLBOE z8`E3H5(GHLz5f^u0TrMZ}L9i)j-%B#A8zp8X47h2-CvyJbTC22VSip zxwu7!oA3JP1z)Yj+l!X#sy2DJ%F3$gt>ccGwU)*$lZI($J=bA5*cLNgugigKw<`_o z(*!Y{BhB^W@|MkQ<$(Cn`6_HgpUh)!+!c^mioA@@w z$73_bBn3yCKF zOrp9i<|Q>*i&-S*qeflwC+;1&&gO&hs>Ae4rg1z)S?+% zX!7pJe4_`5Lj-uEeM^t<97*GBJ@{c)NhbkK&M?P&p&Qp$TB!^}^^*><7~yB;ysOK) zYpljN9)&TI6yh3JxN*hLeEHU|$H&c|19sN0kn;wCNSHiKf#*j!hKu=&H!AvTUS5T< zs0S~x-$x4`W~OJC3?s&b0Jb~!9S#?^CD?R`1a_YAkxJ-qzDE1&YAgF}N3cj12L1^_ zN_k1Gq`_U-YQMn6$%~h-CHoE?YPj zRNE-^B5bLM=s+l|{Hb2imUtsnnvUXnH>?^7>WIfw4ET1Qw3iRMAyOALiWiewi*%&!8aiw`}R3A%&OV59WHJmoKkFWXy(l)VnCl_ zqlnAfl%`m|n1CSt6ng|wljRHGSw+~RXd-)v_yQ)Imf(>S{w$?lt-!V|y;~-}u0fw3{Tq zgAtft#{M)Uc5{zun?mPhQh9K_qe_H(xEiqNGJG@`6CCBjV?YT!0gd4w!QI`P$U#49 zzKEWM9c$JHTK8&*Me9y{%mF-W%`cd}d6Rw&E>=-fN}wr|&F-=NHr2_Nv0Ib-EvbmS z1Yu|-rqWZmzCK&N3RaXQSPV)X9Bnac-bX8QGd1x7yW5=im8mNtZb>W%VXI4O5n7L= z*G@I>2ev$xfsxF#6bk$tUbpfI0Pl*VR)E#9zFS(fc08^S%bBo@B6pIVyP8 zr#`b0BoGjq#LT_14kUhFy0#fe$q}a5Z({-85q6UddE#`k28eZL+LzwWhzr_LNvO46 zn_ljZd-+Ow4sYSb;4wI6k{jXj1Ltt^FXGF;fAUoREKw2iU?Ltn#d4{eG1>j)f*D^f z7h)r`&KmTErOaSnu1QKLz4Zs(iA96Y4TeY2;7LW65&sE7 z;-bvi=FflnE+wpW;e82pj++ajj5XJVCC!nHOL|Me@3(WlZ{dE!3ho{^c#`4rg^RUA zA7~Syk-CFgDD9P(deHh}YW>98P@#c`Wze^tK%A*?g@} zL8g&*3<~!XZ-vNnaIhCtWmO0v>?OYpC}$sqcbOopnCtf2W+-{?81`=tXM&0;@Ou7ro;SAEOIX%y6ZO$)@`VTrOzw z_}?|+>DJ4Mqen_!;?semd0CQOF^CHPd%wb`Z$xefKupN5aFdQ};lNpL&M=lm;U?jX z{SthzQ_jSrz{g;0GF7LmKh!Ap_)yn8rV#f*omH_7hLU`>K#GG#ZSy~xX0}TnIADk+ z!C5PvIhjP83+23oh5)|6o@2cT5*za>*vk$VJbryjEjd+A%2Y690M>1asmI)xOh+nc zdi~@mzpBbPUDP*mG;Aq1L7W^BIB0-}Dv`dof`L1DjFxLcS;ce13KzW>B;_B>md<`;^$k9^Yp2d@WO&6Kb3D=lRYYDO@*VQiVH@=}Lit98%RYck6 zk{4fRxaXibFrZ(1jg+D7O{acjtkOxJp2+wO{zN#-pjS)KhACE~76*jPahv5WpSfXj z!7?ySRmYd^Hn9Dn>OG=wk0ToPDyj4m92{Q5^&JqODY@1274#F zymdW;MrQjRZkyBKvRIfe;VJyau^6Xl3{Mm?& zRbsb&-RFEP-bBsJ7KZV0+<2aiC4|a)&cKjY7gybdoAXZir@Nj@d^-2%;$+t%nV?3H z%V$vaYIQn|E|>n8J?*t9ML>kVbIMz?II;Ixz^N)R)qyKu+nmrqW6mhO6P{2+p17ep zll!NoC)59xsvXv&M<>c6#ikpavKS}0A7PYj3a#l8!Z}`=y!vSUj-d9rrQGCnqEl^b zusoSkaN;MUHd?>yKbjqB?Y}_@Cr1L{&!UVngj?pg%6Po|jMEUDKI(JPu(BUUl|}3j zCYX&4re2c4sLFb08yPIis-C#C(zoKV?x8W{$s|fdji=Y|UTWfyM3|V%IQtUch$}H{ zwGCVLNl0$E{I=TI>3IVl2}xr?EE6vfYf7!nU%zu6eSWGUotD$t=kLa4w#mLczrT6E z#UsO9PgUW;Pl8ni51e4rC`p`g9f>|m+1DcU;g+|4vGu}%^6KV}8T7OIGDRbw4QG$7 z8YH&3YhdG)g&CKwzF_MhloRcMH5R|Q1G3eTZdg&t{BUgRVzJEI+rme*eG9`vkkO-> z>wNR5YSq;|3}z&F`tlsH2r%*MeLok89vebgZ^bwHW^uoUNzW<9=a}#zZ}iD0?Dkps z_5RI5AK=zsys*DPFhknhGl8b=#W_OtYQY}04FlW?Vpaxhq(@~v5ue_b#LDV@d3sG$ z3$tcKUuhBeb%g^!yqt%Qu($ub+HE&H>BR%?D{`0iG??kLvlPNWTL<+6WZ zLKAljw7~Rz+Z|yu1I#4)J5KrBn;*85z4>|1|Pzi@EOJxMZ>VfgNcv89P(U@ zXt_r(FufZO-C!T1jyq5jt`%MHY{=Fm>NAt4t-_^UanPM^J@b__+YVY%uUxp{4BnMQ ze6AF!CH=Hx9hYPsYV}Hw@D)gyfr-K)Jde&$R0fJmKu~Eb!YPcDV%C(g@C*k!(}0K+ z*)EV8&TQxX;nCt165i*AgD)SzM%rX=!>9^t1)2J->Z`^3ZY?J!F+1Q@V`mgW z@5dw(Ly`a)xq!w2O5{xZ5*P%oluE-G9pdIWPQADmuRa%}5w;sv3C?z1Nl&+FOCYrn zsR0`vg(!8dQSrJa?nXOs|ym86Aj1y4(|zJ z-+s(o0wxOHqi=6*0aV{#Yr_xSe#rnEV8pD0L?YaRFSQsCRul8|0 zmSI^~;UPe5Vgta17F5NJ4RdZwWEYk+Z0bKi&7}d0QUfH~dXBuf9b#-@Yr!$yAztn# zB^%SSNT`ORQ}UaG^H5PcDvb690WDktg%W{o+USK?6tL0;XVe9aGq1RAoSU6e>zjY=L=d|9*$zUu|zdTb@|S**5i4 zt_Uw%T`+3e>8+Dd8j?!#7j>#0mxxg477@xzFdim?lS58?@a5i^9C5<3VvG@l3hr{y z6z`6rHyov7^FajY+Mr$q$taw@gigb}$zi3&Tvip;l#`N&s$f z5Vl0ZF>KBj2biQgypFwKQeg?kFhXWoHFZ^<1MQD&aXOmQ4MMwfyZf7=>AL#&BTL)w z!kBBPT8GeDohGqA&1BgW<7DT#i87u!^yXi)$a4He4Lw)kC7@8if50!!FDcfhOcH3p`~k z@9G1#fk-qWfyvwJ{n2mT`y=>PE)X3fZ&Dx4@e8biV&BtVjZXWc_>FT^-1kxB>!(xhUKs_vrnH&J?Tfj{K1pPK_Srb`0Lxjk{r1Rg3%;%p?bXp{2? zX@npHxDxc_S$<2f29`00KT_u26+w7p4bXg#b(z$pcMA{9ZvJ`ni)66)=C%%WiE{_h z#c%M|M?EwC?a&Cmc?hs74otMx46;G1Td&kc`o-7?cQ?xM1K*dX@ZXAjmYA#~&Ihf} z2PKgD?ZXkmKtu?*$4YQ+dFb%VW1%|I;G+AIQ80FuR8;1@F?kjbfKJ%oxbL(HZ3it^ zEhW^VjciZ39`c~LKe8w#oARWI7&B#{W#=PO{z!UhFQzwmNn(A(MV%C5AEo(kYLBCa zJWJy^VWZEdw1oW+JtN=LV8p}p+GzYP&HmB$U`6~!n=QRNVlhuIc%t~t9Xw(j(2jpo z!pC=vzU!O&HBPE4ZqA!M-`s=^-2&5&Y+uXi662(T{G;uX#<0dVycP*LqeXGdjO^lF z?2n+MEJXx_9LCN!cXRPVoz0~p1+6%daBEWZyFbwcslNsS&U#OffKXl^Eyz-Q&v54JIl!B${r$X_1WhJ&!g##IB6{54Y)q{(sf>+>}=tn%Jn1 z{pbtuv{bblvEpN-%kHtQRFWOhqorMS1;&vx94)wiOHPA19to6mv$^Du&5B<6PA(gK z+faOh%q?6qDG3C}(WUp;_KeZkJ$(1He9$+sfA9|EH@9-2Gg$LD{0}x8qjw|Y|4p+(Z1Y7>mFlZlg)Dz?v&gNRMj(a+e=A zG~RG(ItN`A1pW5Is}cDJ9#rdfZ*Ynt&9D<_jvf~?WTb1 z!QRaLHP5$K@UUZ^`R^NDK}@sxK7NIxSyQ|e7Oo?|tZyIc@saX7+X)_vWZqQ$`E zC4~NNa&% z%n^8NNv6L|0$RI}mitFNF8^kYoByTIAC4$ozEHy8oLuv4_?HFE{{}sTzgW zL|%?v^@G!lkyFBXAtMXI%~MUTSc=1k`*XL3)6+e*>50lTiq}xD7!18fFu!?H4C$0d zP!bZ?FdsH%BZrVmR120^9G~ru^V(i*#iazR}{ z2HFMUK6t|%;V6?ZsXO;>=&LP%%Z|Z+a{cqasVV$#-+cMH7B}R*0K})C7jxLS7Rsvx z$YE*QYiPDNOM5Z?7G_eDkkT_+*Z#M@Na(+yH4)D4zwBQM6o`qB*&uO7DlBaA5hb7t zK5K4~+$khDScu3I5M&8+^Qx2CGXog~88&Ywoqaaq*sB(DMJimdam6*+Ys5@`VCr^Wh*bE?9WcnnbQE+-R+pvzRBX%a4MKr7#F*-id zzggCwh z1l4uXeMP*3gte7(rv~u+?F@Z*yoR%oMZPv5&;?o!xs|ZNdcMNd>nUK!V*>#rvJ<0d zH@=Gvnhy~~lV{IS!nJ^wo>NO`ft7rG(8c-&0A+rs1$T@qWHSFK`W9U2GXdBg zXPMP8E_nbRf@ddf>?VHjs4YfT0py~?sH8MM0vSgs(w6fDhqKt$?)LL*+i==%(cKU( z+2&HQ1TD|;o!q`RfwZxz6R+7^&iCHnGU|WheF`3eQE8Iea&=sw(YC*r)+5Ce)%pm) z+}DWlb9r%mn40_iH+aLIKzBkWDllZmJ-UKUiG$$bIqFl|N6oAKH?=iUilU9w2O98-tVTTSh)9{{coOW1E z?Hsv9a8LLP?gH{r#cqcPTBJ>c7fp)6(N=MBW?^|+QGEqZ?eo*|y{48Z!?7MpfsPyz zUw1cJJMOIDYf4w8!tjG$atm<#@@^wUo9R!Z?JGGyrF9Y05B$HmxsyPI!u4M9b*rU+ z|FZbJ(9{U}n{E)<@lB5ezLk%P43^-e;RN1o%HIxA1lt`x2fC6EJtJTVyCKCat?6&| zMe0Bh?ai1GpkV*UnES!+^i2xUCN$LV91k5)=XMwY1ver4q(hn_nGou<2@L>gfbPR^ zhm+0cx=KH?Nqp*<9Tf{bMu`!CLLYER9_v2xZB3WEo}z&OGf87EXv=Zy4{J^TZ~&|} zUmm^4QO zsz5bHRTR2pzzWd6p7_GZ^$PTEz&5FgAJ*Yr^qB2{3uq(~jFDz*VV zD7VZuj784R+2Eapk7ThKqRMY;^!#eEu|J{dVZVcMrjmxd4+soRe6BKb4qkW#4HS{3 z9?Cw-AtJQ*LD49Z0x^rKBC!yoM3fLOh0zGbExT@sNXOJJ?4>q*YZ=%4$g>D_N!h{Dh1e1`aaa`*|eQbB}gE< zM)*EW>s)F_OO)DF%qj0b>4NYcWDlNN(%-2KDX_h~{4KiV_f*B3{oUKFy7t1r;#Mbq zaEpxNkNAz5Yq8jLy--2quLF%#Q3SrSEq;bdj}jYs{0>in@tM-8!YtE#D8~eg1S^is z|18o1HGRQy(GyANZ8j~nzPCQjm!5e-*Y0S?RY6!*~)d_KS{XpBp@%iXx~D5>TK zz-T<$Oua~T^S=5W%L(vwb^R2siq!an?(IV#s(rq{M{bMwdKs6mW5Z&Lv$vLYxMVAK zF<2h%xUR!+AYr@(-6vV0G?)HH`V^J@9>L`Or`(b}Zx4&tLQtw6Me?ngpO~3h+MUOR z04fKllI#vX?r%@Ky__(kDcNvfJBuYu9b@vB14MfCfT36{8=926m)+gO(C0c`@kowH0wVyP-olWo?U|KqvrlE zPk#98Uw)Wab7=_idV(QMEVu)#G`aQEO?)W2S~@C|=;;}@0AVBZpd*#M*bEAIOq}5Q zpkpe~gUwW+C)OogLKNy3$iGyrw zgC+8PW02V)9D=Uuf(Oe17eWyRMkc!jGU&(FXrgE=CKEQWsVJLN4_TPw+>!W05K^~w1aZrplAFaz_96l{>f z3=1O)+;?I`41VTbhnyJv*7$X6#`gWeAvkSte9nNv(=G2ADLF?sj*`2;Bu7O>sAwhD z1H+9Zgfr3)(2Yx`L`a^c`Y^$Yk;z>5U6kXhJyfHO&Ugj%&kSXuL&}+=Ipj(ZMEY zsI$irsF%*+7%HJqHc~BAD3j1YPl&}QEU|TlE zM)|j-!Qz4nbqaeFUg3xa>+Af;PJYuSG{Zq|iPlEZdrRR}W&sM}Ip)r()ZDA54b|C?DGG>Wrq`7j_6jqmHfwvt7tuVjqkpC{j))3~5MXM(N zHeHg6%AfcKhEDLqM8E)%6Mwd`pkJV%x>8LgF$(=|wnDCB)xM3!CoYgVo1Qcp1kpo*DsGd1smh-R~ zPdNpaD}qvDEjcN~pMtFA-3O+QmtP2o+TrDpm7~CK?SHynOA&cLKK;{Qe|$2zzZzps zsQza90;3uVROW6;kO@ zc1>UJtz%Ti--F?3A#b3}kb^>gi7h6nL+KAIgR(FHc+XlP)e#}${yzzy)aWJ#Qp#Uy zDKi}*{Cl)YlXarMasFhG7-%mLePvSqEH;jtaKIdD;9Tv!2K5|>P z5Vc-He@}q8;!J?72Z6@^o^ys&6MRlQkT%1n z0q^Dg_`{PQ|MK)`a@h)un3r*%497th-zdRt;sWyJh0lM%lF;kHOm`7{)3U+yVB(v4 z)qU>p><#XkXv`muLF5@lIS`Wub@m=3KM?lGPt6*^N30)ix?o!SZIrrH zyAfvyha1@9)nSNf1~HeH?dhczc|?tTMgFDtJU85TQtlLB-PxOu7$~lH7$u}ka%hHR z=x7DtHQ8va)5&3}lyiq69heeo9P!{d{C>8PiGW|3{ zrV=tSTo9^R@*)eCXVi`N)M_b>HnH#W6$WM3oXg{)HyV|99_X>ih9rw$n=2L0 zy=WUVE4cwlrOqm#Kn6fdc3e(Hnb1@K8*N0}=^5{@uBd#h_eFT(oo%Nw5$eaP;FpE?(T1#`e z3X9P(=tn}n=g82Fvt&%3T=zsBBgbDByQxAI_BhJ|2{TC+VFKN%PNoB~c0 zQS~^XM_$4`a-s_>64rnz3F2#DF?)4wEWZbtXJGN);HKm1%6Q5d1mS_q(AKrCRfvLz zKK=Zx%zuYax=;sA#PX;A9pm6}IdZ4^!Gp|9bmx8jwpjBx%X?Ov+l3M>4_O(TQ1#)i`E^FswiUPMJb>g1sYz`YQ-AspOe-ExY{AGoHs_|xiax7Y&cId`x^0MU&2+B&&_yN}TK4?u$Iv8WX4R*7xaiy(4cjTHrY4!wy1r;B@)Q zl@B~b{(Q^C1c?y<1XTRUX~dY2-+sMAPXFGf!h)%>z{QEZ`(3Zflp z>vqQm=T<#B7aQIpmPO_bC8Ue)rC^Tf4#TNHm`z-uoxMqt4Lgb9oZsduz%{2wate2O``tB2kHEDwA>!>X{20TY5YF@dB70StQbw4xF z_x9cOm3mOcAQ^Th5`DnDz^&}AefRzUeD~zpchBJB{`Vh#`0?c5|9tZOlYjs5<&Qu7 z`*%P5aQyxAACCX}{a;T0Z}Jx$jeF6=A;TmiPbHnmu=KlT>7SdW-#1JD(k%Uo8 z&`;Wwe$poOlQylNw2A$sP31htej0-vnB?0Qlat3Yx@yCWcDaq6>D7HO z2VsY_lnXHeB0IXNa*fI#)-_{Di!+KbQz>Z1Igx$uK3TElQG}kT``}BSDt$X) z#|OGojR&WTx$+=tS(qPznh%B_obO2uKG-yQqPt0pl54acU-u{m2DTnYKRAN7c1-;+ zVmiKl5ZQ&t#B)-Hq@ft{BhjYTKiAlgJ1vi1k;PW>NQ^mf^r$PdIZyBt#+QBf*NL^Y zg*mahwosE`jju`=?Q*^1h${w4t4uSV1w9I~07&g#Q-NFKP){D&X(go!?sC1~Ax^%O zh;x2asw!iQt>xP1xDpOI8dVswi-`F)1U4QbE|(5WG_>X;+qwVV$aOj;%DAi=nw+KT zWH3z47X2u>F@KTz^LVZCp#An3Z0>V)G$ZUMPoI7_ZS+l|Pe|t^ej=}IS$NG2wm$Yv z5E^i!ZrC8?rdh=DVl!%{6#!i=tlMEQyhTg z5bCUyfOIc)ces6y9(u%jZH;B1#Nju}!#$Xh%fX7$sn_A+n3gXPOH-236WKB(ZwK7y z2$<2kb!QvW1IH`wAoigenY=j2B&1C(8vqZr%0qXy(JdWgponPN+bs(V@vRCYU2_`l zxt-s8_rm%7&6z+pR3~;lR64xfm2HUnqCn}buHaqPrKrlI%=lV5zn8cHB2)xHOKWrU zZJPk3a5|l3)`WMHzpOsPR18jWd>MGe8|YRUyOx)o-o_r4)Fb6HcRB&IzRo8jmBpO@ zgrfxHQsidWDqD%2p6Rcc5N>(A+1+jY$>R&WiA6 zhNx3gf&)yNBhXuDtV9e!7G0`{fp@;|ZWT9*3I$!h>7+u)u25owSJ%_Q2gu^OL%5Ur z4K};0LJBVM^d2Krj2D)<-sGT)me9j}(L;WCuU$zny&wJC!A5NVtla}cc8n6u?_Z#C z%;k(E8nr>o2Ov}gS@IYVU!Rs)kM92PHYfD(k;4Z{yq*wxB5O_L!zsC=Kd5To7227h z1q`z@RUq6$VDdo4izquxBJJ`lbAU^NP@w2g>oPd)TvfFC7lxsc^U3`q%(d~&>=s5f z>r{eGX2mvlPq4`Y=>AXQwT1nygY|J|SdJh7b|p&hi=b8}xKq`mT4f!WtQ@7J-~B`{4NIQJ}C zE5?^mOhyHUZ$jq}P5ZNfCKg@^Xgo(l6 zLz9_Ll9)jRU2GkuHcdgl;oXe7Dc+e>2J=(wV^iUFjRnz$ZixCzv}9G1`m^#%61*QP zv@C9liOCCLwXFlmd%Z z1c|qYp~qyHbwQRebw!=ArwBwgshFSnhqR#4dkg3lF;^Q6M^y;hU;f-2J*OcY z9t^kw21Oom(qyEiM;AUxqEDg}iO?I998w6}KP6F!By13I2$s*8LmiTIa~nmqlnk0+ ztKhw-g=lp0JHixLT=xSjj?;-uu<4OXoKmUC70o`wu@Oq8y5bMWV`%*X!+-6`s8P&o>vB^V5qLKfQQ+`Rvu%vzZnh zUtGMMKYMra;(S;z{C#;2%+sG{C$G-mdUhq0`Q`RU6ut#dv$s7 zpKo3${HGTe?E7^pvbLq>3w%Gj5KT~VXs}g>Keqa24VT^Dlo~^(Qk+hgggP$ekNEkNtv$%e) z-do&c*h%_^?T-2J;C~Km-XF!A1Kg5wN%;>xcqQmB`kuFok!d3S`t>RDJVN9aYc4HF zCKmzzrMWVruth;=yrc$;*9)X1`VbX79FRvLmc~!EI9g#)tW60h?V!A(`|EkxU^C3MRO{>A%0?9 z2n>ngm7*{gfII%PMU7@ZQuq<-@n~= zYqPE4!>_hjWL&en+$j?utvIxp2Sv*M7_K!rKtjFgz5-V`eZ0}o@TqSI>^$mc-N(ge zT-+JVFq2Jnh983Ic~P@zPaQ>IXu90DQLF)n3&fKRR6;!9;lSW%w4I9vl?7B3Chz0W za(>?JaKRtJS6G21F|U#z;wl+}_^+ejZ=##-esWtz2l`6^p45KAVK zF-XrWrGompA!CN+zh&N8nRMMO7=Er*(C@S#az>K>4s9tAp|XJkQZ-O$Fi|`)ic(LK zVwlWCSGT)P62K4$X(@eIo4L5q;R+N z{i`irz~S$3rQqRs^?pb^B8u5LuI336{zK;tGd5mru^GVpHpUj~OE5FW;4(fmlxA

4@k}u*szz3V+IxHp>(@R(*RlsOjS15%cfo{zd2p91obkvE7 zr71Vea+g!=fO=hP4QB0ANc`m`JkG{EWCr2*+-6q3Z?Ld@#DGW6^#{#+&qaai%*NiJ?9`L&H3$w;!P< z*Ld`o;zId`A&pmNc)lxtj)5AXXkhuFyuo{%&>CpvL@xiW76{26luRIs&|;Zv<2%%P zEQ+#04Wzri-Yxn)A2mR*xMQqWm<}T$eq4}=9j#y;UqAW&uTTE;=c(+%rZ$Buj!AQo zN!uX%$ZA(CfmWl%L1$V!A?X|Dly~#|ove0OcX*jX@Bf)MhD!@y3vvY>Z*-N4W#Qn^ zDi^e58fsNXbL#BUq-UBgt2laD>VmH?yQC#f)gX49cFB*^l!`Hxz~7(|<+dvQ|Gd5Z zZync>E!u_=7=DIf7)B5TK@fYAT#d)qlqia(6vy$UCE4cKvNWb7CwC@Smm(>N5x>Gi z%F+xj@ZR6_etQ4iTdQjAkM7fbPWSGPXW)oucUA4LTD5D}{z4^rJm1oi1&M_SpR!Cs zlG-NxG)ROW3X_LzQD9;+>EmV7BquI&ppkqgn4ku4(y3LO$yw`q z1>it(cT#H4)?`*QEUz^xy538%l^eXUZGLGQuhD@`Nk>QL+b*;Zw~m}#go|W| zoM22cjD|JBASRLc+xGJ(rPAR76upZmTi@#@%9i)KiL%wbZXz!3-KDRqMd$Fe3_A}O zKjKv#gm-uXURQ}K1^s9#jY_Y6vcB=j^#vBwY8|M$t!0fY!y4K;-jJcu8V`-E#PO3* z&S`vAI#Iq@v#*g}ud~c02P{U*Yz4wi;J69x>=ftK&uJ-M_~j8ah*=qfdRy2zQJJWS z!@w)dBp@2B6Bltgv*kmmOjxUD)Rs?6B{HU93rm(zzwIJ@Pzl&1bBQ|N5z3Yd<#6*= z9s66)S=Yl*+5;8puT$l6=xt+4Q2R70ss6ZO#a{fFCs6b+weQ2V>dSq9)LG2l$uTud zQ!5^A#}7NBr{O4xsWve}!%N^w0RG9s7MO=?C6AMGm;oPc(OR5Dnbds4m>rTqPjlPdQoi&LM26Z*|m!E-?N&`e+(g0|AM7Yl}AmI5<(!5gx-wx z_Q?7CyHy=Gx%hHP;!8&gaq(=FHcuCtq(C)Q8 z3RnwCmEPh*vghX*Rd`iM{DJIVzG|;7?~1|n3UBWm9vnpmTFCt~U2YGDCN$3W`K(=x zg(kK+&7}p^N1=1Ke{1kJkSNYZ zYMrO4>dwX=H647W7R1f+}ZM2GfE|I zeT(m+-sa|}TKPDIvVod&A#+{fPAL4;rpg%*+I2N2XsYDl1@3f@?H7Ef(0dtYaNEMC z$dlT|dpzTbO^dw^hcmdifq9;0xs*SIq|hHPG=1suCaG=s}SY;xqAuF zeuL1<7@FvWQQv$AE`y_cT@dU~8Z!^&#%vT3OH76QK8TJSBAb`F(`Eozyq=)*ds9xA z)d+IBzDGIjpu>V+h~{wgPn{QMAR)WHmdy; zE{;Ew8;XdsP+RA8*;4UF6s|v=(_ut_?S?NiW0@c&`{b8~4D;?Vy}E^4+hAmQr!nIH z@a&IIE@o(GJ#h*`yY z*78b4J*K&J{22Rq!c-EBc3)vVHT7$lY;6e&`WNzcPcSP(BPk`!ef2Y*UT{9Uws+Uo z2fW$+@J1NJs6^bxw7ZWTbP%ceYs|d<+ekgW5Gl5~1<^NrLyHfvdFns2D2c_VurR>2 zs?=&>;W7)7BNBOZajd9BmY&@}`4BJUFfy0N)>UaR@K9Fz6{7LFI5QKdFRm`$Ms{ck zdk``z{~)pPN090X65&Y9crgJ!{gHj1rRj~@Ab>xe-Qjx=!L5v1WU0ZF09f(tmVN=D z7V5D_b8eoTzT&8aby^J}Ar#T}#TkL8(^qB!$eGh;i6Vt%09>=kQ5OFQoQr9apmx?; zY9em06tZf5NGx$x;^yJb!4c+#9=ie0+?T|pR%3`ZW2mLh5yQCH?virB}3>nut+SyBRYS2b3u()Bt7*7lS7Y#wYFkwpv}7g*&bhx3|?< zc6xR9;=Ik;wkP9+r$gH25I((7LYzkExAq44=qRqtCOcI~V6=$gyhdsm|2#RN+6zb(lQT9l}4D8WF(tK_L{Eky%LY#!M4y{&LFZ3zgfA7lt|jRxh0loj``+ZhNk zTv_-f)&;q{pn-&7IUC6gx|>Hb&yhLW^t0>po-Dj?1}D0LivrF%m>KHX_=ytu!io;9 zM&-$_sFSg%2VTMish%2QuB|NDN{og%3*}lPh2n+s+&kfGx!fOMpZTyl_m9}Z#I|*M ztpytPEHsRgA=IV`rYC+YgsL6Zv1R_6rBHICQvwyN2q(v0oJLOtnoytC#fy$73UYd3HqYR6I7CRN8$e3LBGb?6wjIGKyFZ5f7pA+Q>+gPl^tbY*dgGJpc+$0_ zMd#@{+H{^UYt=9Dp7(iv6Ir5`iBke+e(`GfSgCMVe9KLZ;YG*uaWU!~ceMPQ9$aW= z^v8W*V&3 zpJ@E_ePQ9NU;7b$*&{WzANza%dU9~=NmncTo+qtUU!38w#$D|8jBFQA5Kjxga_;o^ z8ZW**p3!9uqGJLk53fR^ZMD0Ls7DajEPz)AMs7*pVN0s-%ABi$OTb}d+~*v1w~9rL z88lK1b&a&95TE;5Gzd`)zARmR!QdK{gx$Jd|HbWX@I=lrOWxl@jcTN|k8t`4CD1%P zIbfkVeG7VX`~1h~2c(T+xAq@jJbj28o~bGJ1EDCE?{EkAdmyTH&SGw!o$c^3X<~#Y zcF#Y#Rv9Swa08<27>*?)fW~oYD$%Mltve!27=&{_nLb z)gKw7;d^b^f;jur9z-FHwAaLQO){>nEBzDwdtLwDFd5wC>iqak{&mV}6n*{5BS~ME z^mUbJow+oqow$*BEl6N78sApKw`=p?HqdGd$~4w0*Byw&bpTgtxn2}^lz|BUA1;Z^86H}Ay!)>@k4nl+y8d6MT48LW#N zHCw&0pe3$ei3>V#3V2NfjzxUG{{n%v^q33>SVsHMYE(US@Kts22J40N4Yk0A)MrEL za$SmXo%D^eU5Cm$_jPe!mjYiG_l=gWy%AOAMoRo0_55?KrKKk=?> zlnbe7A@oF={n^!C+{~WDwV@W^?`#3sHJ@eCPny5TtP9Cz78?b;X2o`CIGm}DaI1*E z^A904mbleWvcU1Wz9xRr{Voe9Ri3a-<>y9`ZF*;&+Em6H?K)?0YgFzkP38UlBU@FU zS8Ib4`Ud9EPVI$5AIU7XfN<5!uN+hl6?rf;)ucr`R@be3gdWX6vz%@$nyIZCb+y$9 ztQl>G1z+2!9zCM-aWyl2c3LM1#+J z>zoA+!P2%ce4{tE`D#~4iX6D};M@*I-rVsEQ|EKIdcCb@*IQfR6VSGem>aF;YooQ* zZ;;mClHK0LK5=`H7~PG5;~ZCpaHW`k1_urg6e0+PTOZPHe)wFd7N0;v5MpoVl=HW_ zE^n<>hna0H=W45VthTnxsu`1})&X5;EH7tx$!@Nkt81-rTYIE2j}O^=fz^m7*x3s8 zX|3zERvfPbNN6g{ah<0yqDPw!;89C01UOf&s}86JWLjGa4b`R;5YU#425d|2(5!1_ z4Vo=`jpf)r#vmWuwIK}0`NG##uFTjeqz7YjbA&(Ix1HKVT)u+9#WJ*myj{x%fTaXUp`pYt_H{ zk-l56j(3i1&a1s^eW=oWiz zkyv<|SW;A|$1g#)jbKc*Mb1W=C^xx;gz0u9iwS>h&VyFb!Hd0C^Pn4MZnf12Tz9v- zL3`ccF71du%C$Db&^n^52M<pr(E_?tGvAfyabs^c|Sh9}%~tK40;DxoAO)RoFF2W?jNPzF~QLt~6KM zZOcZR&Ai5@l{u3STVKG6s8V})(Rd*GIJ_Qh1#fBKYpr8e>m2Gzo8`XpXw8dueqgud zzVha~`D}mpdF)yA23%|0&vfhL{1^`*+2OXMQ&=YFF>1FjFhYx(o>Mj`dX(HUYOJye za~k}F@ryXXwnDZK+5)K_W3rybyn8DJE#PI>KG(mt_{;3Ma8#b7Qkq=x#V+W{$@2%N z_U9kD5h+Yx?w{Pn9otxGIi&rI^}@99{uwt^aPFC>Qq{1$64rHNE?72at%zN|k(H-M z_Ej{l@n3LA*uL1^#iG;xp7C)`+yu-zTe2SeNYfDZMEzUJr)7#_vZ$U1=aH_3?1p(u zP0PS|+wB)ShZl%-hK9qg0XtJ3r7?W-<-tofBRb0$mwhO)mSM04L)5_@WT;(j)|+ZX z`x7W`zS_m^vM8HlWBjCt)v~W>JlAgnY0&D#jgqNK%^tnhqDgD!nl{>sB?w6~oVcf1 zN*SO4{?XQ#>)+5%{%x+suAy8oWKj%SDF2DhZ>q#qYD7+hCc{q-IoRpy*-)KOSfEGy zRlNCQ6CmguDk3PR=7~i?vowehk3h;PPuMYL9Vvm7)^yI@gDJ*d#~mnoULFF)Ki5)G zAMRE@KIbrD1;2{YHJjm@&1ks5u4hhSX;x93ES<6H_zkYaoTRHZKBBE!0n6ZD<6B)K zii_`pM6d~%;c@S@898*sZLEp$`V=3cEEOsNHiTB7wYH@%F`(gLJ9P>&CAUO_FxzR< zkoC4v0<bZ5X9+gNz!oB(hd9yifCqblU}BiLhDf$1S(W zsxBUJZE0qBTP>+;Hkd=KB+(FfDXhxp*)gMJz0g#INA``Ou$m1)W5|9HlzD6)D&6tL zRX39wl?j@#4gJ&wZfWmMBtVy9D@6T*x1iA|ZTi;2OW30UvV6UDQKfv7Ud#()VlAVY zuVZ#r3*E*k7O>M`3k5_=bBE0f1oSVk3T%7xGen|psee5Bm_ySI=YkC>RA8tSFe-;8 zb)@s^iZ2Z`FwW<^DUxhh<)ag(UFV%Ogcu*p;;Dk9nz7kXggdC?cZjaVv=+#~y0vMq zM;U_V5PeiPVnpXYSX`Sxqpd01sSgV1`9~5FSDcj1%PR5ew?tY$%Mp0^>2QP1+9}?4686#k@9s8O6AW7x! zJdFnWjf=2z#s@)%ww8pW&SW$J=Fr$3YIcW9%DCS7?zV~wo5Yh3u>eJo0)OLFGfg~COHinAmAs%Ux7N=_F6sPM@kgCSq_vIHAy*O4$b9o z+Ym?=%qp8KbQk8*p3JAMA#~>oldhQKVL9Kdo2SKU<%zV~xR0K}P(1$jd`2LgqDoff z@FQ$&U?LYE8?%9{D5^h>m}+PZ(Nf%NEmd7_k%?UabNR#oS{`A%)~5SAOblK*ivrXC zbpQO(_Qfd=s^Oqwtgyc3#H%gkS!?NzmX5|4v>=}r1~*c zyYOUY=T-^SxenfV5@5b5{XzFeKhmsncL;AS~a=}H| z?SpgrQ67z3tA5z}k}=R3rd9FJ7Sw%W!2x8ohlkI@o2RfxPmq*C>hnd%#tY;xyjer} zxE@60Us_B8^e@}~YKQ;WdM%VK+S}q$KAtaOi~88Eghq2;9Mtzy4s$VMkNqplb4wtBbh57Lk{RjQCiL9 z`8Hit+vw29!}i-W(^_oC8d@gh64wKQ-ZUF+bq^0Ka@P?y=_|~4at2tS^>K=o8>;Yw z*pSB<_8MCz@cgJs8-Dr6zSJL` z-?nbBL6X=w!G*)vnHOgKEbHp-f<=fM&^7QOM#69iT-D@1GImn?6x1b=pdz_%jgo;O zI-qp3FdF(vEzsGCxbzj``IQ$qW!YnHZRdEc8fQg!1}HKyIL{u zN>|;{jpwKG-&{Y(Cj8y=8GOA>L`AVY&W)4UNs1ZCSv^sa!Q(xKTb`aFt~B!w$Cg1@ zjkxDOSa%OHS*Vejvh*l?79+wWJ`je{iW!+ zdz5|MZhQZ!JtG+=&D<|@Z?>w(0Au%{oJ~t?nbwL6ccp_6v?Hy6*ojAY0!98Qf~zZwidyd$qgWeCbdhBnXjQLIA>rN;Dy$h>ppad zilk2n3*q|WB*exO(-6_6PpBN%tF|#t$3JO?B*-XuY+{17;$x@ zV=;+AfUZv{cGo8$vvc3ywH6m_-Ryz%zeA{Pwr-cI6D6_rNmZUl^i*lh~i!aN4vGpX7C~*8!4jvpja`1;~Gb zTmcQWQH0CIkCnqv)R&K)4e!O&W$a!K{6U|6Dv{{XIa(7ie>@Bswka{W3EaruhYa?u4;f9I4_*z;@5;WV z(>Gd2f26jxp{asO)-y|J#`hS`9>c3lt%cr~QEqnnb!4jy1h&X^J+(@-a_J-5qS@uw zZM%tbKoop-KHGxBb;9@2^IoDt@=$<>yyr@U8UWDW!lKyQN;S{0_3S|FlGzPgM(!2_ zg=>}{`vM$69eG3Nn(}HZr8l5$AP7sOXmQ)HgMSfik1Yq3EhqAF1m(|p<4S8TlXF!F zZRCWVWB!=D&K7dk&Rrv(2xrG8E=&m~!wW0|ty#xkzGfiiV5mFRn^}G=G-Sg+LoaZ; zuzbmLm2ks>87>(7fLJjVf@e>hWzOiw>a&_+^QtDK)7xtHCw7d-ax}G!Gh@$AU(zfi zW!GY5*KFrcGbg0B=o3;=;M%1!e%LhTfY_7ykN2@X2S?n#z?So4JW^?$*|3G#$}OkL zyvQz!xspu@vj_?Tswh=Fs>t|C#sZ7*0;|cjR5X`1<>e2+M5az@_|PKFl@iZj0>X0rT^L7?_n{Dsej@|SY-_;~ckUW78^WO;vr!?M z`CScBR8IAif?)F(mbq&R0EtcAwr!B2%NlH+&^BdwZ&7BVMIWbRu2jZGL-(T1x&hBU zpj}{A|u`#cK;;itqLUBzQcrUocf_|aW0vCp)EwL z%@xdg$QaO!AwV7Gwu}~qU@)2>tY}G_^);48O4ob_Gkr(@2NA5{Q@r()dWwcPd}VnU z=dJy2J2$kt(Ym7)8^;+$X=?E5^>%9aSMtnm;5A!KK~-7$q1J9~A7T~VWr-wp^>0`5 zI*oReL?m>GQczT7i+u>))lpA7Zt8$pfo!)!#zKTEgu(K zcpBHanSU%k+SRv-s9tfmNTfjHBDUN7Y)smN5=qr~vDLg^_%nf|ZBO?n=3gc=RPQ;* zTUUQoS^|j%80r)aFs*UIuxpxIv^05(HBROfpVn;6imS5zu<_l^dt3SY&iA+O+}^&wdFP&Df!k zDe?Q;|MmdFu;cmFDJ&Xo5_UXcrxE-}9Bn+@c{=lN_GTtl$!xJWOWOC7Eg9u4yr#ET zPlgZV`<3=-*k1YSjQwd(k3wv=&x=0s!P&k?N!dEF%`hC)RCV6c0dY}@bjZs#RxF6LV=bUN3_lm@;8s6{oXy$s=y%+_q1|S*I@TE&Jh{kZi!OEv z2quEF`37F&+{0Ht?qx6_Wk7x!#_kNvG-Zy(DSEmqB$%}>kH zvQR2i&x4mr*jmdUH-^c=EG#FU_ z)*Rz_wun;F1k;Lugkei>q*F=e8-D?F1IsMuvLo>0m{RYqC#57%og(yw&&{vZ%^wO_GV=swakp9;$ES z?E#k^3xBO`Plg;N+A%Hf&$ecpkCE-g`F?w_2n`uXeRoF8!L`L8ksiSTmLh?C!T3N< z?HlTgO4RbS%Ao;~t~Rt3G=j(A)NJX;Csmt8uoAgbP-|iLZNv7ISW54ixn%TDqrM=t z&CDTU1dEN5%41{MxUnW%F}96VF&pldOXRbA*k~WWang=&VfRb^#lXWW^-LYmIHB9= zpguUW-8EeF$&vm_G?lf$28uA3=8cy35~|S52e*i{ zr$S<_XYe~U&DP$Gbwf}gzHXNsKdVws9g47+1&x3V=9MkBZfpUhghkZ*Ctn{teU@Uk z%o{x%=d$-t8s->Y##|Fv@U|t@^3kMtP7oskC~vBEbhKyeX{`;xMFFY{cZ+rOw&tQ8-OWDf zu4a9^V_SclVe9H|Z~L}t5z-i{`Ue*2wR{BF+98ZM{Vk zBMwoSZZ$*mD?4LqSUKdZuljI|mpabPkXr6B4^*%T9p3hmdD?V-;{sH^sEqe02!Vjk@Bm$|Pxa9wa2+ z+`+vjX(5Ztjp38MW0Tm>vf&F5Vz+Cjk0@dI$jX}mVuXo7`RtS%3!c+`xBufD$qhz; z%ptU*v0-@a7aPXcEDSOASvR^CV(qn?SSDlzy}!#zBVyk%nYO`Fd_!zZM-4ok=H%wZ z*%{(3^JdAJw1R949UNFTU*I(<>VtpIJPlZhJh$|vb$!{q!{`b(3dliTi{g(+k?J}SCO|QNxvO^$jy-ar z@iBe(d{uOdzNT+(i+lh|scv^Xm4!%OybSq(6~D2CS?l>TSBb<;bqpt3Krnq}|G^rW zV{doIhS{hVg?)1kgNTWzHZ(_vC!dY;Vg-~dhA!)wawi|YE?zd~U8->mj(M+p09fIfw%L4w4(n+RtE+vIU^bLdt(KNS4cMwG#U)izgi zfJ9`}r>yi}JLg*T+-iGy6YQvPt&@;!`Q(DXIBGfg z2!bo#pYNy5zp&T#(XR&Q_I|6@JQe-1xc;sRW}(%2hE$F~O%d~ScaQzD4Jb*|uWsG- zc>{q3EmN5p!ZPHNhXNkO3)8J`VLQi(U55w%0y={QEVk6~bKpdG@uS_Nx9ly86us+2 zef{DU>FJ#w?(ZC5oMINq*BnIQ7omg0AAX9iopo&dh?Q9!thm5b2XeBku}Jvr1W#Z^ zLNCDG$1`X?2WSZPZ=STzqm%U4JuzIcKi8nVDCK_xGR=nOHL;M8+9|yq;1XHk^f~|v ztDz3b%=zT_t25kV4yLl0N|*`OynA;A!f&GmlxrSO;Fq~ z(!;gUqsqTZVuR zo3x&Wm2K$0^xOm?LT!w+-=X1cO{x!JwHu)2E7 zC0#TzTd{jx4tD(wpk3Um5zKtGB@^l++?O!+7!fd|@Kf)Qw$+lumNpgFc$FupiN9{vqDI>|;x{G#xae&9dZTA=ba2rqW?3`gXdKmK4 zR$hO?=j2pqo>ez_f5T~z?wsi*EBhE8s`8u35z5C^3D~vN_=zf5zhQzEC_Ld>u3esl z$#2#X_86C1b*<7L*TNsDx;4Z9UPps4ZjRU1tDC?oW(ihYwS&J~t|zHIn@@6mt2R$h zZ{ZR01G~v-7hH z7TZf}A!q6v9Gc+%gc*Ng`*!C)`EZZ7Xn64!-k&|Ll`cQJ#Z7IPFEQF#Qx`Q#(%%`L z84Hx~tat~VMIQLfv_+Y$IJjH#M{JS7-_#@7s=SrcYoD_YDJXUF$ErVvja@+xu@_;* zj065i)m3qkCd~*%(g(g|P;Frg5xhqr%J1hO?&OolzBPXdhgS{|FhVdz?Ax4E!aT0r zJHb^45sm>9swXT1ZBA-4Z~hHTN4RCfpIY*?>ppEmUGHDO2?jpRQe~{^PY|{AhHnAo z3z>&5quR2N8VW%R$l0`MO4h-4K~9nuD`opo5z*f{efDbQ&+AuiWE(?g2{d^(vOQO@ zu!$Ma8MgYL!O4JAKJ!yQ3eF%WDleWhL0w>4!w(DV*RZp7H}xbX>&*$h^;=;};IqJu z_VseuEZ?m_Xr54^jJATs@j-e4j?wAS#|#$U+*AM_2*c0AZ>paz3Hwt&*5(BZ%>Y&rbG^uK83_<5?DpWR{E2t zp&s@zwt>B3s3%}oc;*5}!Cv5cknomCf99|Gh%ulT3mI6Us0ge?_a6j{+kTxU(`QGb%X z;=?d8nLjKzr3~$o3S2-|eRY$c((5uA?%i;uPyQDyGrM(0wm2xjEp+V+HXR>>hHv3- zj1)e|<8RjYKKmf-zCKic!QVKgH&Cxa4hIGnJRk?7mVU5eNT6)|#csDcJ;MNqMOO|V zxHA;v`hOazYUV~ych(5l==*r9BCeYT>?QSVS3{T%Y}v0KoEIk?nter__Rhzn8)T6 z_*wf5Zy2#|(fW_tcbI~l9Y1TIAGFm(kE?KQELB(C=uEEUJ`D2(2H_E4ls7e*VGWHh zLPbXhZpDult;~|;bh*0M}RwoH0Ox;u(MZ5*=(O~ zaK67h*gwPrrU=e%rM%VraTrdewEOLlUrI5P>V4~Qq5}KxG{V^WW%_v+8p=0%voh@* zJ>J_%QrUaiFPE1kq(5Odqz%4Ey2*JD`-s<2R9p5FdV;j2 z_@d2>?wX7MupT!Eq$EU$_jo{2s|!IwP3+TS1ftriBfYh$P%1ZXlH0fWf~iCLX&ZrL z|KYRnF0^b2H#+(Oxjs1j^z;Qp7_!!cuhp)I7vJl?ze1nwzjB&oX? z^TW<{F2?#aAe({OsK4^y`~WxIVePZhO9RkG0D&Ij9Btgy1_J}Z+-Bx+Fb|61S^JBF z!#&AK8f&SIpL%qqk!o+crL>rd!maGCRJSeP3rk%jp_d7BLzEnGLiUIsuC3*@pE0*c3LHiGb_J-d$6OP>v=DviasuBOYnn9!a$!NC`u!3{IqwF3+JlIW5 z+8mrRvR89CqFmO70q7?fzCHSCI%O9+|PJ*wGXwa_Ke$vCg1*g6Jgx1H?OXL z;+2vA0Qh<^8sFBgU+es~zIwIu8)WKKH*=*d5U#p!mRs)q&plNX=z*H_a!^}gc zSnk=ca7*_lLfTO5;DBu1wP@IxM}ji~_h@9MG`oP(oc_3TzWa=u6M1t1LUj92ZD9uD zm1fQ~Vj4D$hmmx<6vIF%r0ag5UBmx(94a}-;wEo~^kusoohZaPKJ4!i_;~9Cj-U;W zh(GxC2yosI9l`ROyKwH#!yVbEmXKdq1oG>v}ELijs-`HJ3_-7eQ?x$+{of@i5zq`Wlbq}5W#+ld!G;FX_4}nMPJOSC{73F`CFKT zyq)J}JzZa8Kpo-Fy^|l&k&%Edn7RHxY+t={WrITGx`vh$1g-b{A)}B>v|Hxmd-n!o z6u6=A_iTd-4UGSVdxj9@PL4*F>i6TDpJUE+@{59Uc#JsOgRnTBM~>&xsuWnRHXqYj z!RA-%*3`gMOVu>oe5dO13v8^^bPSrX9US0&iDI6lVYjMOM{UQ1}Ly;m@O(gL?Vb}eArQJgrx zzljU&4-gd&o|KQzsnVf)ea1kS$Jb+{Ta%zB((m`(k(fO@I5l(&x41_Vu(Fu3#kbKZ zK2idp^q@A^4#V;8!aAqr^Vc8Mro?e7)o=(P#cMY z7KNoN_>X362twPa&au!Pp3DohHH#JQWA{(9aJyKV>1M+-jgf{Ig?kTp5Er%Q#GFU6 z{54R!-o|%OWOes(%@#RvA8!bXc)#al$4|L-(r|UEn@2M`^T@|E_}CZIQpxF4+&kyj zFw3x62noKkoFP=z-@dTX$q%JGIlv}1t{W^WUgj7rBEwP{E?MMgYU5ifO5;N&uFk<) zUqN>h;1>roY}ce#X3d##S_3`948xm>e`#$zevvhA{PsW^Ru=YnYLjDa3N(^5c6e6) zy9ax=wrzPuf<|d#dMc5I%uG@&j6OAFU=ECnD*dvZ3b|&S-*0bL_%B-;j~Uud222JS zF5WzZ8-opBM_$(BXPiFlq4yumu(B6fD7=xk^a7+wH4;6Y-WxWb#C1?u5TMDkMUKo< z;hvAQ1=38%#eUddU~ts-Ygk*KHq^ph93g{=)toDgby!7T;b$9~1C5XCvnI_-NGC)1 z+vkzOj!AKA?3g&S6y+I`wAce(3@Ki~zthDFgf0q+#BC%C+(s z91RT=j-k0bL0|M__vCQ4A~8W+sM=OtJll@3Vr($avtw6ko!4fk?U~u98O}k#f*tJI zpy6x7&Vw<*CYmsB;aN1ybmFnJXyxN#JgvEWrD#gEapE4gS0l;XW^$i z2%aCD!f&D?b6~G2iT7vd!`L^q4)Fk747y@`u}BIWM4VQfp&w>8V^6h+9q2A@@>IfX zz|s-;p!X8epuyPM@WshXwD?wSKfiw2R(^91+*b}gk?nX|VN4ndZC-5D4+x|W9^DRK zR$%k(-@(&Lol^G`quUXSxhB4Qh(t(QP?<^et1+co`u2W%*;2&dtGdI z^}!ayR0cN$fax4CFaQsB$4yG6C&`o(GPZlL1L2sFcn}NQ1Z^6OtpR&fiBQ6pR2CI- zX_;~8yH??_fX9i6MI=!V%w5sDK8*^iNgY!CYzHqV;vRiKRpJD6v5YtQ_zT3ZmF~f}B zp*ah04JQf|Q2C{_kQ+vZomU(S(jU*V;m`Yyc0b_)hga~C*XDLsh8=WK>-FM-11aPAA8wsj&srkGem z4|CoGJ)Qr+8iD&|_9+`S61_JfhOvy$Hz%@_vPq1`edV^=L^27{#h#g3>0DdvcC_)9 zt;i-OBw6<`AfHl$pJC^Y83x$h$@Y1LYHy$KpYqDUi>J>LE7TyE!IUVax^;NyH4XRA z;PLN71f2Ld5zE{5)8~VsfWF^5`bBA>Gl`WMWLLO%*|Lw_XDYtGoslC%1?_59A3V09 ztLMQvFpUP7&fwc&Y=VV=OGSOQJ)YP;5_V>V39jvoP|iLJvi(vs?Xuv?y4I6Z>6v>= zr7Ss78G!QzR@M=R<675g)l%qhnqoU6N7s%Xs>gn9@z{o49?vmR2*(_&A>?=lSJplg zQB3gY`t~kRQr$WauOiU-3EgD5XjRxRjFDHa&T+q9jTAOEe$9|``0)_WZO!}oaN*CM zD)5dGZ5Q1@lYtS@C5AAK<n#KWbWkwLbZcOLuB=F98m__be z@Le6vc2CX@4;}{}*-ok6X&f8L0!21ENlS|>FRrcN>0A%_dZ5LZfNE2$3jg=je^vig zyILZbAmOa4e&Ho~gc6aC|6XNoZ(QK( zK~=poGdgnY;;-uU|4~(IxABc~&OrY?QfDYROHJA@L3xOOxA6M~N^)po(e&t@)~|*8A|@M~)}ex3O)juljJ^0sTvB zfnDT%hO&C^u}_)%Gvxji{ywknS$q8rfA8Ygm-yw{@FQ|PtDaZeNM(B;qi1JT^&9V} zMDJ~S4_qeogY#I@HffZwn4dYZa)jFbbU z9XQ8Fi#Q${O=zvf((hQSG&nxEzqI~~DXNbbe{a@5r|wt(MI4RVtS+K$t^YgJ*G=>c z^$0rtVLvT{UcCLS_0?0?qhFub+R^b7wd|cOLlHIfoLc$DpYi(;GHzFYhrScrNPVZS z+tquU(1$%}1rg}H)q6KhpZ3s~!NOJVCVbDTf37Z7ul?*&^q^&-UNoI z`+LZh%*_HtEk-Us~!xT?3dtfWUMUG>&Od_VN`4{kT=!nQv~P57P2tbVlxo(}8yZjgE( zdUQ(a4{}{%3VZ)mmF0+brS(6O?WfkDN7e$L*W?H5>u0ca)PWyS-ZPYD+gfji-e5ad zKWCeSz78d+pxvZ?if^WOZ-%jxqX>JQwiXU0{!MxA!dC4V&lgB{oym0&xk)o~>D8}t z-O0az{x{TYT5{JruSt?#ec(Op`kz|rD{!5l45t`f+bOE|(&%y@IlN^1{XhTTeN)mI z2JX7~f8UBxR~=HN1|Y`{x;!+&KckU81O*2RcE|gw!ux1!4yiP~9BST2LFsIej_L11 z20Qi?#i!byRVzqiqwm16;ILlLm1>)EeP0T3Ze31V{`Ee({R9ed4E__)?^!w(;K-!E zFBM_gs4C=R>B8{B^82t#cZrZE#WSRyqnv-JF5~~7f^)^{Mn~!dR43p+N1E5?GJgGt z{3-W2=s(9$?|*N>0sE|4gVS>r4$zfq9X#v@=Fw~`4sPBC-d659t-u6&H&cCPkYBx( zy0?1ogUpeUq1*i(4Bo#346i`%=3%Ag0{j*A`h(i#2vX0@K$0s-4vO<3Oeb6BlAKB! zQJB$RZlexvSc0?RJxY@zm3u3c7|MS6E9;-f$nCJ5D&6NMUbXD`|P4y0IcxrX@DdlBMD?hGYd+UkW9`;!EruQ%Y zy3F#Y5$i5ELk}mHBbNt8gikfzW|KGvyz0B@b zH7eFMl_)F6Z#KdE7-fG7og|tOSj#A@*WZUtoTsVhTCL|i_1Xjni?Xr71+B&r(fa&# zj7h)0Yw13cCr_a<^?0X|-`XumU_ZE1SO3ay^P!6B!&K`>u^b0zHBM!>@E>zG%Y7+~ z+Ka!2Q`F8bxfr|gj|9*@Aw=(~-$rmW9weS~dN&Nshxi;{N*ZF;D<^^<}7)A@c zR;>o<djE5>Mh5vO^mlWp3ozpmN5X3>s}qL zbxLnnx082FM(CO9_5W5?cW7@Zmzs9ikeiPb*j@^5qKLML|GNtt)v&a`<(DNiAGZ5Q z^Zsmgr(Ummoi|Zt_N<3M-QsZ+PQG-VyZWa7yDp8bkSrxf<72c1M^x7Iyjf3pi!;=o zV;{W`_)G6H?9Eo(!+-p@dWYi+=bY>@P`vH)Lylee^)m*itDiGpYUqKr|3USikWzib za0orO^Qvyqv77+jWOX6ugQXO2a~ug&)s4Iryw!rogL4PSmwJ_ts-$Nvs?XVPL9^M? z)MTQNW74^mj9v}fd{|Qz%j5oB6TpXY-*Zb)Yps}&&m+W(=Xte8xU!pZUYOsg6 zLLGxXV{^Ybv~bY481njn9@PBYJnMsBxbNpJm8JjuKJpH&74_%mdEH|wdMJ5ZoOx2S zrHvnW-_Pr0EaMyWb1@hFB{7(5dZgHJ8O_?&eON~gtx80~>;D4#;k+R{NMzTwf>ymA z9jku3ZPtZ;Cw=#qz+ni7200O)xSa(H6`?9eR<7!1Fa*J-hc2hBUf!X@D3;#LgoS}El{qv z^J5?Cf=I|d`V@VDzh1(wA}aK@M=6f+3-%4^r}+0Vv}XnXa{Oj|Fr+wlOnECIyn2Hp z8~A=+$CFy|HoZ5m7keYcKI`)Uw`udOEGZwkMmHspE6m#?GA$m!u`|r@Ja@FhJ0bq) zmWnMvFY**KSlC=dl6(Xrn&@wzq5c(Y1@lNz5=V7)qdBVFGD&QUUDT7_M7=#;RX!7| ze(iPXko$3Jueu)ijG%!Fn~l<^aL=Mb;GepNe*Tr`l50k6p}7$;Xj$iS@_US=-a(6| z5usXdwg5*Fj#||BL$mxos!~H^-kLw3qMdB){7b!0>z-67S3ugle!S9rnX_9iS<%)! zMSjre?I|QTWPadrl29&=PxV}?kHR;faXUTB(?a{^w}uSFzc0}`g=HGrE*}G3bJG$~ z^&Y<+Kra~|qHTkx@!mEx?=iTkz0N^TZXanY=4U^~_ow)K*L33vXrS%C4-~Yl>$RqzOJp|XR?lC4fh3>GQRw?1lA@13HLbL)(V*bjC3IyP^D{uuvHvkH45tO7V++PG7Tt9|8T13ixe+2wleSfdox z%js}-1~sSe0vofjOis?3@%_sEoM-TT4x#jjAB1R`?y9S=Dl5)%#oH_G)g8cDq~Bln7{a6SF7rz zUL&sgKEe0hY<%I$FK1vZwXeSBYr?EovZ;Ze{Y&aP(txu|b(C}cm%Y!Gy?l#X^#L^~ zMBk{P^jPx2 zoX;`#EbbrZyzN3vKeSD?{?GE?IlBG<>+=6z{V%M?{}m(OXZZV{@E23~@4x6bqOcpp z_6hu4A8mZh+Jf$|m3?fdJ*#UB#>N|qMw2FW&Bm`S=FDgEv2JV4(YkK?1D%h#7pD0Y z*7$NQ=P!#e{hr>l`@qde^ZVM%0GoI@SQNG;_eF5$1y_fCW{5MHbbpohx$gT{ACZpQM9<&79oJlX1f0!h@hi-$ z`_gWrjW{>vdSQLuoO>UxB_6v?n(ga&Va^w}>sB`$akQ|UH+ig-~I^4!bx$TtIXYJ{}CD>yV#A7>Eg^`})%6!Q=60_gpNZ(0Gbkx=jUw>3pn+Yi^ z4T~K5d&Ml1qv?C(#eNQc7BumfELWZuR@|!JG^y{P1jqP~$ihB?&zs)^XMHA0|A*S_ zeH7v}h!@FoOr>d35F@)NEjNC;2NH6q-eG#uS+1aKL*HuCcDcs7O+UxD=5)7BDrHx{ z2soo(aAEzi$M`5vhw<*yhtQ3E%v0R@a(t(i;#%Spa5G9yn?%d=9DfBn$5p!O68j+E zqV68IuTZ)TG&;pLLKL?8O~A6pBYZDfw(j?JKZsV(!_#jd{Wa07 z<8SU&aeUHu&1gRGzgIy+JtBhHFB!!p|N9y!*t+ihhFEt-_wgb+YRi*c>g(uDTTQdJ zxby(!{}{QS;D5b0_pR-yIblD#1yI7I8V zM)=-lk5D%(`V(n$?TM1!V;#b(x?*7+y&LsOebe3U|Gj$c_uit5`Y%x}(gaX_xTtqh zFM?7fTQiNI{&8m}qds~b-VgA{=E&vZNt;P zYyWZ#+eGTu*u9a{-o!4`+nA%1`aY;PVQcOo?JicHxSR7f{@%6`P~7h{B7KP2(b}_C z#AMajy%tOO-a}BNRXMXI*i8_8GW!i5ZvleQ{+q}r@Kqa^@#_!f%~893tpz8_ z@HfXxT43A{Z|SG#{b0SScP^v6^hmg-hW!)o@%I@d(fi@*6g07kZBeWOW>I-~ltKYBw0-L~D!XL1*P`%-QRhN=>)JvG#PxSwd`d1&t+0tI8 zBlHt@zRnW=7`K2xE>grD1;2tO{Yv1#`)p{7c)I8xp9I(0Ru)2}UZI(BbBh^1qS8u;W z%ZD>8T>K523n(2W#&Uzg0tokoZ5%pG4DswgMfi-l=ai4^Uh+Q1a*oK>4#(XlV6jbRKG_RqL+6cc?F}6Gy9X z_zA`tefK)#+^Ey~CYqDDIFPoUb0Fog#tlz42!Gg@v$|9dJaCB4x5LLi{S751od^qv z@jH%AwDEcUk{iN7-8Q;xtpd**82s?i9qh&?%-bsdx&>5!jNf#kHt^S`O>u7GuMK>^ z1%&heZ-9?qK0(TBFtsqjZ~rq)_J3ev^&x+~^*d1iNA)}Q#s~ikff_Dk{Rc|Oe?JFJ zqW&Git^WkdRs46={-ZSiO&R$0dXoPUc){^z_+I@yM@n?uo`$fN2f-M6W~iD0ZkBg?PZkn3jTl1H0_%GFM{l^<1e_WAxPJ40TWH#)viAB z#npQ1EtI7tbiUC>OB)jg(GI@#Ha@x@9>VD0y1bZ+`jrCtuumT^rmrtYaC2Bb<;a(q zs^4~hdt|+e+?LY7#a}|h4U3CuIQ_X;Lc^XqT|(ni_{Di~=?r7*!ZQC2IUO&dd5(5P zFlV70Zn(jM{SumU*q+5S3~(G?%%Yv(EikWXK?W=|kV`agjrp=1I{!qNnigt!SL36~Q{5_%_* zWEh`7k}Sall4LI$Hh>#yIf>?0M^4atjC!BfZ2h7mhjr{6gqdn?D1zWR}%IwGzD%pr7RKouf zDq(vGm2kU+N|;(oe<1=+MhOjQ1z_ zO%3hv(mt-sp}t^&!+z=L)!>gM+zDCkJv#M+b6AX9sdghX-;=rw4LL z#|Lsr=Ld2L1B1B?69c(~k%3&oj2#e7K4gzE01M?g%9e9PoiF5s-WPG2?iX-M{|h*U zfdWq9pny|YDBu(x3OI#{0#4zgh|{o9z$ttba0(+>kYjB22}X_PA!;tI1ivMWCOjZA zgg)Y0K{c=~^#Z>DL0Fnw)SkrWH zA-B5x(z5D%V<<<|;X+R6auKKLbOEPyyMR+VUcf0`FW{8U7jR1V3pj;=0#0F}h|@4p zz$t7LaON1{hDmN5B|=inZxKd@aMUp}oHJl#C}+aRFwPt!!#Hz{4CBl(GK@3F$S}?v zBf~gzj11$9&8OA1% zB+N}9Nf?|!k}x@eBw=&{Ny6*|l7!(2Bni`#NHUC1AW4{?K$2|0XWa;1zS33Q9>X26 zKY5)=|=aEu`9sHDS_4`F%Bfff20ZB`#3^PlpgpMUt!odGl#TY4H*&>FW|IY35QY z)4?TF(zYd3(yNY#J~}jPyt&kHaE8;YK6>th!1)RcE0jJPZz$qLRa0)>MoWf24r%+SGX?Q8%6jBN}g^`Z2 zER9X|_)E2PEUVK;d=&8k9R+-bjlq0E#$Z0-VlbajF_=%77|bU`4CWIa2J;CG1$>5u z!F)o(U_RmCW8O8uwynofIy|$DcIt$h4!+f8d~+j`J&ZeFu9Q<9Z`J3_A>ENRUz_?R zuXB$dt}WwliA#MtoG03aVqVyWLSC~EMZB^RMZB^TMZB^VMZB^XMZB^ZMZB^bMZB^d zg}i1zig;y1ig;y5ZZ5{cqFa$7CPvEuHb%-YjEs^Ytc;Q&%#4yD?2M8j42_Z@ERB*O zOpTHuY>kv*7#k%+SQ{lnn7g|Oa~x6A<*oJGeL6;bVfjnkW2Jy&R4C0X`7{nu#58@Gm2k{7-c4+#YMR@5eC63M$N&`A3lV-S?NSY8eku+g#B56Y5 zMAC%MiKGd+6G;=MCz2+#PbSUmz(mqyAtsV0+hH-Zt_T;;(D6pb{29#Z#v(h>#u05o zAt&%(#A#SB;1sS4IECQ?PT{qHQ`juv6b=hGg}DMw;j4(#uvEY)+!SyMBMUjXcaV?% z9T-j+A!fwb@6@d}7hz=)XT;1%3Bb-M35KB&5`?7@5`?J{5`?W05`?i45`?u85`?)C z5`?``5)6YQBnXQmBnXoWS7vzjbIH?KUoArBa{h?VN#p>f6UZ^Fj+P_Dj+P_bj+P_z zj+P?~kCr1OkCr1mkCr1;PawyzJz95J24 za{A(QnVh~jT_&e5PM68)i_>Lt`r>q%oW3|+E~g((m&xgi(`9mm)6W)-r)hu1EqKN) zdma|XYL{_Gj87m12p=uQ@I6wB&^=O$usu?WkUdh0a6M9rP(4zLFg;R=5ItIo;d!JK zp?RbfVR@q;mgja?E%eC~iko~9zoYnp+!6eS*e&KGtAMP4^6nl=mb*_lH5!^srF}LBZkXvXgg|K37!&f1<&{fDSY%Pp9_1ed@wFsSkBt*~vSbq`ktM4zi7eTLNo2_~OeD)}!z8j~ z9VU?_`|xo)wr{n^tk#E6N6Z&+0o{YS495exgxG;x!sb9Op>QCV@HUW3$QsBc3=QNG zS_X3&E(UT50Ry?hT(ez!>EovT{nY$JjhXwn@uT{vovUrvPqo&cHlkxN53n(i$B;3I zN4OZoBUB9H5he!l2oZyLgoi;qLc<^)VPPPTAz=`Ya4?8RD7ewCqdo49-Yn&ex;|0@ zG=G!?!@&p%Ld6IP!pH~-Ld*yW!p{f^LemHd!qx~0LfR+^hPx3Ggu)RLgvpI|WTo{3 zj!G?Sh@Y47MLdq;2O3B48y1WCg~Vch;joxrC@kg|28;QHz+!&kub5xx8^LebE9MvS ziur}R)n)i;uG>`|qh~^DlOtlSkP|2?;xv2}a0*!koWfKAr_fZuDI67W3PA;&!cGCF zP*cQdcq!l%QVKYQk;}_4QeS1OmX2k0`iPGrKA@w3&#*C=PskX|CtM8X6DkJt2@`|) zgowd>!oy%bp`n1!urQcUNEpl~9CSp|J%;`myRUfyB4DM%U+ak64UrM?GMOx3Xd+pL zt4U-DYm>+l{w9$nOim(8IGse6usew?;dv5S!uUk84EK}Bk}a4-mh8i)-@*p$;-=t3 zSc3YkSvQfkZ+8fH*ai5ZUA!F}A9ZsyJy80OUDB7>s}H+5>!Wz}+q*b#eU7*(&w@R& z`XA%P+k@(9^(Fq7^{+l!P7|$LZ(3Ndp0sA2deO@I^rDq@=|wB+(Ti5rp%<;t--}l0 z?nNu~_M|m*_M#Q~deI79Yjxd8?-<;MzCDG0ah3a7m7m#f>IHAEIIbA&=L@rEz~ioI z>ceFeQFnV%LSuVTnx6Kcly>%@luq`blqU9|l>YUgl-Bj2 zl&W-(KgE6if1kQHVz)5!8!%oMW1EM^K> zvJamvmc=_C4!hr%x;=(F+Jp(Dz#5E}Vs>Dp6j^|gQiT1HQiS@EQiS)BQiSx8QiSo5 zQiSf&QViE4r3ld@r3lNbi_qw|wlrqwYl}EKyn#=L^F*W<^8(+6yoTx`USYY2R|qcR z6>f`oh1McoVYG->$SmR&9t(L5g+;u=UJe_i6q181d@c_2_y;26G#%WCy*qZPasLCpFomqzyy+H5hjsj z_F)1^vKA9alI>VHgR0wr+trap+h6H+(|wC%o*<@qfZ6-3s| z6TH>&3I5})sXR-;a}zutaZ>#ae{+=uHtC0Hqv+{R8Bh{hC~^Y}n*-Wyk()ncYb@LDwno!+z!K$^6Py zk!oR#^p4H#xZ{Jq7}uJ8ooH%oF6I}0i}{7yVt(PZ zm|r+8<`+JT`Gw13e&KNhzu~Z$U-&EL7w#60(z$oN_?@Oj=dV)D*((tyy(q#0f( zk|y*{Bu!YJNScs6ku>3aB56YXMABpfCXyzLFqt&74--j~wU|hnY{$ZgK#uxw!r(iM z-F)A0R{em{n{)LOdjqa917B#<>b8M*qWLQ~jAC+y1-on)`XnCrKF{L00?%tbu@hM@yY_Y8tlPeNEMyy&@2KKA*F)PMzFUPo(@QD`MpvAlq_oHP1@grpz);zJP z+R;)Bwxnl1EArme&{g@Cl8L z+Z%dXfI3&i?g(yRwwT+nTF5Po7IF)lh1|kqA-Awt$Sn*OatnKf+`?Qjw_&Z2TNo?k z7Pc0i(#TKa?{|5(3w`W95+dd%lC*4Y+qX>1=eGSM36~SpuFu@IUzz&MZTm^;Gq>$0 zsn6WDpQJu>+kTSz%x(KhT0Xb!C#lcewx6W_HX!Wu>+qL*==Nd>Lu^1FN&RfVa!Gw{ zz%ohwZNM@~{cXT9N&RiWGD-byz%ohwZNM@~{cXT9N&RiWa!Gw{z%ohwZNM@~vH|g2 zbv;6!yzBWJ*n(Hymm^~QMj0nCUBqb^F5nbq3pj<*0#0GFfKwPO;1uQxIEAqSPGPEu z(=b%PDa;gb3L_ui!+H~MWUFg@$C!v&Yk%s9jRG#mgalcO5fWrMMo5qq8709i$_NRvE+Zt! z(jZ3Mj;ypdqsKc=Sf6c^avwHthc1)Rc80jE$?#A$db;1p5{ zIE9hR%P>;kGf*uZ%j)zIA4PmXM**Kj=rlgkw@CzmVCPA*q?o?Nc5KDk`kfyw2{M*IWhn*Equu58QX za%Fcm7TKNrm8lnIaW1rGQmroH^Hxq$8)tWoE%Yn6CUg^& zyI5!4$E$1n7k8En=7BvM$YZu@5RdH8ARgJ6K|Hb_gLq^c2Jr~@gLs7LK|I3iKpw;5 zARggt5RWjl5DWLJs~Dlf+Jc|juRdRdg|OqrUnpunfj^EvBIT33{ao28u57L1etD=>OOM%jMaVQ^ck!B$mugy_mR_QtnMdg`B>dYPM@*5j~wBADZUo(`sEFHV=q>5J24a{A(QnVh~jT_&e5PM68)i_>Lt`r>rCoPIc6CZ{h>m&p-M zKU?JKru_o9;2F2vId^*ucf|MvQh@N$QVicCr3l?4r3l+2r3l$0r3lv}r3lp{r3lj_ zr3lfZr5K(^N)ehzN)eV9MxPUwn|ps2$C49YeJ@4T({j|gBIZYM1M9`yhVepfVY`r9 zm@ecNmJ7Ls;X-ah1|ksA-6EOFal0&?N?!aC#=>~8{0@d$L;Z_ zh)#WjzhCt`_x5=iU&Q1nexPy$zu~f&U&t)x7dDIeh0bDr;j@@u2rcFpMvM7{(h>ZI z(_(%hwU}R6y}1lOoc}KNtE+Fu%ZPZKOct;?ku1aMB(j9rNn{DXlgJX5Cy^ywPa;bg zpG21MK8Y-0esMAHcTW5mSGY}W)~)qB&#ri zB-w-sB*`L7AW8OM0!gw46G)ORm_U*&!6cH*4oo0PR$u~2vH_p=NATP{d#Qhs>_?L~ z;(oLYAbz9_!}=&0Lis2e!uKc{LiQ*b!t^K^Lh~pY!tp2>Lhwi#hTTyzgxXOugx4GW z@mh~mRRc!*I%mY{NC`mdC<%ts5fX&b5fX&a5fX&Z5fX&Y5fX&X5fX&W5fX&VQ4$Q7 zBP0lwBP0luf7wP{>nZkI)o*jU37^?tIeLQc;XWBg#dyCBzn$Vg{yOhEqrN>vGIxgZ zjK`0d)t_Nkb%)Q68ASimhMm?Ovi>?m)^X169w`d6; zSARoq@rA1;l0R-QZ$~*UwNp1erRuA8y05LbpCPJx2yJ4I(=t569VH$4b;#js*y&`@ zCgeOtoq5v<^^&FG*`d?eSJmD2^4tLz-vH(vKB-*+8R>UjstB6;AS0S%?Tt&R{wTgJcY9$ zV~cv1mm@_a%Vh|!3+vK9CedAvelj9{F{7GB7H~X~EW`68vV`kNWC`Ds$P&&cktMuO zB1^cRM3(SBi7eTHiDa2Qm_(NB!X&c#`0Y7XOZ@ib{LwBf^iTTAS?0I*le64!?<1#= z-`+<~AHThioIZYgA31&e_C9j@`0ah<^zqyK$m!#^_mi{SZ|@_gkKf)$j&Q!4(>7yO zDfZtS&9@K>y=f6+#zpTV4)oGup47@+i&$o{=jZ?UJfgk$$?}3t`HAu}yYrLeCEN6q zvY}os{63i z7qHl!E7=RV)9Orp%_Q355!|q@#oT5u3%O+h3%O;}3b|#a3b|!>3b|!T3b|z)3b}>$ zVs684A-51&$SsU5jHM7IT*qA!1N~+ZPW#D-xSLGYvRF$0axIUg^pz!qPEtqVbrM;9 zVkv#=*e90KS5}``N?%!hVkv!P^@*kQm$f{W(pQ!&!X!G;XO8s{`xE$b*&g=IaNh`T zz2qLAu=mXOTHVL#OYTJJd?D@jwte4i>`>SQ2kp<1z1a2&w-)*xoVQHY+)VAx6jGuc znot@n(PYxh7EL5g)@UMWvPTn1lSP_HnrzZU(qxq;k|w(}ku+JR$)uTWnn;?g(?rr_ zpFVC!eTR)$A3_~%K>-&qKbXs~J&;Qn9>^uE4&)Lh2XYB}1G$8;fn37UKrUfsFqdIt zAeS&OkW0FborWAoo8x4<6}v<0v5%>QFY5m&ejs54zhR=7U+5_27fy=#g_vS~VW*g1 zC@SU`o{IT}tP%W%v0{Fqt(af9!%p2c{Lm}+JF(|>>f+4QFph||LQbHph|};@z$s)E za0*ieoI+Cpr*KrjDFhX83OfayLQN5;;iZ66NGaeHMzA-1vBuZqth}LT2z|sy5g*V| zz-QPP%qL_F<`XUk^9dD$`GkqVd_u%vKH*_7pU_aiXIL1_CnOB!6Apg4oxKU4-#=CD z-;XO6e1{~Q==d>hxKA^|$LL-i$1=N_17I@IVT)cVo6uLA+ zyw2ard(|cNFa4$RwD=j$e=!EQUvaMmE#k{A$+!DUUf^%tERoU}kyam|HTEpV*z>)> z8$&tbC|1ZxFRvs|_wt5wvgdF{svytcczMG)gO@j)GkAH!IfIusoHKZNC7kZ% z4d)DA-f+%yVEQ>`^4*-Yr+x~T?|?k9bpf7W-h>_CiU3oqug395{7fPTXqrHdVQaJ; zA#JoA;cm1Xp>VVuVREz_A#}7H;dQhep?3l~hUL+6gzV9Bg!A=ooNi%^?C?E4E8&Wm z9>EPH7jqka3%P~bLT+KTkXr~Xwwy;rSVc2J;C$gZVLf!}&Z?GL%nf7~C$x!JY2>+GeIpc7HsWQd-2&KR_xFHn~*8-^5ad&WWW8yAw+l zvL}`*+)pf3R$*ePvKbRgl|`9cs@a=~rOFyjELFB@K?GzQ5u+yh}{v~z-%$MVYQH3 z7%k)$HVe6h$wF>nv5;FBEaVpU3b}>3Vs67)A-6DA$SrIwSVw(m5#YzRFQao-xnP~A z4}ZklByxbf3FH_CN6Qf!N6Qf|N6QgHN6QgbN6QgvN6Qg@N6QhCCy-;99xX@c9xbOY z&bjxBJ0seC+G@kme1N%Z^94)aBiOhpFP zbsqL2>%4>9US;xe+xLxj{(K(AJLk_)iZlGn9d~<>v{zLhI%n9Cb01&pxkmfnlM)ub z7p2+o9+WI6_LcRZlpXFtDNEafQns`QrL1KSO4-96l(KleD9xtzpp@0>K`FZgN}j6b zz4aH+jtl5?{UwoHL;6sO4rFjjxi~X@-CtuW$UUblo9(1M~OX;K;OX;K+OX;K)OX;K&OX;K$ zOX;K!OX;KyJ?KmqmeNTRmeNTNzWD;yfjc|*;+V(LCcIB`A0rpvZ{cg(J|=#N-+Z-V zU#|i^ucEF@CJXvBku1}>Nn}YcCy^!HokW)OdlFf~z$CJSlSyO=OOwbF-X@Y|n4CnG za65@CVf%7@%>UL9ybrwAUkr-)9Yha|4xl$2_NEusdeaL}z3GLS-t@vnZ+hu|Z+hu> zZ+hwQ0D9BY-t^MN-t^M98`L+R4WQpy*S&8rUcACRW1P?MK7$L;?WK{UkP|vs#A(`C zz$v{f;FN|Ia7tGTIHk1(oYLO{PHA!hr*yiA)3m#QQ+i&&DUDxqjh{iI^RqF0UG1p4 z1D)p$R~|ixR(3ECw0t0s>GvQWY4#u<>GU8TY4ac+>G2>QY49K(>FyvNY3)EB)7L>f z($qmb($UZR>nP81@l+@0fl*&a@k4h<@S7eN^Gm0T`K8~*{L=Mee(8NNzc5hDFFX|U z3mYT&4JXC?!b~y0@bgt2Ka8~IZ{pUYvuD5!U)P)gLx-Sz1#idCO;+1O<+x@Xw4&pGx4&V?*2XF|L12}}k0USc!01jbo z0Ef^ufJ1m1#9;^;z#+^G;1EhSyET#Vq?fk7)vl|%xK|YGAtNO~Q%6ZK%^e{@nmj^+ zG<$>uY5E8W()>L@n zLxE>|!)-vzJ+5|+MIKih$6}9bo@1HEHP5lkLO>C(uyDDKg>B3>xDSF+*>GPO zZFAKBLG;l10raNlz3HXfz3HXTz3HXHz3HX5z3HW^z3HW&z3HWs1L#c;d(%tzdecka z)~Iic`18)jy5+rT7MM{~e$Upp2J=Ag2J)Eh4dRjh4dRgw4&sp>4&sq64&sqM4&sqc z4&sqs4&*W29K<929K;hm)kQiQ)@iv;6|LgxFb;aELpV%32XII?2XII;2XF*WwSPT= zr`n$*c&hz5f~VS_BY3JqINVe1&k;P;{v6W8&$~JDFMD0Pm`CwLOGogV&KC3UVFbWF z=wg29b1}cPyO>|PUd%7eFXk5xiur|#5&VXcVtyf}m|ytW%u!PJHqw{26ARI@kCXrm zjgnv}8X-YA8X-YQ8X-Yg8X-Yw8X-Y=8X-Z58X-ZL8YRI{H9~@LH9~@rb^A7Egwl}U47F<|1G$9 zQYgHr=PSTrFE-1=(?N$AQ$lH~?dfDiYcaV@*pG>2nnjsZrfkflGG%opl_@(ksZ3d> zNoC4bO)68?Yf_oAXA{db3pc4u*}O?*wpqd4el_h;)B13i3EwK%$NyG$`dXqzQlbr- zP#UbyWYWy;Oe9SfXCi5`H4{mbm6=GI?8`*bWLYMXCYv&mG+C3$q?sL=NSZ9jMABqC zK3jzPUGtmv=e(AA4@~C!2V8ltUIx9fCtx9}PFwV(Nuv{ek@ zDOWu?n9Qmx9T1=gowxmLI<@+2I<@y~I<@p{I<@g^I<@X>I<@O;I<@E?bl#S;>C}p| z>FRu>cs5!~u%X+~b)FdKyMN7Y3++y@Bagc5<#MR2UamWJotNuQUFYSxQ`dR9?$mW& zt~+&|m+MYl=jFOn*Lk@d>Z+IPPF?5ax>Ku_T!=jdPi^dY^rw&6#(U-7KOKf3<}ly3<}ls3<}lm3<}lg3<}la3<}lU3<}lOEDEoo85F9O85DJR&1yx6 zZ{nMnw(7Mq!RtKgGG6CUSMj<#bsb)Jr>?{6?$mX7-JQA)ue(#%;dOWFI=t>qU5D2> z)K$FhPF;uB-Ko_|l1e1sWBU;K1J67$D`Dl(vVT6Oz$X;A%ffHNjWQe96=BT7Gpwv4 zy3?@_AkS~`m+#4anZ9T6LOBZxyDQ>%Y|o^KqB1GyD{}e}U(ubyd_{K(^A+7G%vW@$ zFkjJ~!hA({3iB1+Da=>oP>8SSPGP>HJB3=o*)oOI%$M=Z8*|{7&}@A>=34i*H@wf0 z44d}|Jke8z;eEc!^PJ@i@^oounZ|YHb#c>TDK`YHSvb>T4E_YHJpa>S`8^YHB8p*V8N-)zT~))zKs2cB3>B zaVMI-DR6d13utC*3$KSQEmZ4TTBwe-v`~#|X`%Yl(n7VRrG@H7OAFP6))s!vg>)hH# zS9(Spzt*j7bhTUC=z3rJ2=UT$)ML}LmR#vAoaK@{hPx+E@N==sJ*XHZ<@O~}QXZ8> zNqJNjCFN0Bl$1whQBoe2MM-&77A56TS(KDZB~elyl|@N;RI0tp)J)1V)!q&4ENtSB z+J^|m8W9Es5})pM&+rvGAd6+ol$uzCXLEd5o=_g z9?wSQsc1JUPsPG(Z5Se1H>2{-~yBx%*Er%KrV_T1Gy-6 z4CJC{F_4Sm!$2;I2m`q&1`On)RzH}FxATEq)UpS1iQ}3kYfPhwmbb3lN^Lxik-Bmz zY3*;-(ld5;w(yk+>-)jKoc`VI*#f5uP1u9t z-Gn_T22R+6;^L$|c&wbT2gT0`dr(Z>$V0wx0z`JIdESFnD9NKj6}`Z{N%;fyCgkri zZ!-Rhc$4v0yqk=_qTOWt73(JBuSho;f5o}U_$$gy$lqh!Wc(H3CgZR8w$z4i<@0Vl znZSD&(+tv`O?jl>rtb%FC)hT`nTx1}^X-j%LWVern*5nrEeh=H*b*q%sinuW4lNa# zICjTqqC-oy`wlJDf;+TSTkOzMt*TQ?Zyz06s-|~nsXBW&)et)`}n0GsX};+N+*N08IH(1{*Y z(2{H_uQ!=gs!5qts#}>LE{$lsGg@t6(z&N9sM12+fI=cn%M9S^sV+AuT?eQsP5E! zqZ(54jp{+oH@ez2-{_jwe4{H@^Np@g?KgfEYQ9lf*L8FQ@r`X|U%CX}xrxZ1 z=iwgXj*T}s6K8h@Ji%}9tXM^P#;%<{e&)z6cB6TQio;X?y!B1=PfyR&fnVci_hmm0 zH!}@ zd$yjz3COhFQ<1Qb+6m>p@Y5j=+E0pHl5l>Hl5ltMk*>tMc=hNH3=u_lg;#c@d-l?+_)g#^2@~vCxvu{?1-bVCD-^iVk z!iV&xg+277^)}IqR_&q}t=dK}TD6Z}v}z;0Xw^=7(WY&FIu&o zlZ@3C5sf~>{okAZ4bT;xpVc)&VUI$v+=vue7(KS6$SGSRKEKjh`Pq9NLEqFhW-8~YcojcwBeSwCZ+Ce)ywDTG= zvz=hG%IYER za$ftwo_f*2l6ug28_K3r>&d25yUC_gi^--_Tgj$VE6Ju)`^ctK%jiMpZ6cdats$FE z?ciR!UURo@6DONr`@JddHF6g&zQZ%Vjik`}3An;0M(64+W@N5vPa|_xYa5xX+TzGu z)lx_1s&+gwSGDqyxhe*X&ebEt$XpdaM&_#M^2IQ8Swl_s1_KsE(jGk8P1u8C z-h@3U@~yQYU%F$%)2AI*{D1f!A9k&m^CU-MX6DF zDlU!6Q;}#?o{BxA@>H}LnWx8>QF$t&jLK6nhX0)9vh{}u4W zEf1kCFlPiVK$*c@JgyAnqDV53i(E{YZdxhOsi5 zdmtCJ<<`AB-rg^^%+rC-{mBh|quBLsR$Qhl>~|17EO!9Cx7ptGYOTHL)lPfUtA+Na zSKI7OuU6TcUhT0ry;|Y`dT)ch>DBsr)2rQG=w?6b{?rto#&lP5DGFQbNeL_KMd|IU z2c=q84@$ME9+YZLJt);NjKoc`Bb(b=+j)=H6DoBW(#Ea8k_os1Q%2|Nv1MegiZLT|Rje7A zt76W`Torpp=BgMpGFQc-k+~`+jn36$)5u&EqekYcShds^p`_o%898tLeSy;wTR<-N zaoR3DQ=Wd;#G}Ba(RcxkM&ji$XcS(GJfrYZycva;qRc3~6kA5&rHC>LFU65jcqw{} z#LHvGD7+LYM&YISa5J^v)V9}9Ti^80^gi)ts9xfCK4E3KQMeD-t&YQ|z==`$0V_u2 z=ka1Reu^2R@l)Iwjh|x2X#5mEM&qX#G8#X{k0J6jMgyr?_&q9S`E$ z1l`5%Z3}$JrU3?I(s(=1qETDUqEUOzqEVa7qEWlcqEXw*qEY+FqEQ>kr15r;MWec& zMWgzBI@Qq|s1S1Hd<&h1rS zJGWO|?c84Vv~zpa(Tw(9KRdTq-R#`HKEIROJ9nU+yth^E2eS8E@iZx;xo_~C<11+F zI)3|(I=dL_EYD>kz;{ND?9EOg;Yx;mOsO}Hopw=*e zgWAUc4r(z2IH(N`;GkADfP>oEAP(O025?YY9Kb=X^GL9i^!%f{)bvfbUFjK4MQo~v z;oF`b;r#;Xt%kpX?eW}`+3!aET``*}RTU$o*2Cvz=+BJXL;s|V+!g%N-|qC(tpW{F zZZ-yoUFSC#&(|JxQjYQcPf^Z@-Mc)B!fW=V1kUuL^!U<)QgNjRrQ%5sO2v^Ll!_lc zC>1w)P%2*Zpj4dbMd|UO2c_ad4@$*@2Fldp%qo(n)Ou1jYkYg3Z5rQ3*{<M0;riTgY@aHOt`s6W<@gC-|8G zv97U&&mQ5kb$rV23tb+}1DZXMhu8B#JXGrk@lYEW#6vA&5D&GFK|Iu22Juka8N@>^ zX&?`8SA%${l?~#dHg~gZb7oO#b^9Y!`{;ip?++GP*xe|6V0$C*@%A^EkJ{j1K5B=9 z`KT=p=A-sFn2*}zU_NS>gZZd!j=;y;=U_f+ql5XVojwvfjjQ^hzQ%W#y~H2h7jXkt z%6kpB5Kl6*+H`GiJ>#2Dp8Gp;ww&AO-$$Cg$$5F>TVTYb{DB=4^7oiB8Gpr^$@nV< zO~zlbX)^wbS(EWsESrqKV%%i>75gUS?=f*Q{)&~8@mCDhtfU@8?L3?8=7%>#xod5x z*hE!e-T-PKT5oEPS3Ri}je1fm*7T%SBAThVP2-im3H@Kz+7h_}bD zNq8%2O~PBTN^98lIazwjtelw@m^7FNuxB6-k1>OID3%Q3p_nm~u2j-hwCMuC_f9 zceVP7xGNq^#9fhMBJPSI6LD8`nTWgM&Scy@B2C0yv1%gjielR_mdJB1VMi?ft_j8D znU*vkN>935b+^E_AG}W>-VfZT$H5=8PesQcv`@v%AGA+J(jT->#n&ISPet7yv`@w2 zAGA+J=pVRGkJ~?JpNi%`XrGGl_hTH-$M{e5iCmtW<&J{kdHYF$xX*gu(Zsj#6RkU$ zL;1reOvvBk|783X>nG!{xIP(w#qi1aD_&2=U$J>I{))qs@mI{9kiW;*$@nXlPR3tx z^Yj|_Q{_yUAQ;axl%LwfGu!98wJUHft37ZkqrJzS&g~UPI=5F`=-giIymNcC+s^IP z4m-D3yXxFt?IfeU*Za=xRgXKjSG~NxhFzr{w}>a*U#Scs;|B2ReyWat3LOpSN-lyulnAbUiH5>z1qV7dT$@S>D69()2scg&a$5y zu&F1on>RSso7&m7tFfn1`N6(MaJxj}n3^W`=jU4cIT&gaw5ke$XY z+cVW>xJA(D?!MUjKX3t1a}VSG(v>V2%nQ_0b;#Wq;34>eI0HaCD87T25F+gnd+wYHwrYHK~I)zW%WtDW_v zRx9gCtv1$^S}m+MwYRUH)M{Nlsnxbt+O6c3y9J-NgVO?EYlS6kAKioSY5GlimnZAM zT{#stI5J1r<)|FJt&Yf1?RP|uYSSZfR68G$quTz692E~n)Do@3c zQF$t+jLK8-WmKMuH6!!%xHBqG#h_7nDju~)^f88%_ahro>GPPX4VAibEU;-J&OoS1 zID4F$fU~021e_JKCg7~dH34VEuL(FSicP>-v1|g)ifEH?_P90yXGOOOI4j2CByIDl zvG}`mAG#6Y?#DE32-l5Yfp3%W1-ebZ*JIo0d==S7=c~9jI$uS#(fKN-jm}pQZFIhh zXQT5~G@F30$FkA+Dw2)PHy6iPr+ER)lea(($FXkw@^LJOZw`)i=bMLPUHRtXSXaKe zIM$VKE{=8On~P&z`R3wSSH8J8)|GEAj&@>`Pf- z(?AYDp+Oux-VETN$TEO~V#ojviWUPnC@u`(pa?L4gWCE44r(bgfogM^V^dPfFNcFG_E7Jt)=IdQhs3^`KPS>OrYC)q_%P zsRyOnP!CGAonDmQW_nPnt@NN&8)-dz7;AiNOYP_Xny3m}X+6=^P7QnMP3>)_C$-v5 zPinQDp44hTJ*m}(dQz($^`ur?>PfBk)SKGdR8MNPtDe+qTQjI%V;_`f4>xOfL)~(0 zapj8KJ=`GEMqSw22wY%ugSmLy8^}d%a3B}8#erPZCI@m++Z@P6ZFC?Pwbg-K)Mf{B z@wPjVi`wu&E+N0;TVEfQ?rW0gsl|#PBaVCnTb6c(1;RJ?p_IrlpVA`3T*?p`=2C{p zFqbk!hPjj>GR&n6kzp=nhzxTnLu8mwX^~+rWrz%ODOKYy*6Xd^AsTKX;QcB*KaaZy zvT2~@nKWL%vuISavuISOvuISCvuIS0vuIR?R+a}>Xm+!MCCq|g39@nhRXSrhRXSrhRXSrhRXSr zhRXSrhRXSrhRS^?1(owD4VCjLRpW1#DT%}U?jbOkH{S7`W!x#_9Sd*qOcL*#e5kp? z!=V48@PRdqz{lIhU_NRogZZf44CbR&G?tMs*>tMcXPWfd@`6H>JGO-Gc53OhwL?qQ&kikBBRjNI z9qiCjwXQ=;)w2#QRkJ#@R9))S(rZtLmZ~ouTF%mt@|%X-g(h7pw=8rjlLESxMd5WU zgF1Iu2-uN3|`GYo{ z@7Au+*R1w={JpMr=C7LCxxMOX=k}_lo!hI9c5bg4+PS^zXXo~+of+-DZgy_3n%TMi zEG*^T&~qO-KJyiiW}GXxEOfKcO6n=vu(Xb%9ZRbev#_*EF$+tp6tl3jN-+yds}!@a zv`R4xORE&Ku(Xb%9ZRbev#_*Ep*p)*#>h{gp?n()cRI_So%gFS7h=7x(9D4xps9m6 zc+DNaK{a^*2i5EW98}W>a8S)3z(Flx00*^<0UXp)266C~Gk}9y(f|%>Sy$UFD~?nu z*;sE{SW{10Z%4go)q;A_s_pcmRjcVmtM<~1RxPC$t=dR0TD6XzwB9ay(W*uCqE%Zs zM_c#?e_y$8OMCJ)yFD4Lq3@krdkyc{T6MZ(Yt`b8tyOP3wpLB;*jjb7V{6sMj;&Sy zI=A*3*Ri$gSjX0NTJ;hY+SiC$B*LDhRqd_ITGiINs#VRc>$Ix5b)8lClOBj<YX4w9Y8Qj~sKpHCqqa1dk6PJaK5Bo1`KV=% zz{lI{U_NTigZZePf81uLZ(!G3uywwdiaYan-5dPOXHfWF7oHrviEnrO8(ubXztDKR z3i}_OC$L~-o*oxQ<*67kDo@3WQF$tMjLK7SWK^DtDWmdKd>NIeV$H}rJ?@OkQ!!{% zo{C48nlU8c4cqYK+zqYJxodr>3XB;*4K(RZ?Qx?gwIW1MYQ=({)N1uTsnx!FQmZBR zq*j~lNv+n|o7&r9PinQep44hvsOB}rh{5&>{#!nGqG=7Q`qw!O;7>%D|#%TN$IY#5B_%RwkMUfHt zc`O-?pCZa={1jKPFVY-agm3EZz;a9dX$$-q%mbJ)kcY>KK|B;22Juil7{o&{U=Ry9dwdK0aRE3SUWG}O*+w<&p>REYq z8};lwyN!Bwp4~=0JI`*To}Fj6QP0k^+o)&f*=^Lb^Xzu&S$TFF_3S*mjaqH%Sh>v| zRMDdoxu@H|FYKjLJ6J}CcHRbNwo`4N*-rI(W;@m3ne9|pXSP$VoY_wGZ)Q8yv<~gO zPR(qm+B36Vz~Jp@FJ&7M6!%qSKeh2GNK{C3sh}g-R9<5;sZ@V5sZ^UXsZ_TzsZ`T4 zsZ{SWsZ`7|N_eT470 z?giG3$PL;)8aHnRBXLvf7>S!&%}CtTnnvQLRyGnhwZ4(Ksa1}|O|5k_Zr+MV;-=O; z5;wK_3-__-wpE+~*uWm#CM^9S&H_BgNdUWlhvb180RD2Kv^ zM&bmU8ikX$u@N|_&5giGZEyrmYLg>yQX3tCliKVEoYaO#;G{M^3MX&lBXCliAAyr% zz|~v}UPnaCQ+Du}OZ{mJyC2L07C(@OxAj3h)XE3(Q2QRlLoIs{54Gt*Jk**8@lZP+ z#6vB3AP;Z5gLtUb4&u@5v)>?NeGaP(&w;Xv$1Iljw7qp7CB@YXeegWA>r4r*DIINF}`ya8*X z&hTyVa)$gFev9sv>PcCb|8?oJKL49d*_8jyrc{gRG0&#_Z+4$*AwBwR%Kv8f*_8jy zrc_JlFpY!g|Td)FZQW3$8 zzy+2tn2WcHfn3x=269nr8OTK~XCN1~qJdo0q6TtN>l(;KEp0FtZ*>E?s09w>qSko5 zY>hmR$mf@6hdX$dku^+u9=ns57Rnnw82RDt?w`)4=gG-!R6Aee51)nPts%TwozF&n zh~MQ+J>UB8zQGd%eL1e8zUnTOsp&suhxrBi-|-dM*XWgdiFV6-wa+e81r}9C+?^U2 z)SKF4Pfu#aoSxK*H9e^nV|r36w)CV{OzBCjSkjYPF{C%O$Bv%ViWxnr6)P%L8@~CD zHxbK8sPr7iHf;MLzG2PgG45F_+vOTQe}NW!dXiZ38GhdaPU!7dm-E^ew%CgfR@j5i z+g~=FT3$At+FUlBT3a@q+F3T8T39xn+EzB5T2&7^Z%^5DYDw92P5!ps4k~*eH}mYG zOkdc^D12ZyBk=KdG?K5Ey4 z`KX;&a`JXNkM=hzHKneUg>4Vy0IMFv!Q1ly4r<8*IH(N|;Got!fP>oY01j%g130Ly z4&b0xI*5a}&jB3NG6!%_oBX)yJKy^EYA~Orm2K&JW~AmSZ=QLAi1aD4S7wZlL;Yzq zUa+>2czL@Ug_m03D7@4bN8zPbISMbe&rx`(rH;Z&ZFUr1YP}=z@^(B5FSY1Vc&Tky z&L&9JNzRNv^QUcTzc*mT=}FtS<;=5E(dx^o@W&%_1Y(TJ(c{L592GrA_IVX!X6aUChS2mZo(cE^Cs*;F>t~j6cZ=xK{0aD9z14F*n?u|ggq#xu8oC! zQAOp8@p%?FIvH;u=tR6dc22@uQF9XBikFk{R-~MSw_@ZZycHcM;jOqh32#NjiFkV~ zoP@Wc;3T{i|0;Fk`k0cZtu|4$iYih)DSn?eC)H1N6ib5sf)+> z{abu`-1qSS{Nr1xOJ^z$m1!=xKXL9vRSL`C9L{^W`)lrVtPAIG3q7ZONR^yxX;pNN zF8%ZY<|8LT;?;Hgd47cFLmv9|bx*s^{5Hn1jv0T5KGU;f$9)xl$DcKO0Eyhd3Oztg z|4;Gnhxqh4{ycE*>}$|*{U1VOHbL{sOYISUmNoeuMoXO9a_->!epTW(Zo8}1^;p1q zY~n=i0`%ksdRg~l+*%jDE10RB3apOOc3|YRAw1P;E>Er$-=8igl*;c?cb^X9XEw{bNvKh< z-fWKa@AlT4mo+QZZJl|B`jMBroNU~|TdBpWOmo~~x4BYhsrka;G4$E6*4-M)f%eXm zpnMj->sp5Kl-F|0@5>Q0seN4~ANcW(>{qZxo@BY??+|)}7CeRgs>bH9_7D5@^a14i)XPF{f_;R3c)pRb3GXZ- z7Kzt!kNWjc)hXHIs$I)3`}INp|JZ8@Pf0h0TJHUBw=~(_UxUjIM)xy}{XE*Ut|-qMZ9_gUz%8w%E#UW8`20L_UDjsK zp>CAQ?;NbKJg&K8yscfOo?q_obW3k^);itcG zb5}$@@8dTEBs!p{kzBsOci%z<9$?A8^dLrHa!PqJpK|_>&;v_V+wQ7!`_uji&j97! zTynRY>qccw*UIg;Ph^&Ew_p5yK^@%T@H1a2LN)hA$oGOXVhNYVLRUvP{0>II0*#eI zX^tqq9r-oJ%KpCgp_)AE>I()Zs=QbLj#})x0l-12a?hVYb|?_<_W$0$0nUUG8j$pI z96!_L)1*04LeX*jE`Z6x?s0J5!oLKhH{NLZ8A}laf=%#u2RVzBuY32O=}oK83=kz;j_O5H}~!z7BO2o4f~LtlQq|>9{d7x%8~=7Bce1} z>gN;$1X*C&#){ha;tta(+IR63AZ55)DSx|z0=&GIl5PFNnFm(zll;zc6Ijn_FvT|V z+1#Gn7}0I#juI|;WdnPb@maXz_7*?w{(|mlH?d^y5H*y#cpRU}vf;Z6e~jPFG1+qR zGqJKDL4HSf=gvzxj2CBCbuXsk*f8sjb@a)$TrL*EIbvB*2EyOzabOu4H&$#E$3Z79 zi+asv7MI6>f)e9jEcO@6;3wto(1)!6|EF}QTw7>OHKn}Ej*}`V?jTlbx5k1W*Nm>+ z9A_$d+FGnHqReT(3D3{l#vAj>9_{@$&R;>JC<(gXOerka%S-}51{Pdju8ys+Nk8tB zuQY9!d^b+rWf|jL_MAWMyYg|b$yi(U^egBYgJN0;AuMx+dh2Q0Z};)i`glP$3lYzM z!11R2CgZ)=ru|G*sQuZJz1LR{?8Tov0>=~}8SBHbxUK>(pLi#@llFiYu+&-GY@0Pd z2;|=PK4d1Y-W`oMjTf-7C1~;mJd2xuAAX2>;4f2tW{y9^Q328EI|Gsm6*pES9ifk9 zV8Hm!FeGr3k(eLC_}={=_W?bUmk@?oU9viVh$9S?=l}$)MHLt>$quwdAk5an+oTyb zg$P74yyIw5C)Vm9E!(2N=`ctqZklc@D1%#+YLpEEUtbuw3nUR5#SFhy(%LUxAonEMl$|-z&J7<%@qE(*vHz_@|RB$GLBJgB*6^{d@gn?fE<-D?}4dr_YK zudu`v^BVM!0LH7a>Ui`L_8vN_Z?Of}e|~~%V)5a)0~Dk|W_7FCW{vgyR7D}+TCN|G% zvU~UMIH}mb*E^yV8iS*&51Woh=j7t@a$RczD}jpP-f91{gl<2=@a7J2*euf~Q9X*M zbZ6LMJ6#>UWC0=Jq#`Rz9;o+IzUf>A0%G?%ti=QP! zd*MH2pz{nZsoLM+XWK`ZTl&oNmh!TEYCYSUl);C5Bot?0jj=zv3$D~xIcr%B%;Zc* z&_O0S%sSNAPG!%b6wo#V(t8>8;H_t#nQOr(6CGJ<4fKaSujg zWpEbUF`rl6dy$}pg+$w1G1Hesu2X+_)*vovhwTDNxqTMwnKDev`7)2Whs}JukGpRV z3?nF&P=4YH$T@yV?rAgBMY>m3k~Xon)U2@6Zy^o8lP!hr>l*`hX?@@QYeHH*Q>rnI ztxjc{SW1LPwU^~$Wsb_t9hs`)iRiiDG&-o;mrbMTzDP|Y1NZKer8Ne9ZDKiVvMHC! zWPPq%CwggVn6v4HCnv+Wl}cfIc|{*bh5!3{hW`!J_w%}ujH9}pCYdVSL~6U%Jjwnl`@fXq zqBJ3ylj4H>x z@WF4nF@!%#`hE+KTMKv|I;&S7*Z1wG`dqlb6@xUO+w9A5;LGE=lzKoSlEp*W=xlV_w!bt!KU zo1u^&A%)SXgi=g@Sm2-%KJwIZs5@2zsLo*)Nj6aT<0HmYBc2+8BI)PiqNC53QdOtX zg;Q=JQWd!T0KA@R9orHz2xnDzgha2*C8YOt90b6vFRIHdexZsQ1F(#dD?p>PHg*8n zAQ>`xyY5Yt5@o?4tWw|>hh1SOLW(4zy;b)E6tFi56Xa1-aWQi65qw z7H7>j$j?S7b1jmetMzU_UI&94JE|an1Zf{hq3|<|P*0XLoWF3ZhO$=4hs*yi=z*YSR~=j6AEJ2$ykd;g{pJ%p}<}{EaCRqPv_tc z!p}TDF?S&S9W4%(KViluASP>c`r?Q~_Tq%O?c2bVs2G%f5&U5^x2SgNDqX$C*(H zYStb_Pt5_7{SQDN@!P}G`QUhnu92a&xy3EmhdZ(kdwGi|18A$a@UQLU z+c#^~Z;lDg4SYkrVVICm9+K~u60CDdCGwIGFQGbVR1#{CE8Ef*h~o^2SeWK$V;=65 zd`9GBsKxJBy*sC4x7j-7&b4lAgOl<>7VJYqCH-6^5qv*1}~1jzO1*llw0rsfi_4ZZOaxcQJv;YFmn1O z2Ca4dGd5@oW$D=%-WrdD_e$U$#%KOQVhD>)L|WqgBvN^Te)%kkuT>qe9tsb2!G1C? zU5ft?8ZY%l+ijB&z|QutkMtOT>{kUeVA|4Elc3Y8`Y|x+I;^K@XY(i;v3lVc$fQ2INzIsv-@%g z*QzW&g}gTXUoVY8k}gZ5#2b5^<4HR39$O-7UVnIB+V~PF@g7wof%h<-uIh*cVO|=K z#$3ZS*uT9WHR@wy+CJQ<{67NLu`f_5#ukEPX7m`;^}f>8C84ST`GceDOo}=r+gft#M8dr|!k=egK5!zc2m2@bCEfiT@Yx zXvfcZ@L>J{eA1ub&!4$V`rA+O+fVVkd?&wM@$LEG?F08CJjQ(jw_PrJ?U17!aY=-+ zKW)_#8Kf$U^!DY{m(j8%$7wT)Asd<%?|OTsod5L}rxScKtX$%^Qcrv~p&uq5rEE z>DpRV^CxD3)o2!L`d(e$XZ&0z&UGBX+2?3hSa9$D%`FJeezowu`kZ!oKOh9{M#HUA zrXTS!$@sfvUmu}L*r!&3EQzqxz zZf<)vuT&Lh&);U#B!js(v-@P&&lHA-gIF&fq1U}D-Uv~-J;`d_4(1;&l$EhY7w68) z_Ol#xbGwj`9SxOK1_zd4`-EnH02%*#DG8Ap=|iMutC){n&A?R6z6mDDWP1SzFsL7_ zbg{-5Xj~~^Gx~mO@nMjXHt|#VLE%97j$M0pRE*1P3P65OQ?ni@-~ZUyGvQU~Kh0&FF2`Z$UiskqWTVIppM zMQr>*5ovLpu^f|S;e`4?ar~ccT`z-x&VY|1jWLX%B0CUIn?^R~TKaP@g`#EMdk5kllZ^^aFq56j@Xt#Fv8 zEF11Ot$ERMk6+5ZC>w9DgNEoU;o?I@P#dgpb_6p!vUr z{<&*)A+(%#C_t6g#x^cwk*lqm( zEx3t);mY#xi1{6NC|(aDu9VJW4Q%uA#gTRCR>Y0Qn`brZL+ zi#~(nk=O?&g~#{aV3dsF;_Z|o1U~i{D<^wUOr$H3%z;Nxnl6p3jnSgkcFW=f5uEqj>FO%%?k|E%o26?PA&GY!O`wN<|Go~hnAB2zxelSVcn7M!jD(85+%irX zTUk!r^CjM*@6$0gExf$Wf=}*b+^(Sw?zzKbRp)Md^a{sLgY3j)xe|gW=)d#`9Pc3G zRvgO%oMU{`1Z5$`MZrUnZZOkiHTS#^t%L`IKZv8UHvZ|AF+}#(9^U;=+;ihHh!NS+ zrr08;W={=Aoo8P+^^D>9&c0 z0u=mTRLMdS^wr_g0-1NSx|L_&bnc!DWU`GfE9lDEALF{&B*!0PeHH*Al>YBg4K(2X z5e{PgD00|8LUMqsF)s!_v8u*gz5smxG18+yMl$pzX|@B+YpfbGIPpu8BgQZq^N}=I zG=;?;ImAKu+wzZ~rw^4|3z|IoJQ@0o`NYuZzNy#kvb<-nWBaVU{NMf8vW*fk1!F`E z{JnfhlGvvCl@MjtmD(r(F^alxiK)WJOgKbLj7F&HJOxUn3Ku~e5{n4KNhUe8K~Dx# zC{OJXz=*4G93_?N?V7>zi3)${Q~NLJs-;tly#=LLHy!3Ml-_@{)p?W7pbj+XfvO83 zy2McQJLm-cIYUogk1Eknc{3^23HSYb-MY2#sC=_ou-+8)V|@7iOuQmuSqjEvqaN#t zC|p=MN*+SZ(3-+YV`G|(gsB#0HVKx20ezI56O#0A?w|j!>-d=Q8l@{;ipwFmS?OUD z-->|f>e2`2O>jX_f)(+=WCiQ#>W9l!4%23?D`R7vLP5&Ebd81?OiO6)$AJX)%C*2D zUM_Q{q^twXKt-FO!?UHclk>Epmk%t1ovURot5L{Pm$g{Gl&Y+NjG%f{&vYQnSad+L0D0s{)=WOHp98g! z8Yd41#j$8Q1Go2mug2JN{C$`u6}#-U>idjQWteXjvNzx?-2jJo*1w z1Q^l9S*cLeuQ>o0HHs%zH|TV-$MLp<912b$6rSjatss<6v`I9W*y>$~GL)BSit(5P zqRXO=V{KVvK_$55{qd!j*jTAt?`nOSM-FNfr_8KEa4c*UOC)SV%6o*HW}7$`OsZ}KVH!KXCUcLSBg`tbbi6{rjBt;w-}Tzc8ZG_yOcft zuw7z2diU=CPA!rCu4_&g7+KavTKf3lI=CEZ?qHw%fo5|}dj5wpwf`$!FGgA+QLSck zf8f)3md>Urx~mFb;;Z`1&NM8^=CE5uS(uAXOL>gbjVgw-;;`3RELj3rcwW{*kGKS6 zA(B96fJZvY!pUx~z%r_Pd7%PcjXh&W%Q0A>z|f8RN*ud*IJ;+P&WB{Q$u6N-xxydD zQUoL)$C9vhF&X3pdk6z?qkg<5adjsYH#1j?m7HqqQe`ax0ilUQ5PwtN__gIfUOaz6 zDoGtF{5qc{ipeUgBm~t*g2U8kyg?-;MIuidmF#;-u?x}lBi8z?erroj6OdhX^R3l` zG}hLt1GdEy6w_wvwrBT2Bb{Ad%jomsnqLJw4=!gD>$fhb@GRN6OCS1qb2Yxkc&OfW z;9-iXRNv$I$2#SR?YW%E#Wp9_RbQKAw$EL&Ak^5}<84l&4Hs)&6Aq3k;0Z$@6JClm zah7X&vnZKO)2yE&IqvHZ>4;+cg#CR!R`EFI>r2J{!Y@%xCb@#Id~EJD#>Iu=XRN-- z(uM4uv$xt2(@v^3k(nFAFoCyYjhN?ax?axVXY^@(&n&D{`NAeqn;M3Q33K`WZ%qNx zBLwx4^NN4YAU$YgkI36iOLcfsHyjZ<(I6;}s7zZgY|90UBlM=aW4RV8x0!GuIYz5` z7@C?>w%vMBTDmZ*w~SU)fzke&A4AyS4u~l8=Qb>N;P`?IDjxrp@$k3DzJDIDocre= zucHyIYG?(MTEG*b)ZCXyv-x}Q#sciklVcK7U*T*Lo7lODt$vA#A+o53NbE-{a3MKg zol(h45yd!Jyk9?ROZ>|VCCJ9*h)=)>`i1hqU3?#kCjkr1c@a6eoy%)#Z{Yvnie_^P z<&G79;(*S2vr(Z|{3@mjFQYenmO~}}KF3Xth2O>|YUU;Ghc7k>CfBaW)FZ+6uww{(^|UYhNUNy=0wKL7KtTN8 zKj87ch*1xUBqG}@qkRII01B=deW0ZWFO>6^}7o9{AT!iB5C2#vISW)6y8 zd#_2Zy3D;=i?&1R%#?B=Fof&AGPqgnTgLBz*^+ijki+1JQn7tQ z3vNQ*UI*YXgnRU|VLO;c)IR25bTmYXc?pJLJB47D%QZffC24iMQ^tME_>D3&eL2L0 zz8;Oy7iSgU8y5GDKCaPC@FmvOjVtr)Jnvke)wt7P720GwcQS^-hV}Yl0b^K$`{Hvp zuhk7nXj>O=P}v<*uZyv%Ep54gfw5%S<`5*VEf4npuQ2!u z!#8mVu~q_?k;8{aP1^~C-H}3+6V-LzN^f4OZDD3d)py@kZy8{=CxIrjBDsr*4lF$M zx>#Un$kh1s$Sur`IgJHArt6E9u+W_>w+#={8kM_g7aZolRg+h}orZhkpSfL6abUkb zWMrsiM~{4A@nlsmDs6C6F-t9cnCc^?gEuVBx9e#Y$Te8zo{z&_Z>6ms@Ud@F& z;Tc%)pqx9*^o8_v)qI_wgum`k8fMA;^$zz-GfaK~3U@}zUlO8FR@^*Iy{J+ht82Lu zIGvP}G*Si>w8*AJNhR96vq;y30aSQXMt5AyC z7734o!t)c*GAv_iH30p;{i#IVUbYjNNS%ehKjtbPW&&bwKZ?fo+p0b;LPzXT6o#60&mfdF z)B25LvTc9(xuTVSTkUZ*DyT{_-=)vg8tU}8)+!#Ry2}XAN{vkTCH_kv>Y~5q3}qWe zl49}JT?lc^;5hG!`?)Bo^fOzrp|kvsQZgB1sKEOQINniNeqUOtc+ z*0r{e?IAPh+2_?2j4iH$Hc80%OBulLYy#_9ZO|6R?6*R76L2#{@<`Nl>$HA4WBLKMfh|PB&&yii-&F4sY9^$R>(HbGfYFC`xPMI zge2{unn|=C_@z4)X{DTrlGTA?^EzLA8k>2wA{6RStS0anqy!NRWO;UmW)rTx;dhpv zg?Y+&*gj^p)&ghRdYgCH9ih5c?!&&vF>F?xv9*-y z8^;*0S4cBMJG%Gce9A%TRq9KG3|`&DUL5Ko3?}5o2{BB@r=uk?khNPcpcjyGKFvS5 z3RL+3U0kCmH)=g`@+%y24saCqkxgIjV%BssG#B*!?tfhN%>}n;2K>^HB##-l^yBv( z1|^LNtjYfe zhI_vqX_{s*8^ZqgX&4WOv!-31V3BTLxV6AxGmao(aG0JYurT(qhge!YLp|H*tsWmw zsqICA{zWmL69dfF!@WAp1AVK+Aq=DhUa9rA(I?-10-dD+0>;k9oCVyOpvnbz z93a%sYc9-ftHP_QPx^LU4^2cd%WPg@& znjAwY(jBx_As10r^bf8tW4%fxy|2t$6ATz_U$ZWg8ulJ|T)1ZM`mcA|<; z0P*A|L#AMnVdz2Nl79r%;aKUFQ>CH$QE51S2|kJAu}gw5cHwS!4UXa{fssICaJ1Y8 z24+NI1`T0R!$H7wE{`xLs-CO{oia0et`HAT^EHn%BXOs~?b!KoN z=4nzADO)COvbE>6iry|RR@_WE=AuVW!cn}nnp%{eE#P`_rgCGABrg1yhmL|vw6*8V zxkeHhB{j0Yy{%Ls3Y1nB9!o_eP*ciPcq_veTeUsSRY>Fj!>e%I3e}U%`ecDtCNC+9 zwNfsDNt2gw)X`|D)r4ouavPwjJ^90W3n3_5S3Lb3WT1e%S0>fl4+$>w7Z$P)=C;? z8CHc1*xuVmk4em9r9Ad}1(qzzPYmHUBVge+I*;)~m-%L>a&?4-IE%2ImXO59Lq>g#1cA;E|3 zo?AcWaz8-tbek;ayyOgS<dGG=hQn#XMgW7u*3)cq+(vY1C( z9tk*P%Hjsb&uT8Koc`u8U5Vgx+hutJlH{vRDNXc#C2#yo&<=*leWk`qO<&pzkU3~G z=X+0UL`t1GUv7TUX7k6qhP!(U+RQPpVSQ<Vx6OE{z}hNgBZX>La4J)}`_xKNkmVWi)-`{^8Byiv1$zr!|oBY%7C z4pxe(zU*k(P0CVpt_Cd3HYCmD@e+p`i&dyX+U_pb_y4Qn!2p&MI6`@PMbcDoJJ&=P zX1@*%=Yc-7J}4{2Qo3<-*U|v6oEDZ7W3!hpaETo_Udf}5?BsGDWufJZd2}`Qbuh#j zCL4FDUXGz9HMz1&wpnKlb&0;Ev1vXSc-HNl6>$#|Uml8Ka2qbVbq!Z7O4X7HvOEh( zeTmB|60L*Z=?pe`eWmR$`N zCzN7qAxoG0lo&0hV*o8);bPli@wc^mH2!huaxyFtCL@qsna2GU64|JiNS%zkNawge zb5HJXMdFvc%Zdkygc5Sv{YUPP@b6!{zjh8DsEYEIT*W=c@j7^TEBXdnK&{|vP-7oK zZgL3{=NL!@#kTUnV?14_sHcKgV4b*0elkSUNKU$j8a&&m+(i2v8s`r}PMNa~B>{5YTL#vOQHuH$Xd zkRTdI9P%rDmjbqvdhH zNg)zq`5F1_L_62DXNMZh{}sewuV#teLa2;(6kEgNobikUPcvyQsw{=158EC}!~wa> zRS8&{!K#j(;jWxyd-pvLGtgF9SYCo~m`iirskfrNww^?xa@n4(TQgR zw7hbuOQr)$ICUF+m3?k_+>u@ct={`^cafFxMqH?kNs<_@pKUZgD=FP;*#zRE{@1SSOZ zDJKH4KWFf?-kPhG?KlC6&$TpbewZf?PU+lZF4aCl@DXU^&4JJ_INlR!_TiXHD&hL> zKdr0BsoUxdgfT|aWUG}xIlo5#9K2W^&r}R@u(^8dlQ{y<+lA#06NfM!@whRqkk=_N zzu?|;{Qijrj}F8O`H9<7vYBe=aSJLDo?2T32Z;y-jG)YWq<-nHR>3QnPdXcpIT`2W zCV#k$nQCVHtj9tWVz(absJ^4eSRN^1)!|>cAZb3d{CQk5t@Wk9tsiMDlCpPiA6e|#YkREmg~qY$ zW`exvV*cgqp-LbT$YM=to5nhHMd}M-6*>6Nun0Wlzp2igQJ!4JRCRUzMYiH?!Hy5t z3hmwZvnSs+!Kw+<0A*vM8UWW0;hvP#EC^1umZ;qvOp1XAVcvmQd9WF)y6YMK;t7jg zZ}1m~SoiZgLJ`B6m-u}ZAZ3t+ee#vratM}H28X-g$|J?!vF8qHwRq81E}t)Boc4Hl zb0BrxKaXX7AIF8(463+dVXkpZK*`+1mQSi0u@ed@lx!E-x=>-Iq@bbM>THSG4q}j8 zS(hjYo*TfpYTUtRezh3?GvI8tVz(4atK5eKvVjZ3UQ1DfS-N-sdiI2Ja3JlL=}HzF z?7smovjm#Y@wm}4s(C@p%Rw3I;}p-Y@vzV*B{5O3UwdVE4XinjKi~R43;6dU#LgK# z#ixADF8`c|62HJg(|FJ0L9&$gH|U8wW~`RV0U4sxOaG+0>?YEDUw~5lx1~+wWwmR! z>wQ$RPa?_?cz%d?I55Z!xAV^(;J4(%zUa^0uItY2y{=<(=TCw{-XbJ#MPnUo*(sMJ|BbPPbo)U*Nde6E(uM4x6G!@P@72uMegiKxrMXR=ClFzL& zbfi+sTQb{_@7K5x>J=s}=Z?7i7Ongm2E)xVQy&C!pYm}Npx8;afQwxC zaNCXrg<{ZNect_dvnL={5DPSA8;)#ACP62`A_1KjyG)NX38uuw4~X%=2~0G>rFVbV zbztU6ng$K`e$SZy+i$Hml8tqnzyq zCW=jLmgmH%G2)E9QhvV?5;n#vJnmig(mWtQ#j0+;r9+p5RotYMYMVHQZLn|_iATi= zrnXI9r!V|g5Q3AI%{uB$Ty&zAm^Mfu)|@KSz8GsbQb9BJYaG*KK2o_O#~bLe44IpV z-9%<7THRK?h9)hzP>f#Kk$WfpB-p8uQoZS5TkTHMbmPV880+(23 zW;RggM~bux6 ziHA+d+_$AaLBIqJn@VgJqLd7JsFYT;6(<;*lfW16f{RM8@BVX~8c5bg&qZt#*ro@x zm1OCW-3S^QZiW|f%ENQqX|YzcIC5ZK9S@&~NK})ckFC@AP0EZGsEg|fqVNYU#vMA( zC{aOwkfC1{uuDx`Tt;wEvO7|NyTdfyZDdWKK!i^<`obk5dpU9+x6hk-dXqe4=in`$ z@}Hi(gC%)YY)ug~?V1F0A#OL9+3k_tP`B&H*mdP=Gu&?0Q|C^kS=tTI)6kiTF$71Z zayV^K@ICcow0-GcR+f%J$}Fr^ga6ggiW@KTz`+jc$uunn=X|v|-^0#JU^sf#%IKIu zd%d3aj#ud&RHjM!!arFquxRhcR{AU5=s)v4S{|0uGb`mUQOVlhx!prm}CBvG#`3t+6x7;oxv1nv{XQ!vBx3TC;j|muMvdu8bWC0%?zQe(5c7 z2nS9qLZUHnq%>%8;TFP=4=@w%J@6TP%0!+}PuqUzTOb_3`)}!psNY1}_K~}5VNICW z?O+bfmwAcMGtkQU3cWhS(4OOGz{YY^j>j`ZY-A8tYZ#ToVdGF{T2krX+n_ zO24aeuG1@b;UmmduqI$nm3GC;!(Xy>K1JfR*P4jpR9pMPvX7;F%2ITvIi`TCY3s;3 z@f`N-*$@@Vk5@Kwd@t>}gg|H0Z~2?Nnt+j=#8kFQ?p)e-26kOaTU+TMMzk7f>x&4@ z|FG|{uED3QYCW1ZPg^RFEuCeh^|f?t?K7!Rmo$j0M-AuM?bj%rRASQWX>W@d@nf{I z$`m7%^6JH2*Irv`GMP=^J|DM{JDzraDRKdCPpv`{JCFtcZCXKhCT_(MHR|2bxMjMs z?ri*B`#96Ku^v`qhuCMZNA7*wdX-yyggm(5^8;$aYv=;A9Ji0rm&9;xIe5!d`ZqmV zzeb!CFiHw_Z-C`YQbYN6ZmEe2wT@2}%TY1PoIXIFw0oZNxY)$wHb%`tG*9j@{f_$m zxQQlyPX(nf58S8mt$0PeBV~D(XDnUk!cGpuh=Ecy@N8m@4 zxbNk{yp6HVHasw6pk+{V#h4W(Jw_Q_Q;*9UTfPBjdfbFQ8bL~5wux956Ap)e;-4kq z*n^+{3G(9~p{F0=8H^ukDU-j;b209SoO5C^NuD`e05wn1yVbh0QXwbdxv6rVy8x{W zEtb99B;NR^&YfnwvEyz+&sbFmIA)QCl*rwc6d~GVAyE$3!bfgL%C<+zF{f}BZ^I&` zf1V_^ylTPcNvu?`Ttj5GjdS4A;v#;FZ~58q`fmB&2Ka2c4U~xG0LKQ(#asA&+51`_ zH(d%RPZ@DB{whb(!Jdmq8P^D!hHaGaupDW!PuX0g%xH@{rHq|gyM=xiy>&Bw^|9Z% zRB~k`Of}zK7F(}I5i_#P3#3bZ6@43Ci!p`-03=sb+k{lz+FhWrgkMe zINS$jp_SN%81`7oLAKEN9568#(QqkR;W*0LMC2gKqV*LUH)r#6je*9uT?y#(JDjDeUQ7NBN-j(lsncw_CTtb!dJj`+o}k=;O5UrC$D@F z|NYuii0u4R=bwv>oK`-v-aKq&vLR2YQ&LjQB~!^$dlFM-C-?kB;>zT(G?JiREJ|fxw|VAm0Y(;ttv2r*mGRB#@gs z#s{&@L7(%Yic_k&yG;8lc<);Ww$Tk?~$O=&C^L14sQPfT2n%o za6RWwu{*kkOGOv$w_Ts%n9m9nCo+jrxhei;5u7P+3CN;vPTasaxnD|i3uhtY7JRsf zE`Xz_B>AA{^SIv=DPY#LI7r}Ta2WAD$(~b3FY6q&LD8tW4V@45#_gryKcMl?^FW$G zu|xXs81Tch8O3M&7Q#u414g%i?;k_+9Bxix&`Vy*@yH|J3s;k>AAR#4Q%44a+tH`w zw9T8?kFuylkY#xH7@xlK>+b`wdC@TeZTB9>M%~!K9-};tW1ARop=XVc03&sk{3HNK z)A**g>H5j)xy$u@*_NXw{~hRJd=kqC03~@?+6D)@_c(Op9RAK7O=T9^;3(l9N(feQ zp}7rb_!dV6?f(tH`38!q2C1TL78>D^_XGBg*|eJ{bP;7JRk!yp0>D*-Q0@#*%1R2z z%Q7~B0>losGMVdRvHN(39MevO#Rs4GpX046cZ76x+AH@pQ-*5Qhu9y-BB=vYFs$o* z&>l#|--90T!|mhd?rns^*rYog2cZlTh<%XYe)5zDMA@5rPx`Qe2K9yWq65aa^N(SF zwi51ugq1RHAA}#FPI3g+<`aznuNV^U!sDjz{uQhC%;c!3!C&6>)3PoXF*q7IAGYHl zC4c1aU*R|U*_Zg7|EFBISlsEMVC*{%*Pt-v#_RGaOlIaZA-B(#A4<57z$&{z?${@# zDW%nTcVQ7Kz;(f|+_ZMpt5Wu3!-O_83RNOP;6zWrM-@ z=bm`V=a|3nP5FNa%CKMLPH=@n@1`P*9mJ72z=Hi;QoKDfH>$W)a7421bk%^~){XQ8 z&Bk|9;VHmh7=uZ|+3M%hPqb>$zao$OtWSPg|5$ z@?_jDUXL}5Tlcb}-fWa5%PCdw7cmdhLd$@lV-KrxtZ#Y7U3JyAWto478A?A=t$@Vg za!z~7xr1l$({VgWehvSg_CL?P7tb};UxI$K#7c8L8n{?3ab2?!cb2;T8oyCas~Dfv zXRG?*-lG*#KZp}_0=My(bp{XK=NahmCn94AN2x6)8XKtfmJ`k`f| zax{)OPA5ovlFCrXS{Q=41AH{hYApT}1XM3EBC)gu{Eu)NVQT!D+fQsWYlIf;6T4?v zZkfA`#hV?YpxHsN(a zhMs(NgylF6ltP@@8=DxJ#Ovh6Hg8mBL9C8Fa8YZ zWXU~#p0}Twrn=LDTjtMFlnc=gcLrkoi@rI3$4id;E{5#9!htdHIsAQ%pBd#ED$ngL z?4VSIWn8!et+2?^U0B76P?N-4JWs5mikOhc5&D?+ZD;ByxVND7xZk5>@i+MN3;cc&KYa=LN(yF=TAUEncr4;Qm=&fy%gK$?uaP%>Duoy3XjrRPP z+MZ}+bb;vx(y~xUVf9rKc4E9>7!l-g(rV4GlprsW80c^^_*L$Y7*58%+AYRy;u(fs zSN%B~j+c=sy?8vjv=`zJr6Q#RUV_3JD5GWb@Z7ga+gLHcooQ=DkH$>H`;=CGd|IDp zb>bU<O z$WcCmG^!^_Voy{=ka%1@rIr1C8?TjNM7OL&fpt4krW1T+TE7T1_z?FOHMgjjbG<(y zns7F2er>qMD7f5g$%R=^7iC|HIdAWhY*RS<8;ZI z3zty);AzF$h_9w^MhoH8N~qklNaA`~_I2f7IT!dfZ2386M~@?(6OU^pUNW6mYRjCL z;hXs_+UQrMRddnh2jw09*&JhCEuZ~!=i<4hW98^Lb6GuKs!dQTZT%VK{2Xm1G86qu zy!eT_o{|=c_eyP)=NK3-%a|gqT}ipd{wa-%4WU-ROUm&nOthhT^0 zsLfi~>NEb(h%H$qwj*A1M&gqUk*P1-;CzhFU1Cw@KV>V85@DO~plRVnD4fYh;L9o! zyyI#tS*ygAb=hRhxrhfzHPj*v@JrA&NTD3Ba)sl_(p^i(VKFc1Ok%_X%7VJ}Ho{l* zn#2leuSQK|7HPgkhTfp_i_N33^`dsPj3lvRT7zLEWlKcjnxr;hh?}lunO0U`qSX-1 zuR?dM9+<|cWqKQbx^nJ(JY%7uCuL2=Mjpqj?n1eJxaTvBY7v%bQCaFY*~2!*9IjsA z3WpVoeYd+8_Z8|MTv68RpZjcpxklK~wiCbhd?at&PqSEeHs<-wmE~T7 zp3OQNFsSU+xN3=Hmb$k!dm;{T4}q)7_`~6OfjAbDnZ_8Pap{$A?W~{R3EhV25x106 z569fhPQ5Kb;|t70beUjHf?a1Og8Dh03{VyaZ55UW=kAmlp?KbE zBh|HZG=hC0(&D#%_oR?i+CH5%ks{ioztub%uBfc5<-jv@ziai}L{DWLuT@JV8w)W3 z^kr=bwbdZvXb!sTBLI5PR3_a7= zjpY;PziIwpJBX~Da+f~rOjmIm^NCh0=Gjd?O(W_?J$uFSM^v+7k(^_GQd_E(a}gU@ z4jxXy$jlO~@sS)gjQ*Q3fuLim3Bk{%UVh6*y|JGUkxATAcv6qzwphOc!=?2OT5Mq) zrg21PTCuxo+ScBVx@6D%6KCYSPCacLzXTtV@{ilp@-9{_Rz>^w+Z-`3VA%^QLx#C+@9ipMq?6MbX(GH$T5^qj{_k3IDEjA8g(N!$b0 zrigmP^BFA>s|(c{&_Z?tWwbK7)QehGENGYQ>+=?Cdh@yrBgn7ZI%G11?|kZnVdf-*BTsW+dR4Ml%&l^`0Zl5$1?b7|qD42VHtJ4mxg8`8ElQY^yBv}GDn zZ2L=%;-KH*0q;0qrmphzvK*we!docux{vePi&dohZpBY`sqHZ62Fg6#8fW+#>$y8C zfE9{Bwt{q>Hc~wnbAoL{u}sn}+eF|7z4MRxwY4bs;|_*n5w!M4SR<^`@D4|=n-!O?KGZ8NhYT4pU<9`wW6^$k#S%WMa{M8?uT zlM}d;({233m7@jo^Jgq9VBKPhRCci)Ny5rw zc5cZMqq-#a2705sf?m}pOKm*LqhRd9k=s>o)Epw{BRy)BZlR{gU+Y<~bf-^!g2PHT z_ssRKoh>x1nd%+_#yh~TXV7VRL2H#qyUhO_vLJR7S!tJoJ^U@8B+wsHiwhP{yk0!_ zWm(yRZbxEwt)BiZ#&3_rrZ}D)C<6}H_1;X)@mG#(L6Y@c*xC+~wfPgb*2KXMnDHfc z#FuAyf~hKz+EL-5<}HkivM>8?i5d+BQpClYJnKivIfP>WBJ7R6<6EpHOHJ`u?&5P_ zo_;Y#PvkGj*Nooq`tW!ZhF;WDk;tkq{_}T8VW#|=Ho)E4S^Y%5@d8J`4atQv6j#ei za+G4}Sjwq-iV`NAkw{v~L}`?<0Xzs-u(-wcmP7zaw>d5==q*D=)JQL>>uns;D0&5R zmG~pzw8MdQ%DjH8sb#o(ZEeGMhVHuP|tj85<{os+wo zZdg#h%z!u5uXD4JTS<>mLgsOR*#Eg}WmZLzwB?r{E zLH#@MbEm6)*Jcg3%I(tmr}E+oQ=es1uKFCdyV;K$V}kg4CAZj*Ph@**IULeChgnja z0_wSYRi3mHJEU0W`P0~dNW=pHThNvw(ywTV=qp!}YrE)=Fmg@rdCe|SpG(m<#=Y{j zEQp#9GYX^ECzsdWF8xMX@n8Y4@pPzp#Q7z0CEm#6BWaA|Mc??Aq;%ZZ@M4w){B_7D zmXKrI(F1{uty)^+@kWmDv6mD^bEvMZ+aocIyR-niSw=oqjbQ$`GM?Yzs%1Z-4N6H4 zeeiAoW@~(yqM724eGJR1HN^I>d8`bhyaRf!)uy}5r|C~Tfn?JNk{Oz1ih_|O8Rw&&0M&*5{GrvDt@FNbV9JcPh8EI?!A&!XgcJj`-$jW66=JV0`?xs~M@?mRh2OtOmc@kO6RY939i^2Qj?{nX2s zkBR&l^n%i*-|1^vDMXWUMT3~UU{j$F>o(p&w-K`iQB-yo8I2JS@aRM8SbO*xCY%@gqDAd>vSYu zlnqLIREd4^F@9!5yg!BhmE)wf$omw;s(A$utwd~uC~1!g5ras}N9JGQ!ATh-A1AfP zh<3mihfR)si#Aecit}7*qOX?tdl(qC+b4yEytfU`mPy;Ug`_KV#W(Y`ZabPIH;ULJ zukOI_pg+kCE_*(}NFevaX@zkCv-8)(9SNwytqCH59w@_OoNJK$T_7QkxqXN={{+9g zy<6i~|c|zJp{sPpC(7Qhe z%{k<>U&6vEgSq{b%C}evd8wN_^eEEZqW2?=OF~o?-GFnHx3M&Qce4DAd7Oy;1S=Kt zYRkKruT&>lve)C=_}AeQ25LO-IdNx#os_+A$Y6+xnfT}#MaHNhvM(K^E4zPK1Ueg_cf>; z;lU8r3GJY$92Nug1QD^JVF)+O@Nwc{Zs<#7NbgRM<3Hd31i#U_Y%fJXml*~2w zLS{+{M@mn`pKU|dv<}vf`Cu|zx{L9H&3ptprVuWC$e)|v=b>LeCFXotreR%$*YUDe zK*XR0%8Q|iIegjU6IeOdmwT({f%Bi}&pZx!4O}lGD*02)0`r)F`=22C<)15v&&p%B zmt9up-7cFtX+k!K1T!9E)_ix<4saY&_V=~1hu4@t)&I{c6q@Y4TyZjY0)iFxX%HWWjS5+?aoId|2g>0 zo+Deu3s#ob+Muu z&p;QdleS+VNLOE1+{Tj27^<0W;C%+X5hv}nak{72E4LH5(FkfOa51tRWuot9t;+UzxYzsyf2cg>Q^e0=Zs(h*c)oy-ZqRgiRG$$s zl)ieK(jR^_~g@4^FAkaqH5ARqnXii9|llCI3G z15H^v=_BU#{p4CMFN@XlrTVF3d`b3+e1yE+;5f~m$FGoJ^ zglS15Z@lWsstj~#w8J>ouUT1~HzIcMbxoWFqc&=OQ}!U2YFGJ4wJWmYQ?aCIb+yu3 zig(9sb~Ylj0rvKZ=fH8UVsv~cj*rw(58cJ^^LAlBY{gof@vzwm4wU2d*jbmaCUBSU zpqFrxsql1#{hMJtcLGG5k}%LUOP=AQ1ZvF<`tpZgCdB z6w7L?2qzor<`PDfa*#JRyUVkv?m|BFKq)m(WwrO#l+i6h0;~~uPkd$_KQVq5ZbS^b zqK1z{FC#D_;v=(OYThRP2ZmGG>ZqX z*)6?P@275HcEO`nd_)6P>IW-SxTt;`e77o?%d?~mGo_Bp+?=#bAmn(w$-pq)9p+Cp z`&x&WG4oL0F-vm?tmh(_Jt8CFo(Wf*+QVo9CzcSu#g^-CmILK};lDdfzQH>eWAh`4 zJ&mMngnKVe zBTVAOXiw52=nq8x>5D)VTX$VV{fF31yR?h$IZFQa73g`*n0Q}aV9&eJIUlv8s3x68 zyY2|7tiBMB(j_#>H@HQ+#KnJ-v^mODl(@;&;dta~KJO=ry{$q5*x!uxL(UR2u@s3c zfdl=y;D$R*M5VOoiCXX#x2(&RSIiE?pVKC|eiA1zN-s2Hzvv)qn{TliZr*Ygj-D?{ zv3(O>F!uqF<0drxHh$(shfDbVHf(SizpvxpU*lhQLaOaH3u;&_74(5ThPKPO(1SdJ zg>sg>)R;Est9~b0LzABkIV&hIpUOV|EzM`*sw?p*oHVRdCoa53|Mi}$KJIrXQ;v7M zl)r{lLiXfN(yAB@3N|ptf9uyVls4QsN-4aCi6_OIMgkcgD7SX|$=#3-dD!`M?WF$P zvTny%F$^Ay>lR0z?hMzeij-9k;m)*O=p0v8!#f8yARXE{b69sl_6$CPR`6m88;PI= z&n5`+NAf*DOh|a3svk>_IU%J(n=fkixRE|?6R#K~T>6%yAX?EbSi<1yBzYX_UYtQw zNk*z^GS1ZcJoesD5$M$ZuUrG*hJ7%6J zmf3>WT()o*LNDDa9pdYPPja}F*pP!!sO+*X`aRgSL^m1DE&@$H0lG-5n)ayV2W}q$ zW!AxyQ4J|R0`drr-zUWL2chj9@a1pBthFYJOECp8?JoH9(LV0stomNo!C@6V_zcA= z^5tb;=SX)-BsSuV53BPI3_8S8@V`#w3K(Cv(zQ zuU?Htb2XYjVlGB=F`B<){($#tF6J+o`}uxq?e)};z4!Ax2GZ{wX@rcu_pVyCYSsEx zt5#Kwui3rA6V}JqWM&2@`)odJ?Z3`7VOgytO#tPp`ihP6%d+q-pXg~T*>D||Vrv;l zooymV0+=J70o}Pl zK`V*9-?S=g-@=Uj2A`-c=Ir@;d}fAj{was5_I#0DCZaxE+nCu9|6bQ~)52W&9ouIu zmF0#QtbM9h(X04%Kf_F+9NKj&lRW3Zv|RHnx)Q4ew>Y{c-t$p7%tHXis1j1{rG z`2CpGLc7>{s(o#05BaFB9p<|0<(y}^T@NBYI^gc0)d;5?BO+4F;JS7UglQ}NSUy#l z!^*U?xlAE}{%-Bo0aN)pV|qozG|ZXS;40_h{ShzEToV6?33wBPPvv@S?Qrr}}+Q&&=cP+2uIQ*!v+*%^1fGpQnv)@gl;s@g^249OT%2 z$+|MHQhopz1bh%zC$L@Sk&@-bx;mcfa3|4}Uknir+>-VVQ~V#ZMvwK$N&LFl&ID*f z7tbvd?=cCj?Ucn&@&B2Vsq9SoCQO5^%?-kA`K?(BTx@5yk_Uia%lrf!oT`_{6g5y|lUkl{Q%<}jg!ZT_SF&$qE0 zmOk*VGB3kH%gPOU67R+*{XRfeW;nPm`>Wpv-r?I@@8}KLo0LN9L}gQV`}1UTtH^ z>>X88aC>WxZc}*n*3`EV*lJvQYwFvGnxbxRO??|tQ)AIvQ{PT@Q_nmUD6BFIqsycg zoJUe^je(+eZO5|C!AwSEnB~d<^b3%{`Qd-2C9(79-)EZ1G7q!li>_;&nK|KC+RTCd@Zn^ecD8Ow-+HpEuF zCgRQPw1zCGy8f(&N?Ul5SRL+HOc3=YMg;NV+Rum;In0 zV$n~dPXlc(#&Y0bUH}nMqDaNQsV38yI56uB#0Q|Q#!&grKzkXv(sto+r>S`%e!Wr9 z?WDv8RKCOi*wA~R5@j)3sa(u?OBpBhKyTwMiTKP<)iM+)OLR$O30-|t#(Fyj9Hv}D z1?_Mkn~^v!Hq!S8+C7We^BmbXcw)>Avxr-~v9jxuuAp2?o8uW@hNDn3^_=rFn$;Xd z!jdNN$R9o-9K|(QM5jE{kLy$Rghkl%Xrg5svAd7!MbHK44*1dLkHlWeTuSqIzm210 zZLBJTlASbfE0yeR`M0Zo$2Qkun}7Jbw`slo`_Y!nSMo^zp0p*Ik#YU|w|SC9n*0X#cd*h3#UV72-}U{0i(CR#3i3 z6OS#gR|?0>Q}Va`=GvvkqdL|7l~P>E^jBGR%>ozDFZAAgI&vUPAJPYUA5ML*|Hqa( zyP{a}{{IcmKNeN(^d+<&-Uhkk^!l;j`JTo1WGqee^UBE@WC^t6OP6lf;7~63Txy=P zW0*ntz@9LKgys+qwWn%@BYZ7cGt8F;`d>AqKJejC5>DN4`8i>Ik|lslU=qf$+wSd- zP7){hX7@la&Eke)Hi$7XKO4&;IDBWagY$(lJgtcq^^En*oeYQBzWGc{%>Oa8ck)w> zL_Q8|yxh^dU46H0RfFC#^c<0W90o^s1<{fiO4{13v$&;3L+6h$y)E2OXQJo~cyT%^ z$+b|J^S0z~YK%h*F&9vWaP~Dpg^te@DtsK@q~0`dv~bbg z@2x1@Oja1v=V5TFuVjMxZ(%U?gGM6;bXH4ey**>i8)#cfo8d8EHm&dSx8+w)ilFmT) z<%uz*e4~$TsWM4#IqhWhGOg8Y>L>JIkTsz>*0u0@S{M=R*x%^1kK4TU(!6Hq)cl3md)19D(8%4U> zbB)T0IE6)ngcXOX%UfQZir4qM`*U4~G#B;2vjq0+*R%6oxkG%p`S5!YK}P z(eVtqF6eG?S1mnPJ<(OSW|rj%oE!I##7^5*M%Qa$wmhyzjuqDahe%y0)z$_*G+P^2 zuZ`8X8W~pS(KYZJ;Q>M&_mpCR?jcP%jb9ILXD6%O!m!!mFs{`M&&_sAcml}&-q6AQ zKzPFeJ=k{iwI4m&+SF3 z*;Kp-ujT$4Eo@Hpm(6fEOwtp+xK9{42Ied64du{|+*i=jQ?r<`+)VMp-~Nw(ZgwP= zZp9xJdA_I96@IJV?2N>P^1pb$Bmi$~or2l)QUd`qgSg#Mjr+=-TG9K@Rq9LC{3`rg z^Y^cZfAMWayOufGqCDkcMemklxwTj#KLLVoUbBAxJKx=)eZWu!{BfKci+Gn(T%VW-AI^-2DuqBhIF#B3^p_G|9_xiK4UT;ieG%7 z4_?Y&nl*2}_T+fX=Ek4xutMz={O#dDNGLat86p5sn!l5kDNE3<0iH&9OLQ z2v55{{Gjw~!{N&jdYTagrG(Sc^Tv9yIS-p_>6QxCO`T8xiL}XZ2=CSxvBH5By&D`@ z=F4&SC@g5oMgja;+kBz>=TEWxxhcCytixt3bs0g4hq>W(dl@1>VTzd!(Tp&kj!(jx z?dTmPp-h;&r@x>THaP3uqWR56McXtbLUFAL<`iJdC}t2o8ZlJ49Iv!*RK+ z^!=M-+qFfUo_{^`={-%4qlB6xsFbqpi$83HwnZFh9_Q&tojV>06XwMiR_+blnybJSxm1+4& zoNj?kTPimV7N$sP0(xkI#O+eH{BEW#9AW+i&QRO9F=!*K(`BXM4?no^lD^>2?}fpP zag)nkn77*a(j?g;N5eVgv_-0z)!Ak)qHst$$K^Ojen_HSiF_i zIX;G?!tM$ZR0`9yg|rd&@05fCKZ*un%_vJ`3J5ws@N@J>z4-jmS6~bDK|!vo8d%h(2}vjw9xX75$^= z&mlCYB?oJwdOk`(OIl&5kEChJad=u7?d( z-xmD%F+3>JEbt8MKr%c7IcU?Auzz70t%ml89%ijMy4f}}J_j_7c3Jh1Px@EmMeBGkV9o+-dfL_BECGg-^gbne;EC`hpJv(N z6mWTI5x7^=^iG(yM6P_T2_Ao{){{m@L+NcbW7L~dB@P>+Mt!yrrGAK*xjxwx#mt5y zsX&M~m(C`;iHCZ-|#@AMP06Wb3|G3 zQfi}ub1vT&_Gf8zww#q)*>1;)@lSehzK6}6!n7Z9xg*N6A%`upS2RX!n%&Y*hN=3GBPAVzPCv_M1Nz1&}Q3FKs1{^qSr?9@4~X__eI}F~iu@8)$-jZ%JBhi#ha9 zQWbQN5nA8uIeZK*`N*O>c;{9eJ3%e;NzBqd7ku}NhzQ|**KnjU&%R16jo5KukwRuS zOhZ$!a6c-nj{eSgf1n>vk}u1{3HUWo|6wdw9yp-(<92CpAKJ4X4UcCyoXv6QE<*$z z`(EI(II3QT^Lk!xS7Ye&(RN&ZTRkC#B7C<0I_U;)_YCPvxh^V-Y`+TR_cel+1n46t zNLOA3lFPJttQoW~Uj>?_XtwF-8p*f(hg+`#9e>m`jd`e8r#w0=8eG^vT(h+345ej9 z-m7KSjzfVL(i%=>;V;o{UGJJ|u%4D{65{ngwj}zl-bS6gQu`rbM?4(;gAa=}Lk}@i z4d>dI7`5>*$h@bIjb2n8?m0)nh<_alZ<}~ z-n}cB`IZ2@0Hnv0bwf+x(6cS4*R7W8#>GIbbKb@R)@`%ilYWzNO9MA?R>C zV6Y7fCA4xh@LR)DS)!Cf^YskFbbGx;tdKx2kMw7Q`QA?X&DmssU|%KYrLPD%fj&5&r}|$ZePc? zH@uuQ)n|Q--uJdSya#zCX2W}kN0s6mzFjF(>F!!2p`6uhM6SaMdX`GqaB5Fd+W4+& zZ+PuzNv~4VmHmib+_2@cUb`e~!0DJ3&wkO2{gUHeVpO)=<`c4ja*Y)}ayWf08UKNG zS+fm0-K5?JE9bBY;BAe=t<7<5Jk!0}?b2nBl1z*%>9SkWK5xm7CH+Qx`mmy$EYgtb ziATFjx=)Xe;4s9F_}qI}G@^NQrR_<&?u7nn_9E@5>tyS?xz)nUb6>-}8uLe>@|JKx zUzjJTK6T*HhGlVw79KloJg^`szTtkS>EHSQ!A)5uvuYMWi^taJDEPW>SOnhws97j@ zKNL;Bj-CkfMta3h*yyU6TP>(Ca?{lII0$eKUPK7rIpPDr~KIWEw$vIQL@fo4h8 zwOwaupD&DSFZThQugD5Qs}PTF*Eg@EL;s%aD~qoEUKndEF15?FvEOTsl^nsHy6m{7 zV;3AEbz6-kmzM3I2DNe-D&@d@DbL{P;-tEMy$(}Bc-W11!r-!a5z1qC?<>mK-c(n% z$iZ=Wjho^^t!8}OZYTFlUP1mkAm+2@SAf_d3t<0E;dSGWWFxp#(z89+bROooYYtFA zDoZbMoJ|#%zE@h3GS?nGlOMxMgec?is&47amsG09C@hxknvSmZi2UTG$;zR{%aTy9 zzDm&KnLJk3_sFTk!xa^D)pqV%5XJT#16%s5S-tz1c{y3q?uWI<#Ox|?u`$p9-eyRhH7K6b1UxW)Qp z-BMoTmewb97|nWJhH*)&5uI@31++OPWgXM%Y<|p-87{R;h!^XmLx{_-X;jf7Eeghq zbyD5jr>SVYUSG!PvQS!u6z>q7m-_0Eqe7GloTA1Yb1kap_7ExL>Q~kz?})ds^o%RK zhG%y(z6oE}?Lxm&j(Do)Bg`@2*7wC@M902u@j_goJN&6|$k!WKzd@(FhAFZtvJ4lv zI83LF=v?Lq{}N&0D(dL1FFY0&ZX*oKD*xi3rJaUqhY{nBH3>&J^n%-n#dz!GV9`oet#dJkIP8z5^2agL)AT zHizvU*pY`7vLpD20&%FaAIZlvk_xrMY`OQx5Be(KV)xk_Q@-VL^S~w zTAk|n_KEPu2G_@j4UgWcT7$Q;1HG!_@J?%An;pQFFxpWI%@JG6C2k|jR_%IOBB;>I z_iH%?;{i&oIvm$T z`tykGAf?W#~PwvO54>Jj-}dPU*aKR`=l~g(CWaR zeNox!{E}2|F2>zAR%`nk`zGh#IdUW)uGGBWUAj3;Y$C`F?I$iP4qDp}7F;Gv&gBW| zDtsr?_Gmz|fzhq>fp2z%!0`Qn6VlckjKm@Bd8DbSw@f|kM2Zn@2&%=~u{HQKP1y~g z{F5~O*P4gjmd<2t0q+uD8SROM%JcBdK0g!gd29EJh}4^J?HzAzoxUY|$(-IZDc^jn z>)z@aTD>dH*mW$-n{W4BZ#Rx)dFV`UYcc=ZHEM6E*poVk&*%BQwT>A_)sfAH19TB- zI(eXZw?qwWXn#gPQ}PhCpL&mv*Y)sWh(tD}7x)furfd<%z9}&WJbY|lIcnZV$Z#}s z6y^)8k&x%qe2={Va@N|>c56-Pi1kp4VmXr)AR;eKxy@IXuOZK$1d9Z{w8c$3GnDz} zjkNo~agV*ie@pYLrnSfqh7ol1yzJ)d5pcnaB?9g>paXsh`otpD!1b@x*oxme;KkM$ zmrf0q;R5X|eu=o$qY5r%mTQAY>~R^jY`(05VJ$Z|)W0&m%$W{RcgJ>J8k=|8MRp?R zjo4b}Xf9Loo}lM>5cL@v4b;fjby;Sp&G*QuT%;ZGilr@s2TCO=^6#{4Ybo8|p@T&O zJHNjMzYn$TB5e=}wA^Xq8jE*e)rNLZN8FrPD>r&k{#y-bETeP+KMezDl2X!}y@66ZPe;YK+yF zi_}gTe(fkrgGHob`zy!W8x5Lrkt>Nx`7_izOue7O<*h;5C`mfo@piwoknB>f!xe^GyvsfQ+pYZ=e(W1vo}rtMP!UuLm3r!Mvs z9j-G+EgveKzW}dtbpT`ft#D|!OJ+*@t;JbWTjblCx8=Kri1&~Yi5?3_Oiwb;GuxsS zlHqY~exE1tgFEu*i8!sQ=YDk#+53zN`70~pPDX>WhW@Xwn&7zq+u~)kf?rYLaZSI1VM`;|T%UCA zy6EL2WNWu*cK2Ip1HK_r!&->bSRB7Gu4Wgs0>YJX5a5Dx^%LJ8{veW8;j=jon$cuO zJz>=0j(atXOXFZ*SKxMoWpNrJxD_tv$H6JJM^*dUxZ1=A;czUlt(@PJ=AvJgF<8Od znFJmjh!l8q*Lbg&+8^aG>-c5K(_{g$sRs?V@ zfC5-ucr_hvJ?bED9i85Lkhi{#I09U!O!d~(x1O5K;r2Z><01GXY7%Wir?Fx|j~O@m zeNTHs(>J&l8MIw!O^clehR60Ah-EE{^L8IIzD_)I8r{tLhISNgms;m~Y#;n=jjrv% z?n%S3?}XL855;p&<2*r-sxx9Hfn--TLX~hK=WX&pk{sCD6y6_aI~mvbP6W4BAv?v5 zD{at&qHHOAoMSOLl-)Rz#=#ZD>_+%ec$Ko~YlPwR$?(bBZ;u!w z?A|Q))4av-(PXf%$nK_H8YNAJ)cUqLKX+QulWkHVfLBdKGTy&cx5u^?Vgw1 zV*3Ze_GHjXT-&gP*X_w5jqYd76?i!>#p{xZSME10){&7gQ(BjB9RJE}E|&CB^jebC z_?0h@rJ=$+_7=HTaFL@S}jtxE0ZBC zlqV?=qbT!m!cpww51MzhzI5WyQEtUnwW)7A7>HbaJM{2M%geP;<-9S>&`VZekvWZ~ zuHgYAJD|R%L6}+*rVsRQu#E4Ew^HVF5EZZ!Kkc+w){MgrCpcZy5ATS&pdA?}B2G{* zW#bVOEjfTlE_%||K7bxiBbl~{cibr%*UF)+MO{KXoZUP%{`Ux*WI;RleJ2-lU0cN< zGUIE|f3yhLfq2f!!GCJvVKooJ9~lpRWWGjs=;`z%`O0$JK6{uXp4Xo^$Z zQ(J@V(qFd|rzIuI0-AfIb{!KqX3MIuBgXVf4z|Wv6q_kz7-4(PT!3QDNrJg&SV)zQ)V6wt1aI1#0Zcw=?>= z*B6d57M4?y^Q>?miNOtFLsTXlwN>M^JKi}Y9DzSfj}GxwgeLD5I^e!~<`~eo9v?=# zaLdyUu%1xy`7nAJ7E0&|?yg1?jta*dJNjy8k~~TEkCgS%0_8=>rfI=b3&$w(QA4z(GPHxTlmiqR|;KAqo6V6Xs5^o5NQds!`9LG2HC0>-%7kGxEle z*?ir|cd3L6lfwXaEprAHFUGxbd0vlUYbk-9`J=8~`P|F*RL9zleXd zacyP*_g}C6gjilmvnD76W$|O6Ww)JTY|Kx{?OE7ytYmG36@OmWk*tiFGucG7BjSgWmr z^M~gq)G@Dcrmg`6u|~*}mG0OrbaqQ+kW*GHh(1z-s5NhDtdksumAszQuk2%1x>y&n zo;bh2U+#M{HXiY)C8yAxXHx6by`y?2^OM%PrQVr`-`2jBp4KjU_ROIf-IrnAGPnAz zv6yey*%dX>t>Jw8o5w46Bh9TRXfM;crKLiGzZcDFZxK3{Sd|`DIG*c5pyO@e|2Ce) zIUqdH`}WRr!zhiXJ^QGK1!|%J+^eo}3n$AGR=>nH#QpJjbIkOB09Se(%q>Cqe6)rw z+qotfH$`=#mB_m77NGA)H8v^#%D%Eu+S^CaPXr)JT+VaxcS^sc)(x~>YLg$MA7djL zmZ*QZ!4`^^S|N?SwKU$2!f{w}d=8{*NXJE5Do4ObJT!b?vnY5kY);wf@3v~SZC)u!(Q0b%Q?B*O z(MZ~%MX8F$qw1C89V#04)g;fft^Ep%alFL6#RuA1miMjxZt$@gk5vxKm}_N8!RqMx zaAsbk?petZZ~*a;t`l6nS7=G>biKE5a!A6u8d0lTdp{kVP;qSTY2+RhT9y^d`!RdP zR%L?LrgKWWHYRfTjebfyLT_t)axDlf{8DBMX!vKEV<7=gqMXzIpX1x_qE@)7zb#tS zMD~;kkV}(|x_cDx{OxAF`MKbs7Ygro4NvB=zTmOfHqYg*&>0(()EGINn+QTl;gTc5 zdcpyE*ZY<_@!p)Q&PdGT&cZ!WE1$VxL+g_`7=_$MgbTE8HI35wSF<1`kCy!p5&O~g z+uT>dxSQi(bQ_07?R|{)E+ma{Y#qMjStM51hlvv*dw> z1#8!8*tZI^6-qE4!4Dyqq|JF~5u_QNwxbf2 z3^8f#;B8BpNlKQ@c)re`O0#(8lFVsMFF^NtWg{%swR?2YeA!F)X^8WLL#AUa4=<=> zZvBgrN6T+e)z;kDx7sz63G?mMsUfu%y6b=qJ(cdCLxR7Ow`6aIa~gTT&r}AD$vGPN z4knAsQ$CN)vDd(Ia)~vw^4iSr-^*pZy+^?E{(I`4FC}50wa=EdSnH(jP0sa!Z|Hae}T zwRu0xB2C}KHS83}4y#?Oi<}+9i2*6I2M&&_VTYdT{V>i_T@Sx2jm+H|PgI+@X6cXA z`^ag-dmk2`MlP{SzipOGd*wK3eOIe-;eJvC_>*LCF7am;Q+|kAy{FtmTXP)oHT)6M! zxOaX#OdX<*!_tRqP6`*$fvkVqY$>;GPDQBnD0%_8>^GTFv!&ibf<*Dde#YI9M(UN% zn|z0Zw9rqx;sV+~A#S>^HrNlBBI5NrA8Y*{XYgx|*&pTE6x-@=jw8ND-)NjxcFDh} zHMEw`apOAKDMmBFEc-X?&n?T4u(e}fPxQP9@=e&A0{zGDY%TIA{@vid%0Ab()gn8m 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%0A*`OZB(m+Amiq0hZ63M`MyA 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

R`Bu3F2zQu5tA75Y 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%0A#%e_VNdz%ebE(>kN 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�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%0Ddup0*)>$kjmhxW3vv6E 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 Yzb~}5FSHMDw&$Q=;o-|G3MIGx2dP#?J^%m! diff --git a/templates/template/.dockerignore b/templates/template/.dockerignore deleted file mode 100644 index 3729ff0c..00000000 --- a/templates/template/.dockerignore +++ /dev/null @@ -1,25 +0,0 @@ -**/.classpath -**/.dockerignore -**/.env -**/.git -**/.gitignore -**/.project -**/.settings -**/.toolstarget -**/.vs -**/.vscode -**/*.*proj.user -**/*.dbmdl -**/*.jfm -**/azds.yaml -**/bin -**/charts -**/docker-compose* -**/Dockerfile* -**/node_modules -**/npm-debug.log -**/obj -**/secrets.dev.yaml -**/values.dev.yaml -LICENSE -README.md \ No newline at end of file diff --git a/templates/template/.editorconfig b/templates/template/.editorconfig deleted file mode 100644 index a5864573..00000000 --- a/templates/template/.editorconfig +++ /dev/null @@ -1,191 +0,0 @@ -# Rules in this file were initially inferred by Visual Studio IntelliCode from the C:\dev\genocs\clean-architecture-template\src\template codebase based on best match to current usage at 7/9/2021 -# You can modify the rules from these initially generated values to suit your own policies -# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference -[*.cs] - - -#Core editorconfig formatting - indentation - -#use soft tabs (spaces) for indentation -indent_style = space - -#Formatting - new line options - -#place catch statements on a new line -csharp_new_line_before_catch = true -#place else statements on a new line -csharp_new_line_before_else = true -#require members of anonymous types to be on separate lines -csharp_new_line_before_members_in_anonymous_types = true -#require members of object intializers to be on separate lines -csharp_new_line_before_members_in_object_initializers = true -#require braces to be on a new line for anonymous_types, methods, control_blocks, types, lambdas, and object_collection_array_initializers (also known as "Allman" style) -csharp_new_line_before_open_brace = anonymous_types, methods, control_blocks, types, lambdas, object_collection_array_initializers - -#Formatting - organize using options - -#do not place System.* using directives before other using directives -dotnet_sort_system_directives_first = false - -#Formatting - spacing options - -#require NO space between a cast and the value -csharp_space_after_cast = false -#require a space before the colon for bases or interfaces in a type declaration -csharp_space_after_colon_in_inheritance_clause = true -#require a space after a keyword in a control flow statement such as a for loop -csharp_space_after_keywords_in_control_flow_statements = true -#require a space before the colon for bases or interfaces in a type declaration -csharp_space_before_colon_in_inheritance_clause = true -#remove space within empty argument list parentheses -csharp_space_between_method_call_empty_parameter_list_parentheses = false -#remove space between method call name and opening parenthesis -csharp_space_between_method_call_name_and_opening_parenthesis = false -#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call -csharp_space_between_method_call_parameter_list_parentheses = false -#remove space within empty parameter list parentheses for a method declaration -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list. -csharp_space_between_method_declaration_parameter_list_parentheses = false - -#Formatting - wrapping options - -#leave code block on single line -csharp_preserve_single_line_blocks = true - -#Style - Code block preferences - -#prefer curly braces even for one line of code -csharp_prefer_braces = true:suggestion - -#Style - expression bodied member options - -#prefer block bodies for constructors -csharp_style_expression_bodied_constructors = false:suggestion -#prefer expression-bodied members for methods -csharp_style_expression_bodied_methods = true:suggestion - -#Style - expression level options - -#prefer out variables to be declared inline in the argument list of a method call when possible -csharp_style_inlined_variable_declaration = true:suggestion -#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them -dotnet_style_predefined_type_for_member_access = true:suggestion - -#Style - Expression-level preferences - -#prefer objects to be initialized using object initializers when possible -dotnet_style_object_initializer = true:suggestion -#prefer inferred anonymous type member names -dotnet_style_prefer_inferred_anonymous_type_member_names = false:suggestion - -#Style - implicit and explicit types - -#prefer var over explicit type in all cases, unless overridden by another code style rule -csharp_style_var_elsewhere = true:suggestion -#prefer explicit type over var to declare variables with built-in system types such as int -csharp_style_var_for_built_in_types = false:suggestion -#prefer explicit type over var when the type is already mentioned on the right-hand side of a declaration -csharp_style_var_when_type_is_apparent = false:suggestion - -#Style - language keyword and framework type options - -#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them -dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion - -#Style - Miscellaneous preferences - -#prefer anonymous functions over local functions -csharp_style_pattern_local_over_anonymous_function = false:suggestion - -#Style - modifier options - -#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods. -dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion - -#Style - Modifier preferences - -#when this rule is set to a list of modifiers, prefer the specified ordering. -csharp_preferred_modifier_order = public,private,protected,internal,readonly,async,static,sealed,virtual,override:suggestion - -#Style - Pattern matching - -#prefer pattern matching instead of is expression with type casts -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion - -#Style - qualification options - -#prefer fields not to be prefaced with this. or Me. in Visual Basic -dotnet_style_qualification_for_field = false:suggestion -#prefer methods not to be prefaced with this. or Me. in Visual Basic -dotnet_style_qualification_for_method = false:suggestion -#prefer properties not to be prefaced with this. or Me. in Visual Basic -dotnet_style_qualification_for_property = false:suggestion -csharp_indent_labels = one_less_than_current -csharp_using_directive_placement = outside_namespace:silent -csharp_prefer_simple_using_statement = true:suggestion -csharp_style_namespace_declarations = block_scoped:silent -csharp_style_prefer_method_group_conversion = true:silent -csharp_style_prefer_top_level_statements = true:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = true:silent -csharp_style_expression_bodied_indexers = true:silent -csharp_style_expression_bodied_accessors = true:silent -csharp_style_expression_bodied_lambdas = true:silent -csharp_style_expression_bodied_local_functions = false:silent - -[*.{cs,vb}] -dotnet_style_operator_placement_when_wrapping = beginning_of_line -tab_width = 4 -indent_size = 4 -end_of_line = crlf -[*.{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_coalesce_expression = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion diff --git a/templates/template/.env b/templates/template/.env deleted file mode 100644 index a76ec7d7..00000000 --- a/templates/template/.env +++ /dev/null @@ -1,7 +0,0 @@ -# Compose supports declaring default environment variables in an environment file named .env placed in the folder docker-compose command is executed from (current working directory). -# Compose expects each line in an env file to be in VAR=VAL format. Lines beginning with # (i.e. comments) are ignored, as are blank lines. -# Note: Values present in the environment at runtime will always override those defined inside the .env file. Similarly, values passed via command-line arguments take precedence as well. - -# The IP below should be swapped to your real IP or DNS name, like 192.168.88.248, etc. if testing from remote browsers or mobile devices - -PROJECT_EXTERNAL_DNS_NAME_OR_IP=localhost diff --git a/templates/template/.template.config/template.json b/templates/template/.template.config/template.json deleted file mode 100644 index 7e36c3d8..00000000 --- a/templates/template/.template.config/template.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/template", - "author": "Nocco Giovanni Emanuele", - "classifications": [ - "Web/ASP.NET" - ], - "name": "Genocs: Service Template for .NET Core", - "identity": "Genocs.ServiceTemplate", - "groupIdentity": "Genocs.ServiceTemplate", - "shortName": "gnx-webapi", - "tags": { - "language": "C#" // Specify that this template is in C#. - }, - "sourceName": "Genocs.Template", // Will replace the string 'Genocs.Template' with the value provided via -n. - "preferNameDirectory": true, - "symbols": { - "use-cases": { - "type": "parameter", - "datatype": "choice", - "defaultValue": "full", - "choices": [ - { - "choice": "full", - "description": "Full Wallet Account Balance Management (Read/Write)" - } - ], - "replaces": "use-cases", - "onlyIf": [ - { - "after": "\"use-cases\": \"" - } - ] - }, - "Full": { - "type": "computed", - "value": "(use-cases == \"full\")" - } - - }, - "sources": [ - { - "source": "./", - "modifiers": [ - { - "condition": "(Full)", - "exclude": [] - } - ] - } - ], - "primaryOutputs": [ - { - "path": "src/Genocs.Template.Application/Genocs.Template.Application.csproj" - }, - { - "path": "src/Genocs.Template.WebApi/Genocs.Template.WebApi.csproj" - } - ] -} \ No newline at end of file diff --git a/templates/template/.travis.yml b/templates/template/.travis.yml deleted file mode 100644 index ce1bee34..00000000 --- a/templates/template/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: csharp -mono: none -sudo: required -dist: xenial -dotnet: 7.0.101 -branches: - only: - - master - - develop -before_script: - - chmod -R a+x scripts -script: - - ./scripts/build.sh - - ./scripts/test.sh -after_success: - #- ./scripts/dotnet-pack.sh -notifications: - email: - on_success: never - on_failure: always diff --git a/templates/template/Genocs.Template.sln b/templates/template/Genocs.Template.sln deleted file mode 100644 index 365e5cdf..00000000 --- a/templates/template/Genocs.Template.sln +++ /dev/null @@ -1,61 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32112.339 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Template.WebApi", "src\Genocs.Template.WebApi\Genocs.Template.WebApi.csproj", "{DE058D73-748F-4E31-BA5C-48DEF7C6BA41}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Template.AcceptanceTests", "src\Genocs.Template.AcceptanceTests\Genocs.Template.AcceptanceTests.csproj", "{FF2A2975-6B15-49D0-982A-4020591FE745}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Template.IntegrationTests", "src\Genocs.Template.IntegrationTests\Genocs.Template.IntegrationTests.csproj", "{252000C9-DCC7-4222-ACF0-A7DEA1727155}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Template.UnitTests", "src\Genocs.Template.UnitTests\Genocs.Template.UnitTests.csproj", "{D5FDC379-F6F0-427F-9EC1-EC63DBC40183}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Template.Application", "src\Genocs.Template.Application\Genocs.Template.Application.csproj", "{B3DAF7F3-D632-4252-829B-010BF702BDC0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{6335BAF6-440D-4B7D-8618-DB1B32F4E1DB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Solution Items", "_Solution Items", "{1250CDBC-9DDA-447F-97E6-FCBF98F82BAC}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DE058D73-748F-4E31-BA5C-48DEF7C6BA41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DE058D73-748F-4E31-BA5C-48DEF7C6BA41}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DE058D73-748F-4E31-BA5C-48DEF7C6BA41}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DE058D73-748F-4E31-BA5C-48DEF7C6BA41}.Release|Any CPU.Build.0 = Release|Any CPU - {FF2A2975-6B15-49D0-982A-4020591FE745}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF2A2975-6B15-49D0-982A-4020591FE745}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF2A2975-6B15-49D0-982A-4020591FE745}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF2A2975-6B15-49D0-982A-4020591FE745}.Release|Any CPU.Build.0 = Release|Any CPU - {252000C9-DCC7-4222-ACF0-A7DEA1727155}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {252000C9-DCC7-4222-ACF0-A7DEA1727155}.Debug|Any CPU.Build.0 = Debug|Any CPU - {252000C9-DCC7-4222-ACF0-A7DEA1727155}.Release|Any CPU.ActiveCfg = Release|Any CPU - {252000C9-DCC7-4222-ACF0-A7DEA1727155}.Release|Any CPU.Build.0 = Release|Any CPU - {D5FDC379-F6F0-427F-9EC1-EC63DBC40183}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D5FDC379-F6F0-427F-9EC1-EC63DBC40183}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D5FDC379-F6F0-427F-9EC1-EC63DBC40183}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D5FDC379-F6F0-427F-9EC1-EC63DBC40183}.Release|Any CPU.Build.0 = Release|Any CPU - {B3DAF7F3-D632-4252-829B-010BF702BDC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B3DAF7F3-D632-4252-829B-010BF702BDC0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B3DAF7F3-D632-4252-829B-010BF702BDC0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B3DAF7F3-D632-4252-829B-010BF702BDC0}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {FF2A2975-6B15-49D0-982A-4020591FE745} = {6335BAF6-440D-4B7D-8618-DB1B32F4E1DB} - {252000C9-DCC7-4222-ACF0-A7DEA1727155} = {6335BAF6-440D-4B7D-8618-DB1B32F4E1DB} - {D5FDC379-F6F0-427F-9EC1-EC63DBC40183} = {6335BAF6-440D-4B7D-8618-DB1B32F4E1DB} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7085404A-CC53-42BF-9A9F-C0BC3830CC6C} - EndGlobalSection -EndGlobal diff --git a/templates/template/NuGet.config b/templates/template/NuGet.config deleted file mode 100644 index 06e20895..00000000 --- a/templates/template/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/templates/template/README.md b/templates/template/README.md deleted file mode 100644 index 17edff41..00000000 --- a/templates/template/README.md +++ /dev/null @@ -1,1493 +0,0 @@ -# The Genocs Library Service built with Template - - -Genocs.ServiceTemplate implementation. - -![Documentation](https://blog.genocs.com/) - - - -## Usage - -```sh -dotnet new -i Genocs.ServiceTemplate::1.0.0 -dotnet new servicetemplate -n "CompanyName.ProjectName" -``` - -## Usage -Update mongoDB database name before start - - - - -This will be removed - - - of the **Genocs Enterprise Service Principles with .NET Core**. Use cases as central organizing structure, decoupled from frameworks and technology details. Built with small components that are developed and tested in isolation. - ----- - -[![Build Status](https://travis-ci.com/genocs/clean-architecture-template.svg?branch=master)](https://travis-ci.com/genocs/clean-architecture-template) [![Build status](https://ci.appveyor.com/api/projects/status/0i6s33kw3y87tkb2?svg=true)](https://ci.appveyor.com/project/genocs/clean-architecture-template) ![NuGet](https://buildstats.info/nuget/Genocs.CleanArchitectureTemplate) [![All Contributors](https://img.shields.io/badge/all_contributors-12-yellow.svg?style=flat-square)](#contributors) - - - -## Usage - -```sh -dotnet new -i Genocs.ServiceTemplate::1.0.0 -dotnet new servicetemplate -n "CompanyName.ProjectName" -``` - -To get the Clean Architecture updates hit the `WATCH` button. - -Would you like to show Clean Architecture on your GitHub profile? Hit the `FORK` button. - -Really interested in designing modular applications? Support this project with a hit on the `STAR` button. Share with a friend! - -**Manga** is a virtual Wallet application in which a customer can register an account then manage the balance with `Deposits`, `Withdraws` and `Transfers`. - -Run the Docker container in less than 2 minutes using Play With Docker: - -Try in PWD - - -## Motivation - -> Learn how to design modular applications. -> -> Explore the .NET Core features. - -### Learn how to design modular applications - -Learning how to design modular applications will help you become a better engineer. Designing modular applications is the holy grail of software architecture, it is hard to find engineers experienced in designing applications which allows adding new features in a steady speed. - -### Explore the .NET Core features - -.NET Core brings a sweet development environment, an extensible and cross-platform framework. We will explore the benefits of it in the infrastructure layer and we will reduce its relevance in the application layer. The same rule is applied for modern C# language constructions. - -### Learn from the open source community - -This is continually updated, open source project. - -[Contributions](#contributors-) are welcome! - - -## Persistance layer - -This example contains the implementation related to three different storage type: - -- InMemoryDataAccess (usefull only for development) -- Microsoft SQL Server (The popular Relational database developed by Microsoft) -- MongoDB (The popular Document DB) - - -### MongoDB Replicaset - -To set Mongodb as a replicaset - -1. Run Docker compose with 3 mongo container -2. Connect to Mongo Shell -```sh -docker exec -it mongo_db2 /bin/bash -mongo -``` - -3. Initialize the replicaset and check the status - -```ts -rs.initiate( - { - _id : 'rs0', - members: [ - { _id : 0, host : "mongo_db1:27017" }, - { _id : 1, host : "mongo_db2:27017" }, - { _id : 2, host : "mongo_db3:27017" } - ] - } -) - -rs.slaveOk().ok -rs.status() -``` - -## Enterprise service bus - -### RabbitMQ cluster - -The folder docker-infrastructure contains the docker-compose file and everything required to run a two node RabbitMQ cluster. - -This example implement the enterprise service bus through three different library. - -- Rebus -- Bare implementation with Azure Service bus - - -## Containers and orchestrators - -The example is ready to create the docker images for both WebApi and Worker - - -## Contributing - -> Learn from the community. - -Feel free to submit pull requests to help: - -* Fix errors -* Improve sections -* Add new sections -* Submit questions and bugs - -## Index of Clean Architecture Template - -* [Use Cases](#use-cases) -* [Flow of Control](#register-flow-of-control) - * [Register Flow of Control](#register-flow-of-control) - * [Get Customer Details Flow of Control](#get-customer-details-flow-of-control) -* [Architecture Styles](#architecture-styles) - * [Hexagonal Architecture Style](#ports-and-adapters-architecture-style) - * [Ports](#ports) - * [Adapters](#adapters) - * [The Left Side](#the-left-side) - * [The Right Side](#the-right-side) - * [Onion Architecture Style](#onion-architecture-style) - * [Clean Architecture Style](#clean-architecture-style) -* [Design Patterns](#design-patterns) - * [Controller](#controller) - * [ViewModel](#viewmodel) - * [Presenter](#presenter) - * [Standard Output](#standard-output) - * [Error Output](#error-output) - * [Alternative Output](#alternative-output) - * [Unit of Work](#unit-of-work) - * [First-Class Collections](#first-class-collections) - * [Factory](#factory) -* [Domain-Driven Design Patterns](#domain-driven-design-patterns) - * [Value Object](#value-object) - * [Entity](#entity) - * [Aggregate Root](#aggregate-root) - * [Repository](#repository) - * [Use Case](#use-case) -* [Separation of Concerns](#separation-of-concerns) - * [Domain](#domain) - * [Application](#application) - * [Infrastructure](#infrastructure) - * [User Interface](#user-interface) -* [Encapsulation](#encapsulation) -* [Test-Driven Development TDD](#test-driven-development-tdd) - * [Fakes](#fakes) -* [SOLID](#solid) - * [Single Responsibility Principle](#single-responsibility-principle) - * [Open-Closed Principle](#open-closed-principle) - * [Liskov Substitution Principle](#liskov-substitution-principle) - * [Interface Segregation Principle](#interface-segregation-principle) - * [Dependency Inversion Principle](#dependency-inversion-principle) -* [.NET Core Web API](#.net-core-webapi) - * [Swagger and API Versioning](#swagger-and-api-versioning) - * [Microsoft Extensions](#microsoft-extensions) - * [Feature Flags](#feature-flags) - * [Logging](#logging) - * [Data Annotations](#data-annotations) - * [Authentication](#authentication) - * [Authorization](#authorization) -* [Entity Framework Core](#entity-framework-core) - * [Add Migration](#add-migration) - * [Update Database](#update-database) -* [Environment Configurations](#environment-configurations) -* [DevOps](#devops) - * [Running the Application Locally](#running-the-application-locally) - * [Running the Tests Locally](#running-the-tests-locally) - * [Continuous Integration & Continuous Deployment](#continuous-integration-continuous-deployment) -* [Docker](#docker) -* [SQL Server](#sql-server) -* [Related Content and Projects](#related-content-and-projects) - - -## Use Cases - -> Use Cases are delivery independent, they show the intent of a system. -> -> Use Cases are algorithms which interpret the input to generate the output data. - -Application architecture is about usage, a good architecture screams the business use cases to the developer and framework concerns are implementation details. On **Manga** sample the user can `Register` an account then manage the balance by `Deposits`, `Withdrawals` and `Transfers`. - -

- Clean -

- -Following the list of Use Cases: - -| Use Case | Description | -|----------------------|-----------------------------------------------------------------------| -| Register | An customer can register an account using his personal details. | -| Deposit | The customer can deposit an amount. | -| Transfer | The customer can transfer money from one account to another. | -| Withdraw | A customer can withdraw money but not more that the current balance. | -| Get Customer Details | Get customer details including all related accounts and transactions. | -| Get Account Details | Get account details including transactions. | -| Close Account | Closes an account, requires balance to be zero. | - -## Flow of Control - -The flow of control begins in the controller, moves through the use case, and then winds up executing in the presenter. - -### Register Flow of Control - -1. An request in received by the `CustomersController` and an action `Post` is invoked. -2. The action creates an `RegisterInput` message and the `Register` use case is executed. -3. The `Register` use case creates a `Customer` and an `Account`. Repositories are called, the `RegisterOutput` message is built and sent to the `RegisterPresenter`. -4. The `RegisterPresenter` builds the HTTP Response message. -5. The `CustomersController` asks the presenter the current response. - -![Register Flow of Control](https://github.com/genocs/clean-architecture/blob/master/docs/register-flow-of-control.svg) - -### Get Customer Details Flow of Control - -1. An request in received by the `CustomersController` and an action `GetCustomer` is invoked. -2. The action creates an `GetCustomerDetailsInput` message and the `GetCustomerDetails` use case is executed. -3. The `GetCustomerDetails` use case asks the repositories about the `Customer` and the `Account`. It could call the `NotFound` or the `Default` port of the `GetCustomerDetailsPresenter` depending if it exists or not. -4. The `GetCustomerDetailsPresenter` builds the HTTP Response message. -5. The `CustomersController` asks the presenter the current response. - -## Architecture Styles - -Manga uses ideas from popular architectural styles. They Ports and Adapters are the simplest one followed by the others, they complement each other and aim a software made by use cases decoupled from technology implementation details. - -### Hexagonal Architecture Style - -The general idea behind Hexagonal architecture style is that the dependencies (Adapters) required by the software to run are used behind an interface (Port). - -The software is divided into **Application** and **Infrastructure** in which the adapters are interchangeable components developed and tested in isolation. The Application is loosely coupled to the Adapters and their implementation details. - -#### Ports - -Interfaces like `ICustomerRepository`, `IOutputPort` and `IUnitOfWork` are ports required by the application. - -#### Adapters - -The interface implementations, they are specific to a technology and bring external capabilities. For instance the `CustomerRepository` inside the `EntityFrameworkDataAccess` folder provides capabilities to consume an SQL Server database. - -![Ports and Adapters](https://raw.githubusercontent.com/genocs/clean-architecture/master/docs/clean-architecture-ports-and-adapters.png) - -#### The Left Side - -Primary Actors are usually the user interface or the Test Suit. - -#### The Right Side - -The Secondary Actors are usually Databases, Cloud Services or other systems. - -### Onion Architecture Style - -Very similar to Ports and Adapters, I would add that data objects cross boundaries as simple data structures. For instance, when the controller execute an use case it passes and immutable Input message. When the use cases calls an Presenter it gives a Output message (Data Transfer Objects if you like). - -### Clean Architecture Style - -An application architecture implementation guided by tests cases. - -## Design Patterns - -The following Design Patterns will help you continue implementing use cases in a consistent way. - -### Controller - -Controllers receive Requests, build the Input message then call the Use Case, you should notice that the controller do not build the Response, instead this responsibility is delegated to the presenter object. - -```c# -public sealed class CustomersController : Controller -{ - // Code omitted to simplify... - - public async Task Post([FromBody][Required] RegisterRequest request) - { - await _registerUseCase.Execute(new RegisterInput( - new SSN(request.SSN), - new Name(request.Name), - new PositiveAmount(request.InitialAmount))); - - return _presenter.ViewModel; - } -} -``` - -### ViewModel - -ViewModels are Data Transfer Objects, they will be rendered by the MVC framework so we need to follow the framework guidelines. I suggest that you add comments describing each property and the `[Required]` attribute so swagger generators could know the properties that are not nullable. My personal preference is to avoid getters here because you have total control of response object instantiation, so implement the constructor. - -```c# -/// -/// The response for Registration -/// -public sealed class RegisterResponse -{ - /// - /// Customer ID - /// - [Required] - public Guid CustomerId { get; } - - /// - /// SSN - /// - [Required] - public string SSN { get; } - - /// - /// Name - /// - [Required] - public string Name { get; } - - /// - /// Accounts - /// - [Required] - public List Accounts { get; } - - public RegisterResponse( - Guid customerId, - string ssn, - string name, - List accounts) - { - CustomerId = customerId; - SSN = ssn; - Name = name; - Accounts = accounts; - } -} -``` - -### Presenter - -Presenters are called by the application Use Cases and build the Response objects. - -```c# -public sealed class RegisterPresenter : IOutputPort -{ - public IActionResult ViewModel { get; private set; } - - public void Error(string message) - { - var problemDetails = new ProblemDetails() - { - Title = "An error occurred", - Detail = message - }; - - ViewModel = new BadRequestObjectResult(problemDetails); - } - - public void Standard(RegisterOutput output) - { - /// Long object creation omitted... - - ViewModel = new CreatedAtRouteResult("GetCustomer", - new - { - customerId = model.CustomerId - }, - model); - } -} -``` - -It is important to understand that from the Application perspective the use cases see an OutputPort with custom methods to call dependent on the message, and from the Web Api perspective the Controller only see the ViewModel property. - -#### Standard Output - -The output port for the use case regular behavior. - -#### Error Output - -Called when an blocking errors happens. - -#### Alternative Output - -Called when an blocking errors happens. - -### Unit of Work - -```c# -public interface IUnitOfWork -{ - Task Save(); -} -``` - -```c# -public sealed class UnitOfWork : IUnitOfWork, IDisposable -{ - private readonly GenocsContext _context; - - public UnitOfWork(GenocsContext context) - => _context = context; - - public async Task Save() - { - int affectedRows = await context.SaveChangesAsync(); - return affectedRows; - } - - private bool _disposed = false; - - private void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - context.Dispose(); - } - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } -} -``` - -### First-Class Collections - -```c# -public sealed class CreditsCollection -{ - private readonly IList _credits; - - public CreditsCollection() - { - _credits = new List(); - } - - public void Add(IEnumerable credits) - where T : ICredit - { - foreach (var credit in credits) - Add(credit); - } - - public void Add(ICredit credit) - { - _credits.Add(credit); - } - - public IReadOnlyCollection GetTransactions() - { - var transactions = new ReadOnlyCollection(_credits); - return transactions; - } - - public PositiveAmount GetTotal() - { - PositiveAmount total = new PositiveAmount(0); - - foreach (ICredit credit in _credits) - { - total = credit.Sum(total); - } - - return total; - } -} -``` - -### Factory - -```c# -public interface IEntityFactory -{ - ICustomer NewCustomer(SSN ssn, Name name); - IAccount NewAccount(ICustomer customer); - ICredit NewCredit(IAccount account, PositiveAmount amountToDeposit); - IDebit NewDebit(IAccount account, PositiveAmount amountToWithdraw); -} -``` - -```c# -public sealed class EntityFactory : IEntityFactory -{ - public IAccount NewAccount(ICustomer customer) - { - var account = new Account(customer); - return account; - } - - public ICredit NewCredit(IAccount account, PositiveAmount amountToDeposit) - { - var credit = new Credit(account, amountToDeposit); - return credit; - } - - public ICustomer NewCustomer(SSN ssn, Name name) - { - var customer = new Customer(ssn, name); - return customer; - } - - public IDebit NewDebit(IAccount account, PositiveAmount amountToWithdraw) - { - var debit = new Debit(account, amountToWithdraw); - return debit; - } -} -``` - -### Component - -## Domain-Driven Design Patterns - -The following patterns are known to describe business solutions. - -### Value Object - -Describe the tiny domain business rules. Objects that are unique by the has of their properties. Are immutable. - -```c# -public sealed class Name : IEquatable -{ - private readonly string _text; - - private Name() { } - - public Name(string text) - { - if (string.IsNullOrWhiteSpace(text)) - throw new NameShouldNotBeEmptyException("The 'Name' field is required"); - - _text = text; - } - - public override string ToString() - { - return _text; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - if (obj is string) - { - return obj.ToString() == _text; - } - - return ((Name) obj)._text == _text; - } - - public override int GetHashCode() - { - unchecked - { - int hash = 17; - hash = hash * 23 + _text.GetHashCode(); - return hash; - } - } - - public bool Equals(Name other) - { - return this._text == other._text; - } -} -``` - -### Entity - -Mutable objects unique identified by their IDs. - -```c# -public class Credit : ICredit -{ - public Guid Id { get; protected set; } - - public PositiveAmount Amount { get; protected set; } - - public string Description - { - get { return "Credit"; } - } - - public DateTime TransactionDate { get; protected set; } - - public PositiveAmount Sum(PositiveAmount amount) - { - return Amount.Add(amount); - } -} -``` - -### Aggregate Root - -Similar to Entities with the addition that Aggregate Root are responsible to keep the tree of objects consistent. - -```c# -public class Account : IAccount -{ - public Guid Id { get; protected set; } - - public CreditsCollection Credits { get; protected set; } - - public DebitsCollection Debits { get; protected set; } - - protected Account() - { - Credits = new CreditsCollection(); - Debits = new DebitsCollection(); - } - - public ICredit Deposit(IEntityFactory entityFactory, PositiveAmount amountToDeposit) - { - var credit = entityFactory.NewCredit(this, amountToDeposit); - Credits.Add(credit); - return credit; - } - - public IDebit Withdraw(IEntityFactory entityFactory, PositiveAmount amountToWithdraw) - { - if (GetCurrentBalance().LessThan(amountToWithdraw)) - return null; - - var debit = entityFactory.NewDebit(this, amountToWithdraw); - Debits.Add(debit); - return debit; - } - - public bool IsClosingAllowed() - { - return GetCurrentBalance().IsZero(); - } - - public Amount GetCurrentBalance() - { - var totalCredits = Credits - .GetTotal(); - - var totalDebits = Debits - .GetTotal(); - - var totalAmount = totalCredits - .Subtract(totalDebits); - - return totalAmount; - } -} -``` - -### Repository - -```c# -public sealed class CustomerRepository : ICustomerRepository -{ - private readonly GenocsContext _context; - - public CustomerRepository(GenocsContext context) - => _context = context; - - public async Task Add(ICustomer customer) - { - _context.Customers.Add((InMemoryDataAccess.Customer) customer); - await Task.CompletedTask; - } - - public async Task Get(Guid id) - { - Customer customer = _context.Customers - .Where(e => e.Id == id) - .SingleOrDefault(); - - return await Task.FromResult(customer); - } - - public async Task Update(ICustomer customer) - { - Customer customerOld = _context.Customers - .Where(e => e.Id == customer.Id) - .SingleOrDefault(); - - customerOld = (Customer) customer; - await Task.CompletedTask; - } -} -``` - -### Use Case - -```c# -public sealed class Withdraw : IUseCase -{ - // Properties and constructor omitted - - public async Task Execute(WithdrawInput input) - { - IAccount account = await _accountRepository.Get(input.AccountId); - if (account == null) - { - _outputHandler.Error($"The account {input.AccountId} does not exist or is already closed."); - return; - } - - IDebit debit = account.Withdraw(_entityFactory, input.Amount); - - if (debit == null) - { - _outputHandler.Error($"The account {input.AccountId} does not have enough funds to withdraw {input.Amount}."); - return; - } - - await _accountRepository.Update(account, debit); - await _unitOfWork.Save(); - - WithdrawOutput output = new WithdrawOutput( - debit, - account.GetCurrentBalance() - ); - - _outputHandler.Default(output); - } -} -``` - -## Separation of Concerns - -

- Layers -

- -### Domain - -The package that contains the `High Level Modules` which describe the Domain via Aggregate Roots, Entities and Value Objects. By design this project is `Highly Abstract` and `Stable`, in other terms this package contains a considerable amount of interfaces and should not depend on external libraries and frameworks. Ideally it should be loosely coupled even to the .NET Framework. - -### Application - -A project that contains the Application Use Cases which orchestrate the high level business rules. By design the orchestration will depend on abstractions of external services (eg. Repositories). The package exposes Boundaries Interfaces (in other terms Contracts or `Ports`) which are used by the user interface. - -### Infrastructure - -The infrastructure layer is responsible to implement the `Adapters` to the `Secondary Actors`. For instance an SQL Server Database is a secondary actor which is affected by the application use cases, all the implementation and dependencies required to consume the SQL Server is created on infrastructure. By design the infrastructure depends on application layer. - -### User Interface - -The system entry point responsible to render an interface to interact with the User. Made with Controllers which receive HTTP Requests and Presenters which converts the application outputs into ViewModels that are rendered as HTTP Responses. - -## Encapsulation - -> Given a class, the sum of its members complexity should be less that the sum of its parts in isolation. - -Suppose there is a `Customer` entity like this: - -```c# -public class Customer -{ - public Guid Id { get; set; } - public string Name { get; set; } - public string SSN { get; set; } - public bool Active { get; set; } - public string ActivatedBy { get; set; } -} -``` - -The complexity of the previous class is the same if there were variables like the following: - -```c# - Guid Id; - string Name; - string SSN; - bool Active; - string ActivatedBy; -``` - -Classes that are similar to a bag of data leaks unnecessary complexity. Consider reducing the complexity with something like: - -```c# -public class Customer -{ - public Guid Id { get; protected set; } - public string Name { get; protected set; } - public string SSN { get; protected set; } - public bool Active { get; protected set; } - public string ActivatedBy { get; protected set; } -} -``` - -## Test-Driven Development (TDD) - -> You are not allowed to write any production code unless it is to make a failing unit test pass. -> -> You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures. -> -> You are not allowed to write any more production code than is sufficient to pass the one failing unit test. - -http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd - -### Fakes - -> Fake it till you make it - -## SOLID - -### Single Responsibility Principle - -> A class should have one, and only one, reason to change. - -### Open-Closed Principle - -> You should be able to extend a classes behavior, without modifying it. - -### Liskov Substitution Principle - -> Derived classes must be substitutable for their base classes. - -### Interface Segregation Principle - -> Make fine grained interfaces that are client specific. - -### Dependency Inversion Principle - -> Depend on abstractions, not on concretions. - -## .NET Core Web API - -### Swagger and API Versioning - -```c# -namespace Genocs.WebApi.Extensions -{ - using Filters; - using System.Collections.Generic; - using System.Linq; - using System.Reflection; - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Mvc.ApiExplorer; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Extensions.DependencyInjection; - using Swashbuckle.AspNetCore.Examples; - using Swashbuckle.AspNetCore.Swagger; - using Swashbuckle.AspNetCore.SwaggerGen; - - public static class VersionedSwaggerExtensions - { - public static IServiceCollection AddVersionedSwagger(this IServiceCollection services) - { - services.AddApiVersioning(o => - { - o.AssumeDefaultVersionWhenUnspecified = true; - o.DefaultApiVersion = new ApiVersion(1, 0); - }); - - services.AddVersionedApiExplorer(o => o.GroupNameFormat = "'V'VVV"); - - services.AddSwaggerGen(options => - { - var provider = services.BuildServiceProvider() - .GetRequiredService(); - - foreach (var apiVersion in provider.ApiVersionDescriptions) - { - ConfigureVersionedDescription(options, apiVersion); - } - - var xmlCommentsPath = Assembly.GetExecutingAssembly() - .Location.Replace("dll", "xml"); - options.IncludeXmlComments(xmlCommentsPath); - - options.OperationFilter(); - options.DocumentFilter(); - }); - - return services; - } - - private static void ConfigureVersionedDescription( - SwaggerGenOptions options, - ApiVersionDescription apiVersion) - { - var dictionairy = new Dictionary - { - { "1.0", "This API features several endpoints showing different API features for API version V1" }, - { "2.0", "This API features several endpoints showing different API features for API version V2" } - }; - - var apiVersionName = apiVersion.ApiVersion.ToString(); - options.SwaggerDoc(apiVersion.GroupName, - new Info() - { - Title = "Clean Architecture Genocs", - Contact = new Contact() - { - Name = "@giovanninocco", - Email = "giovanni.nocco@genocs.com", - Url = "https://github.com/genocs" - }, - License = new License() - { - Name = "MIT License" - }, - Version = apiVersionName, - Description = dictionairy[apiVersionName] - }); - } - - public static IApplicationBuilder UseVersionedSwagger( - this IApplicationBuilder app, - IApiVersionDescriptionProvider provider) - { - app.UseSwagger(options => - { - options.PreSerializeFilters.Add((swaggerDoc, httpRequest) => - { - if (httpRequest.Path.Value.Contains("/swagger")) - { - swaggerDoc.BasePath = httpRequest.Path.Value.Split("/").FirstOrDefault() ?? ""; - } - - if (httpRequest.Headers.TryGetValue("X-Forwarded-Prefix", out var xForwardedPrefix)) - { - swaggerDoc.BasePath = xForwardedPrefix[0]; - } - }); - }); - - app.UseSwaggerUI(options => - { - // Build a swagger endpoint for each discovered API version - foreach (var description in provider.ApiVersionDescriptions) - { - options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant()); - } - }); - - return app; - } - } -} -``` - -### Microsoft Extensions - -```c# -public sealed class Startup -{ - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureDevelopmentServices(IServiceCollection services) - { - services.AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Version_3_0) - .AddControllersAsServices(); - - services.AddBusinessExceptionFilter(); - - services.AddFeatureFlags(Configuration); - services.AddVersionedSwagger(); - - services.AddUseCases(); - - services.AddInMemoryPersistence(); - - services.AddPresentersV1(); - services.AddPresentersV2(); - } - - public void ConfigureProductionServices(IServiceCollection services) - { - services.AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) - .AddControllersAsServices(); - - services.AddBusinessExceptionFilter(); - - services.AddFeatureFlags(Configuration); - services.AddVersionedSwagger(); - - services.AddUseCases(); - - services.AddSQLServerPersistence(Configuration); - - services.AddPresentersV1(); - services.AddPresentersV2(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure( - IApplicationBuilder app, - IWebHostEnvironment env, - IApiVersionDescriptionProvider provider) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseVersionedSwagger(provider); - app.UseHttpsRedirection(); - app.UseStaticFiles(); - app.UseCookiePolicy(); - app.UseMvc(); - } -} -``` - -### Feature Flags - -```c# -public sealed class CustomControllerFeatureProvider : IApplicationFeatureProvider -{ - private readonly IFeatureManager _featureManager; - - public CustomControllerFeatureProvider(IFeatureManager featureManager) - { - _featureManager = featureManager; - } - - public void PopulateFeature(IEnumerable parts, ControllerFeature feature) - { - for (int i = feature.Controllers.Count - 1; i >= 0; i--) - { - var controller = feature.Controllers[i].AsType(); - foreach (var customAttribute in controller.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == typeof(FeatureGateAttribute).FullName) - { - var constructorArgument = customAttribute.ConstructorArguments.First(); - foreach (var argumentValue in constructorArgument.Value as IEnumerable) - { - var typedArgument = (CustomAttributeTypedArgument) argumentValue; - var typedArgumentValue = (Features) (int) typedArgument.Value; - if (!_featureManager.IsEnabled(typedArgumentValue.ToString())) - feature.Controllers.RemoveAt(i); - } - } - } - } - } -} -``` - -### Logging - -```c# -public static IWebHostBuilder CreateWebHostBuilder(string[] args) -{ - return WebHost.CreateDefaultBuilder(args) - .ConfigureAppConfiguration((hostingContext, config) => - { - var env = hostingContext.HostingEnvironment; - - config.AddJsonFile("appsettings.json", optional : true, reloadOnChange : true) - .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional : true, reloadOnChange : true); - - config.AddEnvironmentVariables(); - - if (args != null) - { - config.AddCommandLine(args); - } - }) - .ConfigureLogging((hostingContext, logging) => - { - // Requires `using Microsoft.Extensions.Logging;` - logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); - logging.AddConsole(); - logging.AddDebug(); - logging.AddEventSourceLogger(); - }) - .UseStartup(typeof(Program).Assembly.FullName); -} -``` - -```c# -public static class FeatureFlagsExtensions -{ - public static IServiceCollection AddFeatureFlags(this IServiceCollection services, IConfiguration configuration) - { - services.AddFeatureManagement(configuration); - - var featureManager = services.BuildServiceProvider() - .GetRequiredService(); - - services.AddMvc() - .ConfigureApplicationPartManager(apm => - apm.FeatureProviders.Add( - new CustomControllerFeatureProvider(featureManager) - )); - - return services; - } -} -``` - -```c# -public enum Features -{ - Transfer, - GetAccountDetailsV2 -} -``` - -### Data Annotations - -Data Annotations are powerful tool from .NET, it can be interpreted by ASP.NET Core and other frameworks to generate Validation, User Interface and other things. On Manga project, Data Annotations are used to create a complete Swagger UI and HTTP Request validation. Of course following the Clean Architecture Principles we need to keep frameworks under control. - -I decided to use Data Annotations on the User Interface layer. Take a look on the `RegisterRequest` class: - -```c# -/// -/// Registration Request -/// -public sealed class RegisterRequest -{ - /// - /// SSN - /// - [Required] - public string SSN { get; set; } - - /// - /// Name - /// - [Required] - public string Name { get; set; } - - /// - /// Initial Amount - /// - [Required] - public decimal InitialAmount { get; set; } -} -``` - -The `RegisterResponse` also needs `[Required]` annotation for Swagger Clients. - -```c# -/// -/// The response for Registration -/// -public sealed class RegisterResponse -{ - /// - /// Customer ID - /// - [Required] - public Guid CustomerId { get; } - - /// - /// SSN - /// - [Required] - public string SSN { get; } - - /// - /// Name - /// - [Required] - public string Name { get; } - - /// - /// Accounts - /// - [Required] - public List Accounts { get; } - - public RegisterResponse( - Guid customerId, - string ssn, - string name, - List accounts) - { - CustomerId = customerId; - SSN = ssn; - Name = name; - Accounts = accounts; - } -} -``` - -References: [Designing and Testing Input Validation in .NET Core: The Clean Architecture way](https://paulovich.net/designing-testing-input-validation-in-dotnet-core-the-clean-architecture-way/) - -## Entity Framework Core - -```c# -public sealed class GenocsContext : DbContext -{ - public GenocsContext(DbContextOptions options) : base(options) - { - - } - - public DbSet Accounts { get; set; } - public DbSet Customers { get; set; } - public DbSet Credits { get; set; } - public DbSet Debits { get; set; } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("Account"); - - modelBuilder.Entity() - .Ignore(p => p.Credits) - .Ignore(p => p.Debits); - - modelBuilder.Entity() - .ToTable("Customer") - .Property(b => b.SSN) - .HasConversion( - v => v.ToString(), - v => new SSN(v)); - - modelBuilder.Entity() - .ToTable("Customer") - .Property(b => b.Name) - .HasConversion( - v => v.ToString(), - v => new Name(v)); - - modelBuilder.Entity() - .Ignore(p => p.Accounts); - - modelBuilder.Entity() - .ToTable("Debit") - .Property(b => b.Amount) - .HasConversion( - v => v.ToAmount().ToDecimal(), - v => new PositiveAmount(v)); - - modelBuilder.Entity() - .ToTable("Credit") - .Property(b => b.Amount) - .HasConversion( - v => v.ToAmount().ToDecimal(), - v => new PositiveAmount(v)); - - modelBuilder.Entity().HasData( - new { Id = new Guid("197d0438-e04b-453d-b5de-eca05960c6ae"), Name = new Name("Test User"), SSN = new SSN("19860817-9999") } - ); - - modelBuilder.Entity().HasData( - new { Id = new Guid("4c510cfe-5d61-4a46-a3d9-c4313426655f"), CustomerId = new Guid("197d0438-e04b-453d-b5de-eca05960c6ae") } - ); - - modelBuilder.Entity().HasData( - new - { - Id = new Guid("f5117315-e789-491a-b662-958c37237f9b"), - AccountId = new Guid("4c510cfe-5d61-4a46-a3d9-c4313426655f"), - Amount = new PositiveAmount(400), - Description = "Credit", - TransactionDate = DateTime.UtcNow - } - ); - - modelBuilder.Entity().HasData( - new - { - Id = new Guid("3d6032df-7a3b-46e6-8706-be971e3d539f"), - AccountId = new Guid("4c510cfe-5d61-4a46-a3d9-c4313426655f"), - Amount = new PositiveAmount(400), - Description = "Debit", - TransactionDate = DateTime.UtcNow - } - ); - } -} -``` - -### Add Migration - -Run the EF Tool to add a migration to the `Genocs.Infrastructure` project. - -```sh -dotnet ef migrations add "InitialCreate" -o "EntityFrameworkDataAccess/Migrations" --project src/{MyCompany.MyProject}.Infrastructure --startup-project src/{MyCompany.MyProject}.WebApi -``` - -### Update Database - -Generate tables and seed the database via Entity Framework Tool: - -```sh -dotnet ef database update --project src/{MyCompany.MyProject}.Infrastructure --startup-project src/{MyCompany.MyProject}.WebApi -``` - -## Environment Configurations - -To run in `Development` mode use: - -```sh -dotnet run --project "src/{MyCompany.MyProject}.WebApi/{MyCompany.MyProject}.WebApi.csproj" --Environment="Development" -``` - -It starts the application and call `ConfigureDevelopmentServices` method which runs the application using in memory persistence. - -The second option is to run in `Production` mode: - -```sh -dotnet run --project "src/{MyCompany.MyProject}.WebApi/{MyCompany.MyProject}.WebApi.csproj" --Environment="Production" -``` - -This command will call `ConfigureProductionServices` then use SQL Server repositories. - -## DevOps - -### Running the Application Locally - -Manga is a cross-platform application, you can run it from Mac, Windows or Unix. To develop new features, you may use Visual Studio or Visual Studio Code :heart:. - -The single requirement is to install the latest .NET Code SDK. - -* [.NET Core SDK 5.0](https://dotnet.microsoft.com/download/dotnet/5.0) - -We made available scripts to create and seed the database quickly via Docker. - -Finally to run it locally use: - -```sh -dotnet run --project "src/{MyCompany.MyProject}.WebApi/{MyCompany.MyProject}.WebApi.csproj" -``` - -### Running the Tests Locally - -Run the following command at the root folder: - -```sh -dotnet test -``` - -### Continuous Integration & Continuous Deployment - -```yml -version: '1.0.{build}' -image: - - Ubuntu -environment: - DOCKER_USER: - secure: YnlezJhfKFUWo+E5/WCikQ== - DOCKER_PASS: - secure: iwibHSi3B80XJ3KjT1sAS1c66AsaOP3UFyUKKWrL1jo= - HEROKU_USERNAME: - secure: CUWu9AI7dgCvD7XMGYEDtb7XQlvkcOSuxpdaKdzOu/M= - HEROKU_API_KEY: - secure: XEo5yF9x7hReDhlb66Aj6xnk2HOFboVzNW6BLR1+shV7MP1DhRl8J+hHg8Do7OKl - HEROKU_APP_NAME: - secure: tKa7ydQJbbA+uovQNa5sBs9OcRWsCj71r4l9wvDG7/I= -services: - - docker -dotnet_csproj: - patch: true - file: '**\*.csproj' - version: '{version}' -build_script: - - docker pull mcr.microsoft.com/mssql/server:2017-latest || true - - docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=' -p 1433:1433 --name sql1 -d mcr.microsoft.com/mssql/server:2017-latest || true - - sleep 10 - - docker exec -i sql1 /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P '' -Q 'ALTER LOGIN SA WITH PASSWORD=""' || true - - dotnet ef database update --project src/{MyCompany.MyProject}.Infrastructure --startup-project src/{MyCompany.MyProject}.WebApi - - dotnet build - - pushd src/{MyCompany.MyProject}.WebApi/ - - dotnet pack --configuration Release - - popd -test_script: - - dotnet test test/{MyCompany.MyProject}.UnitTests/{MyCompany.MyProject}.UnitTests.csproj - - dotnet test test/{MyCompany.MyProject}.IntegrationTests/{MyCompany.MyProject}.IntegrationTests.csproj - - dotnet test test/{MyCompany.MyProject}.AcceptanceTests/{MyCompany.MyProject}.AcceptanceTests.csproj -deploy_script: - - docker build -t {mycompany}/clean-architecture:github . - - docker login -u="$DOCKER_USER" -p="$DOCKER_PASS" - - docker push {mycompany}/clean-architecture:github - - docker login --username=$HEROKU_USERNAME --password=$HEROKU_API_KEY registry.heroku.com - - docker tag {mycompany}/clean-architecture:github registry.heroku.com/$HEROKU_APP_NAME/web - - docker push registry.heroku.com/$HEROKU_APP_NAME/web - - curl https://cli-assets.heroku.com/install.sh | sh - - heroku container:release web -a $HEROKU_APP_NAME -``` - -## Docker - -The project build two different images. One for the the Web API and one for the bus worker. - -```sh -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build -WORKDIR /app - -# Copy everything else and build -COPY . . -RUN dotnet publish src/{MyCompany.MyProject}.WebApi -c release -o out - -# Build runtime image -FROM mcr.microsoft.com/dotnet/aspnet:7.0 -WORKDIR /app -COPY --from=build /app/out . -ENV ASPNETCORE_URLS http://*:80 -ENV ASPNETCORE_ENVIRONMENT Docker -ENTRYPOINT dotnet {Company.Project}.WebApi.dll -``` - -To build the docker images - -```sh -docker build -t company/project.webapi -f .\src\Genocs.MicroserviceLight.Template.WebApi\Dockerfile . -docker build -t company/project.worker -f .\src\Genocs.MicroserviceLight.Template.BusWorker\Dockerfile . -``` - - -## SQL Server - -To spin up a SQL Server in a docker container using the connection string `Server=localhost;User Id=sa;Password=;` run the following command: - -```sh -./src/scripts/sql-docker-up.sh -``` - -## Related Content and Projects - -| Video | Date | -|---------------------------------------|--------------| -| [Hexagonal and Clean Architecture styles. Same or Different?](https://www.youtube.com/watch?v=FNQbyZu-NAo)| Sep 16, 2019 | -| [Clean Architecture Essentials](https://www.youtube.com/watch?v=NjPjCxTIf4M)| Sep 13, 2019 | -| [Shinning Frameworks and DDD?!](https://www.youtube.com/watch?v=OmxBqmmhoHg)| Sep 12, 2019 | -| [Clean Architecture: The User Interface is a detail](https://www.youtube.com/watch?v=lWH_ZDu2zKQ)| Sep 11, 2019 | -| [TDD and Hexagonal Architecture: Clean Tests](https://www.youtube.com/watch?v=j6_XPsqjrhE)| Sep 10, 2019 | -| [Designing and Testing Input Validation with .NET Core: The Clean Architecture way](https://www.youtube.com/watch?v=hyW4d5OcExw)| Sep 9, 2019 | -| [Clean Architecture Manga](https://www.youtube.com/watch?v=ivAkdJmSqLQ) | Aug 6, 2019 | -| [TDD and TDD with .NET Core and VSCode](https://www.youtube.com/watch?v=ORe0r4bpfac&t=360s) | Nov 3, 2018 | -| [Introduction to Clean Architecture](https://www.youtube.com/watch?v=6SeoWIIK1NU&t=50s) | Oct 31, 2018 | - -## Contributors ✨ - -Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): - - - - - - - -
Giovanni Emananuele Nocco
Giovanni Nocco

⚠️
- - - -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! - - diff --git a/templates/template/api-workbench.rest b/templates/template/api-workbench.rest deleted file mode 100644 index 68b92726..00000000 --- a/templates/template/api-workbench.rest +++ /dev/null @@ -1,19 +0,0 @@ -@url = https://localhost:5001 -@apiVersion = api-version=1.0 - -@customerId = 1f7516de-c0b3-4bc6-a09e-564eac27c263 - -### Create a customer -POST {{url}}/api/v1/Customers?{{apiVersion}} HTTP/1.1 -Content-Type: application/json - -{ - "ssn": "2410196814", - "name": "Giovanni3", - "initialAmount": 100 -} - -### Get an existing customer -GET {{url}}/api/v1/Customers/{{customerId}}?{{apiVersion}} HTTP/1.1 - - diff --git a/templates/template/docker-compose.dcproj b/templates/template/docker-compose.dcproj deleted file mode 100644 index ecb283cb..00000000 --- a/templates/template/docker-compose.dcproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - 2.1 - Linux - 0db314b3-916f-41c8-8f82-9ba947f03541 - LaunchBrowser - {Scheme}://localhost:{ServicePort} - genocs.template.webapi - - - - docker-compose.yml - - - - - \ No newline at end of file diff --git a/templates/template/docker-compose.override.yml b/templates/template/docker-compose.override.yml deleted file mode 100644 index e2c19118..00000000 --- a/templates/template/docker-compose.override.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: '3.9' - -services: - servicetemplate.webapi: - environment: - - ASPNETCORE_ENVIRONMENT=Development - - ASPNETCORE_URLS=https://+:443;http://+:80 - networks: - - genocs - ports: - - 80 - - 443 - volumes: - - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro - - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro - -networks: - genocs: - name: genocs-network - external: true diff --git a/templates/template/docker-compose.yml b/templates/template/docker-compose.yml deleted file mode 100644 index c4af6075..00000000 --- a/templates/template/docker-compose.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: '3.9' - -services: - servicetemplate.webapi: - image: ${DOCKER_REGISTRY-}servicetemplate-webapi - build: - context: . - dockerfile: webapi.dockerfile diff --git a/templates/template/k8s/Genocs.Template-kubernetes-ingress.yaml b/templates/template/k8s/Genocs.Template-kubernetes-ingress.yaml deleted file mode 100644 index 55ba5e16..00000000 --- a/templates/template/k8s/Genocs.Template-kubernetes-ingress.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: agic-ingress - annotations: - kubernetes.io/ingress.class: azure/application-gateway -spec: - rules: - - http: - paths: - - path: /foo - pathType: Prefix - backend: - service: - name: servicetemplate-webapi - port: - number: 80 - - path: /bar - pathType: Prefix - backend: - service: - name: qrcode - port: - number: 80 diff --git a/templates/template/k8s/Genocs.Template-kubernetes-webapi.yaml b/templates/template/k8s/Genocs.Template-kubernetes-webapi.yaml deleted file mode 100644 index eb19eb2a..00000000 --- a/templates/template/k8s/Genocs.Template-kubernetes-webapi.yaml +++ /dev/null @@ -1,44 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: servicetemplate - labels: - app: servicetemplate-webapi -spec: - selector: - matchLabels: - app: servicetemplate-webapi - replicas: 1 - template: - metadata: - labels: - app: servicetemplate-webapi - spec: - containers: - - name: servicetemplate-webapi - image: genocs/servicetemplate:latest - env: - - name: ASPNETCORE_ENVIRONMENT - value: "Development" - - name: ApiClients__SecondUrl - value: "http://servicetemplate.default.svc.cluster.local" - resources: - requests: - cpu: 100m - memory: 100Mi - limits: - cpu: 250m - memory: 1024Mi - ports: - - containerPort: 80 ---- -apiVersion: v1 -kind: Service -metadata: - name: servicetemplate -spec: - # type: LoadBalancer - ports: - - port: 80 - selector: - app: servicetemplate-webapi diff --git a/templates/template/k8s/Genocs.Template-kubernetes-worker.yaml b/templates/template/k8s/Genocs.Template-kubernetes-worker.yaml deleted file mode 100644 index 154b15e2..00000000 --- a/templates/template/k8s/Genocs.Template-kubernetes-worker.yaml +++ /dev/null @@ -1,44 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: servicetemplate - labels: - app: servicetemplate-worker -spec: - selector: - matchLabels: - app: servicetemplate-worker - replicas: 1 - template: - metadata: - labels: - app: servicetemplate-worker - spec: - containers: - - name: servicetemplate-worker - image: genocsacr.azurecr.io/servicetemplate-worker:latest - env: - - name: ParticularOptions__TransportConnectionString - value: "<>" - - name: ParticularOptions__PersistenceConnectionString - value: "<>" - resources: - requests: - cpu: 100m - memory: 100Mi - limits: - cpu: 250m - memory: 1024Mi - ports: - - containerPort: 80 ---- -apiVersion: v1 -kind: Service -metadata: - name: servicetemplate -spec: - # type: LoadBalancer - ports: - - port: 80 - selector: - app: servicetemplate-worker diff --git a/templates/template/pipelines/azure-pipeline-build.yml b/templates/template/pipelines/azure-pipeline-build.yml deleted file mode 100644 index 1cd065a8..00000000 --- a/templates/template/pipelines/azure-pipeline-build.yml +++ /dev/null @@ -1,40 +0,0 @@ -pool: - name: Azure Pipelines -#Your build pipeline references an undefined variable named ‘Parameters.RestoreBuildProjects’. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab. See https://go.microsoft.com/fwlink/?linkid=865972 -#Your build pipeline references the ‘BuildConfiguration’ variable, which you’ve selected to be settable at queue time. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab, and then select the option to make it settable at queue time. See https://go.microsoft.com/fwlink/?linkid=865971 -#Your build pipeline references an undefined variable named ‘Parameters.TestProjects’. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab. See https://go.microsoft.com/fwlink/?linkid=865972 -#Your build pipeline references the ‘BuildConfiguration’ variable, which you’ve selected to be settable at queue time. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab, and then select the option to make it settable at queue time. See https://go.microsoft.com/fwlink/?linkid=865971 -#Your build pipeline references the ‘BuildConfiguration’ variable, which you’ve selected to be settable at queue time. Create or edit the build pipeline for this YAML file, define the variable on the Variables tab, and then select the option to make it settable at queue time. See https://go.microsoft.com/fwlink/?linkid=865971 - -steps: - - task: NuGetAuthenticate@0 - displayName: "NuGet Authenticate" - - - task: DotNetCoreCLI@2 - displayName: "Build projects" - inputs: - projects: "$(Parameters.RestoreBuildProjects)" - arguments: "--configuration $(BuildConfiguration)" # Update this to match your need - - # Run the Test (after building) - - task: DotNetCoreCLI@2 - displayName: "Run tests" - inputs: - command: "test" - projects: "$(Parameters.TestProjects)" - arguments: "--configuration $(BuildConfiguration)" - - # Publish the artifact to be ready for deploy - - task: DotNetCoreCLI@2 - displayName: Publish - inputs: - command: "publish" - publishWebProjects: true - arguments: "--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)" - zipAfterPublish: True - - - task: PublishBuildArtifacts@1 - displayName: "Publish Artifact" - inputs: - pathToPublish: "$(build.artifactstagingdirectory)" - condition: succeededOrFailed() diff --git a/templates/template/pipelines/azure-pipeline-docker-acr.yml b/templates/template/pipelines/azure-pipeline-docker-acr.yml deleted file mode 100644 index 6abb1507..00000000 --- a/templates/template/pipelines/azure-pipeline-docker-acr.yml +++ /dev/null @@ -1,64 +0,0 @@ -# Build and push a Docker image to Azure Container Registry -# The stage contains a couple of build and push -# one for the Version and one for Latest -# https://aka.ms/yaml -# https://docs.microsoft.com/azure/devops/pipelines/languages/docker - -name: Build Docker Image and publish on AzureContainerRegistry - -trigger: - - none - -pool: - vmImage: ubuntu-latest - -variables: - buildConfiguration: "Release" - imageName: "$(DockerRegistry).azurecr.io/$(DockerImageName)" - -stages: - - stage: Build - displayName: Build image - jobs: - - job: Build - displayName: Build and push Docker image - steps: - - task: Docker@1 - displayName: "Build the Docker image" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "$(DockerRegistry)" - command: "Build image" - dockerFile: "Dockerfile" - arguments: "--build-arg BuildId=$(Build.BuildId)" - includeLatestTag: true - imageName: "$(ImageName)" - - - task: Docker@1 - displayName: "Push the Docker image to AzureContainerRegistry" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "$(DockerRegistry)" - command: "Push image" - imageName: "$(ImageName)" - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) - - - task: Docker@1 - displayName: "Tag-Latest Build the Docker image" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "$(DockerRegistry)" - command: "Build image" - dockerFile: "Dockerfile" - arguments: "--build-arg BuildId=$(Build.BuildId)" - imageName: "$(ImageName):$(MajorVer).$(MinorVer).$(Build.BuildId)" - - - task: Docker@1 - displayName: "Tag-Latest Push the Docker image to AzureContainerRegistry" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "$(DockerRegistry)" - command: "Push image" - imageName: "$(ImageName):$(MajorVer).$(MinorVer).$(Build.BuildId)" - - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) diff --git a/templates/template/pipelines/azure-pipeline-docker.yml b/templates/template/pipelines/azure-pipeline-docker.yml deleted file mode 100644 index 7a9acfa3..00000000 --- a/templates/template/pipelines/azure-pipeline-docker.yml +++ /dev/null @@ -1,64 +0,0 @@ -# Build and push a Docker image to Docker hub -# The stage contains a couple of build and push -# one for the Version and one for Latest -# https://aka.ms/yaml -# https://docs.microsoft.com/azure/devops/pipelines/languages/docker - -name: Build Docker Image and publish on Docker Hub - -trigger: - - none - -pool: - vmImage: ubuntu-latest - -variables: - buildConfiguration: "Release" - imageName: "$(DockerRegistry)/$(DockerImageName)" - -stages: - - stage: Build - displayName: Build image - jobs: - - job: Build - displayName: Build and push Docker image - steps: - - task: Docker@1 - displayName: "Build the Docker image" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "DockerHub" - command: "Build image" - dockerFile: "Dockerfile" - arguments: "--build-arg BuildId=$(Build.BuildId)" - includeLatestTag: true - imageName: "$(ImageName)" - - - task: Docker@1 - displayName: "Push the Docker image to Docker Hub" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "DockerHub" - command: "Push image" - imageName: "$(ImageName)" - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) - - - task: Docker@1 - displayName: "Tag-Latest Build the Docker image" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "DockerHub" - command: "Build image" - dockerFile: "Dockerfile" - arguments: "--build-arg BuildId=$(Build.BuildId)" - imageName: "$(ImageName):$(MajorVer).$(MinorVer).$(Build.BuildId)" - - - task: Docker@1 - displayName: "Tag-Latest Push the Docker image to Docker Hub" - inputs: - containerRegistryType: "Container Registry" - dockerRegistryEndpoint: "DockerHub" - command: "Push image" - imageName: "$(ImageName):$(MajorVer).$(MinorVer).$(Build.BuildId)" - - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) diff --git a/templates/template/pipelines/azure-pipeline.yml b/templates/template/pipelines/azure-pipeline.yml deleted file mode 100644 index 9bc0f995..00000000 --- a/templates/template/pipelines/azure-pipeline.yml +++ /dev/null @@ -1,126 +0,0 @@ -variables: - repositoryName: workflow - chartPath: charts/workflow - dockerFileName: src/shipping/workflow/Dockerfile - imageName: $(repositoryName):$(Build.SourceBranchName) - azureSubscription: AZURE_PIPELINES_SERVICE_CONN_NAME_VAR_VAL - azureContainerRegistry: ACR_SERVER_VAR_VAL - azureContainerRegistryName: ACR_NAME_VAR_VAL - -name: $(build.sourceBranch)-$(Date:yyyyMMdd)$(Rev:.rr) - -pr: # only valid for GitHub. Using Azure repo it must be configure as a Branch Policy - paths: - include: - - /src/shipping/workflow/ - - branches: - include: - - master - - release/workflow/v* # for bug fixes - -trigger: - batch: true - branches: - include: - # for new release to production: release flow strategy - - release/workflow/v* - - refs/relelase/workflow/v* - - master - - feature/workflow/* - - topic/workflow/* - paths: - include: - - /src/shipping/workflow/ - -resources: - - repo: self - -jobs: - # CI - - job: workflowjobci - displayName: "Workflow CI" - pool: - vmImage: "Ubuntu 20.04" - timeoutInMinutes: 90 - variables: - fullCI: $[ startsWith(variables['build.sourceBranch'], 'refs/heads/release/workflow/v') ] - buildImage: $[ eq(variables['build.sourceBranch'], 'refs/heads/master') ] - steps: - - task: Docker@1 - displayName: "Build testrunner image" - inputs: - azureSubscriptionEndpoint: $(azureSubscription) - azureContainerRegistry: $(azureContainerRegistry) - arguments: "--pull --target testrunner" - dockerFile: $(System.DefaultWorkingDirectory)/$(dockerFileName) - imageName: "$(imageName)-test" - - - task: Docker@1 - displayName: "Run tests" - inputs: - azureSubscriptionEndpoint: $(azureSubscription) - azureContainerRegistry: $(azureContainerRegistry) - command: "run" - containerName: testrunner - volumes: "$(System.DefaultWorkingDirectory)/TestResults:/src/tests/TestResults" - imageName: "$(imageName)-test" - runInBackground: false - - - task: PublishTestResults@2 - displayName: "Publish test results" - inputs: - testResultsFormat: "VSTest" # Options: JUnit, NUnit, VSTest, xUnit - testResultsFiles: "TestResults/*.trx" - searchFolder: "$(System.DefaultWorkingDirectory)" - publishRunAttachments: true - - - task: Docker@1 - condition: or(eq(variables['buildImage'],True),eq(variables['fullCI'],True)) - displayName: "Build runtime image" - inputs: - azureSubscriptionEndpoint: $(azureSubscription) - azureContainerRegistry: $(azureContainerRegistry) - dockerFile: $(System.DefaultWorkingDirectory)/$(dockerFileName) - includeLatestTag: false - imageName: "$(imageName)" - - - task: Docker@1 - condition: eq(variables['fullCI'],True) - displayName: "Push runtime image" - inputs: - azureSubscriptionEndpoint: $(azureSubscription) - azureContainerRegistry: $(azureContainerRegistry) - command: "Push an image" - imageName: "$(imageName)" - includeSourceTags: false - - - task: HelmInstaller@0 - condition: eq(variables['fullCI'],True) - displayName: "Install Helm 3.0.3" - inputs: - helmVersion: 3.0.3 - checkLatestHelmVersion: false - kubectlVersion: 1.12.4 - checkLatestKubectl: false - - - task: HelmDeploy@0 - condition: eq(variables['fullCI'],True) - displayName: "helm package" - inputs: - command: package - chartPath: $(chartPath) - chartVersion: $(Build.SourceBranchName) - updateDependency: true - save: false - arguments: "--app-version $(Build.SourceBranchName)" - - - task: AzureCLI@1 - condition: eq(variables['fullCI'],True) - displayName: "Push a helm package" - inputs: - azureSubscription: $(azureSubscription) - scriptLocation: inlineScript - - inlineScript: | - az acr helm push $(System.ArtifactsDirectory)/$(repositoryName)-$(Build.SourceBranchName).tgz --name $(azureContainerRegistryName) --force; diff --git a/templates/template/scripts/build.sh b/templates/template/scripts/build.sh deleted file mode 100644 index 4fb071e1..00000000 --- a/templates/template/scripts/build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -MYGET_ENV="" -case "$TRAVIS_BRANCH" in - "develop") - MYGET_ENV="-dev" - ;; -esac - -dotnet build ../src/Genocs.Template.WebApi -c Release \ No newline at end of file diff --git a/templates/template/scripts/test.sh b/templates/template/scripts/test.sh deleted file mode 100644 index 6046c35a..00000000 --- a/templates/template/scripts/test.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -dotnet test \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.AcceptanceTests/Genocs.Template.AcceptanceTests.csproj b/templates/template/src/Genocs.Template.AcceptanceTests/Genocs.Template.AcceptanceTests.csproj deleted file mode 100644 index 32cbfc5a..00000000 --- a/templates/template/src/Genocs.Template.AcceptanceTests/Genocs.Template.AcceptanceTests.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - net7.0 - false - - - - TRACE;Full - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/templates/template/src/Genocs.Template.Application/Commands/CreateUser.cs b/templates/template/src/Genocs.Template.Application/Commands/CreateUser.cs deleted file mode 100644 index 4c221f65..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/CreateUser.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands; - -public class CreateUser : ICommand -{ - public Guid UserId { get; } - public string Email { get; } - public string Name { get; } - public string Password { get; } - public string Role { get; } - public IEnumerable Permissions { get; } - - public CreateUser(Guid userId, string email, string name, string password, string role, - IEnumerable permissions) - { - UserId = userId == Guid.Empty ? Guid.NewGuid() : userId; - Email = email; - Name = name; - Password = password; - Role = role; - Permissions = permissions; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/Handlers/CreateUserHandler.cs b/templates/template/src/Genocs.Template.Application/Commands/Handlers/CreateUserHandler.cs deleted file mode 100644 index d1a78f88..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/Handlers/CreateUserHandler.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Genocs.Core.CQRS.Commands; -using Genocs.Template.Application.Domain.Entities; -using Genocs.Template.Application.Domain.Exceptions; -using Genocs.Template.Application.Events; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Services; -using Microsoft.Extensions.Logging; -using System.Text.RegularExpressions; - -namespace Genocs.Template.Application.Commands.Handlers; - -internal sealed class CreateUserHandler : ICommandHandler -{ - private readonly IUserRepository _userRepository; - private readonly IPasswordService _passwordService; - private readonly IMessageBroker _messageBroker; - private readonly ILogger _logger; - - private static readonly Regex EmailRegex = new Regex( - @"^(?("")("".+?(? logger) - { - _userRepository = userRepository; - _passwordService = passwordService; - _messageBroker = messageBroker; - _logger = logger; - } - - public async Task HandleAsync(CreateUser command, CancellationToken cancellationToken = default) - { - if (!EmailRegex.IsMatch(command.Email)) - { - _logger.LogError($"Invalid email: {command.Email}"); - throw new InvalidEmailException(command.Email); - } - - var user = await _userRepository.GetByEmailAsync(command.Email); - if (user is { }) - { - _logger.LogError($"Email already in use: {command.Email}"); - throw new EmailInUseException(command.Email); - } - - user = await _userRepository.GetByNameAsync(command.Name); - if (user is { }) - { - _logger.LogError($"Name already in use: {command.Name}"); - throw new NameInUseException(command.Name); - } - - var role = string.IsNullOrWhiteSpace(command.Role) ? "user" : command.Role.ToLowerInvariant(); - var password = _passwordService.Hash(command.Password); - user = new User(command.UserId, command.Email, command.Name, password, role, DateTime.UtcNow, - command.Permissions); - await _userRepository.AddAsync(user); - _logger.LogInformation($"Created an account for the user with ID: '{user.Id}'."); - await _messageBroker.PublishAsync(new UserCreated(user.Id, user.Name, user.Role)); - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/Handlers/LockUserHandler.cs b/templates/template/src/Genocs.Template.Application/Commands/Handlers/LockUserHandler.cs deleted file mode 100644 index 454d7e6a..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/Handlers/LockUserHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Genocs.Core.CQRS.Commands; -using Genocs.Template.Application.Events; -using Genocs.Template.Application.Exceptions; -using Genocs.Template.Application.Commands; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Services; - -namespace Genocs.Template.Application.Commands.Handlers; - -internal sealed class LockUserHandler : ICommandHandler -{ - private readonly IUserRepository _userRepository; - private readonly IMessageBroker _messageBroker; - - public LockUserHandler(IUserRepository userRepository, IMessageBroker messageBroker) - { - _userRepository = userRepository; - _messageBroker = messageBroker; - } - - public async Task HandleAsync(LockUser command, CancellationToken cancellationToken = default) - { - var user = await _userRepository.GetAsync(command.UserId); - if (user is null) - { - throw new UserNotFoundException(command.UserId); - } - - if (user.Lock()) - { - await _userRepository.UpdateAsync(user); - await _messageBroker.PublishAsync(new UserLocked(user.Id)); - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeAccessTokenHandler.cs b/templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeAccessTokenHandler.cs deleted file mode 100644 index f4d4cc86..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeAccessTokenHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Genocs.Auth; -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands.Handlers; - -internal sealed class RevokeAccessTokenHandler : ICommandHandler -{ - private readonly IAccessTokenService _accessTokenService; - - public RevokeAccessTokenHandler(IAccessTokenService accessTokenService) - { - _accessTokenService = accessTokenService ?? throw new ArgumentNullException(nameof(accessTokenService)); - } - - public async Task HandleAsync(RevokeAccessToken command, CancellationToken cancellationToken = default) - => await _accessTokenService.DeactivateAsync(command.AccessToken); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeRefreshTokenHandler.cs b/templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeRefreshTokenHandler.cs deleted file mode 100644 index 25ce32ef..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/Handlers/RevokeRefreshTokenHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Genocs.Core.CQRS.Commands; -using Genocs.Template.Application.Domain.Exceptions; -using Genocs.Template.Application.Domain.Repositories; - -namespace Genocs.Template.Application.Commands.Handlers; - -internal sealed class RevokeRefreshTokenHandler : ICommandHandler -{ - private readonly IRefreshTokenRepository _refreshTokenRepository; - - public RevokeRefreshTokenHandler(IRefreshTokenRepository refreshTokenRepository) - { - _refreshTokenRepository = refreshTokenRepository; - } - - public async Task HandleAsync(RevokeRefreshToken command, CancellationToken cancellationToken = default) - { - var token = await _refreshTokenRepository.GetAsync(command.RefreshToken); - if (token is null) - { - throw new InvalidRefreshTokenException(); - } - - token.Revoke(DateTime.UtcNow); - await _refreshTokenRepository.UpdateAsync(token); - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/Handlers/SignInHandler.cs b/templates/template/src/Genocs.Template.Application/Commands/Handlers/SignInHandler.cs deleted file mode 100644 index 87713f4c..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/Handlers/SignInHandler.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Genocs.Core.CQRS.Commands; -using Genocs.Template.Application.Domain.Entities; -using Genocs.Template.Application.Domain.Exceptions; -using Genocs.Template.Application.Events; -using Genocs.Template.Application.Commands; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Services; -using Microsoft.Extensions.Logging; - -namespace Genocs.Template.Application.Commands.Handlers; - -internal sealed class SignInHandler : ICommandHandler -{ - private readonly IUserRepository _userRepository; - private readonly IRefreshTokenRepository _refreshTokenRepository; - private readonly IPasswordService _passwordService; - private readonly IJwtProvider _jwtProvider; - private readonly IRng _rng; - private readonly ITokenStorage _storage; - private readonly IMessageBroker _messageBroker; - private readonly ILogger _logger; - - public SignInHandler(IUserRepository userRepository, IRefreshTokenRepository refreshTokenRepository, - IPasswordService passwordService, IJwtProvider jwtProvider, IRng rng, ITokenStorage storage, - IMessageBroker messageBroker, ILogger logger) - { - _userRepository = userRepository; - _refreshTokenRepository = refreshTokenRepository; - _passwordService = passwordService; - _jwtProvider = jwtProvider; - _rng = rng; - _storage = storage; - _messageBroker = messageBroker; - _logger = logger; - } - - public async Task HandleAsync(SignIn command, CancellationToken cancellationToken = default) - { - var user = await _userRepository.GetByNameAsync(command.Name); - if (user is null || !_passwordService.IsValid(user.Password, command.Password)) - { - _logger.LogError($"User with name: {command.Name} was not found."); - throw new InvalidCredentialsException(command.Name); - } - - if (user.Locked) - { - throw new UserLockedException(user.Id); - } - - var claims = user.Permissions.Any() - ? new Dictionary> - { - ["permissions"] = user.Permissions - } - : null; - var auth = _jwtProvider.Create(user.Id, user.Name, user.Role, claims: claims); - auth.RefreshToken = await CreateRefreshTokenAsync(user.Id); - _storage.Set(command.Id, auth); - _logger.LogInformation($"User with id: {user.Id} has been authenticated."); - await _messageBroker.PublishAsync(new SignedIn(user.Id)); - } - - private async Task CreateRefreshTokenAsync(Guid userId) - { - var token = _rng.Generate(30, true); - var refreshToken = new RefreshToken(new AggregateId(), userId, token, DateTime.UtcNow); - await _refreshTokenRepository.AddAsync(refreshToken); - - return token; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/Handlers/UnlockUserHandler.cs b/templates/template/src/Genocs.Template.Application/Commands/Handlers/UnlockUserHandler.cs deleted file mode 100644 index 34c12f3d..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/Handlers/UnlockUserHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Genocs.Core.CQRS.Commands; -using Genocs.Template.Application.Events; -using Genocs.Template.Application.Exceptions; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Services; - -namespace Genocs.Template.Application.Commands.Handlers; - -internal sealed class UnlockUserHandler : ICommandHandler -{ - private readonly IUserRepository _userRepository; - private readonly IMessageBroker _messageBroker; - - public UnlockUserHandler(IUserRepository userRepository, IMessageBroker messageBroker) - { - _userRepository = userRepository; - _messageBroker = messageBroker; - } - - public async Task HandleAsync(UnlockUser command, CancellationToken cancellationToken = default) - { - var user = await _userRepository.GetAsync(command.UserId); - if (user is null) - { - throw new UserNotFoundException(command.UserId); - } - - if (user.Unlock()) - { - await _userRepository.UpdateAsync(user); - await _messageBroker.PublishAsync(new UserUnlocked(user.Id)); - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/Handlers/UseRefreshTokenHandler.cs b/templates/template/src/Genocs.Template.Application/Commands/Handlers/UseRefreshTokenHandler.cs deleted file mode 100644 index b0eaec31..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/Handlers/UseRefreshTokenHandler.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Genocs.Core.CQRS.Commands; -using Genocs.Template.Application.Domain.Exceptions; -using Genocs.Template.Application.Exceptions; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Services; - -namespace Genocs.Template.Application.Commands.Handlers; - -internal sealed class UseRefreshTokenHandler : ICommandHandler -{ - private readonly IRefreshTokenRepository _refreshTokenRepository; - private readonly IUserRepository _userRepository; - private readonly IJwtProvider _jwtProvider; - private readonly ITokenStorage _storage; - - public UseRefreshTokenHandler(IRefreshTokenRepository refreshTokenRepository, IUserRepository userRepository, - IJwtProvider jwtProvider, ITokenStorage storage) - { - _refreshTokenRepository = refreshTokenRepository; - _userRepository = userRepository; - _jwtProvider = jwtProvider; - _storage = storage; - } - - public async Task HandleAsync(UseRefreshToken command, CancellationToken cancellationToken = default) - { - var token = await _refreshTokenRepository.GetAsync(command.RefreshToken); - if (token is null) - { - throw new InvalidRefreshTokenException(); - } - - if (token.Revoked) - { - throw new RevokedRefreshTokenException(); - } - - var user = await _userRepository.GetAsync(token.UserId); - if (user is null) - { - throw new UserNotFoundException(token.UserId); - } - - var claims = user.Permissions.Any() - ? new Dictionary> - { - ["permissions"] = user.Permissions - } - : null; - var auth = _jwtProvider.Create(token.UserId, user.Name, user.Role, claims: claims); - auth.RefreshToken = command.RefreshToken; - _storage.Set(command.Id, auth); - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/LockUser.cs b/templates/template/src/Genocs.Template.Application/Commands/LockUser.cs deleted file mode 100644 index 7151d636..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/LockUser.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands; - -public class LockUser : ICommand -{ - public Guid UserId { get; } - - public LockUser(Guid userId) - { - UserId = userId; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/RevokeAccessToken.cs b/templates/template/src/Genocs.Template.Application/Commands/RevokeAccessToken.cs deleted file mode 100644 index d23bbded..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/RevokeAccessToken.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands; - -public class RevokeAccessToken : ICommand -{ - public string AccessToken { get; } - - public RevokeAccessToken(string accessToken) - { - AccessToken = accessToken; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/RevokeRefreshToken.cs b/templates/template/src/Genocs.Template.Application/Commands/RevokeRefreshToken.cs deleted file mode 100644 index 73a2469a..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/RevokeRefreshToken.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands; - -public class RevokeRefreshToken : ICommand -{ - public string RefreshToken { get; } - - public RevokeRefreshToken(string refreshToken) - { - RefreshToken = refreshToken; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/SignIn.cs b/templates/template/src/Genocs.Template.Application/Commands/SignIn.cs deleted file mode 100644 index 7728cb68..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/SignIn.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands; - -public class SignIn : ICommand -{ - public Guid Id { get; } = Guid.NewGuid(); - public string Name { get; set; } - public string Password { get; set; } - - public SignIn(string name, string password) - { - Name = name; - Password = password; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/UnlockUser.cs b/templates/template/src/Genocs.Template.Application/Commands/UnlockUser.cs deleted file mode 100644 index 4c936233..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/UnlockUser.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands; - -public class UnlockUser : ICommand -{ - public Guid UserId { get; } - - public UnlockUser(Guid userId) - { - UserId = userId; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Commands/UseRefreshToken.cs b/templates/template/src/Genocs.Template.Application/Commands/UseRefreshToken.cs deleted file mode 100644 index b5b4c6a9..00000000 --- a/templates/template/src/Genocs.Template.Application/Commands/UseRefreshToken.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Genocs.Core.CQRS.Commands; - -namespace Genocs.Template.Application.Commands; - -public class UseRefreshToken : ICommand -{ - public Guid Id { get; } = Guid.NewGuid(); - public string RefreshToken { get; } - - public UseRefreshToken(string refreshToken) - { - RefreshToken = refreshToken; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/ContractAttribute.cs b/templates/template/src/Genocs.Template.Application/ContractAttribute.cs deleted file mode 100644 index c4218fa9..00000000 --- a/templates/template/src/Genocs.Template.Application/ContractAttribute.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Genocs.Template.Application; - -// Marker -public class ContractAttribute : Attribute -{ -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/CorrelationContext.cs b/templates/template/src/Genocs.Template.Application/CorrelationContext.cs deleted file mode 100644 index fbbbf9ff..00000000 --- a/templates/template/src/Genocs.Template.Application/CorrelationContext.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Genocs.Template.Application; - -internal class CorrelationContext -{ - public string CorrelationId { get; set; } - public string SpanContext { get; set; } - public UserContext User { get; set; } - public string ResourceId { get; set; } - public string TraceId { get; set; } - public string ConnectionId { get; set; } - public string Name { get; set; } - public DateTime CreatedAt { get; set; } - - public class UserContext - { - public string Id { get; set; } - public bool IsAuthenticated { get; set; } - public string Role { get; set; } - public IDictionary Claims { get; set; } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/CorrelationIdFactory.cs b/templates/template/src/Genocs.Template.Application/CorrelationIdFactory.cs deleted file mode 100644 index 4491b022..00000000 --- a/templates/template/src/Genocs.Template.Application/CorrelationIdFactory.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Genocs.HTTP; -using Genocs.HTTP.Options; -using Genocs.MessageBrokers; -using Microsoft.AspNetCore.Http; - -namespace Genocs.Template.Application; - -internal class CorrelationIdFactory : ICorrelationIdFactory -{ - private static readonly AsyncLocal Holder = new AsyncLocal(); - - private readonly IMessagePropertiesAccessor _messagePropertiesAccessor; - private readonly IHttpContextAccessor _httpContextAccessor; - private readonly string _header; - - public CorrelationIdFactory(IMessagePropertiesAccessor messagePropertiesAccessor, - IHttpContextAccessor httpContextAccessor, HttpClientSettings httpClientOptions) - { - _messagePropertiesAccessor = messagePropertiesAccessor; - _httpContextAccessor = httpContextAccessor; - _header = httpClientOptions.CorrelationIdHeader; - } - - private static string CorrelationId { - get => Holder.Value?.Id; - set { - var holder = Holder.Value; - if (holder is { }) - { - holder.Id = null; - } - - if (value is { }) - { - Holder.Value = new CorrelationIdHolder { Id = value }; - } - } - } - - private class CorrelationIdHolder - { - public string Id; - } - - public string Create() - { - if (!string.IsNullOrWhiteSpace(CorrelationId)) - { - return CorrelationId; - } - - var correlationId = _messagePropertiesAccessor.MessageProperties?.CorrelationId; - if (!string.IsNullOrWhiteSpace(correlationId)) - { - CorrelationId = correlationId; - return CorrelationId; - } - - if (string.IsNullOrWhiteSpace(_header) || _httpContextAccessor.HttpContext is null) - { - CorrelationId = CreateId(); - return CorrelationId; - } - - if (!_httpContextAccessor.HttpContext.Request.Headers.TryGetValue(_header, out var id)) - { - CorrelationId = CreateId(); - return CorrelationId; - } - - correlationId = id.ToString(); - CorrelationId = string.IsNullOrWhiteSpace(correlationId) ? CreateId() : correlationId; - - return CorrelationId; - } - - private static string CreateId() => Guid.NewGuid().ToString("N"); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/DTO/AuthDto.cs b/templates/template/src/Genocs.Template.Application/DTO/AuthDto.cs deleted file mode 100644 index 42354849..00000000 --- a/templates/template/src/Genocs.Template.Application/DTO/AuthDto.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Genocs.Template.Application.DTO; - -public class AuthDto -{ - public Guid UserId { get; set; } - public string Username { get; set; } - public string Role { get; set; } - public string AccessToken { get; set; } - public string RefreshToken { get; set; } - public long Expires { get; set; } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/DTO/PagedDto.cs b/templates/template/src/Genocs.Template.Application/DTO/PagedDto.cs deleted file mode 100644 index f4eeb50e..00000000 --- a/templates/template/src/Genocs.Template.Application/DTO/PagedDto.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Genocs.Template.Application.DTO; - - -/// -/// It will be removed with Core implementation -/// -/// -public class PagedDto -{ - public IEnumerable Items { get; set; } - public bool Empty => Items is null || !Items.Any(); - public int CurrentPage { get; set; } - public int ResultsPerPage { get; set; } - public int TotalPages { get; set; } - public long TotalResults { get; set; } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/DTO/UserDetailsDto.cs b/templates/template/src/Genocs.Template.Application/DTO/UserDetailsDto.cs deleted file mode 100644 index eb1554c1..00000000 --- a/templates/template/src/Genocs.Template.Application/DTO/UserDetailsDto.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Genocs.Template.Application.DTO; - -/// -/// The UserDetails Dto -/// -public class UserDetailsDto : UserDto -{ - public string Email { get; set; } - public string Role { get; set; } - public IEnumerable? Permissions { get; set; } - public decimal Funds { get; set; } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/DTO/UserDto.cs b/templates/template/src/Genocs.Template.Application/DTO/UserDto.cs deleted file mode 100644 index 390f9fa5..00000000 --- a/templates/template/src/Genocs.Template.Application/DTO/UserDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Genocs.Template.Application.DTO; - -public class UserDto -{ - public Guid Id { get; set; } - public string Name { get; set; } - public DateTime CreatedAt { get; set; } - public bool Locked { get; set; } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Decorators/LoggingCommandHandlerDecorator.cs b/templates/template/src/Genocs.Template.Application/Decorators/LoggingCommandHandlerDecorator.cs deleted file mode 100644 index 8b2e6712..00000000 --- a/templates/template/src/Genocs.Template.Application/Decorators/LoggingCommandHandlerDecorator.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Genocs.Common.Types; -using Genocs.Core.CQRS.Commands; -using Genocs.Core.Extensions; -using Genocs.HTTP; -using Microsoft.Extensions.Logging; -using Serilog.Context; - -namespace Genocs.Template.Application.Decorators; - -[Decorator] -internal sealed class LoggingCommandHandlerDecorator : ICommandHandler - where TCommand : class, ICommand -{ - private readonly ICommandHandler _handler; - private readonly ICorrelationIdFactory _correlationIdFactory; - private readonly ILogger> _logger; - - public LoggingCommandHandlerDecorator(ICommandHandler handler, - ICorrelationIdFactory correlationIdFactory, ILogger> logger) - { - _handler = handler; - _correlationIdFactory = correlationIdFactory; - _logger = logger; - } - - public async Task HandleAsync(TCommand command, CancellationToken cancellationToken = default) - { - var correlationId = _correlationIdFactory.Create(); - using (LogContext.PushProperty("CorrelationId", correlationId)) - { - var name = command.GetType().Name.Underscore(); - _logger.LogInformation($"Handling a command: '{name}'..."); - await _handler.HandleAsync(command); - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Decorators/LoggingEventHandlerDecorator.cs b/templates/template/src/Genocs.Template.Application/Decorators/LoggingEventHandlerDecorator.cs deleted file mode 100644 index f3700ffa..00000000 --- a/templates/template/src/Genocs.Template.Application/Decorators/LoggingEventHandlerDecorator.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Genocs.Common.Types; -using Genocs.Core.CQRS.Events; -using Genocs.Core.Extensions; -using Genocs.HTTP; -using Microsoft.Extensions.Logging; -using Serilog.Context; - -namespace Genocs.Template.Application.Decorators; - -[Decorator] -internal sealed class LoggingEventHandlerDecorator : IEventHandler - where TEvent : class, IEvent -{ - private readonly IEventHandler _handler; - private readonly ICorrelationIdFactory _correlationIdFactory; - private readonly ILogger> _logger; - - public LoggingEventHandlerDecorator(IEventHandler handler, ICorrelationIdFactory correlationIdFactory, - ILogger> logger) - { - _handler = handler; - _correlationIdFactory = correlationIdFactory; - _logger = logger; - } - - public async Task HandleAsync(TEvent @event, CancellationToken cancellationToken = default) - { - var correlationId = _correlationIdFactory.Create(); - using (LogContext.PushProperty("CorrelationId", correlationId)) - { - var name = @event.GetType().Name.Underscore(); - _logger.LogInformation($"Handling an event: '{name}'..."); - await _handler.HandleAsync(@event); - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Decorators/OutboxCommandHandlerDecorator.cs b/templates/template/src/Genocs.Template.Application/Decorators/OutboxCommandHandlerDecorator.cs deleted file mode 100644 index d033f3af..00000000 --- a/templates/template/src/Genocs.Template.Application/Decorators/OutboxCommandHandlerDecorator.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Genocs.Common.Types; -using Genocs.Core.CQRS.Commands; -using Genocs.MessageBrokers; -using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.Outbox.Options; - -namespace Genocs.Template.Application.Decorators; - -[Decorator] -internal sealed class OutboxCommandHandlerDecorator : ICommandHandler - where TCommand : class, ICommand -{ - private readonly ICommandHandler _handler; - private readonly IMessageOutbox _outbox; - private readonly string _messageId; - private readonly bool _enabled; - - public OutboxCommandHandlerDecorator(ICommandHandler handler, IMessageOutbox outbox, - OutboxSettings outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) - { - _handler = handler; - _outbox = outbox; - _enabled = outboxOptions.Enabled; - - var messageProperties = messagePropertiesAccessor.MessageProperties; - _messageId = string.IsNullOrWhiteSpace(messageProperties?.MessageId) - ? Guid.NewGuid().ToString("N") - : messageProperties.MessageId; - } - - public Task HandleAsync(TCommand command, CancellationToken cancellationToken = default) - => _enabled - ? _outbox.HandleAsync(_messageId, () => _handler.HandleAsync(command)) - : _handler.HandleAsync(command); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Decorators/OutboxEventHandlerDecorator.cs b/templates/template/src/Genocs.Template.Application/Decorators/OutboxEventHandlerDecorator.cs deleted file mode 100644 index c115dcb0..00000000 --- a/templates/template/src/Genocs.Template.Application/Decorators/OutboxEventHandlerDecorator.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Genocs.Common.Types; -using Genocs.Core.CQRS.Events; -using Genocs.MessageBrokers; -using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.Outbox.Options; - -namespace Genocs.Template.Application.Decorators; - -[Decorator] -internal sealed class OutboxEventHandlerDecorator : IEventHandler - where TEvent : class, IEvent -{ - private readonly IEventHandler _handler; - private readonly IMessageOutbox _outbox; - private readonly string _messageId; - private readonly bool _enabled; - - public OutboxEventHandlerDecorator(IEventHandler handler, IMessageOutbox outbox, - OutboxSettings outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) - { - _handler = handler; - _outbox = outbox; - _enabled = outboxOptions.Enabled; - - var messageProperties = messagePropertiesAccessor.MessageProperties; - _messageId = string.IsNullOrWhiteSpace(messageProperties?.MessageId) - ? Guid.NewGuid().ToString("N") - : messageProperties.MessageId; - } - - public Task HandleAsync(TEvent @event, CancellationToken cancellationToken = default) - => _enabled - ? _outbox.HandleAsync(_messageId, () => _handler.HandleAsync(@event)) - : _handler.HandleAsync(@event); - -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateId.cs b/templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateId.cs deleted file mode 100644 index 939fc9d2..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateId.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace Genocs.Template.Application.Domain.Entities; - -public class AggregateId : IEquatable -{ - public Guid Value { get; } - - public AggregateId() - { - Value = Guid.NewGuid(); - } - - public AggregateId(Guid value) - { - Value = value; - } - - /// - /// The Equals operator - /// - /// - /// - public bool Equals(AggregateId? other) - { - if (ReferenceEquals(null, other)) return false; - return ReferenceEquals(this, other) || Value.Equals(other.Value); - } - - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == GetType() && Equals((AggregateId)obj); - } - - public override int GetHashCode() - => Value.GetHashCode(); - - public static implicit operator Guid(AggregateId id) - => id.Value; - - public static implicit operator AggregateId(Guid id) - => new AggregateId(id); - - /// - /// Return the string data - /// - /// string description about the object - public override string ToString() - => Value.ToString(); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateRoot.cs b/templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateRoot.cs deleted file mode 100644 index 7c2e06c3..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Entities/AggregateRoot.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Genocs.Template.Application.Domain.Entities; - -/// -/// The aggregate root class -/// -public abstract class AggregateRoot -{ - public AggregateId Id { get; protected set; } - public int Version { get; protected set; } - - protected AggregateRoot(AggregateId id, int version = 0) - { - Id = id; - Version = version; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Entities/RefreshToken.cs b/templates/template/src/Genocs.Template.Application/Domain/Entities/RefreshToken.cs deleted file mode 100644 index 8a85cdce..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Entities/RefreshToken.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Genocs.Template.Application.Domain.Exceptions; - -namespace Genocs.Template.Application.Domain.Entities; - -public class RefreshToken : AggregateRoot -{ - public AggregateId UserId { get; private set; } - public string Token { get; private set; } - public DateTime CreatedAt { get; private set; } - public DateTime? RevokedAt { get; private set; } - public bool Revoked - => RevokedAt.HasValue; - - public RefreshToken(AggregateId id, AggregateId userId, string token, DateTime createdAt, - DateTime? revokedAt = null) : base(id) - { - if (string.IsNullOrWhiteSpace(token)) - { - throw new EmptyRefreshTokenException(); - } - - UserId = userId; - Token = token; - CreatedAt = createdAt; - RevokedAt = revokedAt; - } - - public void Revoke(DateTime revokedAt) - { - if (Revoked) - { - throw new RevokedRefreshTokenException(); - } - - RevokedAt = revokedAt; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Entities/Role.cs b/templates/template/src/Genocs.Template.Application/Domain/Entities/Role.cs deleted file mode 100644 index 5c42b8b8..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Entities/Role.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Genocs.Template.Application.Domain.Entities; - -public static class Role -{ - public const string User = "user"; - public const string Admin = "admin"; - - public static bool IsValid(string role) - { - if (string.IsNullOrWhiteSpace(role)) - { - return false; - } - - role = role.ToLowerInvariant(); - - return role == User || role == Admin; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Entities/User.cs b/templates/template/src/Genocs.Template.Application/Domain/Entities/User.cs deleted file mode 100644 index fb08d2ad..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Entities/User.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Genocs.Template.Application.Domain.Exceptions; - -namespace Genocs.Template.Application.Domain.Entities; - -public class User : AggregateRoot -{ - public string Email { get; private set; } - public string Name { get; private set; } - public string Role { get; private set; } - public string Password { get; private set; } - public DateTime CreatedAt { get; private set; } - public IEnumerable? Permissions { get; private set; } - public bool Locked { get; private set; } - - public User(Guid id, string email, string name, string password, string role, DateTime createdAt, - IEnumerable? permissions = null, bool locked = false) : base(id) - { - if (string.IsNullOrWhiteSpace(email)) - { - throw new InvalidEmailException(email); - } - - if (string.IsNullOrWhiteSpace(name)) - { - throw new InvalidNameException(name); - } - - if (string.IsNullOrWhiteSpace(password)) - { - throw new InvalidPasswordException(); - } - - if (!Entities.Role.IsValid(role)) - { - throw new InvalidRoleException(role); - } - - Id = id; - Email = email.ToLowerInvariant(); - Name = name.Trim(); - Password = password; - Role = role.ToLowerInvariant(); - CreatedAt = createdAt; - Permissions = permissions ?? Enumerable.Empty(); - Locked = locked; - } - - - public bool Lock() - { - if (Locked) - { - return false; - } - - Locked = true; - return true; - } - - public bool Unlock() - { - if (!Locked) - { - return false; - } - - Locked = false; - return true; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/DomainException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/DomainException.cs deleted file mode 100644 index 88a5f925..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/DomainException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public abstract class DomainException : Exception -{ - protected DomainException(string message) : base(message) - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmailInUseException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmailInUseException.cs deleted file mode 100644 index 2b60564a..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmailInUseException.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class EmailInUseException : DomainException -{ - public string Email { get; } - - public EmailInUseException(string email) : base($"Email {email} is already in use.") - { - Email = email; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmptyRefreshTokenException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmptyRefreshTokenException.cs deleted file mode 100644 index 507111f8..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/EmptyRefreshTokenException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class EmptyRefreshTokenException : DomainException -{ - public EmptyRefreshTokenException() : base("Empty refresh token.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidAggregateIdException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidAggregateIdException.cs deleted file mode 100644 index c7408daf..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidAggregateIdException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class InvalidAggregateIdException : DomainException -{ - public InvalidAggregateIdException() : base($"Invalid aggregate id.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidCredentialsException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidCredentialsException.cs deleted file mode 100644 index 3ae16a0c..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidCredentialsException.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class InvalidCredentialsException : DomainException -{ - public string Email { get; } - - public InvalidCredentialsException(string email) : base("Invalid credentials.") - { - Email = email; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidEmailException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidEmailException.cs deleted file mode 100644 index 69961afb..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidEmailException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class InvalidEmailException : DomainException -{ - public InvalidEmailException(string email) : base($"Invalid email: {email}.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidNameException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidNameException.cs deleted file mode 100644 index 0d17349c..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidNameException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class InvalidNameException : DomainException -{ - public InvalidNameException(string name) : base($"Invalid name: {name}.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidPasswordException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidPasswordException.cs deleted file mode 100644 index 4e0800b2..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidPasswordException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class InvalidPasswordException : DomainException -{ - public InvalidPasswordException() : base($"Invalid password.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRefreshTokenException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRefreshTokenException.cs deleted file mode 100644 index d6245567..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRefreshTokenException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class InvalidRefreshTokenException : DomainException -{ - public InvalidRefreshTokenException() : base("Invalid refresh token.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRoleException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRoleException.cs deleted file mode 100644 index 821caae2..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/InvalidRoleException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class InvalidRoleException : DomainException -{ - public InvalidRoleException(string role) : base($"Invalid role: {role}.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/NameInUseException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/NameInUseException.cs deleted file mode 100644 index 07c13d5f..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/NameInUseException.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class NameInUseException : DomainException -{ - public string Name { get; } - - public NameInUseException(string name) : base($"Name {name} is already in use.") - { - Name = name; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/RevokedRefreshTokenException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/RevokedRefreshTokenException.cs deleted file mode 100644 index 9eaba101..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/RevokedRefreshTokenException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class RevokedRefreshTokenException : DomainException -{ - public RevokedRefreshTokenException() : base("Revoked refresh token.") - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/UserLockedException.cs b/templates/template/src/Genocs.Template.Application/Domain/Exceptions/UserLockedException.cs deleted file mode 100644 index d783d73f..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Exceptions/UserLockedException.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Genocs.Template.Application.Domain.Exceptions; - -public class UserLockedException : DomainException -{ - public Guid UserId { get; } - - public UserLockedException(Guid userId) : base($"User with ID: '{userId}' is locked.") - { - UserId = userId; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Repositories/IRefreshTokenRepository.cs b/templates/template/src/Genocs.Template.Application/Domain/Repositories/IRefreshTokenRepository.cs deleted file mode 100644 index 882f5b4c..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Repositories/IRefreshTokenRepository.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Genocs.Template.Application.Domain.Entities; - -namespace Genocs.Template.Application.Domain.Repositories; - -public interface IRefreshTokenRepository -{ - Task GetAsync(string token); - Task AddAsync(RefreshToken refreshToken); - Task UpdateAsync(RefreshToken refreshToken); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Domain/Repositories/IUserRepository.cs b/templates/template/src/Genocs.Template.Application/Domain/Repositories/IUserRepository.cs deleted file mode 100644 index 245ddeb0..00000000 --- a/templates/template/src/Genocs.Template.Application/Domain/Repositories/IUserRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Genocs.Template.Application.Domain.Entities; - -namespace Genocs.Template.Application.Domain.Repositories; - -public interface IUserRepository -{ - Task GetAsync(AggregateId id); - Task GetByEmailAsync(string email); - Task GetByNameAsync(string name); - Task AddAsync(User user); - Task UpdateAsync(User user); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Events/SignedIn.cs b/templates/template/src/Genocs.Template.Application/Events/SignedIn.cs deleted file mode 100644 index 314077a7..00000000 --- a/templates/template/src/Genocs.Template.Application/Events/SignedIn.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.Core.CQRS.Events; - -namespace Genocs.Template.Application.Events; - -public class SignedIn : IEvent -{ - public Guid UserId { get; } - - public SignedIn(Guid userId) - { - UserId = userId; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Events/UserCreated.cs b/templates/template/src/Genocs.Template.Application/Events/UserCreated.cs deleted file mode 100644 index 7bbd460e..00000000 --- a/templates/template/src/Genocs.Template.Application/Events/UserCreated.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Genocs.Core.CQRS.Events; - -namespace Genocs.Template.Application.Events; - -public class UserCreated : IEvent -{ - public Guid UserId { get; } - public string Name { get; } - public string Role { get; } - - public UserCreated(Guid userId, string name, string role) - { - UserId = userId; - Name = name; - Role = role; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Events/UserLocked.cs b/templates/template/src/Genocs.Template.Application/Events/UserLocked.cs deleted file mode 100644 index 70b2c536..00000000 --- a/templates/template/src/Genocs.Template.Application/Events/UserLocked.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.Core.CQRS.Events; - -namespace Genocs.Template.Application.Events; - -public class UserLocked : IEvent -{ - public Guid UserId { get; } - - public UserLocked(Guid userId) - { - UserId = userId; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Events/UserUnlocked.cs b/templates/template/src/Genocs.Template.Application/Events/UserUnlocked.cs deleted file mode 100644 index 9b4a8aaa..00000000 --- a/templates/template/src/Genocs.Template.Application/Events/UserUnlocked.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.Core.CQRS.Events; - -namespace Genocs.Template.Application.Events; - -public class UserUnlocked : IEvent -{ - public Guid UserId { get; } - - public UserUnlocked(Guid userId) - { - UserId = userId; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Exceptions/AppException.cs b/templates/template/src/Genocs.Template.Application/Exceptions/AppException.cs deleted file mode 100644 index f13d5238..00000000 --- a/templates/template/src/Genocs.Template.Application/Exceptions/AppException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Template.Application.Exceptions; - -public abstract class AppException : Exception -{ - protected AppException(string message) : base(message) - { - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToMessageMapper.cs b/templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToMessageMapper.cs deleted file mode 100644 index de24f712..00000000 --- a/templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToMessageMapper.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Genocs.MessageBrokers.RabbitMQ; - -namespace Genocs.Template.Application.Exceptions; - -internal sealed class ExceptionToMessageMapper : IExceptionToMessageMapper -{ - public object Map(Exception exception, object message) => null; -} - diff --git a/templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToResponseMapper.cs b/templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToResponseMapper.cs deleted file mode 100644 index 5475e079..00000000 --- a/templates/template/src/Genocs.Template.Application/Exceptions/ExceptionToResponseMapper.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Genocs.Core.Extensions; -using Genocs.Template.Application.Domain.Exceptions; -using Genocs.WebApi.Exceptions; -using System.Collections.Concurrent; -using System.Net; - -namespace Genocs.Template.Application.Exceptions; - -public class ExceptionToResponseMapper : IExceptionToResponseMapper -{ - private static readonly ConcurrentDictionary Codes = new ConcurrentDictionary(); - - public ExceptionResponse Map(Exception exception) - => exception switch - { - DomainException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, - HttpStatusCode.BadRequest), - AppException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, - HttpStatusCode.BadRequest), - _ => new ExceptionResponse(new { code = "error", reason = "There was an error." }, - HttpStatusCode.BadRequest) - }; - - private static string GetCode(Exception exception) - { - var type = exception.GetType(); - if (Codes.TryGetValue(type, out var code)) - { - return code; - } - - var exceptionCode = exception.GetType().Name.Underscore().Replace("_exception", string.Empty); - Codes.TryAdd(type, exceptionCode); - - return exceptionCode; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Exceptions/Extensions.cs b/templates/template/src/Genocs.Template.Application/Exceptions/Extensions.cs deleted file mode 100644 index 0f383875..00000000 --- a/templates/template/src/Genocs.Template.Application/Exceptions/Extensions.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Genocs.Core.Extensions; - -namespace Genocs.Template.Application.Exceptions; - -internal static class Extensions -{ - public static string GetExceptionCode(this Exception exception) - => exception.GetType().Name.Underscore().Replace("_exception", string.Empty); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Exceptions/UserNotFoundException.cs b/templates/template/src/Genocs.Template.Application/Exceptions/UserNotFoundException.cs deleted file mode 100644 index a5fd0e20..00000000 --- a/templates/template/src/Genocs.Template.Application/Exceptions/UserNotFoundException.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Genocs.Template.Application.Exceptions; - -public class UserNotFoundException : AppException -{ - public Guid UserId { get; } - - public UserNotFoundException(Guid userId) : base($"User with ID: '{userId}' was not found.") - { - UserId = userId; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Extensions.cs b/templates/template/src/Genocs.Template.Application/Extensions.cs deleted file mode 100644 index d20ec8d2..00000000 --- a/templates/template/src/Genocs.Template.Application/Extensions.cs +++ /dev/null @@ -1,128 +0,0 @@ -using Genocs.Auth; -using Genocs.Common.Options; -using Genocs.Core.Builders; -using Genocs.Core.CQRS.Commands; -using Genocs.Core.CQRS.Events; -using Genocs.Core.CQRS.Queries; -using Genocs.HTTP; -using Genocs.Template.Application.Mongo; -using Genocs.MessageBrokers; -using Genocs.MessageBrokers.CQRS; -using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.Outbox.MongoDB; -using Genocs.MessageBrokers.RabbitMQ; -using Genocs.Metrics.AppMetrics; -using Genocs.Persistence.MongoDb.Legacy; -using Genocs.Persistence.Redis; -using Genocs.Template.Application.Commands; -using Genocs.Template.Application.Decorators; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Exceptions; -using Genocs.Template.Application.Logging; -using Genocs.Template.Application.Mongo.Documents; -using Genocs.Template.Application.Mongo.Repositories; -using Genocs.Template.Application.Services; -using Genocs.Tracing.Jaeger; -using Genocs.WebApi; -using Genocs.WebApi.CQRS; -using Genocs.WebApi.Swagger; -using Genocs.WebApi.Swagger.Docs; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; -using System.Text; - -namespace Genocs.Template.Application; - -public static class Extensions -{ - public static IGenocsBuilder AddCore(this IGenocsBuilder builder) - { - builder.Services - .AddScoped() - .AddSingleton() - .AddSingleton() - .AddSingleton, PasswordHasher>() - .AddSingleton() - .AddSingleton() - .AddScoped() - .AddScoped() - .AddScoped(); - - builder - .AddErrorHandler() - .AddExceptionToMessageMapper() - .AddCommandHandlers() - .AddEventHandlers() - .AddQueryHandlers() - .AddInMemoryCommandDispatcher() - .AddInMemoryEventDispatcher() - .AddInMemoryQueryDispatcher() - .AddJwt() - .AddHttpClient() - .AddRabbitMq() - .AddMessageOutbox(o => o.AddMongo()) - .AddMongo() - .AddRedis() - .AddJaeger() - .AddMetrics() - .AddMongoRepository("refreshTokens") - .AddMongoRepository("users") - .AddWebApiSwaggerDocs(); - - builder.Services.AddSingleton(); - - builder.Services.TryDecorate(typeof(ICommandHandler<>), typeof(LoggingCommandHandlerDecorator<>)); - builder.Services.TryDecorate(typeof(IEventHandler<>), typeof(LoggingEventHandlerDecorator<>)); - builder.Services.TryDecorate(typeof(ICommandHandler<>), typeof(OutboxCommandHandlerDecorator<>)); - builder.Services.TryDecorate(typeof(IEventHandler<>), typeof(OutboxEventHandlerDecorator<>)); - - return builder; - } - - public static long ToUnixTimeMilliseconds(this DateTime dateTime) - => new DateTimeOffset(dateTime).ToUnixTimeMilliseconds(); - - public static IApplicationBuilder UseCore(this IApplicationBuilder app) - { - app.UseMiddleware() - .UseErrorHandler() - .UseJaeger() - .UseSwaggerDocs() - .UseGenocs() - .UseAccessTokenValidator() - .UseMongo() - .UsePublicContracts() - .UseAuthentication() - .UseMetrics() - .UseRabbitMq() - .SubscribeCommand(); - - return app; - } - - public static async Task GetAppName(this HttpContext httpContext) - => await httpContext.Response.WriteAsync(httpContext.RequestServices?.GetService()?.Name ?? string.Empty); - - internal static CorrelationContext GetCorrelationContext(this IHttpContextAccessor accessor) - => accessor.HttpContext?.Request.Headers.TryGetValue("Correlation-Context", out var json) is true - ? JsonConvert.DeserializeObject(json.FirstOrDefault()) - : null; - - internal static string GetSpanContext(this IMessageProperties messageProperties, string header) - { - if (messageProperties is null) - { - return string.Empty; - } - - if (messageProperties.Headers.TryGetValue(header, out var span) && span is byte[] spanBytes) - { - return Encoding.UTF8.GetString(spanBytes); - } - - return string.Empty; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Genocs.Template.Application.csproj b/templates/template/src/Genocs.Template.Application/Genocs.Template.Application.csproj deleted file mode 100644 index 392b215d..00000000 --- a/templates/template/src/Genocs.Template.Application/Genocs.Template.Application.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - net7.0 - enable - enable - - - - - - - - - - - - - - - - - - - diff --git a/templates/template/src/Genocs.Template.Application/Logging/LogContextMiddleware.cs b/templates/template/src/Genocs.Template.Application/Logging/LogContextMiddleware.cs deleted file mode 100644 index 2746e0ad..00000000 --- a/templates/template/src/Genocs.Template.Application/Logging/LogContextMiddleware.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Genocs.HTTP; -using Microsoft.AspNetCore.Http; -using Serilog.Context; - -namespace Genocs.Template.Application.Logging; - -internal class LogContextMiddleware : IMiddleware -{ - private readonly ICorrelationIdFactory _correlationIdFactory; - - public LogContextMiddleware(ICorrelationIdFactory correlationIdFactory) - { - _correlationIdFactory = correlationIdFactory; - } - - public async Task InvokeAsync(HttpContext context, RequestDelegate next) - { - var correlationId = _correlationIdFactory.Create(); - using (LogContext.PushProperty("CorrelationId", correlationId)) - { - await next(context); - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Mongo/Documents/RefreshTokenDocument.cs b/templates/template/src/Genocs.Template.Application/Mongo/Documents/RefreshTokenDocument.cs deleted file mode 100644 index be1c1a40..00000000 --- a/templates/template/src/Genocs.Template.Application/Mongo/Documents/RefreshTokenDocument.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Genocs.Common.Types; -using Genocs.Template.Application.Domain.Entities; - -namespace Genocs.Template.Application.Mongo.Documents; - -public class RefreshTokenDocument : IIdentifiable -{ - public Guid Id { get; set; } - public Guid UserId { get; set; } - public string Token { get; set; } - public DateTime CreatedAt { get; set; } - public DateTime? RevokedAt { get; set; } - - public RefreshTokenDocument() - { - } - - public RefreshTokenDocument(RefreshToken refreshToken) - { - Id = refreshToken.Id; - UserId = refreshToken.UserId; - Token = refreshToken.Token; - CreatedAt = refreshToken.CreatedAt; - RevokedAt = refreshToken.RevokedAt; - } - - public RefreshToken ToEntity() => new RefreshToken(Id, UserId, Token, CreatedAt, RevokedAt); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Mongo/Documents/UserDocument.cs b/templates/template/src/Genocs.Template.Application/Mongo/Documents/UserDocument.cs deleted file mode 100644 index b0d9c7d4..00000000 --- a/templates/template/src/Genocs.Template.Application/Mongo/Documents/UserDocument.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Genocs.Common.Types; -using Genocs.Template.Application.Domain.Entities; - -namespace Genocs.Template.Application.Mongo.Documents; - -public class UserDocument : IIdentifiable -{ - public Guid Id { get; set; } - public string Email { get; set; } - public string Name { get; set; } - public string Role { get; set; } - public string Password { get; set; } - public DateTime CreatedAt { get; set; } - public IEnumerable? Permissions { get; set; } - public bool Locked { get; set; } - - public UserDocument() - { - } - - public UserDocument(User user) - { - Id = user.Id; - Email = user.Email; - Name = user.Name; - Role = user.Role; - Password = user.Password; - CreatedAt = user.CreatedAt; - Permissions = user.Permissions; - Locked = user.Locked; - } - - public User ToEntity() => new User(Id, Email, Name, Password, Role, CreatedAt, Permissions, Locked); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Mongo/Extensions.cs b/templates/template/src/Genocs.Template.Application/Mongo/Extensions.cs deleted file mode 100644 index d7131890..00000000 --- a/templates/template/src/Genocs.Template.Application/Mongo/Extensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Genocs.Persistence.MongoDb.Legacy; -using Genocs.Template.Application.Mongo.Documents; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using MongoDB.Driver; - -namespace Genocs.Template.Application.Mongo; - -public static class Extensions -{ - public static IApplicationBuilder UseMongo(this IApplicationBuilder builder) - { - using var scope = builder.ApplicationServices.CreateScope(); - var users = scope.ServiceProvider.GetService>().Collection; - var userBuilder = Builders.IndexKeys; - Task.Run(async () => await users.Indexes.CreateManyAsync( - new[] - { - new CreateIndexModel(userBuilder.Ascending(i => i.Email), - new CreateIndexOptions - { - Unique = true - }), - new CreateIndexModel(userBuilder.Ascending(i => i.Name), - new CreateIndexOptions - { - Unique = true - }) - })); - - return builder; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/BrowseUsersHandler.cs b/templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/BrowseUsersHandler.cs deleted file mode 100644 index 56560041..00000000 --- a/templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/BrowseUsersHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Genocs.Core.CQRS.Queries; -using Genocs.Persistence.MongoDb.Legacy; -using Genocs.Template.Application.DTO; -using Genocs.Template.Application.Mongo.Documents; -using Genocs.Template.Application.Queries; -using MongoDB.Driver; -using MongoDB.Driver.Linq; - -namespace Genocs.Template.Application.Mongo.Queries.Handlers; - -public class BrowseUsersHandler : IQueryHandler> -{ - private readonly IMongoDatabase _database; - - public BrowseUsersHandler(IMongoDatabase database) - { - _database = database; - } - - public async Task> HandleAsync(BrowseUsers query, CancellationToken cancellationToken = default) - { - var result = await _database.GetCollection("users") - .AsQueryable() - .OrderByDescending(x => x.CreatedAt) - .PaginateAsync(query); - - var pagedResult = PagedResult.From(result, result.Items.Select(x => Map(x))); - return new PagedDto - { - CurrentPage = pagedResult.CurrentPage, - TotalPages = pagedResult.TotalPages, - ResultsPerPage = pagedResult.ResultsPerPage, - TotalResults = pagedResult.TotalResults, - Items = pagedResult.Items - }; - } - - private static UserDto Map(UserDocument user) - => new UserDto - { - Id = user.Id, - Name = user.Name, - CreatedAt = user.CreatedAt, - Locked = user.Locked - }; -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/GetUserHandler.cs b/templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/GetUserHandler.cs deleted file mode 100644 index 4369ec7d..00000000 --- a/templates/template/src/Genocs.Template.Application/Mongo/Queries/Handlers/GetUserHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Genocs.Core.CQRS.Queries; -using Genocs.Persistence.MongoDb.Legacy; -using Genocs.Template.Application.DTO; -using Genocs.Template.Application.Mongo.Documents; -using Genocs.Template.Application.Queries; - -namespace Genocs.Template.Application.Mongo.Queries.Handlers; - -public class GetUserHandler : IQueryHandler -{ - private readonly IMongoRepository _userRepository; - - public GetUserHandler(IMongoRepository userRepository) - { - _userRepository = userRepository; - } - - public async Task HandleAsync(GetUser query, CancellationToken cancellationToken = default) - { - var user = await _userRepository.GetAsync(query.UserId); - - return user is null - ? null - : new UserDetailsDto - { - Id = user.Id, - Email = user.Email, - Name = user.Name, - Role = user.Role, - CreatedAt = user.CreatedAt, - Locked = user.Locked, - Permissions = user.Permissions, - }; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Mongo/Repositories/RefreshTokenRepository.cs b/templates/template/src/Genocs.Template.Application/Mongo/Repositories/RefreshTokenRepository.cs deleted file mode 100644 index a22d49b0..00000000 --- a/templates/template/src/Genocs.Template.Application/Mongo/Repositories/RefreshTokenRepository.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Genocs.Persistence.MongoDb.Legacy; -using Genocs.Template.Application.Domain.Entities; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Mongo.Documents; - -namespace Genocs.Template.Application.Mongo.Repositories; - -public class RefreshTokenRepository : IRefreshTokenRepository -{ - private readonly IMongoRepository _repository; - - public RefreshTokenRepository(IMongoRepository repository) - { - _repository = repository; - } - - public async Task GetAsync(string token) - { - var refreshToken = await _repository.GetAsync(x => x.Token == token); - return refreshToken?.ToEntity(); - } - - public Task AddAsync(RefreshToken refreshToken) - => _repository.AddAsync(new RefreshTokenDocument(refreshToken)); - - public Task UpdateAsync(RefreshToken refreshToken) - => _repository.UpdateAsync(new RefreshTokenDocument(refreshToken)); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Mongo/Repositories/UserRepository.cs b/templates/template/src/Genocs.Template.Application/Mongo/Repositories/UserRepository.cs deleted file mode 100644 index 51312b73..00000000 --- a/templates/template/src/Genocs.Template.Application/Mongo/Repositories/UserRepository.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Genocs.Persistence.MongoDb.Legacy; -using Genocs.Template.Application.Domain.Entities; -using Genocs.Template.Application.Domain.Repositories; -using Genocs.Template.Application.Mongo.Documents; - -namespace Genocs.Template.Application.Mongo.Repositories; - -public class UserRepository : IUserRepository -{ - private readonly IMongoRepository _repository; - - public UserRepository(IMongoRepository repository) - { - _repository = repository; - } - - public async Task GetAsync(AggregateId id) - { - var document = await _repository.GetAsync(id); - return document?.ToEntity(); - } - - public async Task GetByEmailAsync(string email) - { - if (string.IsNullOrWhiteSpace(email)) - { - return null; - } - - var document = await _repository.GetAsync(x => x.Email == email.ToLowerInvariant()); - return document?.ToEntity(); - } - - public async Task GetByNameAsync(string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - return null; - } - - var document = await _repository.GetAsync(x => x.Name == name); - return document?.ToEntity(); - } - - public Task AddAsync(User user) - => _repository.AddAsync(new UserDocument(user)); - - public Task UpdateAsync(User user) - => _repository.UpdateAsync(new UserDocument(user)); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Queries/BrowseUsers.cs b/templates/template/src/Genocs.Template.Application/Queries/BrowseUsers.cs deleted file mode 100644 index 5438c1e5..00000000 --- a/templates/template/src/Genocs.Template.Application/Queries/BrowseUsers.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Genocs.Core.CQRS.Queries; -using Genocs.Template.Application.DTO; - -namespace Genocs.Template.Application.Queries; - -public class BrowseUsers : PagedQueryBase, IQuery> -{ - public Guid? UserId { get; set; } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Queries/GetUser.cs b/templates/template/src/Genocs.Template.Application/Queries/GetUser.cs deleted file mode 100644 index ccbeaaba..00000000 --- a/templates/template/src/Genocs.Template.Application/Queries/GetUser.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Genocs.Core.CQRS.Queries; -using Genocs.Template.Application.DTO; - -namespace Genocs.Template.Application.Queries; - -public class GetUser : IQuery -{ - public Guid UserId { get; set; } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/IJwtProvider.cs b/templates/template/src/Genocs.Template.Application/Services/IJwtProvider.cs deleted file mode 100644 index 36112b9a..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/IJwtProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Genocs.Template.Application.DTO; - -namespace Genocs.Template.Application.Services; - -/// -/// JwtProvider interface definition -/// -public interface IJwtProvider -{ - AuthDto Create(Guid userId, string username, string role, string? audience = null, - IDictionary>? claims = null); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/IMessageBroker.cs b/templates/template/src/Genocs.Template.Application/Services/IMessageBroker.cs deleted file mode 100644 index 94c3d96b..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/IMessageBroker.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Genocs.Core.CQRS.Events; - -namespace Genocs.Template.Application.Services; - -public interface IMessageBroker -{ - Task PublishAsync(params IEvent[] events); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/IPasswordService.cs b/templates/template/src/Genocs.Template.Application/Services/IPasswordService.cs deleted file mode 100644 index 68bd2ea6..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/IPasswordService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Genocs.Template.Application.Services; - -public interface IPasswordService -{ - bool IsValid(string hash, string password); - string Hash(string password); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/IRng.cs b/templates/template/src/Genocs.Template.Application/Services/IRng.cs deleted file mode 100644 index bb649493..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/IRng.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Genocs.Template.Application.Services; - -public interface IRng -{ - string Generate(int length = 50, bool removeSpecialChars = false); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/ITokenStorage.cs b/templates/template/src/Genocs.Template.Application/Services/ITokenStorage.cs deleted file mode 100644 index 57996213..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/ITokenStorage.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Genocs.Template.Application.DTO; - -namespace Genocs.Template.Application.Services; - -public interface ITokenStorage -{ - void Set(Guid commandId, AuthDto token); - AuthDto Get(Guid commandId); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/JwtProvider.cs b/templates/template/src/Genocs.Template.Application/Services/JwtProvider.cs deleted file mode 100644 index fd666cd9..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/JwtProvider.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Genocs.Auth; -using Genocs.Template.Application.DTO; - -namespace Genocs.Template.Application.Services; - -public class JwtProvider : IJwtProvider -{ - private readonly IJwtHandler _jwtHandler; - - public JwtProvider(IJwtHandler jwtHandler) - { - _jwtHandler = jwtHandler; - } - - public AuthDto Create(Guid userId, string username, string role, string audience = null, - IDictionary> claims = null) - { - var jwt = _jwtHandler.CreateToken(userId.ToString("N"), role, audience, claims); - - return new AuthDto - { - UserId = userId, - Username = username, - AccessToken = jwt.AccessToken, - Role = jwt.Role, - Expires = jwt.Expires - }; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/MessageBroker.cs b/templates/template/src/Genocs.Template.Application/Services/MessageBroker.cs deleted file mode 100644 index 818c30b1..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/MessageBroker.cs +++ /dev/null @@ -1,84 +0,0 @@ -using Genocs.Core.CQRS.Events; -using Genocs.Core.Extensions; -using Genocs.HTTP; -using Genocs.MessageBrokers; -using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.RabbitMQ; -using Genocs.Template.Application; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; - -namespace Genocs.Template.Application.Services; - -internal class MessageBroker : IMessageBroker -{ - private const string DefaultSpanContextHeader = "span_context"; - private readonly IBusPublisher _busPublisher; - private readonly IMessageOutbox _outbox; - private readonly ICorrelationContextAccessor _contextAccessor; - private readonly IHttpContextAccessor _httpContextAccessor; - private readonly IMessagePropertiesAccessor _messagePropertiesAccessor; - private readonly ICorrelationIdFactory _correlationIdFactory; - private readonly ILogger _logger; - private readonly string _spanContextHeader; - - public MessageBroker(IBusPublisher busPublisher, IMessageOutbox outbox, - ICorrelationContextAccessor contextAccessor, IHttpContextAccessor httpContextAccessor, - IMessagePropertiesAccessor messagePropertiesAccessor, ICorrelationIdFactory correlationIdFactory, - RabbitMQOptions options, ILogger logger) - { - if (options is null) - { - throw new ArgumentNullException(nameof(options)); - } - - _busPublisher = busPublisher ?? throw new ArgumentNullException(nameof(busPublisher)); - _outbox = outbox ?? throw new ArgumentNullException(nameof(outbox)); - _contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor)); - _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); - _messagePropertiesAccessor = messagePropertiesAccessor ?? throw new ArgumentNullException(nameof(messagePropertiesAccessor)); - _correlationIdFactory = correlationIdFactory ?? throw new ArgumentNullException(nameof(correlationIdFactory)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _spanContextHeader = string.IsNullOrWhiteSpace(options.SpanContextHeader) - ? DefaultSpanContextHeader - : options.SpanContextHeader; - } - - public Task PublishAsync(params IEvent[] events) => PublishAsync(events?.AsEnumerable()); - - private async Task PublishAsync(IEnumerable? events) - { - if (events is null) - { - return; - } - - var messageProperties = _messagePropertiesAccessor.MessageProperties; - var originatedMessageId = messageProperties?.MessageId; - var correlationId = _correlationIdFactory.Create(); - var spanContext = messageProperties?.GetSpanContext(_spanContextHeader); - var correlationContext = _contextAccessor.CorrelationContext ?? - _httpContextAccessor.GetCorrelationContext(); - var headers = new Dictionary(); - - foreach (var @event in events) - { - if (@event is null) - { - continue; - } - - var messageId = Guid.NewGuid().ToString("N"); - _logger.LogTrace($"Publishing integration event: {@event.GetType().Name.Underscore()} [ID: '{messageId}']."); - if (_outbox.Enabled) - { - await _outbox.SendAsync(@event, originatedMessageId, messageId, correlationId, spanContext, - correlationContext, headers); - continue; - } - - await _busPublisher.PublishAsync(@event, messageId, correlationId, spanContext, correlationContext, - headers); - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/PasswordService.cs b/templates/template/src/Genocs.Template.Application/Services/PasswordService.cs deleted file mode 100644 index 3f02065e..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/PasswordService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.AspNetCore.Identity; - -namespace Genocs.Template.Application.Services; - -public class PasswordService : IPasswordService -{ - private readonly IPasswordHasher _passwordHasher; - - public PasswordService(IPasswordHasher passwordHasher) - { - _passwordHasher = passwordHasher; - } - - public bool IsValid(string hash, string password) - => _passwordHasher.VerifyHashedPassword(this, hash, password) != PasswordVerificationResult.Failed; - - public string Hash(string password) - => _passwordHasher.HashPassword(this, password); -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/Rng.cs b/templates/template/src/Genocs.Template.Application/Services/Rng.cs deleted file mode 100644 index 669bd2c5..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/Rng.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Security.Cryptography; - -namespace Genocs.Template.Application.Services; - -public class Rng : IRng -{ - private static readonly string[] SpecialChars = new[] { "/", "\\", "=", "+", "?", ":", "&" }; - - public string Generate(int length = 50, bool removeSpecialChars = true) - { - using var rng = RandomNumberGenerator.Create(); - var bytes = new byte[length]; - rng.GetBytes(bytes); - var result = Convert.ToBase64String(bytes); - - return removeSpecialChars - ? SpecialChars.Aggregate(result, (current, chars) => current.Replace(chars, string.Empty)) - : result; - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.Application/Services/TokenStorage.cs b/templates/template/src/Genocs.Template.Application/Services/TokenStorage.cs deleted file mode 100644 index 7736e8f8..00000000 --- a/templates/template/src/Genocs.Template.Application/Services/TokenStorage.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Genocs.Template.Application.DTO; -using Microsoft.Extensions.Caching.Memory; - -namespace Genocs.Template.Application.Services; - -internal class TokenStorage : ITokenStorage -{ - private readonly IMemoryCache _cache; - - public TokenStorage(IMemoryCache cache) - { - _cache = cache ?? throw new ArgumentNullException(nameof(cache)); - } - - public void Set(Guid commandId, AuthDto token) - => _cache.Set(GetKey(commandId), token); - - public AuthDto Get(Guid commandId) - => _cache.Get(GetKey(commandId)); - - private static string GetKey(Guid commandId) - => $"users:tokens:{commandId}"; -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.IntegrationTests/Genocs.Template.IntegrationTests.csproj b/templates/template/src/Genocs.Template.IntegrationTests/Genocs.Template.IntegrationTests.csproj deleted file mode 100644 index eebf48e5..00000000 --- a/templates/template/src/Genocs.Template.IntegrationTests/Genocs.Template.IntegrationTests.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net7.0 - false - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.UnitTests/Genocs.Template.UnitTests.csproj b/templates/template/src/Genocs.Template.UnitTests/Genocs.Template.UnitTests.csproj deleted file mode 100644 index 55972e5c..00000000 --- a/templates/template/src/Genocs.Template.UnitTests/Genocs.Template.UnitTests.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - net7.0 - false - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - diff --git a/templates/template/src/Genocs.Template.WebApi/Genocs.Template.WebApi.csproj b/templates/template/src/Genocs.Template.WebApi/Genocs.Template.WebApi.csproj deleted file mode 100644 index 4fe6f236..00000000 --- a/templates/template/src/Genocs.Template.WebApi/Genocs.Template.WebApi.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - net7.0 - enable - enable - __genocs - Linux - ..\.. - - - - - - - - - - - - - - - - - - - - - diff --git a/templates/template/src/Genocs.Template.WebApi/Program.cs b/templates/template/src/Genocs.Template.WebApi/Program.cs deleted file mode 100644 index 1b370866..00000000 --- a/templates/template/src/Genocs.Template.WebApi/Program.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Genocs.Core.Builders; -using Genocs.Logging; -using Genocs.Template.Application; -using Genocs.Template.Application.Commands; -using Genocs.Template.Application.DTO; -using Genocs.Template.Application.Queries; -using Genocs.Template.Application.Services; -using Genocs.WebApi; -using Genocs.WebApi.CQRS; -using Serilog; -using Serilog.Events; - -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel.Override("MassTransit", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); - - -var builder = WebApplication.CreateBuilder(args); - -builder.Host - .UseLogging(); -// .UseVault(); - - -var services = builder.Services; - -services.AddGenocs(builder.Configuration) - .AddWebApi() - .AddCore() - .Build(); - -var app = builder.Build(); - -app.UseCore(); -app.UseDispatcherEndpoints(endpoints => endpoints - .Get("", ctx => ctx.GetAppName()) - .Post("sign-in", afterDispatch: (cmd, ctx) => - { - var auth = ctx.RequestServices.GetRequiredService().Get(cmd.Id); - return ctx.Response.WriteJsonAsync(auth); - }) - .Post("sign-up", afterDispatch: (cmd, ctx) => - { - ctx.Response.Headers.Add("user-id", cmd.UserId.ToString()); - return Task.CompletedTask; - }) - .Post("access-tokens/revoke") - .Post("refresh-tokens/use", afterDispatch: (cmd, ctx) => - { - var auth = ctx.RequestServices.GetRequiredService().Get(cmd.Id); - return ctx.Response.WriteJsonAsync(auth); - }) - .Post("refresh-tokens/revoke") - .Get("users/{userId:guid}") - .Get>("users") - .Put("users/{userId:guid}/lock") - .Put("users/{userId:guid}/unlock")); - -app.Run(); - -Log.CloseAndFlush(); diff --git a/templates/template/src/Genocs.Template.WebApi/Properties/launchSettings.json b/templates/template/src/Genocs.Template.WebApi/Properties/launchSettings.json deleted file mode 100644 index 29653af1..00000000 --- a/templates/template/src/Genocs.Template.WebApi/Properties/launchSettings.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:61699/", - "sslPort": 44323 - } - }, - "profiles": { - "Genocs.Template.WebApi": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "applicationUrl": "https://localhost:5271;http://localhost:5270" - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.WebApi/appsettings.Docker.json b/templates/template/src/Genocs.Template.WebApi/appsettings.Docker.json deleted file mode 100644 index b12f449a..00000000 --- a/templates/template/src/Genocs.Template.WebApi/appsettings.Docker.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "MongoDb": { - "ConnectionString": "mongodb://mongodb" - }, - "Monitoring": { - "Jaeger": "jaeger" - }, - "jaeger": { - "udpHost": "jaeger" - }, - "metrics": { - "influxUrl": "http://influxdb:8086" - }, - "mongo": { - "connectionString": "mongodb://mongodb:27017" - }, - "redis": { - "connectionString": "redis" - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.WebApi/appsettings.json b/templates/template/src/Genocs.Template.WebApi/appsettings.json deleted file mode 100644 index 57681800..00000000 --- a/templates/template/src/Genocs.Template.WebApi/appsettings.json +++ /dev/null @@ -1,241 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Information", - "Microsoft": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "MongoDb": { - "ConnectionString": "mongodb://localhost", - "Database": "placeholder" - }, - "Monitoring": { - "Jaeger": "localhost" - }, - "app": { - "name": "genocs.template Service", - "service": "genocs.template-service", - "instance": "000001", - "version": "v1.0", - "displayBanner": true, - "displayVersion": true - }, - "consul": { - "enabled": false, - "url": "http://localhost:8500", - "service": "genocs.template-service", - "address": "docker.for.win.localhost", - "port": "5070", - "pingEnabled": true, - "pingEndpoint": "ping", - "pingInterval": 3, - "removeAfterInterval": 3 - }, - "fabio": { - "enabled": false, - "url": "http://localhost:9999", - "service": "genocs.template-service" - }, - "httpClient": { - "type": "fabio", - "retries": 3, - "services": {}, - "requestMasking": { - "enabled": true, - "maskTemplate": "*****" - }, - "correlationIdHeader": "x-correlation-id" - }, - "logger": { - "level": "information", - "excludePaths": [ - "/", - "/ping", - "/metrics" - ], - "excludeProperties": [ - "api_key", - "access_key", - "ApiKey", - "ApiSecret", - "ClientId", - "ClientSecret", - "ConnectionString", - "Password", - "Email", - "Login", - "Secret", - "Token" - ], - "console": { - "enabled": true - }, - "elk": { - "enabled": false, - "url": "http://localhost:9200" - }, - "file": { - "enabled": true, - "path": "logs/logs.txt", - "interval": "day" - }, - "seq": { - "enabled": false, - "url": "http://localhost:5341", - "apiKey": "secret" - }, - "azure": { - "enabled": false, - "connectionString": "" - }, - "tags": {} - }, - "jaeger": { - "enabled": true, - "serviceName": "genocs.template", - "udpHost": "localhost", - "udpPort": 6831, - "maxPacketSize": 65000, - "sampler": "const", - "excludePaths": [ - "/", - "/ping", - "/metrics" - ] - }, - "jwt": { - "certificate": { - "location": "certs/localhost.pfx", - "password": "test", - "rawData": "" - }, - "issuer": "genocs-identity-service", - "validIssuer": "genocs-identity-service", - "validateAudience": false, - "validateIssuer": true, - "validateLifetime": true, - "expiry": "01:00:00" - }, - "metrics": { - "enabled": true, - "influxEnabled": false, - "prometheusEnabled": false, - "influxUrl": "http://localhost:8086", - "database": "test", - "env": "local", - "interval": 5 - }, - "prometheus": { - "enabled": false, - "endpoint": "/metrics" - }, - "mongo": { - "connectionString": "mongodb://localhost:27017", - "database": "placeholder-service", - "seed": false - }, - "outbox": { - "enabled": true, - "type": "sequential", - "expiry": 3600, - "intervalMilliseconds": 2000, - "inboxCollection": "inbox", - "outboxCollection": "outbox", - "disableTransactions": true - }, - "rabbitMq": { - "connectionName": "genocs.template-service", - "retries": 3, - "retryInterval": 2, - "conventionsCasing": "snakeCase", - "logger": { - "enabled": true - }, - "username": "guest", - "password": "guest", - "virtualHost": "/", - "port": 5672, - "hostnames": [ - "localhost", - "rabbitmq" - ], - "requestedConnectionTimeout": "00:00:30", - "requestedHeartbeat": "00:01:00", - "socketReadTimeout": "00:00:30", - "socketWriteTimeout": "00:00:30", - "continuationTimeout": "00:00:20", - "handshakeContinuationTimeout": "00:00:10", - "networkRecoveryInterval": "00:00:05", - "exchange": { - "declare": true, - "durable": true, - "autoDelete": false, - "type": "topic", - "name": "genocs.template" - }, - "queue": { - "declare": true, - "durable": true, - "exclusive": false, - "autoDelete": false, - "template": "genocs.template-service/{{exchange}}.{{message}}" - }, - "context": { - "enabled": true, - "header": "message_context" - }, - "spanContextHeader": "span_context" - }, - "redis": { - "connectionString": "localhost", - "instance": "genocs.template-service:", - "database": 0 - }, - "swagger": { - "enabled": true, - "reDocEnabled": false, - "name": "v1", - "title": "Genocs.Template API", - "version": "v1", - "routePrefix": "swagger", - "includeSecurity": true - }, - "security": { - "certificate": { - "header": "Certificate" - } - }, - "vault": { - "enabled": false, - "url": "http://localhost:8200", - "authType": "token", - "token": "secret", - "username": "user", - "password": "secret", - "kv": { - "enabled": true, - "engineVersion": 2, - "mountPoint": "kv", - "path": "genocs.template-service/settings" - }, - "pki": { - "enabled": true, - "roleName": "genocs.template-service", - "commonName": "genocs.template-service.demo.io" - }, - "lease": { - "mongo": { - "type": "database", - "roleName": "genocs.template-service", - "enabled": true, - "autoRenewal": true, - "templates": { - "connectionString": "mongodb://{{username}}:{{password}}@localhost:27017" - } - } - } - } -} \ No newline at end of file diff --git a/templates/template/src/Genocs.Template.WebApi/certs/localhost.cer b/templates/template/src/Genocs.Template.WebApi/certs/localhost.cer deleted file mode 100644 index 31fc2df7..00000000 --- a/templates/template/src/Genocs.Template.WebApi/certs/localhost.cer +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDCTCCAfGgAwIBAgIUFLglzcz4ySPop6UDOY4VfocxoSowDQYJKoZIhvcNAQEL -BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIwMDMwMTExMjU1MloXDTIxMDMw -MTExMjU1MlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAs7oyRinTJp0bER/BMpO/zNiNlW/KXQsP+RKxHCTd4Sjq -X9bdp1IkqMQtDJnxCMHjfmKkPEXLa7BlrmkMXZ3r54ociq0tbUa/S7S6s3oN17Ov -IwM3ohT+eXccTPx1UbrX8hrFfKabIp1e8ARJNsr+UJ1TeQc4h8rZLoCa0JbMXMyQ -bqZ1X8C6hOpKzgB+SwmsIm2w5eRqnbvxwXNS5hyxfL8r6XRObbJNb36xGE0WBjy9 -DIIiChlq8VOldqNBqGjRpN7bIxnVpSLeKq4Y2+jMPeoC9gr2Ncsjbrddac6ePUXj -UebC2Yb/5rL2PyebEWBmVa+OMN1QopQYhyI5hE+oswIDAQABo1MwUTAdBgNVHQ4E -FgQUpKJM7NhUzpmzGare25X3rNoml40wHwYDVR0jBBgwFoAUpKJM7NhUzpmzGare -25X3rNoml40wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAfAFt -SUYlg1zSFmpt5338EJRaTCu0wmXeg+Hn73Bdi3Pa6qh3v+sgaRGzdJXdBLHZhhWB -h+gMRrJQ+ALNzh2vcPH6gS/du4tfFHfRufI2GalN+o95UUiiDmen9yGkyYsuEQp/ -mKYpLHvzsj6Qsx6++N7eI5nQ2d88OE753YPxZbWTUOr1voGodKCgJB36e5Rh2Lvs -Uqn8ePtKPewqjfcKE3wCcN5HNpiC+GyK9SkzPGDuh4VGzZCMA83vuWrYNOE5rMOs -G8NGFdqZ4Pk8wT4RQhJkPEAT0yravTaFE0rOc0pxF5l4PA1FCVmtjOyYZgj7JUeA -zPKUtgIPz28SUzsFdw== ------END CERTIFICATE----- diff --git a/templates/template/src/Genocs.Template.WebApi/certs/localhost.key b/templates/template/src/Genocs.Template.WebApi/certs/localhost.key deleted file mode 100644 index 270c4a91..00000000 --- a/templates/template/src/Genocs.Template.WebApi/certs/localhost.key +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIm5Ia64KZKmwCAggA -MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECO2HnxA2BhMEBIIEyE7V/k2Dt0oB -h4b3WlT6VR2sXWn8n83oWS8GP+XcwrFIS0LWGPtUImh2rxdytXC9pPIoDvZbcKyx -t+UQaEYPZWIn2HM83V5yaNc2WtBXzTpfTH6sMEDkWFtqTuOSrjLaI63kldjLJ0dv -aEa8zHmPO7KEtMawKY1vucJFL5aU1IX5b7YXfgeI9iV7V0qktjQtOlQxJARwh1JV -Vo6VVzArNIiC+Ul39xgtMYe9UcSMJsSFOCQYPsiGX0c2XSz26i+G3W19+QXCZUtm -0eqRxF/BRf95siUu4Yd1Rv4+oUCF4Lio16NHEZ/yGIzfya4QeW0YBtE8KHfM6g9e -HcmaJBhF5NLukfCoGbrZpBg//7ZrMypo8D6U9p5pV7oXyHpm0imCjs/liFDHve6v -szTXFlMgqpMyKliBL/EalDhDXBftvOnKItpO8o42Y/XvmDQ2E/B6tRg04hEWoHH5 -XSE5240BgZCmF277/ulY7d7UCXjV//NiVjSwEurMx5km91M1qXgxhiPOeACg4cho -SaVwG+Oii0M8qBvHIk8F3MHMt3fJJ7RGkI0GZzUrAO2NZgMyChuhq3xj9nn/PdNl -Qv3xTwowciiH50nw6L3pXGAqG/4oqei47M6GoUNf5AH8oy0C4p5i1mWkt36T90GO -b7+sTn2CV1mgzdwO8FwdAhZhkANOlB54ocx23At7FHQOMRQ4yQ9ULv4P9zQeolvN -BWjZtD3qhOL8UeSc8syzBfmcOAURpA0WAw44xC5d7sUJuNQ/anRyukoX3Gl1Z2On -GA7q7qzjs2UPFV82dYyoSTcLHTvdRPFtNkfmFPtN/LH6Q30IOZNB85cyDH5d9X+G -x+6rxD2PCKx/8+5XvHZ7d8I4+0+3Jk/TvOsudKHZsXt2mlvIa65jat11OY+uu+59 -sNiT/gc5EhhErwmjj8swKCV0IdhMHzv4PySbsYzky+kv4sQBlRAUhOcHBQ/53BHm -5iee27rMy+SyzGC2sEgQguGKrdvFSe590wE6aoMFXmf/3QwiiVbzRGh19RJQZElL -hzGLdjEdw1if7o4jvSVuxbtpSPycxphmwDSBh/4HszRr2CAD29xGtI/PnATGlZaP -W8BjC3dAMfN1/YHgD5Y8N1VbFCcxNMRvwzoVLHA1ZtxKOoAmlv3FNIb7o5O6DV82 -QMoWXrlApaBHeHlQCo5ieW/3Pua6Xw3gZConlONqFY1snhfPS3x8Qjh1ETqHokTx -WFCJ/JeE6ZOJVPzjEthnDWuUZ6r8iclLmWN/LV5UfROMUErJSwIPTqORLA6gbLUa -nf0kXTPlTONRsyaqubc8Jbdzf/vwlbT5TG6Sbbul7WmF4Y8mT+hfWMfpuwzXepyR -AMbe+E06zMEtV++hEoArhvB9p02e+Ejb9lRGKiAd0GAdk2xEP5cdd4GUIuE1HFp5 -tQrxriM6lF1tdS6eosb7q870zBpyq22gFKi/JWVrWuArwhBFiNOppc4psm0t9mQC -EQnY2t2lvq34bEMVnbT4MPeiynvacHxJAqcfIVZaHsylLWRpPZFLN8zUBB5FqO0t -y0qda8AUqVKoUYRyaqjwg2gmoELRjqvf8caaQi6cmX7nJRoCM0yTV7KzFJ01J0e/ -eNf8bCYpVnYCrPjwexMCwA== ------END ENCRYPTED PRIVATE KEY----- diff --git a/templates/template/src/Genocs.Template.WebApi/certs/localhost.pem b/templates/template/src/Genocs.Template.WebApi/certs/localhost.pem deleted file mode 100644 index 00d8bbb6..00000000 --- a/templates/template/src/Genocs.Template.WebApi/certs/localhost.pem +++ /dev/null @@ -1,56 +0,0 @@ -Bag Attributes - localKeyID: 7A 10 75 44 7E 71 45 11 36 D7 89 60 43 3D BA 90 F8 61 62 27 -subject=CN = localhost - -issuer=CN = localhost - ------BEGIN CERTIFICATE----- -MIIDCTCCAfGgAwIBAgIUFLglzcz4ySPop6UDOY4VfocxoSowDQYJKoZIhvcNAQEL -BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIwMDMwMTExMjU1MloXDTIxMDMw -MTExMjU1MlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAs7oyRinTJp0bER/BMpO/zNiNlW/KXQsP+RKxHCTd4Sjq -X9bdp1IkqMQtDJnxCMHjfmKkPEXLa7BlrmkMXZ3r54ociq0tbUa/S7S6s3oN17Ov -IwM3ohT+eXccTPx1UbrX8hrFfKabIp1e8ARJNsr+UJ1TeQc4h8rZLoCa0JbMXMyQ -bqZ1X8C6hOpKzgB+SwmsIm2w5eRqnbvxwXNS5hyxfL8r6XRObbJNb36xGE0WBjy9 -DIIiChlq8VOldqNBqGjRpN7bIxnVpSLeKq4Y2+jMPeoC9gr2Ncsjbrddac6ePUXj -UebC2Yb/5rL2PyebEWBmVa+OMN1QopQYhyI5hE+oswIDAQABo1MwUTAdBgNVHQ4E -FgQUpKJM7NhUzpmzGare25X3rNoml40wHwYDVR0jBBgwFoAUpKJM7NhUzpmzGare -25X3rNoml40wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAfAFt -SUYlg1zSFmpt5338EJRaTCu0wmXeg+Hn73Bdi3Pa6qh3v+sgaRGzdJXdBLHZhhWB -h+gMRrJQ+ALNzh2vcPH6gS/du4tfFHfRufI2GalN+o95UUiiDmen9yGkyYsuEQp/ -mKYpLHvzsj6Qsx6++N7eI5nQ2d88OE753YPxZbWTUOr1voGodKCgJB36e5Rh2Lvs -Uqn8ePtKPewqjfcKE3wCcN5HNpiC+GyK9SkzPGDuh4VGzZCMA83vuWrYNOE5rMOs -G8NGFdqZ4Pk8wT4RQhJkPEAT0yravTaFE0rOc0pxF5l4PA1FCVmtjOyYZgj7JUeA -zPKUtgIPz28SUzsFdw== ------END CERTIFICATE----- -Bag Attributes - localKeyID: 7A 10 75 44 7E 71 45 11 36 D7 89 60 43 3D BA 90 F8 61 62 27 -Key Attributes: ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCzujJGKdMmnRsR -H8Eyk7/M2I2Vb8pdCw/5ErEcJN3hKOpf1t2nUiSoxC0MmfEIweN+YqQ8RctrsGWu -aQxdnevnihyKrS1tRr9LtLqzeg3Xs68jAzeiFP55dxxM/HVRutfyGsV8ppsinV7w -BEk2yv5QnVN5BziHytkugJrQlsxczJBupnVfwLqE6krOAH5LCawibbDl5Gqdu/HB -c1LmHLF8vyvpdE5tsk1vfrEYTRYGPL0MgiIKGWrxU6V2o0GoaNGk3tsjGdWlIt4q -rhjb6Mw96gL2CvY1yyNut11pzp49ReNR5sLZhv/msvY/J5sRYGZVr44w3VCilBiH -IjmET6izAgMBAAECggEAFSTMkVCOVLaa3pLbybV0FQdM8M2sAvIwON8oEuWLbNfB -avD+NpcFVQ1vN1JM9vjIaK/2Hlkfq1WfQLt/BuxzOlQXM4FYHMj77E4gwMiVJFEx -Q283dkv9/BA1NiFlM+5FRWg834NCMPpOlvIKIvYSoS1BCrX8wozsq/nZPLzg4fHE -U+vYXYtydYqZ4iurlQ0Bmpwi7qJgDYHNOxQ64g2u1Memy48vOb29vP00dNeCceaL -blzR/x8hd0VvkvzsDgxFaPKDRb62Pu/P3YY8uKzK50WZ1EqW/SRUG5vzYDu14vLZ -Vu/Wlqs4CJ1MxwweKOQoQFeGghzr3+HFvFOYjbWw8QKBgQDoCqK4L0hDfOn6q3wl -G8SpiE6maSnBpUhYqxK9PE3dOYRQfx4of1RfSGVcSHROvrCGCwtQzoWcJeJE0zcS -m4ykddUTomSZvsPi2LcdNtjr3yi4irmVU5UoqhxYx1eghF0sIzxKNsUe6i2fB7sE -2r70ZRwrJvlUWo2dTa5IMr5mTwKBgQDGSMgphRRjm4Xgi4WNSlgdHHzBvuTOS5ko -9nQLD9tqyuJIrniWZPAtJiNPkG3R7Jpyvfxqs6ux5OnP7EFABK5fnODdeZpW33Z2 -mBZirbYKml88rS4S3S/DHurfksGx/wK81YIcgxZkWHNdUH8TBoqQI3N7sA97jrHC -JOOLRhIiXQKBgCD6Mfn/LkP5Ir+vU2tqsN5vMs5Pr9GHjeqcFYOzaFWCcR2Hk1+q -CPGptk4RNgZi7299blRDpZV1hNzHL9KDLM/Kt0edErMO+4PnzM5oFxgelQj1Hj7s -rAwlcPXlDr0PUraNI2pgsk8cdPNfA+NCu1S8ce5oEZM9c1bhzV0RaSHdAoGBAJIf -xuraOPli/plJGOXT+PWTLdl2PZZOHhQS89fHGtMrqvEXKqTixCDxryoObPA8ZmHS -4vcba5eQ9EIXgMqV6I9rxEdTO0t0KRAi6rRUAgj0VOUZVw/t0yn/WeXjeD0dij3x -No6eiFzw1ivZi5xQwMKSbaOkTvSmZxeFKe9Udz69AoGBAM6T1tO0oh7LoqNuXNZb -fA3BiY9Rosr4glEXpJ16LdYXoQOX6pRgk7/itqr9hrLmJxNgFtoXFiKVLRQsxaYr -ffCaiy89SzO/6tSxMRNM8cdMQ2TF7U5O5JR/MICbAaS6/Gw7n5kx90DR3/tZWTeD -AY3jOFQRNNbeE+hTZB1kL61i ------END PRIVATE KEY----- diff --git a/templates/template/src/Genocs.Template.WebApi/certs/localhost.pfx b/templates/template/src/Genocs.Template.WebApi/certs/localhost.pfx deleted file mode 100644 index 8e1885b6b2f9035bd3cda9e0e935af3e58c8152f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2381 zcmV-T39|Muf(c0i0Ru3C2@eJdDuzgg_YDCD0ic2j00e>v{4jzD_%MP4uLcP!hDe6@ z4FLxRpn?OSFoFY|0s#Opf&-NX2`Yw2hW8Bt2LUh~1_~;MNQUP%l~lMKh`H)M^dkX^6?SJCmaoE1rv+`NjJ`y4yfyola;C={Ww4K zHN*CKt+q9{3!s6QqdJ_uc`8DaPx)0@ ze%;&_0Ox=tfJUTK3xO_K2T32T@o>KX7h`;9;v&&zR*aM9{w)lZ%$93q@R7*8MpFq# zV?RJ&V;aLfvugp}!3n6Bk=LBUP%ga?eR8@1Yz_qo#e2~;N6;b^==XEjzWmpK^)~aH*=-cdph+- zS@9brKGEuYznHv0pFd4pt55EQ3DuF0`JnR3MSzZ#1Y?H$-?&UB2B{m-efDv~(-nK7 zsOQb4Es`WVK*YIzP)E2DL**%21(n;fqTq2c;0g2fL7YJ;nyZAv_W`jHc_9&7Fc;=v zXIiDk*>ib)S`w2B`Z*K%^bHGa#9n_*2%I|7IOY7$BdatqsDznnqfL6 zGbx7t_hl!)YE8sWAYMb_QYNQCtsonSiIs6&vDyZDXMXTr`u8JUeCx}~?ZNbo2Q^sh z$m)WIb92L$CeCGi_au2Owt^R_EaBJ$+(|V`YMAzs^+l)9cUvxy$hyN(7|?NZ)uv>; z5KnCRCiSq8w16pe;Y7`l=nvaWKBZM4&llum^I7p9)RFUF?(2O(3Q(`|;+=g`yJ^^F z+*+dE!A}%+Rxu#;|Hn3Lz`k2Ux$bJgB}Heu&A>y}XXf;eS?gZwj-sihGRMHEZx?Er z6^rWS?2WP4LSO#Aq}6Q%L60qKpnaWwZ-R{${8p5Y;&LNQU-9zY6uRSa1jJO;xdQ-_)qr}VHT_; zc?P}Tj9CArG%+5r$a~;pliUh^u4YNS(v_L+czTAtG@s!R#IjFnkAj^!(4JH$tcqM* z*}DK>3Zryp>*=uk?)B%;k-GItHOr-b^`e&NF-V8HU2#R-!ukqzm{V6xmjiVYN->1Qy)A4}5rZ_Ls46g%s)N}#NsL;$+}q!4 zTwXB~voerBO~yIIzd>GUT>WEKSr{k-H^o8dD$EcaVp&}3WEmD$1Hl3p6=RpOyY*vr zsa7YAkNOSCE{PeAvjn*?LK*iL)XPy#Q(;#|FdXHI;>#l9lUO;N0X1FeJg~))1``5DNkanoUYIUtO1ppMyc_<1o6h~ZG!>e_hF0Lhhy`?I7 z;lQm=;28+xt&gQ^ekBK8#7wC{Q{dFF{$*1=$|EDD+B)MVSF(^hL(FwAi-427orWqX zH=d9chv^Cf43vP>M<=P3R=)p>(rLkV6yePl z4*H7G9tze4LZ+)z$37e_PeoYju`v&(klV+45iJjWrrh@I1i<=-SC4ff+fXV1^#o#A zvEsJAAqv0Oe{qM;tJA_u5^<@fxQK`Wh4y0C-o$U)UNYVH;wOk^N((}e7tmk7&ZY|* zMCBqV@TD1$#KKN71()eNN7^sa9JrklHeK- zaEF~3K#fGWd#nohGQ405kWgu!w-|kREyHvB;@#*8h!b_883BaxAov1*cB-*QF!*l~ z6ZZVP{4+_7X9R99@Mg(HL%us8(GB_Tl!8@YPwq0&RHZQ`rPG5~7Ev`Z!>xjHDz}G# zHIs)}$fSH!;IhU2afjjMISTtK*XBNXZV|wZSSGe+cS}~MF3C73s(DXBi*lC=o*A6J z+pgyF Date: Sat, 25 Nov 2023 10:22:38 +0100 Subject: [PATCH 007/104] File updates --- .github/workflows/nuget-publish.yml | 2 +- Directory.Build.props | 11 +- src/Genocs.Auth/Genocs.Auth.csproj | 131 +++++++------- src/Genocs.Auth/README.md | 7 +- src/Genocs.Common/Genocs.Common.csproj | 92 +++++----- src/Genocs.Common/README.md | 3 + .../Genocs.Core.Demo.Contracts.csproj | 38 ++-- .../Genocs.Core.Demo.Domain.csproj | 42 ++--- .../Genocs.Core.Demo.Infrastructure.csproj | 26 +-- .../Genocs.Core.Demo.WebApi.csproj | 58 +++---- .../Genocs.Core.Demo.Worker.csproj | 82 ++++----- .../Genocs.Core.UnitTests.csproj | 51 +++--- src/Genocs.Core/Genocs.Core.csproj | 147 ++++++++-------- src/Genocs.Core/README.md | 3 + .../Genocs.Discovery.Consul.csproj | 114 ++++++------ .../Genocs.HTTP.RestEase.csproj | 126 +++++++------- src/Genocs.HTTP.RestEase/README.md | 3 + src/Genocs.HTTP/Genocs.HTTP.csproj | 112 ++++++------ src/Genocs.HTTP/README.md | 3 + .../Genocs.LoadBalancing.Fabio.csproj | 112 ++++++------ src/Genocs.LoadBalancing.Fabio/README.md | 3 + src/Genocs.Logging/Genocs.Logging.csproj | 133 +++++++------- src/Genocs.Logging/README.md | 3 + ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 108 ++++++------ .../README.md | 3 + .../Genocs.MessageBrokers.Outbox.csproj | 104 +++++------ src/Genocs.MessageBrokers.Outbox/README.md | 3 + .../Genocs.MessageBrokers.RabbitMQ.csproj | 118 ++++++------- src/Genocs.MessageBrokers.RabbitMQ/README.md | 3 + .../Genocs.MessageBrokers.csproj | 104 +++++------ src/Genocs.MessageBrokers/README.md | 3 + src/Genocs.Metrics/Genocs.Metrics.csproj | 164 +++++++++--------- src/Genocs.Metrics/README.md | 3 + .../Genocs.Monitoring.csproj | 124 ++++++------- ...enocs.Persistence.MongoDB.UnitTests.csproj | 70 ++++---- .../Genocs.Persistence.MongoDb.csproj | 112 ++++++------ .../Genocs.Persistence.Redis.csproj | 110 ++++++------ src/Genocs.Persistence.Redis/README.md | 3 + .../Genocs.QueryBuilder.UnitTests.csproj | 70 ++++---- .../Genocs.QueryBuilder.csproj | 92 +++++----- src/Genocs.QueryBuilder/README.md | 3 + .../Genocs.Secrets.Vault.csproj | 112 ++++++------ src/Genocs.Secrets.Vault/README.md | 3 + src/Genocs.Security/Genocs.Security.csproj | 104 +++++------ src/Genocs.Security/README.md | 3 + .../Genocs.ServiceBusAzure.UnitTests.csproj | 50 +++--- .../Genocs.ServiceBusAzure.csproj | 116 ++++++------- src/Genocs.ServiceBusAzure/README.md | 3 + .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 8 +- src/Genocs.Tracing.Jaeger.RabbitMQ/README.md | 3 + src/Genocs.Tracing/Genocs.Tracing.csproj | 133 +++++++------- src/Genocs.Tracing/README.md | 3 + .../Genocs.WebApi.CQRS.csproj | 118 +++++++------ src/Genocs.WebApi.CQRS/README.md | 3 + .../Genocs.WebApi.Security.csproj | 123 ++++++------- src/Genocs.WebApi.Security/README.md | 3 + .../Genocs.WebApi.Swagger.csproj | 119 ++++++------- src/Genocs.WebApi.Swagger/README.md | 3 + src/Genocs.WebApi/Genocs.WebApi.csproj | 120 ++++++------- src/Genocs.WebApi/README.md | 3 + .../Genocs.APIGateway.csproj | 110 ++++++------ .../Genocs.Identities.Application.csproj | 88 +++++----- .../Genocs.Identities.WebApi.csproj | 62 +++---- .../Genocs.Orders.WebApi.csproj | 100 +++++------ .../Genocs.Products.WebApi.csproj | 108 ++++++------ .../Genocs.SignalR.WebApi.csproj | 110 ++++++------ 66 files changed, 2092 insertions(+), 2015 deletions(-) diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index f872f6a2..d3699f74 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -13,7 +13,7 @@ on: description: "Packages Version" # Default value if no value is explicitly provided - default: "5.0.0-preview.5.0" + default: "5.0.0" # Input has to be provided for the workflow to run required: true diff --git a/Directory.Build.props b/Directory.Build.props index 14757c4d..6d96d9df 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,18 +1,19 @@ - $(MSBuildThisFileDirectory)dotnet.ruleset + enable + enable + true + True false false + $(MSBuildThisFileDirectory)dotnet.ruleset true $(OutputPath)$(AssemblyName).xml - true - enable - enable - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 75a32975..026a4723 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -1,74 +1,79 @@  - - net6.0;net7.0 - enable - enable - Genocs.Auth - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The authorization library useful to build .NET Core projects. - The authorization library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Auth + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The authorization library useful to build .NET Core projects. + The authorization library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Auth/README.md b/src/Genocs.Auth/README.md index 637423d1..fbd670e5 100644 --- a/src/Genocs.Auth/README.md +++ b/src/Genocs.Auth/README.md @@ -37,11 +37,8 @@ Following are the project settings needed to enable monitoring ## Release notes -### [2023-10-13] 5.0.0-preview.5.0 -- Added [editorconfig](https://editorconfig.org/) -- Added StyleCop -- Updated logo -- Updated readme +### [2023-11-25] 5.0.0 +- Moved to NET8 ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 53b44aea..67639342 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -1,52 +1,52 @@ - - netstandard2.1 - enable - enable - Genocs.Common - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The commons components library useful to build .NET Core projects. - The commons components library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + netstandard2.1 + enable + enable + Genocs.Common + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The commons components library useful to build .NET Core projects. + The commons components library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Common/README.md b/src/Genocs.Common/README.md index e13b098e..a40658e7 100644 --- a/src/Genocs.Common/README.md +++ b/src/Genocs.Common/README.md @@ -15,6 +15,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 0f133816..51e4ed34 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -1,29 +1,29 @@  - - net7.0 - enable - enable - false - false - + + net7.0 + enable + enable + false + false + - - - + + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 30ad925d..5acf05d1 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -1,28 +1,28 @@  - - net7.0 - enable - enable - false - false - + + net7.0 + enable + enable + false + false + - - - - + + + + - - - - + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj index 10e58d89..2399d182 100644 --- a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj +++ b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj @@ -1,18 +1,18 @@  - - net7.0 - enable - enable - false - false - + + net7.0 + enable + enable + false + false + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index a2f08cea..b6698bcd 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -1,36 +1,36 @@  - - net7.0 - enable - enable - false - false - __genocs - Linux - ..\.. - + + net7.0 + enable + enable + false + false + __genocs + Linux + ..\.. + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index c2a64f4f..435196cd 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -1,44 +1,44 @@  - - net7.0 - enable - enable - false - false - __genocs - Linux - ..\.. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + net7.0 + enable + enable + false + false + __genocs + Linux + ..\.. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index e446d286..1ec0ce24 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -1,29 +1,30 @@  - - net7.0 - enable - enable - false - false - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + net7.0 + enable + enable + false + false + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 43d2c5cd..515041e4 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -1,86 +1,89 @@  - - netstandard2.1;net6.0;net7.0 - enable - enable - Genocs.Core - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The base library useful to build .NET Core projects. - The base library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + netstandard2.1;net6.0;net7.0;net8.0 + enable + enable + Genocs.Core + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The base library to build .NET Core projects. + The base library to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Nove to NET8 + True + latest + True + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Core/README.md b/src/Genocs.Core/README.md index 4d083c6c..66ce6efb 100644 --- a/src/Genocs.Core/README.md +++ b/src/Genocs.Core/README.md @@ -15,6 +15,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index a605130f..1fb0266d 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -1,67 +1,67 @@  - - net6.0;net7.0 - enable - enable - Genocs.Discovery.Consul - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The service discovery by Consul library useful to build .NET Core projects. - The service discovery by Consul library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Discovery.Consul + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The service discovery by Consul library useful to build .NET Core projects. + The service discovery by Consul library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - + - - - - + + + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index b041a3a4..18f92359 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -1,71 +1,71 @@  - - net6.0;net7.0 - enable - enable - Genocs.HTTP.RestEase - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The http support library useful to build .NET Core projects. - The http support library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.HTTP.RestEase + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The http support library useful to build .NET Core projects. + The http support library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - - - + + + + + - + - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.HTTP.RestEase/README.md b/src/Genocs.HTTP.RestEase/README.md index a9b80e9f..782ef191 100644 --- a/src/Genocs.HTTP.RestEase/README.md +++ b/src/Genocs.HTTP.RestEase/README.md @@ -15,6 +15,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index d5617735..f4e14a63 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -1,65 +1,65 @@  - - net6.0;net7.0 - enable - enable - Genocs.HTTP - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The http support library useful to build .NET Core projects. - The http support library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.HTTP + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The http support library useful to build .NET Core projects. + The http support library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.HTTP/README.md b/src/Genocs.HTTP/README.md index d3afafc4..3a471548 100644 --- a/src/Genocs.HTTP/README.md +++ b/src/Genocs.HTTP/README.md @@ -33,6 +33,9 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index fc03c875..6e13cbde 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -1,65 +1,65 @@  - - net6.0;net7.0 - enable - enable - Genocs.LoadBalancing.Fabio - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The load balacer based on Fabio library useful to build .NET Core projects. - The load balacer based on Fabio library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.LoadBalancing.Fabio + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The load balacer based on Fabio library useful to build .NET Core projects. + The load balacer based on Fabio library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - - + + + + - + - - - - - + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.LoadBalancing.Fabio/README.md b/src/Genocs.LoadBalancing.Fabio/README.md index a9b80e9f..782ef191 100644 --- a/src/Genocs.LoadBalancing.Fabio/README.md +++ b/src/Genocs.LoadBalancing.Fabio/README.md @@ -15,6 +15,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 8ef4eb37..027b865c 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -1,73 +1,74 @@ - + - - net6.0;net7.0 - enable - enable - Genocs.Logging - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The logging library useful to build .NET Core projects. - The logging library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Logging + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The logging library useful to build .NET Core projects. + The logging library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Logging/README.md b/src/Genocs.Logging/README.md index e2424fce..0f7a9e47 100644 --- a/src/Genocs.Logging/README.md +++ b/src/Genocs.Logging/README.md @@ -22,6 +22,9 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 22bd7d33..40f3ffd9 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -1,61 +1,61 @@  - - net6.0;net7.0 - enable - enable - Genocs.MessageBrokers.Outbox.MongoDB - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The message brokers outbox MongoDB interface library useful to build .NET Core projects. - The message brokers MongoDB outbox interface library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.MessageBrokers.Outbox.MongoDB + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The message brokers outbox MongoDB interface library useful to build .NET Core projects. + The message brokers MongoDB outbox interface library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - - + + + + - - - - + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md b/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index f05af59a..250c084d 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -1,59 +1,59 @@  - - net6.0;net7.0 - enable - enable - Genocs.MessageBrokers.Outbox - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The message brokers outbox interface library useful to build .NET Core projects. - The message brokers outbox interface library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.MessageBrokers.Outbox + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The message brokers outbox interface library useful to build .NET Core projects. + The message brokers outbox interface library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.MessageBrokers.Outbox/README.md b/src/Genocs.MessageBrokers.Outbox/README.md index c7408fe7..d1b09884 100644 --- a/src/Genocs.MessageBrokers.Outbox/README.md +++ b/src/Genocs.MessageBrokers.Outbox/README.md @@ -26,6 +26,9 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index c46d5eb6..5f3db936 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -1,66 +1,66 @@  - - net6.0;net7.0 - enable - enable - Genocs.MessageBrokers.RabbitMQ - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The message brokers RabbitMQ interface library useful to build .NET Core projects. - The message brokers RabbitMQ outbox interface library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.MessageBrokers.RabbitMQ + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The message brokers RabbitMQ interface library useful to build .NET Core projects. + The message brokers RabbitMQ outbox interface library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/README.md b/src/Genocs.MessageBrokers.RabbitMQ/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/README.md +++ b/src/Genocs.MessageBrokers.RabbitMQ/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 32660229..e1ec685b 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -1,61 +1,61 @@  - - net6.0;net7.0 - enable - enable - Genocs.MessageBrokers - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The message brokers interface library useful to build .NET Core projects. - The message brokers interface library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.MessageBrokers + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The message brokers interface library useful to build .NET Core projects. + The message brokers interface library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.MessageBrokers/README.md b/src/Genocs.MessageBrokers/README.md index da894335..d9e79ee9 100644 --- a/src/Genocs.MessageBrokers/README.md +++ b/src/Genocs.MessageBrokers/README.md @@ -33,6 +33,9 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index be872115..6f524a00 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -1,93 +1,93 @@  - - net6.0;net7.0 - enable - enable - Genocs.Metrics - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The metrics interface library useful to build .NET Core projects. - The metrics interface library useful to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Metrics + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The metrics interface library useful to build .NET Core projects. + The metrics interface library useful to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Metrics/README.md b/src/Genocs.Metrics/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.Metrics/README.md +++ b/src/Genocs.Metrics/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 411d4946..626c5152 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -1,72 +1,72 @@  - - net6.0;net7.0 - enable - enable - Genocs.Monitoring - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - Telemetry and Tracing library. - Telemetry and Tracing library. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Monitoring + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + Telemetry and Tracing library. + Telemetry and Tracing library. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - - + + + + - + - - - - - + + + + + - - - - - - + + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 231034fd..0bdfd86d 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -1,43 +1,43 @@  - - net7.0 - enable - enable - false - false - Genocs - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - + + net7.0 + enable + enable + false + false + Genocs + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + - - - + + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 5a602a9e..4ac9aea0 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -1,65 +1,65 @@  - - net6.0;net7.0 - enable - enable - Genocs.Persistence.MongoDb - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The Persistence MongoDB Library. - The library containing base repository pattern to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Moved to NET7.0 - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Persistence.MongoDb + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The Persistence MongoDB Library. + The library containing base repository pattern to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Moved to NET7.0 + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 0e9b0452..933d7f5a 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -1,64 +1,64 @@  - - net6.0;net7.0 - enable - enable - Genocs.Persistence.Redis - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The Persistence Redis Library. - The library containing base repository pattern to build .NET Core projects. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Persistence.Redis + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The Persistence Redis Library. + The library containing base repository pattern to build .NET Core projects. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Persistence.Redis/README.md b/src/Genocs.Persistence.Redis/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.Persistence.Redis/README.md +++ b/src/Genocs.Persistence.Redis/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 64e44bb9..cca64999 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -1,41 +1,41 @@  - - net7.0 - enable - enable - false - false - + + net7.0 + enable + enable + false + false + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 05d77bb8..4495927c 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -1,52 +1,52 @@  - - netstandard2.1 - enable - enable - Genocs.QueryBuilder - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The Persistence Agnostic Query Builder Library. - The persistence agnostic query builder library. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + netstandard2.1 + enable + enable + Genocs.QueryBuilder + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The Persistence Agnostic Query Builder Library. + The persistence agnostic query builder library. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.QueryBuilder/README.md b/src/Genocs.QueryBuilder/README.md index a9b80e9f..782ef191 100644 --- a/src/Genocs.QueryBuilder/README.md +++ b/src/Genocs.QueryBuilder/README.md @@ -15,6 +15,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 28c03a82..fa69e9c7 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -1,65 +1,65 @@  - - net6.0;net7.0 - enable - enable - Genocs.Secrets.Vault - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The Genocs Secrets Vault library - The Genocs Secrets Vault library - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Secrets.Vault + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The Genocs Secrets Vault library + The Genocs Secrets Vault library + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Secrets.Vault/README.md b/src/Genocs.Secrets.Vault/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.Secrets.Vault/README.md +++ b/src/Genocs.Secrets.Vault/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 20ff53c7..99c0b403 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -1,61 +1,61 @@  - - net6.0;net7.0 - enable - enable - Genocs.Security - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The Genocs Security library - The Genocs Security library - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Moved tAligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Security + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The Genocs Security library + The Genocs Security library + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Moved tAligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Security/README.md b/src/Genocs.Security/README.md index 5212a012..c78df224 100644 --- a/src/Genocs.Security/README.md +++ b/src/Genocs.Security/README.md @@ -15,6 +15,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index e57f1d6e..df4f35a1 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -1,29 +1,29 @@ - - net7.0 - enable - enable - false - false - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + net7.0 + enable + enable + false + false + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 3d1c3707..beea6ba5 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -1,67 +1,67 @@  - - net6.0;net7.0 - enable - enable - Genocs.ServiceBusAzure - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The low level library to use Azure Service Bus. - The low level library to use Azure Service Bus. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.ServiceBusAzure + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The low level library to use Azure Service Bus. + The low level library to use Azure Service Bus. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - - + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.ServiceBusAzure/README.md b/src/Genocs.ServiceBusAzure/README.md index d4ae6e0b..f74281c4 100644 --- a/src/Genocs.ServiceBusAzure/README.md +++ b/src/Genocs.ServiceBusAzure/README.md @@ -33,6 +33,9 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index 20ed6ed9..599e4c9b 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -1,13 +1,13 @@  - net6.0;net7.0 + net6.0;net7.0;net8.0 enable enable Genocs.Tracing.Jaeger.RabbitMQ 10.0 true - 5.0.0-preview1.0 + 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,8 +48,8 @@ - - + + diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md b/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md index a9b80e9f..782ef191 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md @@ -15,6 +15,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 883d19f0..2dae17c0 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -1,77 +1,76 @@  - - net6.0;net7.0 - enable - enable - Genocs.Tracing - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The tracing library to use Azure Service Bus. - The tracing library to use Azure Service Bus. - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.Tracing + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The tracing library to use Azure Service Bus. + The tracing library to use Azure Service Bus. + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + + + + + + - - - - - + + + + + - - - - - + + + - - - + + + + + + + - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.Tracing/README.md b/src/Genocs.Tracing/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.Tracing/README.md +++ b/src/Genocs.Tracing/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 0038d4a9..6406246b 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -1,64 +1,62 @@  - - net6.0;net7.0 - enable - enable - Genocs.WebApi.CQRS - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The web api CORS library - The web api CORS library - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - - - - - True - \ - - - True - \ - - - True - \ - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.WebApi.CQRS + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The web api CORS library + The web api CORS library + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + + + + + True + \ + + + True + \ + + + True + \ + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.WebApi.CQRS/README.md b/src/Genocs.WebApi.CQRS/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.WebApi.CQRS/README.md +++ b/src/Genocs.WebApi.CQRS/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 17675bac..1be0fd48 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -1,68 +1,73 @@  - - net6.0;net7.0 - enable - enable - Genocs.WebApi.Security - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The web api Security library - The web api Security library - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.WebApi.Security + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The web api Security library + The web api Security library + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.WebApi.Security/README.md b/src/Genocs.WebApi.Security/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.WebApi.Security/README.md +++ b/src/Genocs.WebApi.Security/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index ca65c0cd..b48c4b52 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -1,68 +1,69 @@  - - net6.0 - enable - enable - Genocs.WebApi.Swagger - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The web api Swagger library - The web api Swagger library - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0 + enable + enable + Genocs.WebApi.Swagger + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The web api Swagger library + The web api Swagger library + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Genocs.WebApi.Swagger/README.md b/src/Genocs.WebApi.Swagger/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.WebApi.Swagger/README.md +++ b/src/Genocs.WebApi.Swagger/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 16ea95c1..38dec1e4 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -1,70 +1,70 @@  - - net6.0;net7.0 - enable - enable - Genocs.WebApi - 10.0 - true - 5.0.0-preview.5.0 - 5.0.0 - Nocco Giovanni Emanuele - Genocs - The web api library - The web api library - Genocs 2023 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md - Aligned to the ecosystem - True - latest - True - + + net6.0;net7.0;net8.0 + enable + enable + Genocs.WebApi + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + The web api library + The web api library + Genocs 2023 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + True + - - - True - \ - - - True - \ - - - True - \ - - + + + True + \ + + + True + \ + + + True + \ + + - - - + + + - - - + + + - - - - + + + + - - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.WebApi/README.md b/src/Genocs.WebApi/README.md index 783a9116..93568a5e 100644 --- a/src/Genocs.WebApi/README.md +++ b/src/Genocs.WebApi/README.md @@ -16,6 +16,9 @@ Please check the GitHub repository getting more info. ## Release notes +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 45aaa59a..4242b21c 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -1,59 +1,59 @@  - - net7.0 - enable - enable - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ - True - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + net7.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ + True + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 8c8aa249..2401ed65 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -1,52 +1,52 @@  - - net7.0 - enable - enable - + + net7.0 + enable + enable + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj index bc4c5329..4e62d6d2 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj +++ b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj @@ -1,37 +1,37 @@  - - net7.0 - enable - enable - _genocs - Linux - ..\.. - + + net7.0 + enable + enable + _genocs + Linux + ..\.. + - - - - - + + + + + - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index df5837db..e0de5165 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -1,56 +1,56 @@  - - net7.0 - enable - enable - _genocs - Linux - ..\.. - + + net7.0 + enable + enable + _genocs + Linux + ..\.. + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index f4cab645..4dc51975 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -1,63 +1,63 @@  - - net7.0 - enable - enable - _genocs - Linux - ..\.. - + + net7.0 + enable + enable + _genocs + Linux + ..\.. + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 53fd8644..9232e274 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -1,64 +1,64 @@  - - net7.0 - enable - enable - _genocs - Linux - ..\.. - + + net7.0 + enable + enable + _genocs + Linux + ..\.. + - - - + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file From 2dde44c057ee340bb9aebceb367f2d9cd3b084d7 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 10:46:10 +0100 Subject: [PATCH 008/104] Minor fix --- src/Genocs.Common/Types/MessageAttribute.cs | 23 +- src/Genocs.Core.UnitTests/UnitTest1.cs | 4 +- src/Genocs.Core/Builders/GenocsBuilder.cs | 8 +- src/Genocs.Core/CQRS/Queries/PagedResult.cs | 125 ++- .../Collections/Extensions/ListExtensions.cs | 102 ++- .../IRepositoryOfTEntityAndTPrimaryKey.cs | 660 ++++++++------- .../Extensions/StringExtensions.cs | 791 +++++++++--------- .../Repositories/MongoRepository.cs | 1 - .../InMemoryDynamicQueriesUnitTests.cs | 5 +- .../Genocs.QueryBuilder.UnitTests.csproj | 10 +- src/Genocs.QueryBuilder/QueryItem.cs | 13 +- src/Genocs.Secrets.Vault/Extensions.cs | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 4 +- .../SimpleUnitTests.cs | 4 +- 14 files changed, 872 insertions(+), 880 deletions(-) diff --git a/src/Genocs.Common/Types/MessageAttribute.cs b/src/Genocs.Common/Types/MessageAttribute.cs index 5dbc8107..c226ccc0 100644 --- a/src/Genocs.Common/Types/MessageAttribute.cs +++ b/src/Genocs.Common/Types/MessageAttribute.cs @@ -1,28 +1,28 @@ namespace Genocs.Common.Types; /// -/// MessageAttribute class +/// MessageAttribute class. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public class MessageAttribute : Attribute { /// - /// The Exchange used by the system + /// The Exchange used by the system. /// public string Exchange { get; } /// - /// The Topic used to send/receive message + /// The Topic used to send/receive message. /// public string Topic { get; } /// - /// The queue + /// The queue. /// public string Queue { get; } /// - /// The type of the queue + /// The type of the queue. /// public string QueueType { get; } @@ -32,12 +32,12 @@ public class MessageAttribute : Attribute public string ErrorQueue { get; } /// - /// The subscriptionId + /// The subscriptionId. /// public string SubscriptionId { get; } /// - /// Standard constructor + /// Standard constructor. /// /// /// @@ -45,8 +45,13 @@ public class MessageAttribute : Attribute /// /// /// - public MessageAttribute(string? exchange = null, string? topic = null, string? queue = null, - string? queueType = null, string? errorQueue = null, string? subscriptionId = null) + public MessageAttribute( + string? exchange = null, + string? topic = null, + string? queue = null, + string? queueType = null, + string? errorQueue = null, + string? subscriptionId = null) { Exchange = exchange ?? string.Empty; Topic = topic ?? string.Empty; diff --git a/src/Genocs.Core.UnitTests/UnitTest1.cs b/src/Genocs.Core.UnitTests/UnitTest1.cs index aef15efe..44fa45bc 100644 --- a/src/Genocs.Core.UnitTests/UnitTest1.cs +++ b/src/Genocs.Core.UnitTests/UnitTest1.cs @@ -1,7 +1,7 @@ -namespace Genocs.Core.UnitTests; - using Xunit; +namespace Genocs.Core.UnitTests; + public class UnitTest1 { [Fact] diff --git a/src/Genocs.Core/Builders/GenocsBuilder.cs b/src/Genocs.Core/Builders/GenocsBuilder.cs index f3571e83..c7972562 100644 --- a/src/Genocs.Core/Builders/GenocsBuilder.cs +++ b/src/Genocs.Core/Builders/GenocsBuilder.cs @@ -1,14 +1,12 @@ -namespace Genocs.Core.Builders; - using Genocs.Common.Types; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using System; using System.Collections.Concurrent; -using System.Collections.Generic; + +namespace Genocs.Core.Builders; /// -/// Genocs builder implementation +/// Genocs builder implementation. /// public sealed class GenocsBuilder : IGenocsBuilder { diff --git a/src/Genocs.Core/CQRS/Queries/PagedResult.cs b/src/Genocs.Core/CQRS/Queries/PagedResult.cs index be31ae0f..250adb3b 100644 --- a/src/Genocs.Core/CQRS/Queries/PagedResult.cs +++ b/src/Genocs.Core/CQRS/Queries/PagedResult.cs @@ -1,74 +1,71 @@ -namespace Genocs.Core.CQRS.Queries +using System.Text.Json.Serialization; + +namespace Genocs.Core.CQRS.Queries; + +/// +/// The paged result. +/// +/// +public class PagedResult : PagedResultBase { - using System.Collections.Generic; - using System.Linq; - using System.Text.Json.Serialization; + /// + /// Returned items + /// + public IEnumerable Items { get; } /// - /// The paged result + /// Default constructor /// - /// - public class PagedResult : PagedResultBase + protected PagedResult() { - /// - /// Returned items - /// - public IEnumerable Items { get; } - - /// - /// Default constructor - /// - protected PagedResult() - { - Items = Enumerable.Empty(); - } + Items = Enumerable.Empty(); + } - /// - /// Standard constructor - /// - /// - /// - /// - /// - /// - [JsonConstructor] - protected PagedResult(IEnumerable items, - int currentPage, - int resultsPerPage, - int totalPages, - long totalResults) : - base(currentPage, resultsPerPage, totalPages, totalResults) - { - Items = items; - } + /// + /// Standard constructor + /// + /// + /// + /// + /// + /// + [JsonConstructor] + protected PagedResult(IEnumerable items, + int currentPage, + int resultsPerPage, + int totalPages, + long totalResults) : + base(currentPage, resultsPerPage, totalPages, totalResults) + { + Items = items; + } - /// - /// Create helper - /// - /// - /// - /// - /// - /// - /// - public static PagedResult Create(IEnumerable items, - int currentPage, int resultsPerPage, - int totalPages, long totalResults) - => new PagedResult(items, currentPage, resultsPerPage, totalPages, totalResults); + /// + /// Create helper + /// + /// + /// + /// + /// + /// + /// + public static PagedResult Create(IEnumerable items, + int currentPage, int resultsPerPage, + int totalPages, long totalResults) + => new PagedResult(items, currentPage, resultsPerPage, totalPages, totalResults); - /// - /// From helper - /// - /// - /// - /// - public static PagedResult From(PagedResultBase result, IEnumerable items) - => new PagedResult(items, result.CurrentPage, result.ResultsPerPage, - result.TotalPages, result.TotalResults); + /// + /// From helper + /// + /// + /// + /// + public static PagedResult From(PagedResultBase result, IEnumerable items) + => new PagedResult(items, result.CurrentPage, result.ResultsPerPage, + result.TotalPages, result.TotalResults); - /// - /// Static helper to get Empty result - /// - public static PagedResult Empty => new PagedResult(); - } + /// + /// Static helper to get Empty result + /// + public static PagedResult Empty => new PagedResult(); } \ No newline at end of file diff --git a/src/Genocs.Core/Collections/Extensions/ListExtensions.cs b/src/Genocs.Core/Collections/Extensions/ListExtensions.cs index 16d76145..e6d54ebb 100644 --- a/src/Genocs.Core/Collections/Extensions/ListExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/ListExtensions.cs @@ -1,73 +1,69 @@ -namespace Genocs.Core.Collections.Extensions -{ - using System; - using System.Collections.Generic; +namespace Genocs.Core.Collections.Extensions; +/// +/// Extension methods for . +/// +public static class ListExtensions +{ /// - /// Extension methods for . + /// Sort a list by a topological sorting, which consider their dependencies /// - public static class ListExtensions + /// The type of the members of values. + /// A list of objects to sort + /// Function to resolve the dependencies + /// + public static List SortByDependencies(this IEnumerable source, Func> getDependencies) { - /// - /// Sort a list by a topological sorting, which consider their dependencies - /// - /// The type of the members of values. - /// A list of objects to sort - /// Function to resolve the dependencies - /// - public static List SortByDependencies(this IEnumerable source, Func> getDependencies) + /* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp + * http://en.wikipedia.org/wiki/Topological_sorting + */ + + var sorted = new List(); + var visited = new Dictionary(); + + foreach (var item in source) { - /* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp - * http://en.wikipedia.org/wiki/Topological_sorting - */ + SortByDependenciesVisit(item, getDependencies, sorted, visited); + } - var sorted = new List(); - var visited = new Dictionary(); + return sorted; + } + + /// + /// + /// + /// The type of the members of values. + /// Item to resolve + /// Function to resolve the dependencies + /// List with the sortet items + /// Dictionary with the visited items + private static void SortByDependenciesVisit(T item, Func> getDependencies, List sorted, Dictionary visited) + { + bool inProcess; + var alreadyVisited = visited.TryGetValue(item, out inProcess); - foreach (var item in source) + if (alreadyVisited) + { + if (inProcess) { - SortByDependenciesVisit(item, getDependencies, sorted, visited); + throw new ArgumentException("Cyclic dependency found! Item: " + item); } - - return sorted; } - - /// - /// - /// - /// The type of the members of values. - /// Item to resolve - /// Function to resolve the dependencies - /// List with the sortet items - /// Dictionary with the visited items - private static void SortByDependenciesVisit(T item, Func> getDependencies, List sorted, Dictionary visited) + else { - bool inProcess; - var alreadyVisited = visited.TryGetValue(item, out inProcess); + visited[item] = true; - if (alreadyVisited) + var dependencies = getDependencies(item); + if (dependencies != null) { - if (inProcess) + foreach (var dependency in dependencies) { - throw new ArgumentException("Cyclic dependency found! Item: " + item); + SortByDependenciesVisit(dependency, getDependencies, sorted, visited); } } - else - { - visited[item] = true; - var dependencies = getDependencies(item); - if (dependencies != null) - { - foreach (var dependency in dependencies) - { - SortByDependenciesVisit(dependency, getDependencies, sorted, visited); - } - } - - visited[item] = false; - sorted.Add(item); - } + visited[item] = false; + sorted.Add(item); } } } diff --git a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs index b3026231..63143af9 100644 --- a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs @@ -1,334 +1,330 @@ -namespace Genocs.Core.Domain.Repositories +using Genocs.Common.Types; +using System.Linq.Expressions; + +namespace Genocs.Core.Domain.Repositories; + +/// +/// This interface is implemented by all repositories to ensure implementation of fixed methods. +/// +/// Main Entity type this repository works on +/// Primary key type of the entity +public interface IRepositoryOfEntity : IRepository + where TEntity : IIdentifiable { - using Genocs.Common.Types; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Linq.Expressions; - using System.Threading.Tasks; - - /// - /// This interface is implemented by all repositories to ensure implementation of fixed methods. - /// - /// Main Entity type this repository works on - /// Primary key type of the entity - public interface IRepositoryOfEntity : IRepository where TEntity : IIdentifiable - { - #region Select/Get/Query - - /// - /// Used to get a IQueryable that is used to retrieve entities from entire table. - /// - /// IQueryable to be used to select entities from database - IQueryable GetAll(); - - /// - /// Used to get a IQueryable that is used to retrieve entities from entire table. - /// One or more - /// - /// A list of include expressions. - /// IQueryable to be used to select entities from database - IQueryable GetAllIncluding(params Expression>[] propertySelectors); - - /// - /// Used to get all entities. - /// - /// List of all entities - List GetAllList(); - - /// - /// Used to get all entities. - /// - /// List of all entities - Task> GetAllListAsync(); - - /// - /// Used to get all entities based on given . - /// - /// A condition to filter entities - /// List of all entities - List GetAllList(Expression> predicate); - - /// - /// Used to get all entities based on given . - /// - /// A condition to filter entities - /// List of all entities - Task> GetAllListAsync(Expression> predicate); - - /// - /// Used to run a query over entire entities. - /// attribute is not always necessary (as opposite to ) - /// if finishes IQueryable with ToList, FirstOrDefault etc.. - /// - /// Type of return value of this method - /// This method is used to query over entities - /// Query result - T Query(Func, T> queryMethod); - - /// - /// Gets an entity with given primary key. - /// - /// Primary key of the entity to get - /// Entity - TEntity Get(TIdentifiable id); - - /// - /// Gets an entity with given primary key. - /// - /// Primary key of the entity to get - /// Entity - Task GetAsync(TIdentifiable id); - - /// - /// Gets exactly one entity with given predicate. - /// Throws exception if no entity or more than one entity. - /// - /// Entity - TEntity Single(Expression> predicate); - - /// - /// Gets exactly one entity with given predicate. - /// Throws exception if no entity or more than one entity. - /// - /// Entity - Task SingleAsync(Expression> predicate); - - /// - /// Gets an entity with given primary key or null if not found. - /// - /// Primary key of the entity to get - /// Entity or null - TEntity FirstOrDefault(TIdentifiable id); - - /// - /// Gets an entity with given primary key or null if not found. - /// - /// Primary key of the entity to get - /// Entity or null - Task FirstOrDefaultAsync(TIdentifiable id); - - /// - /// Gets an entity with given given predicate or null if not found. - /// - /// Predicate to filter entities - TEntity FirstOrDefault(Expression> predicate); - - /// - /// Gets an entity with given given predicate or null if not found. - /// - /// Predicate to filter entities - Task FirstOrDefaultAsync(Expression> predicate); - - /// - /// Creates an entity with given primary key without database access. - /// - /// Primary key of the entity to load - /// Entity - TEntity Load(TIdentifiable id); - - #endregion - - #region Insert - - /// - /// Inserts a new entity. - /// - /// Inserted entity - TEntity Insert(TEntity entity); - - /// - /// Inserts a new entity. - /// - /// Inserted entity - Task InsertAsync(TEntity entity); - - /// - /// Inserts a new entity and gets it's Id. - /// It may require to save current unit of work - /// to be able to retrieve id. - /// - /// Entity - /// Id of the entity - TIdentifiable InsertAndGetId(TEntity entity); - - /// - /// Inserts a new entity and gets it's Id. - /// It may require to save current unit of work - /// to be able to retrieve id. - /// - /// Entity - /// Id of the entity - Task InsertAndGetIdAsync(TEntity entity); - - /// - /// Inserts or updates given entity depending on Id's value. - /// - /// Entity - TEntity InsertOrUpdate(TEntity entity); - - /// - /// Inserts or updates given entity depending on Id's value. - /// - /// Entity - Task InsertOrUpdateAsync(TEntity entity); - - /// - /// Inserts or updates given entity depending on Id's value. - /// Also returns Id of the entity. - /// It may require to save current unit of work - /// to be able to retrieve id. - /// - /// Entity - /// Id of the entity - TIdentifiable InsertOrUpdateAndGetId(TEntity entity); - - /// - /// Inserts or updates given entity depending on Id's value. - /// Also returns Id of the entity. - /// It may require to save current unit of work - /// to be able to retrieve id. - /// - /// Entity - /// Id of the entity - Task InsertOrUpdateAndGetIdAsync(TEntity entity); - - #endregion - - #region Update - - /// - /// Updates an existing entity. - /// - /// Entity - TEntity Update(TEntity entity); - - /// - /// Updates an existing entity. - /// - /// Entity - Task UpdateAsync(TEntity entity); - - /// - /// Updates an existing entity. - /// - /// Id of the entity - /// Action that can be used to change values of the entity - /// Updated entity - TEntity Update(TIdentifiable id, Action updateAction); - - /// - /// Updates an existing entity. - /// - /// Id of the entity - /// Action that can be used to change values of the entity - /// Updated entity - Task UpdateAsync(TIdentifiable id, Func updateAction); - - #endregion - - #region Delete - - /// - /// Deletes an entity. - /// - /// Entity to be deleted - void Delete(TEntity entity); - - /// - /// Deletes an entity. - /// - /// Entity to be deleted - Task DeleteAsync(TEntity entity); - - /// - /// Deletes an entity by primary key. - /// - /// Primary key of the entity - void Delete(TIdentifiable id); - - /// - /// Deletes an entity by primary key. - /// - /// Primary key of the entity - Task DeleteAsync(TIdentifiable id); - - /// - /// Deletes many entities by function. - /// Notice that: All entities fits to given predicate are retrieved and deleted. - /// This may cause major performance problems if there are too many entities with - /// given predicate. - /// - /// A condition to filter entities - void Delete(Expression> predicate); - - /// - /// Deletes many entities by function. - /// Notice that: All entities fits to given predicate are retrieved and deleted. - /// This may cause major performance problems if there are too many entities with - /// given predicate. - /// - /// A condition to filter entities - Task DeleteAsync(Expression> predicate); - - #endregion - - #region Aggregates - - /// - /// Gets count of all entities in this repository. - /// - /// Count of entities - int Count(); - - /// - /// Gets count of all entities in this repository. - /// - /// Count of entities - Task CountAsync(); - - /// - /// Gets count of all entities in this repository based on given . - /// - /// A method to filter count - /// Count of entities - int Count(Expression> predicate); - - /// - /// Gets count of all entities in this repository based on given . - /// - /// A method to filter count - /// Count of entities - Task CountAsync(Expression> predicate); - - /// - /// Gets count of all entities in this repository (use if expected return value is greater than . - /// - /// Count of entities - long LongCount(); - - /// - /// Gets count of all entities in this repository (use if expected return value is greater than . - /// - /// Count of entities - Task LongCountAsync(); - - /// - /// Gets count of all entities in this repository based on given - /// (use this overload if expected return value is greater than ). - /// - /// A method to filter count - /// Count of entities - long LongCount(Expression> predicate); - - /// - /// Gets count of all entities in this repository based on given - /// (use this overload if expected return value is greater than ). - /// - /// A method to filter count - /// Count of entities - Task LongCountAsync(Expression> predicate); - - #endregion - } + #region Select/Get/Query + + /// + /// Used to get a IQueryable that is used to retrieve entities from entire table. + /// + /// IQueryable to be used to select entities from database + IQueryable GetAll(); + + /// + /// Used to get a IQueryable that is used to retrieve entities from entire table. + /// One or more + /// + /// A list of include expressions. + /// IQueryable to be used to select entities from database + IQueryable GetAllIncluding(params Expression>[] propertySelectors); + + /// + /// Used to get all entities. + /// + /// List of all entities + List GetAllList(); + + /// + /// Used to get all entities. + /// + /// List of all entities + Task> GetAllListAsync(); + + /// + /// Used to get all entities based on given . + /// + /// A condition to filter entities + /// List of all entities + List GetAllList(Expression> predicate); + + /// + /// Used to get all entities based on given . + /// + /// A condition to filter entities. + /// List of all entities. + Task> GetAllListAsync(Expression> predicate); + + /// + /// Used to run a query over entire entities. + /// attribute is not always necessary (as opposite to ) + /// if finishes IQueryable with ToList, FirstOrDefault etc.. + /// + /// Type of return value of this method. + /// This method is used to query over entities. + /// Query result + T Query(Func, T> queryMethod); + + /// + /// Gets an entity with given primary key. + /// + /// Primary key of the entity to get. + /// Entity. + TEntity Get(TIdentifiable id); + + /// + /// Gets an entity with given primary key. + /// + /// Primary key of the entity to get. + /// Entity + Task GetAsync(TIdentifiable id); + + /// + /// Gets exactly one entity with given predicate. + /// Throws exception if no entity or more than one entity. + /// + /// Entity + TEntity Single(Expression> predicate); + + /// + /// Gets exactly one entity with given predicate. + /// Throws exception if no entity or more than one entity. + /// + /// Entity. + Task SingleAsync(Expression> predicate); + + /// + /// Gets an entity with given primary key or null if not found. + /// + /// Primary key of the entity to get + /// Entity or null + TEntity FirstOrDefault(TIdentifiable id); + + /// + /// Gets an entity with given primary key or null if not found. + /// + /// Primary key of the entity to get + /// Entity or null + Task FirstOrDefaultAsync(TIdentifiable id); + + /// + /// Gets an entity with given given predicate or null if not found. + /// + /// Predicate to filter entities + TEntity FirstOrDefault(Expression> predicate); + + /// + /// Gets an entity with given given predicate or null if not found. + /// + /// Predicate to filter entities + Task FirstOrDefaultAsync(Expression> predicate); + + /// + /// Creates an entity with given primary key without database access. + /// + /// Primary key of the entity to load + /// Entity + TEntity Load(TIdentifiable id); + + #endregion + + #region Insert + + /// + /// Inserts a new entity. + /// + /// Inserted entity + TEntity Insert(TEntity entity); + + /// + /// Inserts a new entity. + /// + /// Inserted entity + Task InsertAsync(TEntity entity); + + /// + /// Inserts a new entity and gets it's Id. + /// It may require to save current unit of work + /// to be able to retrieve id. + /// + /// Entity + /// Id of the entity + TIdentifiable InsertAndGetId(TEntity entity); + + /// + /// Inserts a new entity and gets it's Id. + /// It may require to save current unit of work + /// to be able to retrieve id. + /// + /// Entity + /// Id of the entity + Task InsertAndGetIdAsync(TEntity entity); + + /// + /// Inserts or updates given entity depending on Id's value. + /// + /// Entity + TEntity InsertOrUpdate(TEntity entity); + + /// + /// Inserts or updates given entity depending on Id's value. + /// + /// Entity + Task InsertOrUpdateAsync(TEntity entity); + + /// + /// Inserts or updates given entity depending on Id's value. + /// Also returns Id of the entity. + /// It may require to save current unit of work + /// to be able to retrieve id. + /// + /// Entity + /// Id of the entity + TIdentifiable InsertOrUpdateAndGetId(TEntity entity); + + /// + /// Inserts or updates given entity depending on Id's value. + /// Also returns Id of the entity. + /// It may require to save current unit of work + /// to be able to retrieve id. + /// + /// Entity + /// Id of the entity + Task InsertOrUpdateAndGetIdAsync(TEntity entity); + + #endregion + + #region Update + + /// + /// Updates an existing entity. + /// + /// Entity + TEntity Update(TEntity entity); + + /// + /// Updates an existing entity. + /// + /// Entity + Task UpdateAsync(TEntity entity); + + /// + /// Updates an existing entity. + /// + /// Id of the entity + /// Action that can be used to change values of the entity + /// Updated entity + TEntity Update(TIdentifiable id, Action updateAction); + + /// + /// Updates an existing entity. + /// + /// Id of the entity + /// Action that can be used to change values of the entity + /// Updated entity + Task UpdateAsync(TIdentifiable id, Func updateAction); + + #endregion + + #region Delete + + /// + /// Deletes an entity. + /// + /// Entity to be deleted + void Delete(TEntity entity); + + /// + /// Deletes an entity. + /// + /// Entity to be deleted + Task DeleteAsync(TEntity entity); + + /// + /// Deletes an entity by primary key. + /// + /// Primary key of the entity + void Delete(TIdentifiable id); + + /// + /// Deletes an entity by primary key. + /// + /// Primary key of the entity + Task DeleteAsync(TIdentifiable id); + + /// + /// Deletes many entities by function. + /// Notice that: All entities fits to given predicate are retrieved and deleted. + /// This may cause major performance problems if there are too many entities with + /// given predicate. + /// + /// A condition to filter entities + void Delete(Expression> predicate); + + /// + /// Deletes many entities by function. + /// Notice that: All entities fits to given predicate are retrieved and deleted. + /// This may cause major performance problems if there are too many entities with + /// given predicate. + /// + /// A condition to filter entities + Task DeleteAsync(Expression> predicate); + + #endregion + + #region Aggregates + + /// + /// Gets count of all entities in this repository. + /// + /// Count of entities + int Count(); + + /// + /// Gets count of all entities in this repository. + /// + /// Count of entities + Task CountAsync(); + + /// + /// Gets count of all entities in this repository based on given . + /// + /// A method to filter count + /// Count of entities + int Count(Expression> predicate); + + /// + /// Gets count of all entities in this repository based on given . + /// + /// A method to filter count + /// Count of entities + Task CountAsync(Expression> predicate); + + /// + /// Gets count of all entities in this repository (use if expected return value is greater than . + /// + /// Count of entities + long LongCount(); + + /// + /// Gets count of all entities in this repository (use if expected return value is greater than . + /// + /// Count of entities + Task LongCountAsync(); + + /// + /// Gets count of all entities in this repository based on given + /// (use this overload if expected return value is greater than ). + /// + /// A method to filter count + /// Count of entities + long LongCount(Expression> predicate); + + /// + /// Gets count of all entities in this repository based on given + /// (use this overload if expected return value is greater than ). + /// + /// A method to filter count + /// Count of entities + Task LongCountAsync(Expression> predicate); + + #endregion } diff --git a/src/Genocs.Core/Extensions/StringExtensions.cs b/src/Genocs.Core/Extensions/StringExtensions.cs index d87882ae..10d5c3ca 100644 --- a/src/Genocs.Core/Extensions/StringExtensions.cs +++ b/src/Genocs.Core/Extensions/StringExtensions.cs @@ -1,526 +1,523 @@ -namespace Genocs.Core.Extensions +using Genocs.Core.Collections.Extensions; +using System.Globalization; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; + +namespace Genocs.Core.Extensions; + +/// +/// Extension methods for String class. +/// +public static class StringExtensions { - using System; - using System.Globalization; - using System.Linq; - using System.Security.Cryptography; - using System.Text; - using System.Text.RegularExpressions; - using Genocs.Core.Collections.Extensions; + /// + /// Adds a char to end of given string if it does not ends with the char. + /// + public static string EnsureEndsWith(this string str, char c) + { + return EnsureEndsWith(str, c, StringComparison.Ordinal); + } /// - /// Extension methods for String class. + /// Adds a char to end of given string if it does not ends with the char. /// - public static class StringExtensions + public static string EnsureEndsWith(this string str, char c, StringComparison comparisonType) { - /// - /// Adds a char to end of given string if it does not ends with the char. - /// - public static string EnsureEndsWith(this string str, char c) + if (str == null) { - return EnsureEndsWith(str, c, StringComparison.Ordinal); + throw new ArgumentNullException(nameof(str)); } - /// - /// Adds a char to end of given string if it does not ends with the char. - /// - public static string EnsureEndsWith(this string str, char c, StringComparison comparisonType) + if (str.EndsWith(c.ToString(), comparisonType)) { - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } + return str; + } - if (str.EndsWith(c.ToString(), comparisonType)) - { - return str; - } + return str + c; + } - return str + c; + /// + /// Adds a char to end of given string if it does not ends with the char. + /// + public static string EnsureEndsWith(this string str, char c, bool ignoreCase, CultureInfo culture) + { + if (str == null) + { + throw new ArgumentNullException(nameof(str)); } - /// - /// Adds a char to end of given string if it does not ends with the char. - /// - public static string EnsureEndsWith(this string str, char c, bool ignoreCase, CultureInfo culture) + if (str.EndsWith(c.ToString(culture), ignoreCase, culture)) { - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } + return str; + } - if (str.EndsWith(c.ToString(culture), ignoreCase, culture)) - { - return str; - } + return str + c; + } - return str + c; - } + /// + /// Adds a char to beginning of given string if it does not starts with the char. + /// + public static string EnsureStartsWith(this string str, char c) + { + return EnsureStartsWith(str, c, StringComparison.Ordinal); + } - /// - /// Adds a char to beginning of given string if it does not starts with the char. - /// - public static string EnsureStartsWith(this string str, char c) + /// + /// Adds a char to beginning of given string if it does not starts with the char. + /// + public static string EnsureStartsWith(this string str, char c, StringComparison comparisonType) + { + if (str == null) { - return EnsureStartsWith(str, c, StringComparison.Ordinal); + throw new ArgumentNullException(nameof(str)); } - /// - /// Adds a char to beginning of given string if it does not starts with the char. - /// - public static string EnsureStartsWith(this string str, char c, StringComparison comparisonType) + if (str.StartsWith(c.ToString(), comparisonType)) { - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } + return str; + } - if (str.StartsWith(c.ToString(), comparisonType)) - { - return str; - } + return c + str; + } - return c + str; + /// + /// Adds a char to beginning of given string if it does not starts with the char. + /// + public static string EnsureStartsWith(this string str, char c, bool ignoreCase, CultureInfo culture) + { + if (str == null) + { + throw new ArgumentNullException("str"); } - /// - /// Adds a char to beginning of given string if it does not starts with the char. - /// - public static string EnsureStartsWith(this string str, char c, bool ignoreCase, CultureInfo culture) + if (str.StartsWith(c.ToString(culture), ignoreCase, culture)) { - if (str == null) - { - throw new ArgumentNullException("str"); - } + return str; + } - if (str.StartsWith(c.ToString(culture), ignoreCase, culture)) - { - return str; - } + return c + str; + } - return c + str; + /// + /// Gets a substring of a string from beginning of the string. + /// + /// Thrown if is null + /// Thrown if is bigger that string's length + public static string Left(this string str, int len) + { + if (str == null) + { + throw new ArgumentNullException("str"); } - /// - /// Gets a substring of a string from beginning of the string. - /// - /// Thrown if is null - /// Thrown if is bigger that string's length - public static string Left(this string str, int len) + if (str.Length < len) { - if (str == null) - { - throw new ArgumentNullException("str"); - } + throw new ArgumentException("len argument can not be bigger than given string's length!"); + } - if (str.Length < len) - { - throw new ArgumentException("len argument can not be bigger than given string's length!"); - } + return str.Substring(0, len); + } - return str.Substring(0, len); - } + /// + /// Converts line endings in the string to . + /// + public static string NormalizeLineEndings(this string str) + { + return str.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine); + } - /// - /// Converts line endings in the string to . - /// - public static string NormalizeLineEndings(this string str) + /// + /// Gets index of nth occurence of a char in a string. + /// + /// source string to be searched + /// Char to search in + /// Count of the occurence + public static int NthIndexOf(this string str, char c, int n) + { + if (str == null) { - return str.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine); + throw new ArgumentNullException(nameof(str)); } - /// - /// Gets index of nth occurence of a char in a string. - /// - /// source string to be searched - /// Char to search in - /// Count of the occurence - public static int NthIndexOf(this string str, char c, int n) + var count = 0; + for (var i = 0; i < str.Length; i++) { - if (str == null) + if (str[i] != c) { - throw new ArgumentNullException(nameof(str)); + continue; } - var count = 0; - for (var i = 0; i < str.Length; i++) + if ((++count) == n) { - if (str[i] != c) - { - continue; - } - - if ((++count) == n) - { - return i; - } + return i; } - - return -1; } - /// - /// Removes first occurrence of the given postfixes from end of the given string. - /// Ordering is important. If one of the postFixes is matched, others will not be tested. - /// - /// The string. - /// one or more postfix. - /// Modified string or the same string if it has not any of given postfixes - public static string RemovePostFix(this string str, params string[] postFixes) - { - if (str == null) - { - return null; - } - - if (str == string.Empty) - { - return string.Empty; - } + return -1; + } - if (postFixes.IsNullOrEmpty()) - { - return str; - } + /// + /// Removes first occurrence of the given postfixes from end of the given string. + /// Ordering is important. If one of the postFixes is matched, others will not be tested. + /// + /// The string. + /// one or more postfix. + /// Modified string or the same string if it has not any of given postfixes + public static string RemovePostFix(this string str, params string[] postFixes) + { + if (str == null) + { + return null; + } - foreach (var postFix in postFixes) - { - if (str.EndsWith(postFix)) - { - return str.Left(str.Length - postFix.Length); - } - } + if (str == string.Empty) + { + return string.Empty; + } + if (postFixes.IsNullOrEmpty()) + { return str; } - /// - /// Removes first occurrence of the given prefixes from beginning of the given string. - /// Ordering is important. If one of the preFixes is matched, others will not be tested. - /// - /// The string. - /// one or more prefix. - /// Modified string or the same string if it has not any of given prefixes - public static string RemovePreFix(this string str, params string[] preFixes) + foreach (var postFix in postFixes) { - if (str == null) + if (str.EndsWith(postFix)) { - return null; + return str.Left(str.Length - postFix.Length); } + } - if (str == string.Empty) - { - return string.Empty; - } + return str; + } - if (preFixes.IsNullOrEmpty()) - { - return str; - } + /// + /// Removes first occurrence of the given prefixes from beginning of the given string. + /// Ordering is important. If one of the preFixes is matched, others will not be tested. + /// + /// The string. + /// one or more prefix. + /// Modified string or the same string if it has not any of given prefixes + public static string RemovePreFix(this string str, params string[] preFixes) + { + if (str == null) + { + return null; + } - foreach (var preFix in preFixes) - { - if (str.StartsWith(preFix)) - { - return str.Right(str.Length - preFix.Length); - } - } + if (str == string.Empty) + { + return string.Empty; + } + if (preFixes.IsNullOrEmpty()) + { return str; } - /// - /// Gets a substring of a string from end of the string. - /// - /// Thrown if is null - /// Thrown if is bigger that string's length - public static string Right(this string str, int len) + foreach (var preFix in preFixes) { - if (str == null) + if (str.StartsWith(preFix)) { - throw new ArgumentNullException("str"); + return str.Right(str.Length - preFix.Length); } + } - if (str.Length < len) - { - throw new ArgumentException("len argument can not be bigger than given string's length!"); - } + return str; + } - return str.Substring(str.Length - len, len); + /// + /// Gets a substring of a string from end of the string. + /// + /// Thrown if is null + /// Thrown if is bigger that string's length + public static string Right(this string str, int len) + { + if (str == null) + { + throw new ArgumentNullException("str"); } - /// - /// Uses string.Split method to split given string by given separator. - /// - public static string[] Split(this string str, string separator) + if (str.Length < len) { - return str.Split(new[] { separator }, StringSplitOptions.None); + throw new ArgumentException("len argument can not be bigger than given string's length!"); } - /// - /// Uses string.Split method to split given string by given separator. - /// - public static string[] Split(this string str, string separator, StringSplitOptions options) + return str.Substring(str.Length - len, len); + } + + /// + /// Uses string.Split method to split given string by given separator. + /// + public static string[] Split(this string str, string separator) + { + return str.Split(new[] { separator }, StringSplitOptions.None); + } + + /// + /// Uses string.Split method to split given string by given separator. + /// + public static string[] Split(this string str, string separator, StringSplitOptions options) + { + return str.Split(new[] { separator }, options); + } + + /// + /// Uses string.Split method to split given string by . + /// + public static string[] SplitToLines(this string str) + { + return str.Split(Environment.NewLine); + } + + /// + /// Uses string.Split method to split given string by . + /// + public static string[] SplitToLines(this string str, StringSplitOptions options) + { + return str.Split(Environment.NewLine, options); + } + + /// + /// Converts PascalCase string to camelCase string. + /// + /// String to convert + /// Invariant culture + /// camelCase of the string + public static string ToCamelCase(this string str, bool invariantCulture = true) + { + if (string.IsNullOrWhiteSpace(str)) { - return str.Split(new[] { separator }, options); + return str; } - /// - /// Uses string.Split method to split given string by . - /// - public static string[] SplitToLines(this string str) + if (str.Length == 1) { - return str.Split(Environment.NewLine); + return invariantCulture ? str.ToLowerInvariant() : str.ToLower(); } - /// - /// Uses string.Split method to split given string by . - /// - public static string[] SplitToLines(this string str, StringSplitOptions options) + return (invariantCulture ? char.ToLowerInvariant(str[0]) : char.ToLower(str[0])) + str.Substring(1); + } + + /// + /// Converts PascalCase string to camelCase string in specified culture. + /// + /// String to convert + /// An object that supplies culture-specific casing rules + /// camelCase of the string + public static string ToCamelCase(this string str, CultureInfo culture) + { + if (string.IsNullOrWhiteSpace(str)) { - return str.Split(Environment.NewLine, options); + return str; } - /// - /// Converts PascalCase string to camelCase string. - /// - /// String to convert - /// Invariant culture - /// camelCase of the string - public static string ToCamelCase(this string str, bool invariantCulture = true) + if (str.Length == 1) { - if (string.IsNullOrWhiteSpace(str)) - { - return str; - } - - if (str.Length == 1) - { - return invariantCulture ? str.ToLowerInvariant() : str.ToLower(); - } - - return (invariantCulture ? char.ToLowerInvariant(str[0]) : char.ToLower(str[0])) + str.Substring(1); + return str.ToLower(culture); } - /// - /// Converts PascalCase string to camelCase string in specified culture. - /// - /// String to convert - /// An object that supplies culture-specific casing rules - /// camelCase of the string - public static string ToCamelCase(this string str, CultureInfo culture) + return char.ToLower(str[0], culture) + str.Substring(1); + } + + /// + /// Converts given PascalCase/camelCase string to sentence (by splitting words by space). + /// Example: "ThisIsSampleSentence" is converted to "This is a sample sentence". + /// + /// String to convert. + /// Invariant culture + public static string ToSentenceCase(this string str, bool invariantCulture = false) + { + if (string.IsNullOrWhiteSpace(str)) { - if (string.IsNullOrWhiteSpace(str)) - { - return str; - } + return str; + } - if (str.Length == 1) - { - return str.ToLower(culture); - } + return Regex.Replace( + str, + "[a-z][A-Z]", + m => m.Value[0] + " " + (invariantCulture ? char.ToLowerInvariant(m.Value[1]) : char.ToLower(m.Value[1])) + ); + } - return char.ToLower(str[0], culture) + str.Substring(1); + /// + /// Converts given PascalCase/camelCase string to sentence (by splitting words by space). + /// Example: "ThisIsSampleSentence" is converted to "This is a sample sentence". + /// + /// String to convert. + /// An object that supplies culture-specific casing rules. + public static string ToSentenceCase(this string str, CultureInfo culture) + { + if (string.IsNullOrWhiteSpace(str)) + { + return str; } - /// - /// Converts given PascalCase/camelCase string to sentence (by splitting words by space). - /// Example: "ThisIsSampleSentence" is converted to "This is a sample sentence". - /// - /// String to convert. - /// Invariant culture - public static string ToSentenceCase(this string str, bool invariantCulture = false) - { - if (string.IsNullOrWhiteSpace(str)) - { - return str; - } + return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1], culture)); + } - return Regex.Replace( - str, - "[a-z][A-Z]", - m => m.Value[0] + " " + (invariantCulture ? char.ToLowerInvariant(m.Value[1]) : char.ToLower(m.Value[1])) - ); + /// + /// Converts string to enum value. + /// + /// Type of enum + /// String value to convert + /// Returns enum object + public static T ToEnum(this string value) + where T : struct + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); } - /// - /// Converts given PascalCase/camelCase string to sentence (by splitting words by space). - /// Example: "ThisIsSampleSentence" is converted to "This is a sample sentence". - /// - /// String to convert. - /// An object that supplies culture-specific casing rules. - public static string ToSentenceCase(this string str, CultureInfo culture) - { - if (string.IsNullOrWhiteSpace(str)) - { - return str; - } + return (T)Enum.Parse(typeof(T), value); + } - return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1], culture)); + /// + /// Converts string to enum value. + /// + /// Type of enum + /// String value to convert + /// Ignore case + /// Returns enum object + public static T ToEnum(this string value, bool ignoreCase) + where T : struct + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); } - /// - /// Converts string to enum value. - /// - /// Type of enum - /// String value to convert - /// Returns enum object - public static T ToEnum(this string value) - where T : struct + return (T)Enum.Parse(typeof(T), value, ignoreCase); + } + + public static string ToMd5(this string str) + { + using (var md5 = MD5.Create()) { - if (value == null) + var inputBytes = Encoding.UTF8.GetBytes(str); + var hashBytes = md5.ComputeHash(inputBytes); + + var sb = new StringBuilder(); + foreach (var hashByte in hashBytes) { - throw new ArgumentNullException(nameof(value)); + sb.Append(hashByte.ToString("X2")); } - return (T)Enum.Parse(typeof(T), value); + return sb.ToString(); } + } - /// - /// Converts string to enum value. - /// - /// Type of enum - /// String value to convert - /// Ignore case - /// Returns enum object - public static T ToEnum(this string value, bool ignoreCase) - where T : struct + /// + /// Converts camelCase string to PascalCase string. + /// + /// String to convert + /// Invariant culture + /// PascalCase of the string + public static string ToPascalCase(this string str, bool invariantCulture = true) + { + if (string.IsNullOrWhiteSpace(str)) { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - return (T)Enum.Parse(typeof(T), value, ignoreCase); + return str; } - public static string ToMd5(this string str) + if (str.Length == 1) { - using (var md5 = MD5.Create()) - { - var inputBytes = Encoding.UTF8.GetBytes(str); - var hashBytes = md5.ComputeHash(inputBytes); + return invariantCulture ? str.ToUpperInvariant(): str.ToUpper(); + } - var sb = new StringBuilder(); - foreach (var hashByte in hashBytes) - { - sb.Append(hashByte.ToString("X2")); - } + return (invariantCulture ? char.ToUpperInvariant(str[0]) : char.ToUpper(str[0])) + str.Substring(1); + } - return sb.ToString(); - } + /// + /// Converts camelCase string to PascalCase string in specified culture. + /// + /// String to convert + /// An object that supplies culture-specific casing rules + /// PascalCase of the string + public static string ToPascalCase(this string str, CultureInfo culture) + { + if (string.IsNullOrWhiteSpace(str)) + { + return str; } - /// - /// Converts camelCase string to PascalCase string. - /// - /// String to convert - /// Invariant culture - /// PascalCase of the string - public static string ToPascalCase(this string str, bool invariantCulture = true) + if (str.Length == 1) { - if (string.IsNullOrWhiteSpace(str)) - { - return str; - } + return str.ToUpper(culture); + } - if (str.Length == 1) - { - return invariantCulture ? str.ToUpperInvariant(): str.ToUpper(); - } + return char.ToUpper(str[0], culture) + str.Substring(1); + } - return (invariantCulture ? char.ToUpperInvariant(str[0]) : char.ToUpper(str[0])) + str.Substring(1); + /// + /// Gets a substring of a string from beginning of the string if it exceeds maximum length. + /// + /// Thrown if is null + public static string Truncate(this string str, int maxLength) + { + if (str == null) + { + return null; } - /// - /// Converts camelCase string to PascalCase string in specified culture. - /// - /// String to convert - /// An object that supplies culture-specific casing rules - /// PascalCase of the string - public static string ToPascalCase(this string str, CultureInfo culture) + if (str.Length <= maxLength) { - if (string.IsNullOrWhiteSpace(str)) - { - return str; - } - - if (str.Length == 1) - { - return str.ToUpper(culture); - } - - return char.ToUpper(str[0], culture) + str.Substring(1); + return str; } - /// - /// Gets a substring of a string from beginning of the string if it exceeds maximum length. - /// - /// Thrown if is null - public static string Truncate(this string str, int maxLength) - { - if (str == null) - { - return null; - } + return str.Left(maxLength); + } - if (str.Length <= maxLength) - { - return str; - } + /// + /// Gets a substring of a string from beginning of the string if it exceeds maximum length. + /// It adds a "..." postfix to end of the string if it's truncated. + /// Returning string can not be longer than maxLength. + /// + /// Thrown if is null + public static string TruncateWithPostfix(this string str, int maxLength) + { + return TruncateWithPostfix(str, maxLength, "..."); + } - return str.Left(maxLength); + /// + /// Gets a substring of a string from beginning of the string if it exceeds maximum length. + /// It adds given to end of the string if it's truncated. + /// Returning string can not be longer than maxLength. + /// + /// Thrown if is null + public static string TruncateWithPostfix(this string str, int maxLength, string postfix) + { + if (str == null) + { + return null; } - /// - /// Gets a substring of a string from beginning of the string if it exceeds maximum length. - /// It adds a "..." postfix to end of the string if it's truncated. - /// Returning string can not be longer than maxLength. - /// - /// Thrown if is null - public static string TruncateWithPostfix(this string str, int maxLength) + if (str == string.Empty || maxLength == 0) { - return TruncateWithPostfix(str, maxLength, "..."); + return string.Empty; } - /// - /// Gets a substring of a string from beginning of the string if it exceeds maximum length. - /// It adds given to end of the string if it's truncated. - /// Returning string can not be longer than maxLength. - /// - /// Thrown if is null - public static string TruncateWithPostfix(this string str, int maxLength, string postfix) + if (str.Length <= maxLength) { - if (str == null) - { - return null; - } - - if (str == string.Empty || maxLength == 0) - { - return string.Empty; - } - - if (str.Length <= maxLength) - { - return str; - } - - if (maxLength <= postfix.Length) - { - return postfix.Left(maxLength); - } + return str; + } - return str.Left(maxLength - postfix.Length) + postfix; + if (maxLength <= postfix.Length) + { + return postfix.Left(maxLength); } - /// - /// Helper method - /// - /// - /// - public static string Underscore(this string value) - => string.Concat(value.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x : x.ToString())) - .ToLowerInvariant(); + return str.Left(maxLength - postfix.Length) + postfix; } + + /// + /// Helper method + /// + /// + /// + public static string Underscore(this string value) + => string.Concat(value.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x : x.ToString())) + .ToLowerInvariant(); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/MongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/MongoRepository.cs index 98cb51bd..e882d4c4 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/MongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/MongoRepository.cs @@ -3,7 +3,6 @@ using Genocs.Core.Domain.Repositories; using MongoDB.Driver; using MongoDB.Driver.Linq; -using System; using System.Linq.Expressions; namespace Genocs.Persistence.MongoDb.Repositories; diff --git a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs index 46be433b..d8e17690 100644 --- a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs +++ b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/InMemoryDynamicQueriesUnitTests.cs @@ -237,7 +237,7 @@ public async Task ApplyGreaterThanOperatorToNullableIntGetItemTest() { var users = await GetUsers(); - QueryItem queryItem = new QueryItem(propertyName: "Childrens", propertyValue: "2", propertyType: "numeric", operatorType: QueryOperator.GreaterThan); + QueryItem queryItem = new QueryItem(propertyName: "Childs", propertyValue: "2", propertyType: "numeric", operatorType: QueryOperator.GreaterThan); IQueryable usersQuery = users.AsQueryable(); usersQuery = usersQuery.Where(DynamicQueryBuilder.BuildAdvancedSearchExpressionTree(queryItem, "User")); @@ -246,8 +246,6 @@ public async Task ApplyGreaterThanOperatorToNullableIntGetItemTest() Assert.Single(result); } - - [Fact] public async Task ApplyOperatorWithQueryItemListTest() { @@ -282,7 +280,6 @@ public async Task ApplyCombinedFirstNameAndAgeReturnEmpty() Assert.Empty(result); } - [Fact] public async Task ApplyOperatorOnNestedObjectThatCanBeNull() { diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index cca64999..6a2f5323 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -9,7 +9,6 @@ - all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -28,8 +27,15 @@ - + + + + + + + + diff --git a/src/Genocs.QueryBuilder/QueryItem.cs b/src/Genocs.QueryBuilder/QueryItem.cs index e650685a..51b5466f 100644 --- a/src/Genocs.QueryBuilder/QueryItem.cs +++ b/src/Genocs.QueryBuilder/QueryItem.cs @@ -1,10 +1,10 @@ -namespace Genocs.QueryBuilder +namespace Genocs.QueryBuilder; + +/// +/// The QueryItem class +/// +public class QueryItem { - /// - /// - /// - public class QueryItem - { public QueryItem(string propertyName, string propertyValue, string propertyType = "string", @@ -34,5 +34,4 @@ public QueryItem(string propertyName, public string PropertyValue { get; set; } public QueryOperator OperatorType { get; set; } public bool ParentCanBeNull { get; set; } -} } \ No newline at end of file diff --git a/src/Genocs.Secrets.Vault/Extensions.cs b/src/Genocs.Secrets.Vault/Extensions.cs index c0ce47b4..5594ffba 100644 --- a/src/Genocs.Secrets.Vault/Extensions.cs +++ b/src/Genocs.Secrets.Vault/Extensions.cs @@ -16,7 +16,7 @@ namespace Genocs.Secrets.Vault; /// -/// The Extensions helper class +/// The Extensions helper class. /// public static class Extensions { diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index df4f35a1..f0f435b3 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -7,6 +7,7 @@ false false + @@ -19,6 +20,7 @@ all + all diff --git a/src/Genocs.ServiceBusAzure.UnitTests/SimpleUnitTests.cs b/src/Genocs.ServiceBusAzure.UnitTests/SimpleUnitTests.cs index 95b53906..5c7d02bb 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/SimpleUnitTests.cs +++ b/src/Genocs.ServiceBusAzure.UnitTests/SimpleUnitTests.cs @@ -1,6 +1,6 @@ -namespace Genocs.ServiceBusAzure.UnitTests; +using Xunit; -using Xunit; +namespace Genocs.ServiceBusAzure.UnitTests; public class SimpleUnitTests { From 8f328458cfdc28303e78f1d87d11e98a9f348280 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 11:13:31 +0100 Subject: [PATCH 009/104] Updated clients to net8 --- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 2 +- .../Genocs.Core.Demo.Infrastructure.csproj | 2 +- .../Genocs.Core.Demo.WebApi.csproj | 2 +- .../Genocs.Core.Demo.Worker.csproj | 2 +- .../Genocs.Core.UnitTests.csproj | 2 +- src/Genocs.Core/Builders/Extensions.cs | 45 ++++++++++--------- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 2 +- .../Genocs.APIGateway.csproj | 2 +- .../Genocs.Identities.Application.csproj | 2 +- .../Genocs.Identities.WebApi.csproj | 2 +- .../Genocs.Orders.WebApi.csproj | 2 +- .../Genocs.Products.WebApi.csproj | 2 +- .../Genocs.SignalR.WebApi.csproj | 2 +- 16 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 51e4ed34..d22d8958 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 5acf05d1..2bb7f0e8 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj index 2399d182..25bdc20b 100644 --- a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj +++ b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index b6698bcd..e45798f7 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 435196cd..c2178982 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 1ec0ce24..f60018cf 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs index 790822de..8c785fda 100644 --- a/src/Genocs.Core/Builders/Extensions.cs +++ b/src/Genocs.Core/Builders/Extensions.cs @@ -6,18 +6,17 @@ namespace Genocs.Core.Builders; - /// -/// Builders Extensions +/// Builders Extensions. /// public static class Extensions { /// - /// The Builder + /// The Builder. /// /// /// - /// + /// The builder. public static IGenocsBuilder AddGenocs(this IServiceCollection services, IConfiguration? configuration = null) { var builder = GenocsBuilder.Create(services, configuration); @@ -30,17 +29,23 @@ public static IGenocsBuilder AddGenocs(this IServiceCollection services, IConfig { return builder; } - var version = appOptions.DisplayVersion ? $" {appOptions.Version}" : string.Empty; - Console.WriteLine(Figgle.FiggleFonts.Doom.Render($"{appOptions.Name}{version}")); + + string version = appOptions.DisplayVersion ? $" {appOptions.Version}" : string.Empty; + Console.WriteLine(Figgle.FiggleFonts.Doom.Render(appOptions.Name + version)); + ConsoleColor current = Console.BackgroundColor; + + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine("Runtime Version: {0}", Environment.Version.ToString()); + Console.ForegroundColor = current; return builder; } /// - /// Run the application initializer + /// Run the application initializer. /// - /// - /// + /// The application builder. + /// The application builder. public static IApplicationBuilder UseGenocs(this IApplicationBuilder app) { using var scope = app.ApplicationServices.CreateScope(); @@ -51,12 +56,12 @@ public static IApplicationBuilder UseGenocs(this IApplicationBuilder app) } /// - /// Get option helper method + /// Get option helper method. /// - /// + /// The option type parameter. /// /// - /// + /// The option. public static TModel GetOptions(this IConfiguration configuration, string sectionName) where TModel : new() { @@ -66,22 +71,22 @@ public static TModel GetOptions(this IConfiguration configuration, strin } /// - /// Get option helper method + /// Get option helper method. /// - /// - /// - /// - /// - public static TModel GetOptions(this IGenocsBuilder builder, string settingsSectionName) + /// The option type parameter. + /// The builder. + /// The default section name. + /// The option. + public static TModel GetOptions(this IGenocsBuilder builder, string sectionName) where TModel : new() { if (builder.Configuration != null) { - return builder.Configuration.GetOptions(settingsSectionName); + return builder.Configuration.GetOptions(sectionName); } using var serviceProvider = builder.Services.BuildServiceProvider(); var configuration = serviceProvider.GetRequiredService(); - return configuration.GetOptions(settingsSectionName); + return configuration.GetOptions(sectionName); } } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 0bdfd86d..992910fe 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 6a2f5323..85761c70 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index f0f435b3..5edd8867 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 4242b21c..945409db 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 2401ed65..7299d2b4 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable diff --git a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj index 4e62d6d2..3192bd1b 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj +++ b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable _genocs diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index e0de5165..504d6de6 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable _genocs diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index 4dc51975..4870b644 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable _genocs diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 9232e274..46fada65 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 enable enable _genocs From dd10e1afa7a1cf6f5c7b1780413fff9ae9cd0775 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 11:41:26 +0100 Subject: [PATCH 010/104] Pagages updated wip --- Directory.Build.props | 2 +- src/Genocs.Auth/Genocs.Auth.csproj | 19 ++++++++++--------- src/Genocs.Common/Genocs.Common.csproj | 2 +- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 2 +- .../Genocs.Core.Demo.Infrastructure.csproj | 2 +- .../Genocs.Core.Demo.WebApi.csproj | 3 +-- .../Genocs.Core.Demo.Worker.csproj | 3 +-- .../Genocs.Core.UnitTests.csproj | 2 +- src/Genocs.Core/Genocs.Core.csproj | 4 ++-- .../Genocs.Discovery.Consul.csproj | 2 +- .../Genocs.HTTP.RestEase.csproj | 2 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 4 ++-- .../Genocs.LoadBalancing.Fabio.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 8 ++++---- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 2 +- .../Genocs.MessageBrokers.Outbox.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- .../Genocs.MessageBrokers.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- .../Genocs.Monitoring.csproj | 2 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 ++-- .../Genocs.QueryBuilder.csproj | 2 +- .../Genocs.Secrets.Vault.csproj | 2 +- src/Genocs.Security/Genocs.Security.csproj | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 2 +- .../Genocs.ServiceBusAzure.csproj | 2 +- src/Genocs.Tracing/Genocs.Tracing.csproj | 2 +- .../Genocs.WebApi.CQRS.csproj | 2 +- .../Genocs.WebApi.Security.csproj | 2 +- .../Genocs.WebApi.Swagger.csproj | 2 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 2 +- .../Genocs.APIGateway.csproj | 2 +- .../Genocs.Identities.Application.csproj | 2 +- .../Genocs.Identities.WebApi.csproj | 3 +-- .../Genocs.Orders.WebApi.csproj | 2 +- .../Genocs.Products.WebApi.csproj | 2 +- .../Genocs.SignalR.WebApi.csproj | 2 +- 41 files changed, 56 insertions(+), 58 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6d96d9df..c58c334e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 026a4723..845168c0 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -50,9 +50,9 @@ - - - + + + @@ -60,17 +60,18 @@ - - - - + + + + + - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 67639342..31cc4a1a 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -43,7 +43,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index d22d8958..48fd17f8 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -20,7 +20,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 2bb7f0e8..1ad003f7 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -19,7 +19,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj index 25bdc20b..4b8f673d 100644 --- a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj +++ b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index e45798f7..e0e202c6 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -13,7 +13,6 @@ - @@ -27,7 +26,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index c2178982..6b1d02f5 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -17,7 +17,6 @@ - @@ -36,7 +35,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index f60018cf..3a69fbd9 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -21,7 +21,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 515041e4..f82317a5 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -64,7 +64,7 @@ - + @@ -80,7 +80,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 1fb0266d..b344febb 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -58,7 +58,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 18f92359..5b4ac798 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -63,7 +63,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index f4e14a63..e16d1ac2 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -51,12 +51,12 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 6e13cbde..34570824 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -56,7 +56,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 027b865c..bfa6de1d 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -52,20 +52,20 @@ - + - + - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 40f3ffd9..9c54804e 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -53,7 +53,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 250c084d..905af51b 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -51,7 +51,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 5f3db936..e9b5c60b 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -57,7 +57,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index e1ec685b..4941b75f 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -52,7 +52,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 6f524a00..b0edaf2b 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -84,7 +84,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 626c5152..7d8179c5 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -63,7 +63,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 992910fe..733b05ae 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -34,7 +34,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 4ac9aea0..67e23f7d 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -56,7 +56,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 933d7f5a..c0044ef1 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -55,7 +55,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 85761c70..3cc47d82 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -15,7 +15,7 @@ - + all @@ -39,7 +39,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 4495927c..c95075e6 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -43,7 +43,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index fa69e9c7..8c04dca1 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -56,7 +56,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 99c0b403..395b0e2a 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -52,7 +52,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 5edd8867..960a7886 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index beea6ba5..bf5bb8bf 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -58,7 +58,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 2dae17c0..0921f078 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -67,7 +67,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 6406246b..2568e7c3 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -53,7 +53,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 1be0fd48..8bef31a5 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -64,7 +64,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index b48c4b52..864beb9c 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -60,7 +60,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 38dec1e4..9da21a8c 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -61,7 +61,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 945409db..00445ede 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -50,7 +50,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 7299d2b4..9f13a8c6 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -43,7 +43,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj index 3192bd1b..375b3935 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj +++ b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj @@ -10,7 +10,6 @@ - @@ -28,7 +27,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 504d6de6..784377a3 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -48,7 +48,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index 4870b644..bb25c5c8 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -54,7 +54,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 46fada65..fb93a363 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -55,7 +55,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 5a3ab6d535046b6f35d40f682c6e3fa371905db4 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 12:16:52 +0100 Subject: [PATCH 011/104] Cleanup config file --- Directory.Build.props | 8 +++++--- src/Genocs.Auth/Genocs.Auth.csproj | 12 +----------- src/Genocs.Common/Genocs.Common.csproj | 14 ++------------ .../Genocs.Core.Demo.Contracts.csproj | 12 ------------ .../Genocs.Core.Demo.Domain.csproj | 9 --------- .../Genocs.Core.Demo.Infrastructure.csproj | 9 --------- .../Genocs.Core.Demo.WebApi.csproj | 9 --------- .../Genocs.Core.Demo.Worker.csproj | 10 ---------- .../Genocs.Core.UnitTests.csproj | 9 --------- src/Genocs.Core/Genocs.Core.csproj | 11 ----------- .../Genocs.Discovery.Consul.csproj | 11 ----------- .../Genocs.HTTP.RestEase.csproj | 10 ---------- src/Genocs.HTTP/Genocs.HTTP.csproj | 10 ---------- .../Genocs.LoadBalancing.Fabio.csproj | 10 ---------- src/Genocs.Logging/Genocs.Logging.csproj | 14 ++------------ .../Genocs.MessageBrokers.Outbox.MongoDB.csproj | 9 --------- .../Genocs.MessageBrokers.Outbox.csproj | 9 --------- .../Genocs.MessageBrokers.RabbitMQ.csproj | 9 --------- .../Genocs.MessageBrokers.csproj | 10 ---------- src/Genocs.Metrics/Genocs.Metrics.csproj | 11 ----------- src/Genocs.Monitoring/Genocs.Monitoring.csproj | 11 ----------- .../Genocs.Persistence.MongoDB.UnitTests.csproj | 9 --------- .../Genocs.Persistence.MongoDb.csproj | 10 ---------- .../Genocs.Persistence.Redis.csproj | 10 ---------- .../Genocs.QueryBuilder.UnitTests.csproj | 8 -------- src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj | 10 ---------- .../Genocs.Secrets.Vault.csproj | 11 ----------- src/Genocs.Security/Genocs.Security.csproj | 11 ----------- .../Genocs.ServiceBusAzure.UnitTests.csproj | 9 --------- .../Genocs.ServiceBusAzure.csproj | 10 ---------- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 3 --- src/Genocs.Tracing/Genocs.Tracing.csproj | 10 ---------- src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj | 11 ----------- .../Genocs.WebApi.Security.csproj | 11 ----------- .../Genocs.WebApi.Swagger.csproj | 11 ----------- src/Genocs.WebApi/Genocs.WebApi.csproj | 11 ----------- .../Genocs.APIGateway/Genocs.APIGateway.csproj | 9 --------- .../Genocs.Identities.Application.csproj | 10 ---------- .../Genocs.Identities.WebApi.csproj | 11 +---------- .../Genocs.Orders.WebApi.csproj | 8 -------- .../Genocs.Products.WebApi.csproj | 9 --------- .../Genocs.SignalR.WebApi.csproj | 10 ---------- 42 files changed, 11 insertions(+), 408 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c58c334e..88b9512c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,11 +4,11 @@ enable enable true - True false false $(MSBuildThisFileDirectory)dotnet.ruleset - true + True + True $(OutputPath)$(AssemblyName).xml @@ -17,10 +17,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + + all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 845168c0..c04827fd 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Auth 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -69,12 +66,5 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 31cc4a1a..daec94f7 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -1,9 +1,7 @@ - + netstandard2.1 - enable - enable Genocs.Common 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -41,12 +38,5 @@ \ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 48fd17f8..0758161e 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -2,28 +2,16 @@ net8.0 - enable - enable false false - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 1ad003f7..c8fab86c 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable false false @@ -18,11 +16,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj index 4b8f673d..dc1d6876 100644 --- a/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj +++ b/src/Genocs.Core.Demo.Infrastructure/Genocs.Core.Demo.Infrastructure.csproj @@ -2,17 +2,8 @@ net8.0 - enable - enable false false - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index e0e202c6..767607a9 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable false false __genocs @@ -25,11 +23,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 6b1d02f5..0a191434 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable false false __genocs @@ -24,7 +22,6 @@ - @@ -33,11 +30,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 3a69fbd9..d0778a8d 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable false false @@ -20,11 +18,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - \ No newline at end of file diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index f82317a5..d51cbb9f 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -2,8 +2,6 @@ netstandard2.1;net6.0;net7.0;net8.0 - enable - enable Genocs.Core 10.0 true @@ -24,8 +22,6 @@ Nove to NET8 True latest - True - True @@ -79,11 +75,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index b344febb..f0638c19 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Discovery.Consul 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -56,12 +53,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 5b4ac798..71d5cb3f 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -3,8 +3,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.HTTP.RestEase 10.0 true @@ -25,7 +23,6 @@ Aligned to the ecosystem True latest - True @@ -61,11 +58,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index e16d1ac2..56422747 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.HTTP 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -55,11 +52,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 34570824..ffdf5ccd 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.LoadBalancing.Fabio 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -55,11 +52,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index bfa6de1d..cb8d94cc 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Logging 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -57,18 +54,11 @@ - + - + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 9c54804e..adb98f23 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.MessageBrokers.Outbox.MongoDB 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -52,10 +49,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 905af51b..de9da6e1 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.MessageBrokers.Outbox 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -50,10 +47,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index e9b5c60b..67c51a15 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.MessageBrokers.RabbitMQ 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -56,11 +53,5 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 4941b75f..c5b04270 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.MessageBrokers 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -51,11 +48,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index b0edaf2b..40f1d414 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Metrics 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -82,12 +79,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 7d8179c5..b01bb0a2 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Monitoring 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -61,12 +58,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 733b05ae..7fcd5d08 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable false false Genocs @@ -33,11 +31,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 67e23f7d..b5a2258a 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Persistence.MongoDb 10.0 true @@ -24,7 +22,6 @@ Moved to NET7.0 True latest - True @@ -55,11 +52,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index c0044ef1..a485f40e 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Persistence.Redis 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -54,11 +51,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 3cc47d82..09355ae3 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable false false @@ -38,10 +36,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index c95075e6..00aeca30 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -2,8 +2,6 @@ netstandard2.1 - enable - enable Genocs.QueryBuilder 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -42,11 +39,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 8c04dca1..20b2909d 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Secrets.Vault 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -54,12 +51,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 395b0e2a..40b3b78c 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Security 10.0 true @@ -24,7 +22,6 @@ Moved tAligned to the ecosystem True latest - True @@ -42,7 +39,6 @@ - @@ -51,11 +47,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 960a7886..96078a67 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable false false @@ -21,11 +19,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - \ No newline at end of file diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index bf5bb8bf..2ffa8e23 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.ServiceBusAzure 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -57,11 +54,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index 599e4c9b..f255ce05 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Tracing.Jaeger.RabbitMQ 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 0921f078..aa55c854 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.Tracing 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -66,11 +63,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 2568e7c3..c4d1239e 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.WebApi.CQRS 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -51,12 +48,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 8bef31a5..7b275cd1 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.WebApi.Security 10.0 true @@ -24,8 +22,6 @@ Aligned to the ecosystem True latest - True - True @@ -63,11 +59,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 864beb9c..3226607d 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -2,8 +2,6 @@ net6.0 - enable - enable Genocs.WebApi.Swagger 10.0 true @@ -24,8 +22,6 @@ Aligned to the ecosystem True latest - True - True @@ -59,11 +55,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 9da21a8c..8ef3e008 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -2,8 +2,6 @@ net6.0;net7.0;net8.0 - enable - enable Genocs.WebApi 10.0 true @@ -24,7 +22,6 @@ Aligned to the ecosystem True latest - True @@ -59,12 +56,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 00445ede..67c2681a 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable @@ -49,11 +47,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 9f13a8c6..0dfaf34a 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable @@ -41,12 +39,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj index 375b3935..39116205 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj +++ b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable _genocs Linux ..\.. @@ -25,12 +23,5 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 784377a3..265b8599 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable _genocs Linux ..\.. @@ -47,10 +45,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index bb25c5c8..411d6070 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -2,8 +2,6 @@ net8.0 - enable - enable _genocs Linux ..\.. @@ -53,11 +51,4 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index fb93a363..558b0e73 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -1,8 +1,6 @@  net8.0 - enable - enable _genocs Linux ..\.. @@ -53,12 +51,4 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - \ No newline at end of file From a7dd4583ac302f1841d2b1c152849deb761f3cc2 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 12:30:58 +0100 Subject: [PATCH 012/104] updated docker files and github actions --- .github/dependabot.yml | 2 +- .github/workflows/build_and_test.yml | 6 ++---- .github/workflows/dockerhub-publish.yml | 10 +++++----- .github/workflows/manual.yml | 8 ++++---- .github/workflows/nuget-publish.yml | 6 +++--- demo-webapi.dockerfile | 6 ++---- demo-worker.dockerfile | 6 ++---- src/apps/apigateway.dockerfile | 6 ++---- src/apps/identity-webapi.dockerfile | 6 ++---- src/apps/order-webapi.dockerfile | 6 ++---- src/apps/product-webapi.dockerfile | 7 ++----- src/apps/signalr-webapi.dockerfile | 22 +++++++++++++--------- 12 files changed, 40 insertions(+), 51 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 03ec5454..c982b5fe 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,4 +8,4 @@ updates: - package-ecosystem: "nuget" # See documentation for possible values directory: "/" # Location of package manifests schedule: - interval: "daily" + interval: "weekly" # How often to check for updates (can be "daily", "weekly" or "monthly") diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 50b58032..794d6d59 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -1,6 +1,4 @@ -# This is a manually triggered dockerhub build and publish - -name: Publish to Dockerhub +name: Build test and pack on: push: @@ -20,7 +18,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml index 3dd29382..8b656b21 100644 --- a/.github/workflows/dockerhub-publish.yml +++ b/.github/workflows/dockerhub-publish.yml @@ -31,7 +31,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore @@ -48,11 +48,11 @@ jobs: - name: Docker Hub Log in uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a with: - username: ${{secrets.DOCKER_USERNAME}} - password: ${{secrets.DOCKER_PASSWORD}} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push image to Dockerhub run: | - docker build -f webapi.dockerfile -t genocs/demo-webapi:${{github.event.inputs.version}} -t genocs/demo-webapi:latest . - docker push genocs/demo-webapi:${{github.event.inputs.version}} + docker build -f webapi.dockerfile -t genocs/demo-webapi:${{ github.event.inputs.version }} -t genocs/demo-webapi:latest . + docker push genocs/demo-webapi:${{ github.event.inputs.version }} docker push genocs/demo-webapi:latest diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 99a3c53a..47ebde80 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -29,7 +29,7 @@ jobs: steps: # Runs a single command using the runners shell - name: Send greeting - run: echo "Hello ${{github.event.inputs.name}}" + run: echo "Hello ${{ github.event.inputs.name }}" - name: Print Run Number run: echo "Hello $env:GITHUB_RUN_NUMBER" @@ -38,10 +38,10 @@ jobs: run: echo "Hello $env:GITHUB_RUN_ATTEMPT" - name: Output Run ID - run: echo ${{github.run_id}} + run: echo ${{ github.run_id }} - name: Output Run Number - run: echo ${{github.run_number}} + run: echo ${{ github.run_number }} - name: Output Run Attempt - run: echo ${{github.run_attempt}} + run: echo ${{ github.run_attempt }} diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index d3699f74..aa8893aa 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -31,7 +31,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore @@ -43,7 +43,7 @@ jobs: run: dotnet test --no-build --verbosity normal - name: Pack - run: dotnet pack -c Debug -o out -p:PackageVersion=${{github.event.inputs.version}} --no-build --verbosity normal + run: dotnet pack -c Debug -o out -p:PackageVersion=${{ github.event.inputs.version }} --no-build --verbosity normal - name: Push packages to Nuget - run: dotnet nuget push ./out/*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json --skip-duplicate --no-symbols + run: dotnet nuget push ./out/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate --no-symbols diff --git a/demo-webapi.dockerfile b/demo-webapi.dockerfile index 8ad8f855..963017d9 100644 --- a/demo-webapi.dockerfile +++ b/demo-webapi.dockerfile @@ -1,13 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -#FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /src COPY ["src/Genocs.Core", "src/Genocs.Core/"] COPY ["src/Genocs.Common", "src/Genocs.Common/"] diff --git a/demo-worker.dockerfile b/demo-worker.dockerfile index 80a9bb69..dc372871 100644 --- a/demo-worker.dockerfile +++ b/demo-worker.dockerfile @@ -1,13 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -#FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /src COPY ["src/Genocs.Core.Demo.Worker", "src/Genocs.Core.Demo.Worker/"] COPY ["src/Genocs.Core.Demo.Contracts", "src/Genocs.Core.Demo.Contracts/"] diff --git a/src/apps/apigateway.dockerfile b/src/apps/apigateway.dockerfile index 37b9b1e0..fcc5007e 100644 --- a/src/apps/apigateway.dockerfile +++ b/src/apps/apigateway.dockerfile @@ -1,13 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -#FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /src COPY ["api-gateway/Genocs.APIGateway", "Genocs.APIGateway/"] diff --git a/src/apps/identity-webapi.dockerfile b/src/apps/identity-webapi.dockerfile index cba04136..6ea34df3 100644 --- a/src/apps/identity-webapi.dockerfile +++ b/src/apps/identity-webapi.dockerfile @@ -1,13 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -#FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /src COPY ["identity/Genocs.Identities.WebApi", "Genocs.Identities.WebApi/"] COPY ["identity/Genocs.Identities.Application", "Genocs.Identities.Application/"] diff --git a/src/apps/order-webapi.dockerfile b/src/apps/order-webapi.dockerfile index 45881ddb..c0554e39 100644 --- a/src/apps/order-webapi.dockerfile +++ b/src/apps/order-webapi.dockerfile @@ -1,13 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -#FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /src COPY ["orders/Genocs.Orders.WebApi", "Genocs.Orders.WebApi/"] diff --git a/src/apps/product-webapi.dockerfile b/src/apps/product-webapi.dockerfile index b9860e42..ee7efb2f 100644 --- a/src/apps/product-webapi.dockerfile +++ b/src/apps/product-webapi.dockerfile @@ -1,14 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -#FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 - -#FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /src COPY ["products/Genocs.Products.WebApi", "Genocs.Products.WebApi/"] diff --git a/src/apps/signalr-webapi.dockerfile b/src/apps/signalr-webapi.dockerfile index 8fd57672..a7dd7061 100644 --- a/src/apps/signalr-webapi.dockerfile +++ b/src/apps/signalr-webapi.dockerfile @@ -1,20 +1,24 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 -#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim -#FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +# FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 +# FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim +# FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim +# FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine +# FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base + WORKDIR /app EXPOSE 80 EXPOSE 443 -#FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env -#FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env +# FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env +# FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build-env # FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build-env -#FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +# FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build-env +# FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env + WORKDIR /src COPY ["signalr/Genocs.SignalR.WebApi", "Genocs.SignalR.WebApi/"] From 8293914cac430f3b15921f6aa8de64619b1aac19 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 12:53:37 +0100 Subject: [PATCH 013/104] Added default assembly name --- src/Genocs.Auth/Genocs.Auth.csproj | 2 ++ src/Genocs.Common/Genocs.Common.csproj | 2 ++ src/Genocs.Core/Genocs.Core.csproj | 2 ++ src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj | 2 ++ src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj | 2 ++ src/Genocs.HTTP/Genocs.HTTP.csproj | 2 ++ .../Genocs.LoadBalancing.Fabio.csproj | 2 ++ src/Genocs.Logging/Genocs.Logging.csproj | 2 ++ .../Genocs.MessageBrokers.Outbox.MongoDB.csproj | 2 ++ .../Genocs.MessageBrokers.Outbox.csproj | 2 ++ .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 ++ src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj | 2 ++ src/Genocs.Metrics/Genocs.Metrics.csproj | 2 ++ src/Genocs.Monitoring/Genocs.Monitoring.csproj | 2 ++ .../Genocs.Persistence.MongoDb.csproj | 2 ++ src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj | 2 ++ src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj | 2 ++ src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj | 2 ++ src/Genocs.Security/Genocs.Security.csproj | 2 ++ src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj | 2 ++ src/Genocs.Tracing/Genocs.Tracing.csproj | 2 ++ src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj | 2 ++ src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj | 2 ++ src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj | 2 ++ src/Genocs.WebApi/Genocs.WebApi.csproj | 2 ++ 25 files changed, 50 insertions(+) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index c04827fd..45e2aba8 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Auth + Genocs.Auth + Genocs.Auth 10.0 true 5.0.0 diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index daec94f7..fa608135 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -3,6 +3,8 @@ netstandard2.1 Genocs.Common + Genocs.Common + Genocs.Common 10.0 true 5.0.0 diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index d51cbb9f..afd59378 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -3,6 +3,8 @@ netstandard2.1;net6.0;net7.0;net8.0 Genocs.Core + Genocs.Core + Genocs.Core 10.0 true 5.0.0 diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index f0638c19..980aeadc 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Discovery.Consul + Genocs.Discovery.Consul + Genocs.Discovery.Consul 10.0 true 5.0.0 diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 71d5cb3f..49a320ef 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -4,6 +4,8 @@ net6.0;net7.0;net8.0 Genocs.HTTP.RestEase + Genocs.HTTP.RestEase + Genocs.HTTP.RestEase 10.0 true 5.0.0 diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 56422747..ab33cf60 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.HTTP + Genocs.HTTP + Genocs.HTTP 10.0 true 5.0.0 diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index ffdf5ccd..139d2f4b 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.LoadBalancing.Fabio + Genocs.LoadBalancing.Fabio + Genocs.LoadBalancing.Fabio 10.0 true 5.0.0 diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index cb8d94cc..78108ed3 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Logging + Genocs.Logging + Genocs.Logging 10.0 true 5.0.0 diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index adb98f23..233afd33 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.MessageBrokers.Outbox.MongoDB + Genocs.MessageBrokers.Outbox.MongoDB + Genocs.MessageBrokers.Outbox.MongoDB 10.0 true 5.0.0 diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index de9da6e1..3fe4bfca 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.MessageBrokers.Outbox + Genocs.MessageBrokers.Outbox + Genocs.MessageBrokers.Outbox 10.0 true 5.0.0 diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 67c51a15..f53be894 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.MessageBrokers.RabbitMQ + Genocs.MessageBrokers.RabbitMQ + Genocs.MessageBrokers.RabbitMQ 10.0 true 5.0.0 diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index c5b04270..9e4d779f 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.MessageBrokers + Genocs.MessageBrokers + Genocs.MessageBrokers 10.0 true 5.0.0 diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 40f1d414..59152034 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Metrics + Genocs.Metrics + Genocs.Metrics 10.0 true 5.0.0 diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index b01bb0a2..5f5e5012 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Monitoring + Genocs.Monitoring + Genocs.Monitoring 10.0 true 5.0.0 diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index b5a2258a..d55f1e4b 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Persistence.MongoDb + Genocs.Persistence.MongoDb + Genocs.Persistence.MongoDb 10.0 true 5.0.0 diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index a485f40e..1056188f 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Persistence.Redis + Genocs.Persistence.Redis + Genocs.Persistence.Redis 10.0 true 5.0.0 diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 00aeca30..5938e46d 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -3,6 +3,8 @@ netstandard2.1 Genocs.QueryBuilder + Genocs.QueryBuilder + Genocs.QueryBuilder 10.0 true 5.0.0 diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 20b2909d..c9e279b0 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Secrets.Vault + Genocs.Secrets.Vault + Genocs.Secrets.Vault 10.0 true 5.0.0 diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 40b3b78c..863e298f 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Security + Genocs.Security + Genocs.Security 10.0 true 5.0.0 diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 2ffa8e23..357dec80 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.ServiceBusAzure + Genocs.ServiceBusAzure + Genocs.ServiceBusAzure 10.0 true 5.0.0 diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index aa55c854..eaaa9a9d 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.Tracing + Genocs.Tracing + Genocs.Tracing 10.0 true 5.0.0 diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index c4d1239e..252d41c7 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.WebApi.CQRS + Genocs.WebApi.CQRS + Genocs.WebApi.CQRS 10.0 true 5.0.0 diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 7b275cd1..7cbd818e 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.WebApi.Security + Genocs.WebApi.Security + Genocs.WebApi.Security 10.0 true 5.0.0 diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 3226607d..2dbfdfdf 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -3,6 +3,8 @@ net6.0 Genocs.WebApi.Swagger + Genocs.WebApi.Swagger + Genocs.WebApi.Swagger 10.0 true 5.0.0 diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 8ef3e008..7fd1487a 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -3,6 +3,8 @@ net6.0;net7.0;net8.0 Genocs.WebApi + Genocs.WebApi + Genocs.WebApi 10.0 true 5.0.0 From 19f2e027fd0dbab7871171e6af05be8d5e10b88e Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 13:22:28 +0100 Subject: [PATCH 014/104] Fix for pack --- .github/workflows/build_and_test.yml | 4 ++-- .../api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj | 2 ++ .../Genocs.Identities.Application.csproj | 2 ++ .../Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj | 2 ++ .../orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj | 2 ++ .../Genocs.Products.WebApi/Genocs.Products.WebApi.csproj | 2 ++ .../Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj | 2 ++ 7 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 794d6d59..c4579a69 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -27,7 +27,7 @@ jobs: run: dotnet build -c Debug --no-restore - name: Test - run: dotnet test --no-build --verbosity normal + run: dotnet test -c Debug --no-build --verbosity normal - name: Pack - run: dotnet pack --no-build --verbosity normal + run: dotnet pack -c Debug --no-build --verbosity normal diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 67c2681a..96435d80 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -2,6 +2,8 @@ net8.0 + false + false diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 0dfaf34a..bd14d270 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -2,6 +2,8 @@ net8.0 + false + false diff --git a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj index 39116205..4fcd0720 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj +++ b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj @@ -2,6 +2,8 @@ net8.0 + false + false _genocs Linux ..\.. diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 265b8599..2b34626c 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -2,6 +2,8 @@ net8.0 + false + false _genocs Linux ..\.. diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index 411d6070..e9095f05 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -2,6 +2,8 @@ net8.0 + false + false _genocs Linux ..\.. diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 558b0e73..57ce88ef 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -1,6 +1,8 @@  net8.0 + false + false _genocs Linux ..\.. From bb303eae19f13d330e0bc14c864e6e2fca4e001b Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 16:55:59 +0100 Subject: [PATCH 015/104] Added wildcard --- src/Genocs.Auth/Genocs.Auth.csproj | 2 +- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 4 +-- src/Genocs.Core/Genocs.Core.csproj | 2 +- .../Genocs.Discovery.Consul.csproj | 4 +-- .../Genocs.HTTP.RestEase.csproj | 8 ++--- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Genocs.LoadBalancing.Fabio.csproj | 6 ++-- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 4 +-- .../Genocs.MessageBrokers.Outbox.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- .../Genocs.MessageBrokers.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- .../Genocs.Monitoring.csproj | 6 ++-- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 8 ++--- .../Genocs.Secrets.Vault.csproj | 2 +- src/Genocs.Security/Genocs.Security.csproj | 2 +- .../Genocs.ServiceBusAzure.csproj | 2 +- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 4 +-- src/Genocs.Tracing/Genocs.Tracing.csproj | 6 ++-- .../Genocs.WebApi.CQRS.csproj | 4 +-- .../Genocs.WebApi.Security.csproj | 4 +-- .../Genocs.WebApi.Swagger.csproj | 4 +-- src/Genocs.WebApi/Genocs.WebApi.csproj | 2 +- .../Genocs.APIGateway.csproj | 18 +++++----- .../Genocs.Identities.Application.csproj | 35 +++++++++---------- .../Genocs.Orders.WebApi.csproj | 32 ++++++++--------- .../Genocs.Products.WebApi.csproj | 32 ++++++++--------- .../Genocs.SignalR.WebApi.csproj | 34 +++++++++--------- 33 files changed, 122 insertions(+), 123 deletions(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 45e2aba8..3fcc2d52 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 0758161e..2448a384 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index c8fab86c..51e0d7f3 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index afd59378..9b070bbb 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 980aeadc..58360ef2 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -48,8 +48,8 @@ - - + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 49a320ef..19248746 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -51,10 +51,10 @@ - - - - + + + + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index ab33cf60..8472b903 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 139d2f4b..112ba4a3 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -49,9 +49,9 @@ - - - + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 78108ed3..c9f5adb3 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 233afd33..7e5e75aa 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -47,8 +47,8 @@ - - + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 3fe4bfca..71108981 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index f53be894..1b7fffb1 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 9e4d779f..5d2d59d4 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 59152034..d79747be 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 5f5e5012..4866c69a 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -49,9 +49,9 @@ - - - + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 7fcd5d08..118510b4 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index d55f1e4b..8abaaccd 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 1056188f..f7705a8d 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 09355ae3..4517b19e 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -7,11 +7,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -32,8 +32,8 @@ - - + + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index c9e279b0..7726dc90 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 863e298f..b8fb77f6 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 357dec80..c8902c12 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index f255ce05..ff212e70 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -45,8 +45,8 @@ - - + + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index eaaa9a9d..2bbea06c 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -48,9 +48,9 @@ - - - + + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 252d41c7..2aaacf42 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -47,7 +47,7 @@ - - + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 7cbd818e..f5eaff5b 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -46,7 +46,7 @@ - + @@ -58,7 +58,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 2dbfdfdf..254f9b9e 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -4,7 +4,7 @@ net6.0 Genocs.WebApi.Swagger Genocs.WebApi.Swagger - Genocs.WebApi.Swagger + Genocs.WebApi.Swagger 10.0 true 5.0.0 @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 7fd1487a..4ee8058d 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -47,7 +47,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 96435d80..56083883 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -19,15 +19,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index bd14d270..a63b5c53 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -6,24 +6,6 @@ false - - - - - - - - - - - - - - - - - - @@ -41,4 +23,21 @@ + + + + + + + + + + + + + + + + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 2b34626c..32488735 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -29,22 +29,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index e9095f05..c721f991 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -30,22 +30,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 57ce88ef..1a810ccc 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -34,23 +34,23 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file From b5a32dd6c5256892c73f086b9686f953e6ced46a Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 25 Nov 2023 17:16:18 +0100 Subject: [PATCH 016/104] minor fix --- .../Genocs.Core.Demo.Worker.csproj | 10 ++-------- .../Genocs.APIGateway/Genocs.APIGateway.csproj | 3 --- .../Genocs.Identities.Application.csproj | 8 -------- .../Genocs.Identities.WebApi.csproj | 7 +------ .../Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj | 5 ----- 5 files changed, 3 insertions(+), 30 deletions(-) diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 0a191434..3bdb8728 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -9,17 +9,11 @@ ..\.. - - - - - - - - + + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 56083883..f68c444d 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -20,9 +20,6 @@ - - - diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index a63b5c53..2370404a 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -9,34 +9,26 @@ - - - - - - - - diff --git a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj index 4fcd0720..1a601e87 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj +++ b/src/apps/identity/Genocs.Identities.WebApi/Genocs.Identities.WebApi.csproj @@ -9,11 +9,6 @@ ..\.. - - - - - @@ -25,5 +20,5 @@ - + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 32488735..274707a7 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -31,11 +31,7 @@ - - - - @@ -44,7 +40,6 @@ - From 7c66fc3f57bc60bf44f35e391f80a5855baba357 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 28 Nov 2023 18:28:16 +0100 Subject: [PATCH 017/104] Clean warnings --- src/Genocs.Common/Types/IIdentifiable.cs | 8 +- src/Genocs.Core/CQRS/Queries/PagedResult.cs | 42 +- .../Auditing/CreationAuditedEntity.cs | 89 ++-- .../Domain/Entities/Auditing/IAudited.cs | 31 +- .../Entities/Auditing/ICreationAudited.cs | 39 +- src/Genocs.Core/Domain/Entities/Entity.cs | 13 +- .../Domain/Entities/EntityExtensions.cs | 1 - .../Entities/EntityNotFoundException.cs | 126 +++-- .../Domain/Entities/IAggregateRoot.cs | 31 +- src/Genocs.Core/Domain/Entities/IEntity.cs | 13 +- .../Domain/Entities/IEntityOfTPrimaryKey.cs | 19 +- .../Domain/Entities/ISoftDelete.cs | 23 +- .../Domain/Repositories/IRepository.cs | 4 +- .../IRepositoryOfTEntityAndTPrimaryKey.cs | 123 +++-- .../Domain/Repositories/RepositoryBase.cs | 446 +++++++++--------- 15 files changed, 501 insertions(+), 507 deletions(-) diff --git a/src/Genocs.Common/Types/IIdentifiable.cs b/src/Genocs.Common/Types/IIdentifiable.cs index 0da19004..59e3ff30 100644 --- a/src/Genocs.Common/Types/IIdentifiable.cs +++ b/src/Genocs.Common/Types/IIdentifiable.cs @@ -1,19 +1,19 @@ namespace Genocs.Common.Types; /// -/// Identifiable interface definition +/// Identifiable interface definition. /// -/// +/// The Identifiable type. public interface IIdentifiable { /// - /// The Id getter + /// The Id getter. /// T Id { get; } /// /// Checks if this entity is transient (not persisted to database and it has not an ). /// - /// True, if this entity is transient + /// True, if this entity is transient, otherwise false. bool IsTransient(); } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/PagedResult.cs b/src/Genocs.Core/CQRS/Queries/PagedResult.cs index 250adb3b..2620f2d2 100644 --- a/src/Genocs.Core/CQRS/Queries/PagedResult.cs +++ b/src/Genocs.Core/CQRS/Queries/PagedResult.cs @@ -5,16 +5,16 @@ namespace Genocs.Core.CQRS.Queries; /// /// The paged result. /// -/// +/// The page result type. public class PagedResult : PagedResultBase { /// - /// Returned items + /// Returned items. /// public IEnumerable Items { get; } /// - /// Default constructor + /// Default constructor. /// protected PagedResult() { @@ -22,7 +22,7 @@ protected PagedResult() } /// - /// Standard constructor + /// Standard constructor. /// /// /// @@ -30,18 +30,19 @@ protected PagedResult() /// /// [JsonConstructor] - protected PagedResult(IEnumerable items, + protected PagedResult( + IEnumerable items, int currentPage, int resultsPerPage, int totalPages, - long totalResults) : - base(currentPage, resultsPerPage, totalPages, totalResults) + long totalResults) + : base(currentPage, resultsPerPage, totalPages, totalResults) { Items = items; } /// - /// Create helper + /// Create helper. /// /// /// @@ -49,23 +50,32 @@ protected PagedResult(IEnumerable items, /// /// /// - public static PagedResult Create(IEnumerable items, - int currentPage, int resultsPerPage, - int totalPages, long totalResults) + public static PagedResult Create( + IEnumerable items, + int currentPage, + int resultsPerPage, + int totalPages, + long totalResults) => new PagedResult(items, currentPage, resultsPerPage, totalPages, totalResults); /// - /// From helper + /// From helper. /// /// /// /// - public static PagedResult From(PagedResultBase result, IEnumerable items) - => new PagedResult(items, result.CurrentPage, result.ResultsPerPage, - result.TotalPages, result.TotalResults); + public static PagedResult From( + PagedResultBase result, + IEnumerable items) + => new PagedResult( + items, + result.CurrentPage, + result.ResultsPerPage, + result.TotalPages, + result.TotalResults); /// - /// Static helper to get Empty result + /// Static helper to get Empty result. /// public static PagedResult Empty => new PagedResult(); } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs index 0de55ae5..c1988a36 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs @@ -1,59 +1,58 @@ -namespace Genocs.Core.Domain.Entities.Auditing +using System.ComponentModel.DataAnnotations.Schema; + +// using Genocs.Timing; + +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// A shortcut of for most used primary key type (). +/// +[Serializable] +public abstract class CreationAuditedEntity : CreationAuditedEntity, IEntity { - using System; - using System.ComponentModel.DataAnnotations.Schema; - //using Genocs.Timing; +} + +/// +/// This class can be used to simplify implementing . +/// +/// Type of the primary key of the entity +[Serializable] +public abstract class CreationAuditedEntity : Entity, ICreationAudited +{ /// - /// A shortcut of for most used primary key type (). + /// Creation time of this entity. /// - [Serializable] - public abstract class CreationAuditedEntity : CreationAuditedEntity, IEntity - { + public virtual DateTime CreationTime { get; set; } - } + /// + /// Creator of this entity. + /// + public virtual long? CreatorUserId { get; set; } /// - /// This class can be used to simplify implementing . + /// Constructor. /// - /// Type of the primary key of the entity - [Serializable] - public abstract class CreationAuditedEntity : Entity, ICreationAudited + protected CreationAuditedEntity() { - /// - /// Creation time of this entity. - /// - public virtual DateTime CreationTime { get; set; } - - /// - /// Creator of this entity. - /// - public virtual long? CreatorUserId { get; set; } - - /// - /// Constructor. - /// - protected CreationAuditedEntity() - { - //CreationTime = Clock.Now; - CreationTime = DateTime.Now; - - } + // CreationTime = Clock.Now; + CreationTime = DateTime.Now; + } +} +/// +/// This class can be used to simplify implementing . +/// +/// Type of the primary key of the entity. +/// Type of the user. +[Serializable] +public abstract class CreationAuditedEntity : CreationAuditedEntity, ICreationAudited + where TUser : IEntity +{ /// - /// This class can be used to simplify implementing . + /// Reference to the creator user of this entity. /// - /// Type of the primary key of the entity - /// Type of the user - [Serializable] - public abstract class CreationAuditedEntity : CreationAuditedEntity, ICreationAudited - where TUser : IEntity - { - /// - /// Reference to the creator user of this entity. - /// - [ForeignKey("CreatorUserId")] - public virtual TUser CreatorUser { get; set; } - } + [ForeignKey("CreatorUserId")] + public virtual TUser CreatorUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/IAudited.cs index 2a967930..45873b8c 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IAudited.cs @@ -1,21 +1,20 @@ -namespace Genocs.Core.Domain.Entities.Auditing +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// This interface is implemented by entities which must be audited. +/// Related properties automatically set when saving/updating objects. +/// +public interface IAudited : ICreationAudited, IModificationAudited { - /// - /// This interface is implemented by entities which must be audited. - /// Related properties automatically set when saving/updating objects. - /// - public interface IAudited : ICreationAudited, IModificationAudited - { - } +} - /// - /// Adds navigation properties to interface for user. - /// - /// Type of the user - public interface IAudited : IAudited, ICreationAudited, IModificationAudited - where TUser : IEntity - { +/// +/// Adds navigation properties to interface for user. +/// +/// Type of the user. +public interface IAudited : IAudited, ICreationAudited, IModificationAudited + where TUser : IEntity +{ - } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs index b220f065..9ffac146 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs @@ -1,27 +1,26 @@ -namespace Genocs.Core.Domain.Entities.Auditing +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// This interface is implemented by entities that is wanted to store creation information (who and when created). +/// Creation time and creator user are automatically set when saving to database. +/// +public interface ICreationAudited : IHasCreationTime { /// - /// This interface is implemented by entities that is wanted to store creation information (who and when created). - /// Creation time and creator user are automatically set when saving to database. + /// Id of the creator user of this entity. /// - public interface ICreationAudited : IHasCreationTime - { - /// - /// Id of the creator user of this entity. - /// - long? CreatorUserId { get; set; } - } + long? CreatorUserId { get; set; } +} +/// +/// Adds navigation properties to interface for user. +/// +/// Type of the user +public interface ICreationAudited : ICreationAudited + where TUser : IEntity +{ /// - /// Adds navigation properties to interface for user. + /// Reference to the creator user of this entity. /// - /// Type of the user - public interface ICreationAudited : ICreationAudited - where TUser : IEntity - { - /// - /// Reference to the creator user of this entity. - /// - TUser CreatorUser { get; set; } - } + TUser CreatorUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Entity.cs b/src/Genocs.Core/Domain/Entities/Entity.cs index 7e1c7cba..644df88c 100644 --- a/src/Genocs.Core/Domain/Entities/Entity.cs +++ b/src/Genocs.Core/Domain/Entities/Entity.cs @@ -1,9 +1,8 @@ using System.Reflection; -//using Genocs.Extensions; +// using Genocs.Extensions; namespace Genocs.Core.Domain.Entities; - /// /// A shortcut of for most used primary key type (). /// @@ -17,7 +16,7 @@ public abstract class Entity : Entity, IEntity /// Basic implementation of IEntity interface. /// An entity can inherit this class of directly implement to IEntity interface. /// -/// Type of the primary key of the entity +/// Type of the primary key of the entity. [Serializable] public abstract class Entity : IEntity { @@ -37,7 +36,7 @@ public virtual bool IsTransient() return true; } - //Workaround for EF Core since it sets int/long to min value when attaching to dbcontext + // Workaround for EF Core since it sets int/long to min value when attaching to dB context if (typeof(TPrimaryKey) == typeof(int)) { return Convert.ToInt32(Id) <= 0; @@ -59,20 +58,20 @@ public override bool Equals(object obj) return false; } - //Same instances must be considered as equal + // Same instances must be considered as equal if (ReferenceEquals(this, obj)) { return true; } - //Transient objects are not considered as equal + // Transient objects are not considered as equal var other = (Entity)obj; if (IsTransient() && other.IsTransient()) { return false; } - //Must have a IS-A relation of types or must be same type + // Must have a IS-A relation of types or must be same type var typeOfThis = GetType(); var typeOfOther = other.GetType(); if (!typeOfThis.GetTypeInfo().IsAssignableFrom(typeOfOther) && !typeOfOther.GetTypeInfo().IsAssignableFrom(typeOfThis)) diff --git a/src/Genocs.Core/Domain/Entities/EntityExtensions.cs b/src/Genocs.Core/Domain/Entities/EntityExtensions.cs index 66666e4b..ac7868d7 100644 --- a/src/Genocs.Core/Domain/Entities/EntityExtensions.cs +++ b/src/Genocs.Core/Domain/Entities/EntityExtensions.cs @@ -3,7 +3,6 @@ namespace Genocs.Core.Domain.Entities; - /// /// Some useful extension methods for Entities. /// diff --git a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs index ea0a21f7..f5fd0b4a 100644 --- a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs +++ b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs @@ -1,80 +1,78 @@ -namespace Genocs.Core.Domain.Entities -{ - using System; - using System.Runtime.Serialization; - using Genocs.Core.Exceptions; +using Genocs.Core.Exceptions; +using System.Runtime.Serialization; + +namespace Genocs.Core.Domain.Entities; +/// +/// This exception is thrown if an entity excepted to be found but not found. +/// +[Serializable] +public class EntityNotFoundException : GenocsException +{ /// - /// This exception is thrown if an entity excepted to be found but not found. + /// Type of the entity. /// - [Serializable] - public class EntityNotFoundException : GenocsException - { - /// - /// Type of the entity. - /// - public Type EntityType { get; set; } + public Type EntityType { get; set; } - /// - /// Id of the Entity. - /// - public object Id { get; set; } + /// + /// Id of the Entity. + /// + public object Id { get; set; } - /// - /// Creates a new object. - /// - public EntityNotFoundException() - { + /// + /// Creates a new object. + /// + public EntityNotFoundException() + { - } + } - /// - /// Creates a new object. - /// - public EntityNotFoundException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { + /// + /// Creates a new object. + /// + public EntityNotFoundException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { - } - - /// - /// Creates a new object. - /// - public EntityNotFoundException(Type entityType, object id) - : this(entityType, id, null) - { + } + + /// + /// Creates a new object. + /// + public EntityNotFoundException(Type entityType, object id) + : this(entityType, id, null) + { - } + } - /// - /// Creates a new object. - /// - public EntityNotFoundException(Type entityType, object id, Exception innerException) - : base($"There is no such an entity. Entity type: {entityType.FullName}, id: {id}", innerException) - { - EntityType = entityType; - Id = id; - } + /// + /// Creates a new object. + /// + public EntityNotFoundException(Type entityType, object id, Exception innerException) + : base($"There is no such an entity. Entity type: {entityType.FullName}, id: {id}", innerException) + { + EntityType = entityType; + Id = id; + } - /// - /// Creates a new object. - /// - /// Exception message - public EntityNotFoundException(string message) - : base(message) - { + /// + /// Creates a new object. + /// + /// Exception message + public EntityNotFoundException(string message) + : base(message) + { - } + } - /// - /// Creates a new object. - /// - /// Exception message - /// Inner exception - public EntityNotFoundException(string message, Exception innerException) - : base(message, innerException) - { + /// + /// Creates a new object. + /// + /// Exception message + /// Inner exception + public EntityNotFoundException(string message, Exception innerException) + : base(message, innerException) + { - } } } diff --git a/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs index 20c1f6ea..a094292f 100644 --- a/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs @@ -1,21 +1,22 @@ -namespace Genocs.Core.Domain.Entities +// using System.Collections.Generic; +// using Genocs.Events.Bus; + +namespace Genocs.Core.Domain.Entities; + +public interface IAggregateRoot : IAggregateRoot, IEntity { - //using System.Collections.Generic; - //using Genocs.Events.Bus; - public interface IAggregateRoot : IAggregateRoot, IEntity - { +} - } +public interface IAggregateRoot : IEntity/*, IGeneratesDomainEvents */ +{ - public interface IAggregateRoot : IEntity/*, IGeneratesDomainEvents */ - { +} - } /* - public interface IGeneratesDomainEvents - { - ICollection DomainEvents { get; } - } - */ -} \ No newline at end of file +public interface IGeneratesDomainEvents +{ + ICollection DomainEvents { get; } +} + +*/ diff --git a/src/Genocs.Core/Domain/Entities/IEntity.cs b/src/Genocs.Core/Domain/Entities/IEntity.cs index 69eb3aff..a00f7270 100644 --- a/src/Genocs.Core/Domain/Entities/IEntity.cs +++ b/src/Genocs.Core/Domain/Entities/IEntity.cs @@ -1,12 +1,11 @@ using Genocs.Common.Types; -namespace Genocs.Core.Domain.Entities +namespace Genocs.Core.Domain.Entities; + +/// +/// A shortcut of for most used primary key type (). +/// +public interface IEntity : IIdentifiable { - /// - /// A shortcut of for most used primary key type (). - /// - public interface IEntity : IIdentifiable - { - } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs b/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs index 057839c1..e85c21c2 100644 --- a/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs @@ -1,14 +1,13 @@ -namespace Genocs.Core.Domain.Entities +namespace Genocs.Core.Domain.Entities; + +/// +/// Defines interface for base entity type. All entities in the system must implement this interface. +/// +/// Type of the primary key of the entity. +public interface IEntity { /// - /// Defines interface for base entity type. All entities in the system must implement this interface. + /// Unique identifier for this entity. /// - /// Type of the primary key of the entity - public interface IEntity - { - /// - /// Unique identifier for this entity. - /// - TPrimaryKey Id { get; set; } - } + TPrimaryKey Id { get; set; } } diff --git a/src/Genocs.Core/Domain/Entities/ISoftDelete.cs b/src/Genocs.Core/Domain/Entities/ISoftDelete.cs index 8d747ddb..67044680 100644 --- a/src/Genocs.Core/Domain/Entities/ISoftDelete.cs +++ b/src/Genocs.Core/Domain/Entities/ISoftDelete.cs @@ -1,16 +1,15 @@ -namespace Genocs.Core.Domain.Entities +namespace Genocs.Core.Domain.Entities; + +/// +/// Used to standardize soft deleting entities. +/// Soft-delete entities are not actually deleted, +/// marked as IsDeleted = true in the database, +/// but can not be retrieved to the application. +/// +public interface ISoftDelete { /// - /// Used to standardize soft deleting entities. - /// Soft-delete entities are not actually deleted, - /// marked as IsDeleted = true in the database, - /// but can not be retrieved to the application. + /// Used to mark an Entity as 'Deleted'. /// - public interface ISoftDelete - { - /// - /// Used to mark an Entity as 'Deleted'. - /// - bool IsDeleted { get; set; } - } + bool IsDeleted { get; set; } } diff --git a/src/Genocs.Core/Domain/Repositories/IRepository.cs b/src/Genocs.Core/Domain/Repositories/IRepository.cs index 018363e5..fb265b43 100644 --- a/src/Genocs.Core/Domain/Repositories/IRepository.cs +++ b/src/Genocs.Core/Domain/Repositories/IRepository.cs @@ -1,13 +1,13 @@ using Genocs.Common.Types; - namespace Genocs.Core.Domain.Repositories; /// /// This interface is used to identify a repository so can be used to be registered by convention. /// Implement generic version instead of this one. /// -public interface IRepository where TEntity : IIdentifiable +public interface IRepository + where TEntity : IIdentifiable { } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs index 63143af9..239916cc 100644 --- a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs @@ -6,8 +6,8 @@ namespace Genocs.Core.Domain.Repositories; /// /// This interface is implemented by all repositories to ensure implementation of fixed methods. /// -/// Main Entity type this repository works on -/// Primary key type of the entity +/// Main Entity type this repository works on. +/// Primary key type of the entity. public interface IRepositoryOfEntity : IRepository where TEntity : IIdentifiable { @@ -16,34 +16,34 @@ public interface IRepositoryOfEntity : IRepository /// Used to get a IQueryable that is used to retrieve entities from entire table. /// - /// IQueryable to be used to select entities from database + /// IQueryable to be used to select entities from database. IQueryable GetAll(); /// /// Used to get a IQueryable that is used to retrieve entities from entire table. - /// One or more + /// One or more. /// /// A list of include expressions. - /// IQueryable to be used to select entities from database + /// IQueryable to be used to select entities from database. IQueryable GetAllIncluding(params Expression>[] propertySelectors); /// /// Used to get all entities. /// - /// List of all entities + /// List of all entities. List GetAllList(); /// /// Used to get all entities. /// - /// List of all entities + /// List of all entities. Task> GetAllListAsync(); /// /// Used to get all entities based on given . /// - /// A condition to filter entities - /// List of all entities + /// A condition to filter entities. + /// List of all entities. List GetAllList(Expression> predicate); /// @@ -55,12 +55,11 @@ public interface IRepositoryOfEntity : IRepository /// Used to run a query over entire entities. - /// attribute is not always necessary (as opposite to ) /// if finishes IQueryable with ToList, FirstOrDefault etc.. /// /// Type of return value of this method. /// This method is used to query over entities. - /// Query result + /// Query result. T Query(Func, T> queryMethod); /// @@ -74,14 +73,14 @@ public interface IRepositoryOfEntity : IRepository /// Primary key of the entity to get. - /// Entity + /// Entity. Task GetAsync(TIdentifiable id); /// /// Gets exactly one entity with given predicate. /// Throws exception if no entity or more than one entity. /// - /// Entity + /// Entity. TEntity Single(Expression> predicate); /// @@ -94,34 +93,34 @@ public interface IRepositoryOfEntity : IRepository /// Gets an entity with given primary key or null if not found. /// - /// Primary key of the entity to get - /// Entity or null + /// Primary key of the entity to get. + /// Entity or null. TEntity FirstOrDefault(TIdentifiable id); /// /// Gets an entity with given primary key or null if not found. /// - /// Primary key of the entity to get - /// Entity or null + /// Primary key of the entity to get. + /// Entity or null. Task FirstOrDefaultAsync(TIdentifiable id); /// - /// Gets an entity with given given predicate or null if not found. + /// Gets an entity with given predicate or null if not found. /// - /// Predicate to filter entities + /// Predicate to filter entities. TEntity FirstOrDefault(Expression> predicate); /// - /// Gets an entity with given given predicate or null if not found. + /// Gets an entity with given predicate or null if not found. /// - /// Predicate to filter entities + /// Predicate to filter entities. Task FirstOrDefaultAsync(Expression> predicate); /// /// Creates an entity with given primary key without database access. /// - /// Primary key of the entity to load - /// Entity + /// Primary key of the entity to load. + /// Entity. TEntity Load(TIdentifiable id); #endregion @@ -131,13 +130,13 @@ public interface IRepositoryOfEntity : IRepository /// Inserts a new entity. /// - /// Inserted entity + /// Inserted entity. TEntity Insert(TEntity entity); /// /// Inserts a new entity. /// - /// Inserted entity + /// Inserted entity. Task InsertAsync(TEntity entity); /// @@ -145,8 +144,8 @@ public interface IRepositoryOfEntity : IRepository - /// Entity - /// Id of the entity + /// Entity. + /// Id of the entity. TIdentifiable InsertAndGetId(TEntity entity); /// @@ -154,20 +153,20 @@ public interface IRepositoryOfEntity : IRepository - /// Entity - /// Id of the entity + /// Entity. + /// Id of the entity. Task InsertAndGetIdAsync(TEntity entity); /// /// Inserts or updates given entity depending on Id's value. /// - /// Entity + /// Entity. TEntity InsertOrUpdate(TEntity entity); /// /// Inserts or updates given entity depending on Id's value. /// - /// Entity + /// Entity. Task InsertOrUpdateAsync(TEntity entity); /// @@ -176,8 +175,8 @@ public interface IRepositoryOfEntity : IRepository - /// Entity - /// Id of the entity + /// Entity. + /// Id of the entity. TIdentifiable InsertOrUpdateAndGetId(TEntity entity); /// @@ -186,8 +185,8 @@ public interface IRepositoryOfEntity : IRepository - /// Entity - /// Id of the entity + /// Entity. + /// Id of the entity. Task InsertOrUpdateAndGetIdAsync(TEntity entity); #endregion @@ -197,29 +196,29 @@ public interface IRepositoryOfEntity : IRepository /// Updates an existing entity. /// - /// Entity + /// Entity. TEntity Update(TEntity entity); /// - /// Updates an existing entity. + /// Updates an existing entity. /// - /// Entity + /// Entity. Task UpdateAsync(TEntity entity); /// /// Updates an existing entity. /// - /// Id of the entity - /// Action that can be used to change values of the entity - /// Updated entity + /// Id of the entity. + /// Action that can be used to change values of the entity. + /// Updated entity. TEntity Update(TIdentifiable id, Action updateAction); /// /// Updates an existing entity. /// - /// Id of the entity - /// Action that can be used to change values of the entity - /// Updated entity + /// Id of the entity. + /// Action that can be used to change values of the entity. + /// Updated entity. Task UpdateAsync(TIdentifiable id, Func updateAction); #endregion @@ -229,25 +228,25 @@ public interface IRepositoryOfEntity : IRepository /// Deletes an entity. /// - /// Entity to be deleted + /// Entity to be deleted. void Delete(TEntity entity); /// /// Deletes an entity. /// - /// Entity to be deleted + /// Entity to be deleted. Task DeleteAsync(TEntity entity); /// /// Deletes an entity by primary key. /// - /// Primary key of the entity + /// Primary key of the entity. void Delete(TIdentifiable id); /// /// Deletes an entity by primary key. /// - /// Primary key of the entity + /// Primary key of the entity. Task DeleteAsync(TIdentifiable id); /// @@ -256,7 +255,7 @@ public interface IRepositoryOfEntity : IRepository - /// A condition to filter entities + /// A condition to filter entities. void Delete(Expression> predicate); /// @@ -265,7 +264,7 @@ public interface IRepositoryOfEntity : IRepository - /// A condition to filter entities + /// A condition to filter entities. Task DeleteAsync(Expression> predicate); #endregion @@ -275,55 +274,55 @@ public interface IRepositoryOfEntity : IRepository /// Gets count of all entities in this repository. /// - /// Count of entities + /// Count of entities. int Count(); /// /// Gets count of all entities in this repository. /// - /// Count of entities + /// Count of entities. Task CountAsync(); /// /// Gets count of all entities in this repository based on given . /// - /// A method to filter count - /// Count of entities + /// A method to filter count. + /// Count of entities. int Count(Expression> predicate); /// /// Gets count of all entities in this repository based on given . /// - /// A method to filter count - /// Count of entities + /// A method to filter count. + /// Count of entities. Task CountAsync(Expression> predicate); /// /// Gets count of all entities in this repository (use if expected return value is greater than . /// - /// Count of entities + /// Count of entities. long LongCount(); /// /// Gets count of all entities in this repository (use if expected return value is greater than . /// - /// Count of entities + /// Count of entities. Task LongCountAsync(); /// /// Gets count of all entities in this repository based on given /// (use this overload if expected return value is greater than ). /// - /// A method to filter count - /// Count of entities + /// A method to filter count. + /// Count of entities. long LongCount(Expression> predicate); /// /// Gets count of all entities in this repository based on given /// (use this overload if expected return value is greater than ). /// - /// A method to filter count - /// Count of entities + /// A method to filter count. + /// Count of entities. Task LongCountAsync(Expression> predicate); #endregion diff --git a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs index f3a05ebf..73df5ee8 100644 --- a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs +++ b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs @@ -1,278 +1,272 @@ -namespace Genocs.Core.Domain.Repositories +using System.Linq.Expressions; +using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; + +// using Genocs.Core.Dependency; +// using Genocs.Core.Domain.Uow; +// using Genocs.Core.MultiTenancy; +// using Genocs.Core.Reflection.Extensions; + +namespace Genocs.Core.Domain.Repositories; + +/// +/// Base class to implement . +/// It implements some methods in most simple way. +/// +/// Type of the Entity for this repository. +/// Type of the Primary Key for this repository. +public abstract class RepositoryBase : IRepository/*, IUnitOfWorkManagerAccessor */ + where TEntity : class, IIdentifiable { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Linq.Expressions; - using System.Threading.Tasks; - using Genocs.Common.Types; - //using Genocs.Core.Dependency; - using Genocs.Core.Domain.Entities; - //using Genocs.Core.Domain.Uow; - //using Genocs.Core.MultiTenancy; - //using Genocs.Core.Reflection.Extensions; - - /// - /// Base class to implement . - /// It implements some methods in most simple way. + /// The multi tenancy side. /// - /// Type of the Entity for this repository - /// Primary key of the entity - public abstract class RepositoryBase : IRepository/*, IUnitOfWorkManagerAccessor */ - where TEntity : class, IIdentifiable - { - /// - /// The multi tenancy side - /// - //public static MultiTenancySides? MultiTenancySide { get; private set; } + // public static MultiTenancySides? MultiTenancySide { get; private set; } - //public IUnitOfWorkManager UnitOfWorkManager { get; set; } + // public IUnitOfWorkManager UnitOfWorkManager { get; set; } - //public IIocResolver IocResolver { get; set; } + // public IIocResolver IocResolver { get; set; } - static RepositoryBase() + static RepositoryBase() + { + /* + var attr = typeof (TEntity).GetSingleAttributeOfTypeOrBaseTypesOrNull(); + if (attr != null) { - /* - var attr = typeof (TEntity).GetSingleAttributeOfTypeOrBaseTypesOrNull(); - if (attr != null) - { - MultiTenancySide = attr.Side; - } - */ + MultiTenancySide = attr.Side; } + */ + } - public abstract IQueryable GetAll(); + public abstract IQueryable GetAll(); - public virtual IQueryable GetAllIncluding(params Expression>[] propertySelectors) - { - return GetAll(); - } + public virtual IQueryable GetAllIncluding(params Expression>[] propertySelectors) + { + return GetAll(); + } - public virtual List GetAllList() - { - return GetAll().ToList(); - } + public virtual List GetAllList() + { + return GetAll().ToList(); + } - public virtual Task> GetAllListAsync() - { - return Task.FromResult(GetAllList()); - } - - public virtual List GetAllList(Expression> predicate) - { - return GetAll().Where(predicate).ToList(); - } + public virtual Task> GetAllListAsync() + { + return Task.FromResult(GetAllList()); + } - public virtual Task> GetAllListAsync(Expression> predicate) + public virtual List GetAllList(Expression> predicate) + { + return GetAll().Where(predicate).ToList(); + } + + public virtual Task> GetAllListAsync(Expression> predicate) + { + return Task.FromResult(GetAllList(predicate)); + } + + public virtual T Query(Func, T> queryMethod) + { + return queryMethod(GetAll()); + } + + public virtual TEntity Get(TPrimaryKey id) + { + var entity = FirstOrDefault(id); + if (entity == null) { - return Task.FromResult(GetAllList(predicate)); + throw new EntityNotFoundException(typeof(TEntity), id); } - public virtual T Query(Func, T> queryMethod) + return entity; + } + + public virtual async Task GetAsync(TPrimaryKey id) + { + var entity = await FirstOrDefaultAsync(id); + if (entity == null) { - return queryMethod(GetAll()); + throw new EntityNotFoundException(typeof(TEntity), id); } - - public virtual TEntity Get(TPrimaryKey id) - { - var entity = FirstOrDefault(id); - if (entity == null) - { - throw new EntityNotFoundException(typeof(TEntity), id); - } - return entity; - } + return entity; + } - public virtual async Task GetAsync(TPrimaryKey id) - { - var entity = await FirstOrDefaultAsync(id); - if (entity == null) - { - throw new EntityNotFoundException(typeof(TEntity), id); - } + public virtual TEntity Single(Expression> predicate) + { + return GetAll().Single(predicate); + } - return entity; - } - - public virtual TEntity Single(Expression> predicate) - { - return GetAll().Single(predicate); - } + public virtual Task SingleAsync(Expression> predicate) + { + return Task.FromResult(Single(predicate)); + } - public virtual Task SingleAsync(Expression> predicate) - { - return Task.FromResult(Single(predicate)); - } - - public virtual TEntity FirstOrDefault(TPrimaryKey id) - { - return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id)); - } + public virtual TEntity FirstOrDefault(TPrimaryKey id) + { + return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id)); + } - public virtual Task FirstOrDefaultAsync(TPrimaryKey id) - { - return Task.FromResult(FirstOrDefault(id)); - } - - public virtual TEntity FirstOrDefault(Expression> predicate) - { - return GetAll().FirstOrDefault(predicate); - } + public virtual Task FirstOrDefaultAsync(TPrimaryKey id) + { + return Task.FromResult(FirstOrDefault(id)); + } - public virtual Task FirstOrDefaultAsync(Expression> predicate) - { - return Task.FromResult(FirstOrDefault(predicate)); - } - - public virtual TEntity Load(TPrimaryKey id) - { - return Get(id); - } + public virtual TEntity FirstOrDefault(Expression> predicate) + { + return GetAll().FirstOrDefault(predicate); + } - public abstract TEntity Insert(TEntity entity); - - public virtual Task InsertAsync(TEntity entity) - { - return Task.FromResult(Insert(entity)); - } + public virtual Task FirstOrDefaultAsync(Expression> predicate) + { + return Task.FromResult(FirstOrDefault(predicate)); + } - public virtual TPrimaryKey InsertAndGetId(TEntity entity) - { - return Insert(entity).Id; - } + public virtual TEntity Load(TPrimaryKey id) + { + return Get(id); + } - public virtual Task InsertAndGetIdAsync(TEntity entity) - { - return Task.FromResult(InsertAndGetId(entity)); - } + public abstract TEntity Insert(TEntity entity); - public virtual TEntity InsertOrUpdate(TEntity entity) - { - return entity.IsTransient() - ? Insert(entity) - : Update(entity); - } - - public virtual async Task InsertOrUpdateAsync(TEntity entity) - { - return entity.IsTransient() - ? await InsertAsync(entity) - : await UpdateAsync(entity); - } + public virtual Task InsertAsync(TEntity entity) + { + return Task.FromResult(Insert(entity)); + } - public virtual TPrimaryKey InsertOrUpdateAndGetId(TEntity entity) - { - return InsertOrUpdate(entity).Id; - } + public virtual TPrimaryKey InsertAndGetId(TEntity entity) + { + return Insert(entity).Id; + } - public virtual Task InsertOrUpdateAndGetIdAsync(TEntity entity) - { - return Task.FromResult(InsertOrUpdateAndGetId(entity)); - } + public virtual Task InsertAndGetIdAsync(TEntity entity) + { + return Task.FromResult(InsertAndGetId(entity)); + } - public abstract TEntity Update(TEntity entity); - - public virtual Task UpdateAsync(TEntity entity) - { - return Task.FromResult(Update(entity)); - } + public virtual TEntity InsertOrUpdate(TEntity entity) + { + return entity.IsTransient() + ? Insert(entity) + : Update(entity); + } - public virtual TEntity Update(TPrimaryKey id, Action updateAction) - { - var entity = Get(id); - updateAction(entity); - return entity; - } + public virtual async Task InsertOrUpdateAsync(TEntity entity) + { + return entity.IsTransient() + ? await InsertAsync(entity) + : await UpdateAsync(entity); + } - public virtual async Task UpdateAsync(TPrimaryKey id, Func updateAction) - { - var entity = await GetAsync(id); - await updateAction(entity); - return entity; - } + public virtual TPrimaryKey InsertOrUpdateAndGetId(TEntity entity) + { + return InsertOrUpdate(entity).Id; + } - public abstract void Delete(TEntity entity); - - public virtual Task DeleteAsync(TEntity entity) - { - Delete(entity); - return Task.FromResult(0); - } + public virtual Task InsertOrUpdateAndGetIdAsync(TEntity entity) + { + return Task.FromResult(InsertOrUpdateAndGetId(entity)); + } - public abstract void Delete(TPrimaryKey id); - - public virtual Task DeleteAsync(TPrimaryKey id) - { - Delete(id); - return Task.FromResult(0); - } + public abstract TEntity Update(TEntity entity); - public virtual void Delete(Expression> predicate) - { - foreach (var entity in GetAll().Where(predicate).ToList()) - { - Delete(entity); - } - } + public virtual Task UpdateAsync(TEntity entity) + { + return Task.FromResult(Update(entity)); + } - public virtual Task DeleteAsync(Expression> predicate) - { - Delete(predicate); - return Task.FromResult(0); - } + public virtual TEntity Update(TPrimaryKey id, Action updateAction) + { + var entity = Get(id); + updateAction(entity); + return entity; + } - public virtual int Count() - { - return GetAll().Count(); - } + public virtual async Task UpdateAsync(TPrimaryKey id, Func updateAction) + { + var entity = await GetAsync(id); + await updateAction(entity); + return entity; + } - public virtual Task CountAsync() - { - return Task.FromResult(Count()); - } + public abstract void Delete(TEntity entity); - public virtual int Count(Expression> predicate) - { - return GetAll().Where(predicate).Count(); - } + public virtual Task DeleteAsync(TEntity entity) + { + Delete(entity); + return Task.FromResult(0); + } - public virtual Task CountAsync(Expression> predicate) - { - return Task.FromResult(Count(predicate)); - } + public abstract void Delete(TPrimaryKey id); - public virtual long LongCount() - { - return GetAll().LongCount(); - } + public virtual Task DeleteAsync(TPrimaryKey id) + { + Delete(id); + return Task.FromResult(0); + } - public virtual Task LongCountAsync() + public virtual void Delete(Expression> predicate) + { + foreach (var entity in GetAll().Where(predicate).ToList()) { - return Task.FromResult(LongCount()); + Delete(entity); } + } - public virtual long LongCount(Expression> predicate) - { - return GetAll().Where(predicate).LongCount(); - } + public virtual Task DeleteAsync(Expression> predicate) + { + Delete(predicate); + return Task.FromResult(0); + } - public virtual Task LongCountAsync(Expression> predicate) - { - return Task.FromResult(LongCount(predicate)); - } + public virtual int Count() + { + return GetAll().Count(); + } - protected virtual Expression> CreateEqualityExpressionForId(TPrimaryKey id) - { - var lambdaParam = Expression.Parameter(typeof(TEntity)); + public virtual Task CountAsync() + { + return Task.FromResult(Count()); + } + + public virtual int Count(Expression> predicate) + { + return GetAll().Where(predicate).Count(); + } - var lambdaBody = Expression.Equal( - Expression.PropertyOrField(lambdaParam, "Id"), - Expression.Constant(id, typeof(TPrimaryKey)) - ); + public virtual Task CountAsync(Expression> predicate) + { + return Task.FromResult(Count(predicate)); + } - return Expression.Lambda>(lambdaBody, lambdaParam); - } + public virtual long LongCount() + { + return GetAll().LongCount(); + } + + public virtual Task LongCountAsync() + { + return Task.FromResult(LongCount()); + } + + public virtual long LongCount(Expression> predicate) + { + return GetAll().Where(predicate).LongCount(); + } + + public virtual Task LongCountAsync(Expression> predicate) + { + return Task.FromResult(LongCount(predicate)); + } + + protected virtual Expression> CreateEqualityExpressionForId(TPrimaryKey id) + { + var lambdaParam = Expression.Parameter(typeof(TEntity)); + + var lambdaBody = Expression.Equal( + Expression.PropertyOrField(lambdaParam, "Id"), + Expression.Constant(id, typeof(TPrimaryKey))); + + return Expression.Lambda>(lambdaBody, lambdaParam); } } From b21a55ec751c8186b73e7da84bd1a38256ff7984 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 28 Nov 2023 18:43:28 +0100 Subject: [PATCH 018/104] Before big refactory --- .../Aggregates/Order.cs | 2 +- src/Genocs.Core.Demo.Worker/Program.cs | 1 + .../Internals/MongoMessageOutbox.cs | 1 + .../Extensions/MongoDbExtensions.cs | 2 ++ .../{ => Clean}/IMongoDbEntity.cs | 4 +-- .../{ => Clean}/MongoDbRepository.cs | 8 ++--- .../MongoDbRepositoryBaseOfEntity.cs | 2 +- .../MongoDbRepositoryBaseOfEntityAndKey.cs | 15 ++++---- .../Repositories/IMongoDbInitializer.cs | 2 +- .../Repositories/IMongoDbOptionsBuilder.cs | 12 +++---- .../Repositories/IMongoDbRepository.cs | 9 ++--- .../Repositories/IMongoDbSeeder.cs | 6 ++-- .../Repositories/IMongoSessionFactory.cs | 6 ++-- .../{ => Mentor}/IMongoRepository.cs | 9 +++-- .../{ => Mentor}/MongoRepository.cs | 22 ++++++------ .../Repositories/Pagination.cs | 34 +++++++++++++------ .../Mongo/Extensions.cs | 2 +- .../Mongo/Queries/Handlers/GetUserHandler.cs | 2 +- .../Repositories/RefreshTokenRepository.cs | 2 +- .../Mongo/Repositories/UserRepository.cs | 2 +- .../Commands/Handlers/CreateOrderHandler.cs | 2 +- .../Queries/Handlers/GetOrderHandler.cs | 2 +- .../Commands/Handlers/CreateProductHandler.cs | 2 +- .../Queries/Handlers/GetProductHandler.cs | 2 +- 24 files changed, 86 insertions(+), 65 deletions(-) rename src/Genocs.Persistence.MongoDb/Repositories/{ => Clean}/IMongoDbEntity.cs (51%) rename src/Genocs.Persistence.MongoDb/Repositories/{ => Clean}/MongoDbRepository.cs (74%) rename src/Genocs.Persistence.MongoDb/Repositories/{ => Clean}/MongoDbRepositoryBaseOfEntity.cs (95%) rename src/Genocs.Persistence.MongoDb/Repositories/{ => Clean}/MongoDbRepositoryBaseOfEntityAndKey.cs (90%) rename src/Genocs.Persistence.MongoDb/Repositories/{ => Mentor}/IMongoRepository.cs (77%) rename src/Genocs.Persistence.MongoDb/Repositories/{ => Mentor}/MongoRepository.cs (94%) diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs index c7b7d5f6..923d6e00 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs @@ -1,7 +1,7 @@ using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Entities.Auditing; using Genocs.Core.Domain.Repositories; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Clean; namespace Genocs.Core.Demo.Domain.Aggregates; diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index f7a7d566..6e538c4d 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -10,6 +10,7 @@ using Genocs.Monitoring; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Clean; using Genocs.ServiceBusAzure.Options; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs index 86ddfc79..291ef5f6 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs @@ -1,6 +1,7 @@ using Genocs.MessageBrokers.Outbox.Messages; using Genocs.MessageBrokers.Outbox.Options; using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; using Microsoft.Extensions.Logging; using MongoDB.Driver; using System.Text.Json; diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs index 38d8fd3f..93968790 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs @@ -5,6 +5,8 @@ using Genocs.Persistence.MongoDb.Initializers; using Genocs.Persistence.MongoDb.Options; using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Clean; +using Genocs.Persistence.MongoDb.Repositories.Mentor; using Genocs.Persistence.MongoDb.Seeders; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbEntity.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs similarity index 51% rename from src/Genocs.Persistence.MongoDb/Repositories/IMongoDbEntity.cs rename to src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs index cfdc0a94..93499548 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbEntity.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs @@ -1,9 +1,9 @@ using Genocs.Common.Types; -namespace Genocs.Persistence.MongoDb.Repositories; +namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// -/// General purpose Entity used by default in MongoDB +/// General purpose Entity used by default in MongoDB. /// public interface IMongoDbEntity : IIdentifiable { diff --git a/src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs similarity index 74% rename from src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepository.cs rename to src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs index 1f384738..f5096f89 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs @@ -1,13 +1,13 @@ using Genocs.Common.Types; -namespace Genocs.Persistence.MongoDb.Repositories; - +namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// /// Implements IRepository for MongoDB. /// /// Type of the Entity for this repository -public class MongoDbRepository : MongoDbRepositoryBase, IMongoDbRepository where TEntity : class, IIdentifiable +public class MongoDbRepository : MongoDbRepositoryBase, IMongoDbRepository + where TEntity : class, IIdentifiable { /// /// @@ -16,5 +16,5 @@ public class MongoDbRepository : MongoDbRepositoryBase, public MongoDbRepository(IMongoDatabaseProvider databaseProvider) : base(databaseProvider) { - } + } } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepositoryBaseOfEntity.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs similarity index 95% rename from src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepositoryBaseOfEntity.cs rename to src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs index 707e59b6..e095df7c 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepositoryBaseOfEntity.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs @@ -3,7 +3,7 @@ using MongoDB.Driver.Linq; using System.Linq.Expressions; -namespace Genocs.Persistence.MongoDb.Repositories; +namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// diff --git a/src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs similarity index 90% rename from src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs rename to src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs index 7d91044c..2dd39fd6 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs @@ -2,11 +2,12 @@ using Genocs.Core.CQRS.Queries; using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; using MongoDB.Driver; using MongoDB.Driver.Linq; using System.Linq.Expressions; -namespace Genocs.Persistence.MongoDb.Repositories; +namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// @@ -32,10 +33,10 @@ public virtual IMongoCollection Collection { get { - Attribute[] attrs = Attribute.GetCustomAttributes(typeof(TEntity)); // Reflection. + var attrs = Attribute.GetCustomAttributes(typeof(TEntity)); // Reflection. // Displaying output. - foreach (Attribute attr in attrs) + foreach (var attr in attrs) { if (attr is TableMappingAttribute) { @@ -76,7 +77,7 @@ public override IQueryable GetAll() /// public override TEntity Get(TPrimaryKey id) { - FilterDefinition filter = Builders.Filter.Eq(m => m.Id, id); + var filter = Builders.Filter.Eq(m => m.Id, id); var entity = Collection.Find(filter).FirstOrDefault(); if (entity == null) { @@ -93,7 +94,7 @@ public override TEntity Get(TPrimaryKey id) /// public override TEntity FirstOrDefault(TPrimaryKey id) { - FilterDefinition filter = Builders.Filter.Eq(m => m.Id, id); + var filter = Builders.Filter.Eq(m => m.Id, id); return Collection.Find(filter).FirstOrDefault(); } @@ -137,8 +138,8 @@ public override void Delete(TEntity entity) /// public override void Delete(TPrimaryKey id) { - FilterDefinition query = Builders.Filter.Eq(m => m.Id, id); - DeleteResult deleteResult = Collection.DeleteOneAsync(query).Result; + var query = Builders.Filter.Eq(m => m.Id, id); + var deleteResult = Collection.DeleteOneAsync(query).Result; } public IMongoQueryable GetMongoQueryable() diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs index 186da79a..a2858825 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbInitializer.cs @@ -3,7 +3,7 @@ namespace Genocs.Persistence.MongoDb.Repositories; /// -/// The MongoDbInitializer interface placeholder +/// The MongoDbInitializer interface placeholder. /// public interface IMongoDbInitializer : IInitializer { diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs index a0fbbf6a..36e91713 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs @@ -3,34 +3,34 @@ namespace Genocs.Persistence.MongoDb.Repositories; /// -/// The MongoDB Options Builder +/// The MongoDB Options Builder. /// public interface IMongoDbOptionsBuilder { /// - /// Setup the Connection string + /// Setup the Connection string. /// /// /// IMongoDbOptionsBuilder WithConnectionString(string connectionString); /// - /// Setup the Database name + /// Setup the Database name. /// /// /// IMongoDbOptionsBuilder WithDatabase(string database); /// - /// Setup the database Seed + /// Setup the database Seed. /// /// /// IMongoDbOptionsBuilder WithSeed(bool seed); /// - /// Get the settings + /// Get the settings. /// - /// MongoDbSettings instance + /// MongoDbSettings instance. MongoDbSettings Build(); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs index b5e603cb..5131ff4d 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs @@ -1,13 +1,14 @@ using Genocs.Common.Types; +using Genocs.Persistence.MongoDb.Repositories.Mentor; namespace Genocs.Persistence.MongoDb.Repositories; - /// -/// The MongoDb repository interface +/// The MongoDb repository interface. /// -/// -public interface IMongoDbRepository : IMongoRepository where TEntity : IIdentifiable +/// The type of the entity. +public interface IMongoDbRepository : IMongoRepository + where TEntity : IIdentifiable { } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs index 3f5ca7ae..50445be5 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs @@ -3,14 +3,14 @@ namespace Genocs.Persistence.MongoDb.Repositories; /// -/// The MongoDb seeder +/// The MongoDb seeder. /// public interface IMongoDbSeeder { /// - /// Database Seed + /// Database Seed. /// - /// + /// The database. /// Task SeedAsync(IMongoDatabase database); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs index aeb08733..b6b4c6a2 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs @@ -3,13 +3,13 @@ namespace Genocs.Persistence.MongoDb.Repositories; /// -/// The MongoDb Session Factory +/// The MongoDb Session Factory. /// public interface IMongoSessionFactory { /// - /// Create a new session + /// Create a new session. /// - /// + /// The ClientSessionHandle. Task CreateAsync(); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs similarity index 77% rename from src/Genocs.Persistence.MongoDb/Repositories/IMongoRepository.cs rename to src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs index 7fdb11df..cf1f2878 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs @@ -5,9 +5,10 @@ using MongoDB.Driver.Linq; using System.Linq.Expressions; -namespace Genocs.Persistence.MongoDb.Repositories; +namespace Genocs.Persistence.MongoDb.Repositories.Mentor; -public interface IMongoRepository : IRepositoryOfEntity where TEntity : IIdentifiable +public interface IMongoRepository : IRepositoryOfEntity + where TEntity : IIdentifiable { IMongoCollection Collection { get; } @@ -16,10 +17,12 @@ public interface IMongoRepository : IRepositoryOfEntity Task GetAsync(Expression> predicate); Task> FindAsync(Expression> predicate); - Task> BrowseAsync(Expression> predicate, TQuery query) where TQuery : IPagedQuery; + Task> BrowseAsync(Expression> predicate, TQuery query) + where TQuery : IPagedQuery; Task AddAsync(TEntity entity); Task UpdateAsync(TEntity entity, Expression> predicate); + Task ExistsAsync(Expression> predicate); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/MongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs similarity index 94% rename from src/Genocs.Persistence.MongoDb/Repositories/MongoRepository.cs rename to src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs index e882d4c4..b1e8f06e 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/MongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs @@ -5,7 +5,7 @@ using MongoDB.Driver.Linq; using System.Linq.Expressions; -namespace Genocs.Persistence.MongoDb.Repositories; +namespace Genocs.Persistence.MongoDb.Repositories.Mentor; internal class MongoRepository : IMongoRepository where TEntity : IIdentifiable @@ -18,7 +18,7 @@ public MongoRepository(IMongoDatabase database, string collectionName) public IMongoCollection Collection { get; } /// - /// It returns the Mongo Collection as Queryable + /// It returns the Mongo Collection as Queryable. /// /// public IMongoQueryable GetMongoQueryable() @@ -40,7 +40,7 @@ public Task> BrowseAsync(Expression Collection.AsQueryable().Where(predicate).PaginateAsync(query); /// - /// It adds an entity to the Mongo Collection + /// It adds an entity to the Mongo Collection. /// /// /// @@ -48,24 +48,24 @@ public Task AddAsync(TEntity entity) => Collection.InsertOneAsync(entity); /// - /// It updates an entity in the Mongo Collection + /// It updates an entity in the Mongo Collection. /// - /// The entity - /// The updated entity + /// The entity. + /// The updated entity. public Task UpdateAsync(TEntity entity) => UpdateAsync(entity, e => e.Id.Equals(entity.Id)); /// - /// It updates an entity in the Mongo Collection in async mode + /// It updates an entity in the Mongo Collection in async mode. /// - /// The entity - /// The predicate - /// The updated entity + /// The entity. + /// The predicate. + /// The updated entity. public Task UpdateAsync(TEntity entity, Expression> predicate) => Collection.ReplaceOneAsync(predicate, entity); /// - /// It deletes an entity from the Mongo Collection in async mode + /// It deletes an entity from the Mongo Collection in async mode. /// /// /// diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Pagination.cs b/src/Genocs.Persistence.MongoDb/Repositories/Pagination.cs index fed767f6..2096828c 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Pagination.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Pagination.cs @@ -7,11 +7,21 @@ namespace Genocs.Persistence.MongoDb.Repositories; public static class Pagination { - public static async Task> PaginateAsync(this IMongoQueryable collection, IPagedQuery query) - => await collection.PaginateAsync(query.OrderBy, query.SortOrder, query.Page, query.Results); - - public static async Task> PaginateAsync(this IMongoQueryable collection, string? orderBy, - string? sortOrder, int page = 1, int resultsPerPage = 10) + public static async Task> PaginateAsync( + this IMongoQueryable collection, + IPagedQuery query) + => await collection.PaginateAsync( + query.OrderBy, + query.SortOrder, + query.Page, + query.Results); + + public static async Task> PaginateAsync( + this IMongoQueryable collection, + string? orderBy, + string? sortOrder, + int page = 1, + int resultsPerPage = 10) { if (page <= 0) { @@ -23,14 +33,14 @@ public static async Task> PaginateAsync(this IMongoQueryable.Empty; } - var totalResults = await collection.CountAsync(); - var totalPages = (int)Math.Ceiling((decimal)totalResults / resultsPerPage); + int totalResults = await collection.CountAsync(); + int totalPages = (int)Math.Ceiling((decimal)totalResults / resultsPerPage); List data; if (string.IsNullOrWhiteSpace(orderBy)) @@ -54,8 +64,10 @@ public static async Task> PaginateAsync(this IMongoQueryable Limit(this IMongoQueryable collection, IPagedQuery query) => collection.Limit(query.Page, query.Results); - public static IMongoQueryable Limit(this IMongoQueryable collection, - int page = 1, int resultsPerPage = 10) + public static IMongoQueryable Limit( + this IMongoQueryable collection, + int page = 1, + int resultsPerPage = 10) { if (page <= 0) { @@ -67,7 +79,7 @@ public static IMongoQueryable Limit(this IMongoQueryable collection, resultsPerPage = 10; } - var skip = (page - 1) * resultsPerPage; + int skip = (page - 1) * resultsPerPage; var data = collection .Skip(skip) diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs index cc9c8d93..435ed3c6 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Identities.Application.Mongo.Documents; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using MongoDB.Driver; diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs index 5edbedbb..9dba71ff 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs @@ -2,7 +2,7 @@ using Genocs.Identities.Application.DTO; using Genocs.Identities.Application.Mongo.Documents; using Genocs.Identities.Application.Queries; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; namespace Genocs.Identities.Application.Mongo.Queries.Handlers; diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs index dea8a35e..0a4cc536 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs @@ -1,7 +1,7 @@ using Genocs.Identities.Application.Domain.Entities; using Genocs.Identities.Application.Domain.Repositories; using Genocs.Identities.Application.Mongo.Documents; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; namespace Genocs.Identities.Application.Mongo.Repositories; diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs index b5a52111..f20e43a6 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs @@ -1,7 +1,7 @@ using Genocs.Identities.Application.Domain.Entities; using Genocs.Identities.Application.Domain.Repositories; using Genocs.Identities.Application.Mongo.Documents; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; namespace Genocs.Identities.Application.Mongo.Repositories; diff --git a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs index df8a7c13..cbc1d243 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs @@ -4,7 +4,7 @@ using Genocs.Orders.WebApi.Domain; using Genocs.Orders.WebApi.Events; using Genocs.Orders.WebApi.Services; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; using OpenTracing; namespace Genocs.Orders.WebApi.Commands.Handlers; diff --git a/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs b/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs index d0f67e04..4f98dbcb 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs @@ -1,7 +1,7 @@ using Genocs.Core.CQRS.Queries; using Genocs.Orders.WebApi.Domain; using Genocs.Orders.WebApi.DTO; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; namespace Genocs.Orders.WebApi.Queries.Handlers; diff --git a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs index 8328a404..ae2474c4 100644 --- a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs +++ b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs @@ -1,7 +1,7 @@ using Genocs.Core.CQRS.Commands; using Genocs.MessageBrokers; using Genocs.MessageBrokers.Outbox; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; using Genocs.Products.WebApi.Domain; using Genocs.Products.WebApi.Events; using OpenTracing; diff --git a/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs b/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs index 9414e599..2becb5d1 100644 --- a/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs +++ b/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs @@ -1,5 +1,5 @@ using Genocs.Core.CQRS.Queries; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Repositories.Mentor; using Genocs.Products.WebApi.DTO; namespace Genocs.Products.WebApi.Queries.Handlers; From 3bb4589e3596ca7cb1aed17129a3aab2ef5b9dd5 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 28 Nov 2023 20:01:38 +0100 Subject: [PATCH 019/104] Implemented Mongo functionality --- .../IRepositoryOfTEntityAndTPrimaryKey.cs | 10 +- .../Extensions.cs | 8 +- .../Messages/OutboxMessage.cs | 6 +- .../Options/OutboxSettings.cs | 6 +- .../Outbox/InMemoryMessageOutbox.cs | 18 ++- .../Clean/MongoDbRepositoryBaseOfEntity.cs | 4 +- .../MongoDbRepositoryBaseOfEntityAndKey.cs | 130 ++++++++---------- .../Repositories/Mentor/IMongoRepository.cs | 2 +- .../Repositories/Mentor/MongoRepository.cs | 41 ++---- 9 files changed, 101 insertions(+), 124 deletions(-) diff --git a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs index 239916cc..82283219 100644 --- a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs @@ -8,7 +8,7 @@ namespace Genocs.Core.Domain.Repositories; /// /// Main Entity type this repository works on. /// Primary key type of the entity. -public interface IRepositoryOfEntity : IRepository +public interface IRepositoryOfEntity : IRepository where TEntity : IIdentifiable { #region Select/Get/Query @@ -146,7 +146,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - TIdentifiable InsertAndGetId(TEntity entity); + TIdentifiable InsertAndGetId(TEntity entity); /// /// Inserts a new entity and gets it's Id. @@ -155,7 +155,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - Task InsertAndGetIdAsync(TEntity entity); + Task InsertAndGetIdAsync(TEntity entity); /// /// Inserts or updates given entity depending on Id's value. @@ -177,7 +177,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - TIdentifiable InsertOrUpdateAndGetId(TEntity entity); + TIdentifiable InsertOrUpdateAndGetId(TEntity entity); /// /// Inserts or updates given entity depending on Id's value. @@ -187,7 +187,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - Task InsertOrUpdateAndGetIdAsync(TEntity entity); + Task InsertOrUpdateAndGetIdAsync(TEntity entity); #endregion diff --git a/src/Genocs.MessageBrokers.Outbox/Extensions.cs b/src/Genocs.MessageBrokers.Outbox/Extensions.cs index 21ea730a..ce2d06c4 100644 --- a/src/Genocs.MessageBrokers.Outbox/Extensions.cs +++ b/src/Genocs.MessageBrokers.Outbox/Extensions.cs @@ -12,8 +12,10 @@ public static class Extensions private const string SectionName = "outbox"; private const string RegistryName = "messageBrokers.outbox"; - public static IGenocsBuilder AddMessageOutbox(this IGenocsBuilder builder, - Action configure = null, string sectionName = SectionName) + public static IGenocsBuilder AddMessageOutbox( + this IGenocsBuilder builder, + Action? configure = null, + string sectionName = SectionName) { if (string.IsNullOrWhiteSpace(sectionName)) { @@ -48,7 +50,7 @@ public static IGenocsBuilder AddMessageOutbox(this IGenocsBuilder builder, return builder; } - public static IMessageOutboxConfigurator AddInMemory(this IMessageOutboxConfigurator configurator, string? mongoSectionName = null) + public static IMessageOutboxConfigurator AddInMemory(this IMessageOutboxConfigurator configurator) { configurator.Builder.Services.AddTransient(); diff --git a/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs b/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs index 8d251cc4..5d0f2e16 100644 --- a/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs +++ b/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs @@ -5,9 +5,9 @@ namespace Genocs.MessageBrokers.Outbox.Messages; public sealed class OutboxMessage : IIdentifiable { public string Id { get; set; } - public string OriginatedMessageId { get; set; } - public string CorrelationId { get; set; } - public string SpanContext { get; set; } + public string? OriginatedMessageId { get; set; } + public string? CorrelationId { get; set; } + public string? SpanContext { get; set; } public Dictionary Headers { get; set; } = new(); public string MessageType { get; set; } public string MessageContextType { get; set; } diff --git a/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs b/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs index 9904c770..f26273a7 100644 --- a/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs +++ b/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs @@ -5,8 +5,8 @@ public class OutboxSettings public bool Enabled { get; set; } public int Expiry { get; set; } public double IntervalMilliseconds { get; set; } - public string InboxCollection { get; set; } - public string OutboxCollection { get; set; } - public string Type { get; set; } + public string? InboxCollection { get; set; } + public string? OutboxCollection { get; set; } + public string? Type { get; set; } public bool DisableTransactions { get; set; } } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs index fc6e60cb..316b435f 100644 --- a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs @@ -7,11 +7,9 @@ namespace Genocs.MessageBrokers.Outbox.Outbox; internal sealed class InMemoryMessageOutbox : IMessageOutbox, IMessageOutboxAccessor { - private readonly ConcurrentDictionary _inboxMessages = - new(); + private readonly ConcurrentDictionary _inboxMessages = new(); - private readonly ConcurrentDictionary _outboxMessages = - new(); + private readonly ConcurrentDictionary _outboxMessages = new(); private readonly ILogger _logger; private readonly int _expiry; @@ -58,9 +56,15 @@ public async Task HandleAsync(string messageId, Func handler) _logger.LogTrace($"Processed a message with id: '{messageId}'."); } - public Task SendAsync(T message, string originatedMessageId = null, string messageId = null, - string correlationId = null, string spanContext = null, object messageContext = null, - IDictionary headers = null) where T : class + public Task SendAsync( + T message, + string? originatedMessageId = null, + string? messageId = null, + string? correlationId = null, + string? spanContext = null, + object? messageContext = null, + IDictionary? headers = null) + where T : class { if (!Enabled) { diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs index e095df7c..b6427474 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs @@ -38,7 +38,7 @@ public IMongoQueryable GetMongoQueryable() /// /// /// - public async Task> BrowseAsync(Expression> predicate, - TQuery query) where TQuery : IPagedQuery + public async Task> BrowseAsync(Expression> predicate, TQuery query) + where TQuery : IPagedQuery => await Collection.AsQueryable().Where(predicate).PaginateAsync(query); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs index 2dd39fd6..6933b1f5 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs @@ -9,33 +9,40 @@ namespace Genocs.Persistence.MongoDb.Repositories.Clean; - /// /// Implements IRepository for MongoDB. /// -/// Type of the Entity for this repository -/// Primary key of the entity +/// Type of the Entity for this repository. +/// Primary key of the entity. public class MongoDbRepositoryBase : RepositoryBase, IMongoRepository where TEntity : class, IIdentifiable { /// - /// Todo + /// Get the Mongodb database. /// public virtual IMongoDatabase Database { get { return _databaseProvider.Database; } } + private readonly IMongoDatabaseProvider _databaseProvider; + protected IMongoCollection? _collection; + /// - /// Todo + /// Get the Mongodb collection from a custom attribute or from the entity name. /// public virtual IMongoCollection Collection { get { - var attrs = Attribute.GetCustomAttributes(typeof(TEntity)); // Reflection. + if (_collection != null) + { + return _collection; + } - // Displaying output. + var attrs = Attribute.GetCustomAttributes(typeof(TEntity)); // Reflection. + + // Displaying output. foreach (var attr in attrs) { if (attr is TableMappingAttribute) @@ -43,15 +50,15 @@ public virtual IMongoCollection Collection return _databaseProvider.Database.GetCollection((attr as TableMappingAttribute).Name); } } - return _databaseProvider.Database.GetCollection(typeof(TEntity).Name); - } - } - private readonly IMongoDatabaseProvider _databaseProvider; + _collection = _databaseProvider.Database.GetCollection(typeof(TEntity).Name); + return _collection; + } + } /// - /// Standard constructor + /// Standard constructor. /// /// public MongoDbRepositoryBase(IMongoDatabaseProvider databaseProvider) @@ -60,21 +67,18 @@ public MongoDbRepositoryBase(IMongoDatabaseProvider databaseProvider) } /// - /// Get all entities as IQueryable + /// Get all entities as IQueryable. /// /// public override IQueryable GetAll() - { - return Collection.AsQueryable(); - } - + => Collection.AsQueryable(); /// - /// Get single entity + /// Get single entity. /// /// /// - /// + /// It is thrown if the entity is not found. public override TEntity Get(TPrimaryKey id) { var filter = Builders.Filter.Eq(m => m.Id, id); @@ -88,7 +92,7 @@ public override TEntity Get(TPrimaryKey id) } /// - /// First Or Default entity + /// First Or Default entity. /// /// /// @@ -99,7 +103,7 @@ public override TEntity FirstOrDefault(TPrimaryKey id) } /// - /// Insert an entity + /// Insert an entity. /// /// /// @@ -110,30 +114,25 @@ public override TEntity Insert(TEntity entity) } /// - /// Update an existing entity + /// Update an existing entity. /// /// /// public override TEntity Update(TEntity entity) { - Collection.ReplaceOneAsync( - filter: g => g.Id.Equals(entity.Id), - replacement: entity); + Collection.ReplaceOneAsync(filter: g => g.Id.Equals(entity.Id), replacement: entity); return entity; } /// - /// Delete entity, passing the entire object + /// Delete entity, passing the entire object. /// /// public override void Delete(TEntity entity) - { - Delete(entity.Id); - } - + => Delete(entity.Id); /// - /// Delete entity by primary key + /// Delete entity by primary key. /// /// public override void Delete(TPrimaryKey id) @@ -143,57 +142,40 @@ public override void Delete(TPrimaryKey id) } public IMongoQueryable GetMongoQueryable() - { - throw new NotImplementedException(); - } + => Collection.AsQueryable(); - public Task GetAsync(Expression> predicate) - { - throw new NotImplementedException(); - } + public async Task GetAsync(Expression> predicate) + => await Collection.AsQueryable().Where(predicate).FirstAsync(); - public Task> FindAsync(Expression> predicate) - { - throw new NotImplementedException(); - } + public async Task> FindAsync(Expression> predicate) + => await Collection.AsQueryable().Where(predicate).ToListAsync(); - public Task> BrowseAsync(Expression> predicate, TQuery query) where TQuery : IPagedQuery - { - throw new NotImplementedException(); - } + public async Task> BrowseAsync(Expression> predicate, TQuery query) + where TQuery : IPagedQuery + => await Collection.AsQueryable().Where(predicate).PaginateAsync(query); - public Task AddAsync(TEntity entity) - { - throw new NotImplementedException(); - } + public async Task AddAsync(TEntity entity) + => await Collection.InsertOneAsync(entity); - public Task UpdateAsync(TEntity entity, Expression> predicate) - { - throw new NotImplementedException(); - } + public async Task UpdateAsync(TEntity entity, Expression> predicate) + => await Collection.ReplaceOneAsync(predicate, entity); - public Task ExistsAsync(Expression> predicate) - { - throw new NotImplementedException(); - } + public async Task ExistsAsync(Expression> predicate) + => await Collection.AsQueryable().Where(predicate).AnyAsync(); - public TIdentifiable InsertAndGetId(TEntity entity) - { - throw new NotImplementedException(); - } - public Task InsertAndGetIdAsync(TEntity entity) - { - throw new NotImplementedException(); - } + //public Task InsertAndGetIdAsync(TEntity entity) + //{ + // throw new NotImplementedException(); + //} - public TIdentifiable InsertOrUpdateAndGetId(TEntity entity) - { - throw new NotImplementedException(); - } + //public TIdentifiable InsertOrUpdateAndGetId(TEntity entity) + //{ + // throw new NotImplementedException(); + //} - public Task InsertOrUpdateAndGetIdAsync(TEntity entity) - { - throw new NotImplementedException(); - } + //public Task InsertOrUpdateAndGetIdAsync(TEntity entity) + //{ + // throw new NotImplementedException(); + //} } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs index cf1f2878..16cf0ddf 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs @@ -7,7 +7,7 @@ namespace Genocs.Persistence.MongoDb.Repositories.Mentor; -public interface IMongoRepository : IRepositoryOfEntity +public interface IMongoRepository : IRepositoryOfEntity where TEntity : IIdentifiable { IMongoCollection Collection { get; } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs index b1e8f06e..2bb18e98 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs @@ -35,8 +35,8 @@ public Task GetAsync(Expression> predicate) public async Task> FindAsync(Expression> predicate) => await Collection.Find(predicate).ToListAsync(); - public Task> BrowseAsync(Expression> predicate, - TQuery query) where TQuery : IPagedQuery + public Task> BrowseAsync(Expression> predicate, TQuery query) + where TQuery : IPagedQuery => Collection.AsQueryable().Where(predicate).PaginateAsync(query); /// @@ -82,9 +82,7 @@ public IQueryable GetAll() => Collection.AsQueryable(); public IQueryable GetAllIncluding(params Expression>[] propertySelectors) - { - throw new NotImplementedException(); - } + => GetAll(); public List GetAllList() => Collection.AsQueryable().ToList(); @@ -148,9 +146,7 @@ public async Task FirstOrDefaultAsync(Expression> p } public TEntity Load(TIdentifiable id) - { - throw new NotImplementedException(); - } + => FirstOrDefault(id); public TEntity Insert(TEntity entity) { @@ -164,15 +160,11 @@ public async Task InsertAsync(TEntity entity) return entity; } - public TIdentifiable InsertAndGetId(TEntity entity) - { - throw new NotImplementedException(); - } + public TIdentifiable InsertAndGetId(TEntity entity) + => Insert(entity).Id; - public Task InsertAndGetIdAsync(TEntity entity) - { - throw new NotImplementedException(); - } + public async Task InsertAndGetIdAsync(TEntity entity) + => (await InsertAsync(entity)).Id; public TEntity InsertOrUpdate(TEntity entity) { @@ -186,16 +178,11 @@ public async Task InsertOrUpdateAsync(TEntity entity) return entity; } - public TIdentifiable InsertOrUpdateAndGetId(TEntity entity) - { - throw new NotImplementedException(); - } + public TIdentifiable InsertOrUpdateAndGetId(TEntity entity) + => InsertOrUpdate(entity).Id; - public Task InsertOrUpdateAndGetIdAsync(TEntity entity) - { - - throw new NotImplementedException(); - } + public async Task InsertOrUpdateAndGetIdAsync(TEntity entity) + => (await InsertOrUpdateAsync(entity)).Id; public TEntity Update(TEntity entity) { @@ -203,7 +190,6 @@ public TEntity Update(TEntity entity) return entity; } - public TEntity Update(TIdentifiable id, Action updateAction) { throw new NotImplementedException(); @@ -226,6 +212,7 @@ public Task DeleteAsync(TEntity entity) { throw new ArgumentNullException(nameof(entity)); } + return DeleteAsync(entity.Id); } @@ -235,6 +222,7 @@ public void Delete(TIdentifiable id) { throw new ArgumentNullException(nameof(id)); } + Collection.DeleteOne(c => c.Id.Equals(id)); } @@ -244,6 +232,7 @@ public void Delete(Expression> predicate) { throw new ArgumentNullException(nameof(predicate)); } + Collection.DeleteMany(predicate); } From 296abe7757f025b2d75313e423d9f380f758a160 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 28 Nov 2023 22:11:19 +0100 Subject: [PATCH 020/104] Default mongodb entity with ObjectId --- .../Aggregates/Order.cs | 5 +-- .../Aggregates/User.cs | 7 ++-- .../Controllers/MongoDbController.cs | 2 -- .../Repositories/Clean/IMongoDbEntity.cs | 3 +- .../Repositories/Clean/MongoDbRepository.cs | 11 +++--- .../Clean/MongoDbRepositoryBaseOfEntity.cs | 34 +++---------------- .../MongoDbRepositoryBaseOfEntityAndKey.cs | 31 +++++++---------- .../Repositories/IMongoDbRepository.cs | 5 +-- 8 files changed, 36 insertions(+), 62 deletions(-) diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs index 923d6e00..42bca453 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs @@ -2,11 +2,12 @@ using Genocs.Core.Domain.Entities.Auditing; using Genocs.Core.Domain.Repositories; using Genocs.Persistence.MongoDb.Repositories.Clean; +using MongoDB.Bson; namespace Genocs.Core.Demo.Domain.Aggregates; [TableMapping("Orders")] -public class Order : AggregateRoot, IMongoDbEntity, IHasCreationTime +public class Order : AggregateRoot, IMongoDbEntity, IHasCreationTime { public Order(string orderId, string userId, string cardToken, decimal amount, string currency) { @@ -17,7 +18,7 @@ public Order(string orderId, string userId, string cardToken, decimal amount, st Currency = currency; } - public string OrderId { get; set; } = Guid.NewGuid().ToString(); + public string OrderId { get; set; } = ObjectId.GenerateNewId().ToString(); public string UserId { get; set; } = default!; public DateTime CreationTime { get; set; } = DateTime.UtcNow; public string CardToken { get; set; } = default!; diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs index 2b241a42..ac54b661 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs @@ -1,14 +1,15 @@ using Genocs.Common.Types; using Genocs.Core.Domain.Entities.Auditing; using Genocs.Core.Domain.Repositories; +using MongoDB.Bson; namespace Genocs.Core.Demo.Domain.Aggregates; [TableMapping("Users")] -public class User : IIdentifiable, IHasCreationTime +public class User : IIdentifiable, IHasCreationTime { - public Guid Id { get; set; } + public ObjectId Id { get; set; } public string UserId { get; set; } = default!; public DateTime CreationTime { get; set; } = DateTime.UtcNow; public string Username { get; set; } = default!; @@ -17,7 +18,7 @@ public class User : IIdentifiable, IHasCreationTime public User(string userId, string username, decimal age, string country) { - Id = Guid.NewGuid(); + Id = ObjectId.GenerateNewId(); UserId = userId; Username = username; Age = age; diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs index 69e79b7b..ddc0be37 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs @@ -1,8 +1,6 @@ using Genocs.Core.Demo.Domain.Aggregates; -using Genocs.Core.Domain.Repositories; using Genocs.Persistence.MongoDb.Repositories; using Microsoft.AspNetCore.Mvc; -using MongoDB.Bson; namespace Genocs.Core.Demo.WebApi.Controllers; diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs index 93499548..5520d571 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs @@ -1,11 +1,12 @@ using Genocs.Common.Types; +using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// /// General purpose Entity used by default in MongoDB. /// -public interface IMongoDbEntity : IIdentifiable +public interface IMongoDbEntity : IIdentifiable { } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs index f5096f89..30463760 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs @@ -1,18 +1,19 @@ using Genocs.Common.Types; +using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// /// Implements IRepository for MongoDB. /// -/// Type of the Entity for this repository -public class MongoDbRepository : MongoDbRepositoryBase, IMongoDbRepository - where TEntity : class, IIdentifiable +/// Type of the Entity for this repository. +public class MongoDbRepository : MongoDbRepositoryBase, IMongoDbRepository + where TEntity : class, IIdentifiable { /// - /// + /// The standard constructor. /// - /// + /// The database provider. public MongoDbRepository(IMongoDatabaseProvider databaseProvider) : base(databaseProvider) { diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs index b6427474..5a956c2f 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs @@ -1,44 +1,20 @@ -using Genocs.Core.CQRS.Queries; -using MongoDB.Driver; -using MongoDB.Driver.Linq; -using System.Linq.Expressions; +using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Repositories.Clean; - /// /// Implements base class for IRepository for MongoDB. /// -/// Type of the Entity for this repository -public class MongoDbRepositoryBase : MongoDbRepositoryBase +/// Type of the Entity for this repository. +public class MongoDbRepositoryBase : MongoDbRepositoryBase where TEntity : class, IMongoDbEntity { /// - /// + /// The standard constructor. /// - /// + /// The MongoDB database provider. public MongoDbRepositoryBase(IMongoDatabaseProvider databaseProvider) : base(databaseProvider) { } - - /// - /// It returns the Mongo Collection as Queryable - /// - /// - public IMongoQueryable GetMongoQueryable() - { - return Collection.AsQueryable(); - } - - /// - /// - /// - /// - /// - /// - /// - public async Task> BrowseAsync(Expression> predicate, TQuery query) - where TQuery : IPagedQuery - => await Collection.AsQueryable().Where(predicate).PaginateAsync(query); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs index 6933b1f5..5e44e9ae 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs @@ -18,7 +18,7 @@ public class MongoDbRepositoryBase : RepositoryBase { /// - /// Get the Mongodb database. + /// Get the MongoDB database. /// public virtual IMongoDatabase Database { @@ -29,7 +29,7 @@ public virtual IMongoDatabase Database protected IMongoCollection? _collection; /// - /// Get the Mongodb collection from a custom attribute or from the entity name. + /// Get the MongoDB collection from a custom attribute or from the entity name. /// public virtual IMongoCollection Collection { @@ -141,6 +141,10 @@ public override void Delete(TPrimaryKey id) var deleteResult = Collection.DeleteOneAsync(query).Result; } + /// + /// It returns the Mongo Collection as Queryable. + /// + /// public IMongoQueryable GetMongoQueryable() => Collection.AsQueryable(); @@ -150,6 +154,13 @@ public async Task GetAsync(Expression> predicate) public async Task> FindAsync(Expression> predicate) => await Collection.AsQueryable().Where(predicate).ToListAsync(); + /// + /// Query data from the Mongo Collection and convert it to a PagedResult. + /// + /// The query type. + /// The predicate. + /// The query. + /// The paged result. public async Task> BrowseAsync(Expression> predicate, TQuery query) where TQuery : IPagedQuery => await Collection.AsQueryable().Where(predicate).PaginateAsync(query); @@ -162,20 +173,4 @@ public async Task UpdateAsync(TEntity entity, Expression> pr public async Task ExistsAsync(Expression> predicate) => await Collection.AsQueryable().Where(predicate).AnyAsync(); - - - //public Task InsertAndGetIdAsync(TEntity entity) - //{ - // throw new NotImplementedException(); - //} - - //public TIdentifiable InsertOrUpdateAndGetId(TEntity entity) - //{ - // throw new NotImplementedException(); - //} - - //public Task InsertOrUpdateAndGetIdAsync(TEntity entity) - //{ - // throw new NotImplementedException(); - //} } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs index 5131ff4d..5cb580d4 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs @@ -1,5 +1,6 @@ using Genocs.Common.Types; using Genocs.Persistence.MongoDb.Repositories.Mentor; +using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Repositories; @@ -7,8 +8,8 @@ namespace Genocs.Persistence.MongoDb.Repositories; /// The MongoDb repository interface. /// /// The type of the entity. -public interface IMongoDbRepository : IMongoRepository - where TEntity : IIdentifiable +public interface IMongoDbRepository : IMongoRepository + where TEntity : IIdentifiable { } From f6da2539bd7249928d3221f0a3af95ab5dd513ef Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 30 Nov 2023 18:43:26 +0100 Subject: [PATCH 021/104] Fix error on Console log --- README.md | 14 +-- containers/.env | 0 src/Genocs.Auth/AuthAttribute.cs | 11 +- src/Genocs.Auth/Handlers/JwtHandler.cs | 25 +++- src/Genocs.Core.Demo.WebApi/Program.cs | 5 - src/Genocs.Core/Builders/Extensions.cs | 15 ++- src/Genocs.Metrics/AppMetrics/Extensions.cs | 1 - .../AppMetrics/MetricsOptions.cs | 20 ++-- .../OpenTelemetryInitializer.cs | 111 +++++++++--------- src/Genocs.Secrets.Vault/Extensions.cs | 43 ++++--- src/Genocs.Tracing/Jaeger/Extensions.cs | 8 +- .../api-gateway/Genocs.APIGateway/Startup.cs | 8 +- .../orders/Genocs.Orders.WebApi/Program.cs | 2 + 13 files changed, 141 insertions(+), 122 deletions(-) create mode 100644 containers/.env diff --git a/README.md b/README.md index d1c8a6be..2f8e5045 100644 --- a/README.md +++ b/README.md @@ -68,19 +68,19 @@ You will use ***Docker compose*** to setup the infrastructure components. ``` bash # Setup the infrastructure -docker-compose -f ./containers/infrastructure-bare.yml --project-name genocs-infrastructure up -d -docker-compose -f ./containers/infrastructure-monitoring.yml --project-name genocs-infrastructure up -d -docker-compose -f ./containers/infrastructure-scaling.yml --project-name genocs-infrastructure up -d -docker-compose -f ./containers/infrastructure-security.yml --project-name genocs-infrastructure up -d +docker-compose -f ./containers/infrastructure-bare.yml --env-file ./containers/.env --project-name genocs-app up -d +docker-compose -f ./containers/infrastructure-monitoring.yml --env-file ./containers/.env --project-name genocs-app up -d +docker-compose -f ./containers/infrastructure-scaling.yml --env-file ./containers/.env --project-name genocs-app up -d +docker-compose -f ./containers/infrastructure-security.yml --env-file ./containers/.env --project-name genocs-app up -d # Use this file only in case you want to setup sqlserver database (no need if you use postgres) -docker-compose -f ./containers/infrastructure-sqlserver.yml --project-name genocs-infrastructure up -d +docker-compose -f ./containers/infrastructure-sqlserver.yml --env-file ./containers/.env --project-name genocs-app up -d # Use this file only in case you want to setup elk stack -docker-compose -f ./containers/infrastructure-elk.yml --project-name genocs-infrastructure up -d +docker-compose -f ./containers/infrastructure-elk.yml --env-file ./containers/.env --project-name genocs-app up -d # Use this file only in case you want to setup AI ML components prepared by Genocs -docker-compose -f ./containers/infrastructure-ml.yml --project-name genocs-infrastructure up -d +docker-compose -f ./containers/infrastructure-ml.yml --env-file ./containers/.env --project-name genocs-app up -d ``` `infrastructure-bare.yml` allows to install the basic infrastructure components. Basic components are the [RabbitMQ](https://rabbitmq.com), [Redis](https://redis.io), [Mongo](https://mongodb.com), [Postgres](https://www.postgresql.org/). diff --git a/containers/.env b/containers/.env new file mode 100644 index 00000000..e69de29b diff --git a/src/Genocs.Auth/AuthAttribute.cs b/src/Genocs.Auth/AuthAttribute.cs index 4188f8bd..31c613c5 100644 --- a/src/Genocs.Auth/AuthAttribute.cs +++ b/src/Genocs.Auth/AuthAttribute.cs @@ -3,16 +3,17 @@ namespace Genocs.Auth; /// -/// The authorization Attribute +/// The authorization Attribute. /// public class AuthAttribute : AuthorizeAttribute { /// - /// The AuthAttribute constructor + /// The AuthAttribute constructor. /// - /// The authorization schema - /// The authorization policy - public AuthAttribute(string scheme, string policy = "") : base(policy) + /// The authorization schema. + /// The authorization policy. + public AuthAttribute(string scheme, string policy = "") + : base(policy) { AuthenticationSchemes = scheme; } diff --git a/src/Genocs.Auth/Handlers/JwtHandler.cs b/src/Genocs.Auth/Handlers/JwtHandler.cs index 2af2b6bc..c06eae7c 100644 --- a/src/Genocs.Auth/Handlers/JwtHandler.cs +++ b/src/Genocs.Auth/Handlers/JwtHandler.cs @@ -43,7 +43,17 @@ public JwtHandler(JwtOptions options, TokenValidationParameters tokenValidationP _issuer = options.Issuer; } - public JsonWebToken CreateToken(string userId, + /// + /// Creates a new token. + /// + /// + /// + /// + /// + /// + /// It is thrown when mandatory data is empty. + public JsonWebToken CreateToken( + string userId, string? role = null, string? audience = null, IDictionary>? claims = null) @@ -61,6 +71,7 @@ public JsonWebToken CreateToken(string userId, new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new(JwtRegisteredClaimNames.Iat, now.ToTimestamp().ToString()), }; + if (!string.IsNullOrWhiteSpace(role)) { jwtClaims.Add(new Claim(ClaimTypes.Role, role)); @@ -91,10 +102,9 @@ public JsonWebToken CreateToken(string userId, claims: jwtClaims, notBefore: now, expires: expires, - signingCredentials: _signingCredentials - ); + signingCredentials: _signingCredentials); - var token = new JwtSecurityTokenHandler().WriteToken(jwt); + string token = new JwtSecurityTokenHandler().WriteToken(jwt); return new JsonWebToken { @@ -114,8 +124,11 @@ public JsonWebToken CreateToken(string userId, /// public JsonWebTokenPayload? GetTokenPayload(string accessToken) { - _jwtSecurityTokenHandler.ValidateToken(accessToken, _tokenValidationParameters, - out var validatedSecurityToken); + _jwtSecurityTokenHandler.ValidateToken( + accessToken, + _tokenValidationParameters, + out var validatedSecurityToken); + if (validatedSecurityToken is not JwtSecurityToken jwt) { return null; diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index f5ea325f..670a448e 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -24,7 +24,6 @@ .UseLogging(); // .UseVault(); - // add services to DI container var services = builder.Services; @@ -33,7 +32,6 @@ .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()); - services.AddCors(); services.AddControllers().AddJsonOptions(x => { @@ -56,7 +54,6 @@ // Add Masstransit bus configuration services.AddCustomMassTransit(builder.Configuration); - services.AddOptions(); // Set Custom Open telemetry @@ -64,7 +61,6 @@ var app = builder.Build(); - // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { @@ -72,7 +68,6 @@ app.UseSwaggerUI(); } - // global cors policy app.UseCors(x => x .SetIsOriginAllowed(origin => true) diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs index 8c785fda..6cd7ed22 100644 --- a/src/Genocs.Core/Builders/Extensions.cs +++ b/src/Genocs.Core/Builders/Extensions.cs @@ -20,20 +20,19 @@ public static class Extensions public static IGenocsBuilder AddGenocs(this IServiceCollection services, IConfiguration? configuration = null) { var builder = GenocsBuilder.Create(services, configuration); - var appOptions = builder.GetOptions(AppSettings.Position); - services.AddSingleton(appOptions); + var options = builder.GetOptions(AppSettings.Position); + services.AddSingleton(options); builder.Services.AddMemoryCache(); services.AddSingleton(); - if (!appOptions.DisplayBanner || string.IsNullOrWhiteSpace(appOptions.Name)) + if (!options.DisplayBanner || string.IsNullOrWhiteSpace(options.Name)) { return builder; } - string version = appOptions.DisplayVersion ? $" {appOptions.Version}" : string.Empty; - Console.WriteLine(Figgle.FiggleFonts.Doom.Render(appOptions.Name + version)); - ConsoleColor current = Console.BackgroundColor; - + string version = options.DisplayVersion ? $" {options.Version}" : string.Empty; + Console.WriteLine(Figgle.FiggleFonts.Doom.Render(options.Name + version)); + ConsoleColor current = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("Runtime Version: {0}", Environment.Version.ToString()); Console.ForegroundColor = current; @@ -61,7 +60,7 @@ public static IApplicationBuilder UseGenocs(this IApplicationBuilder app) /// The option type parameter. /// /// - /// The option. + /// The option model or the default options. public static TModel GetOptions(this IConfiguration configuration, string sectionName) where TModel : new() { diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index b2d8f027..facb15b8 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -70,7 +70,6 @@ public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, MetricsOpti _initialized = true; - var metricsBuilder = new MetricsBuilder().Configuration.Configure(cfg => { var tags = metricsOptions.Tags; diff --git a/src/Genocs.Metrics/AppMetrics/MetricsOptions.cs b/src/Genocs.Metrics/AppMetrics/MetricsOptions.cs index 0f8f932a..41095f89 100644 --- a/src/Genocs.Metrics/AppMetrics/MetricsOptions.cs +++ b/src/Genocs.Metrics/AppMetrics/MetricsOptions.cs @@ -1,53 +1,53 @@ namespace Genocs.Metrics.AppMetrics; /// -/// The MetricsOptions class +/// The MetricsOptions class. /// public class MetricsOptions { /// - /// Default section name + /// Default section name. /// public const string Position = "Metrics"; /// - /// It defines whether the section is enabled or not + /// It defines whether the section is enabled or not. /// public bool Enabled { get; set; } /// - /// It defines whether the Influx db is enabled or not + /// It defines whether the Influx db is enabled or not. /// public bool InfluxEnabled { get; set; } /// - /// It defines whether the Prometheus is enabled or not + /// It defines whether the Prometheus is enabled or not. /// public bool PrometheusEnabled { get; set; } /// /// The Prometheus formatter. - /// allowed method are: protobuf or (null) + /// Allowed method are: protobuf or (null). /// public string? PrometheusFormatter { get; set; } /// - /// The InfluxDb url + /// The InfluxDb url. /// public string? InfluxUrl { get; set; } /// - /// The InfluxDb database name + /// The InfluxDb database name. /// public string? Database { get; set; } /// - /// The metrics interval + /// The metrics interval. /// public int Interval { get; set; } = 10; /// - /// List of tags + /// List of tags. /// public IDictionary? Tags { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Monitoring/OpenTelemetryInitializer.cs b/src/Genocs.Monitoring/OpenTelemetryInitializer.cs index 24e60984..a8ea1f30 100644 --- a/src/Genocs.Monitoring/OpenTelemetryInitializer.cs +++ b/src/Genocs.Monitoring/OpenTelemetryInitializer.cs @@ -6,77 +6,74 @@ using OpenTelemetry.Resources; using OpenTelemetry.Trace; -namespace Genocs.Monitoring +namespace Genocs.Monitoring; + +/// +/// The Open Telemetry and Tracing. +/// +public static class OpenTelemetryInitializer { /// - /// The Open Telemetry and Tracing + /// Custom settings for OpenTelemetry. /// - public static class OpenTelemetryInitializer + /// + /// + /// + public static IServiceCollection AddCustomOpenTelemetry(this IServiceCollection services, IConfiguration configuration) { - /// - /// Custom settings for OpenTelemetry - /// - /// - /// - /// - public static IServiceCollection AddCustomOpenTelemetry(this IServiceCollection services, IConfiguration configuration) - { - // Read Settings - string applicationInsightsConnectionString = configuration.GetConnectionString(Constants.ApplicationInsightsConnectionString); - string serviceName = configuration.GetValue(Constants.ServiceName) ?? "IntegrationsWorker"; - - MonitoringSettings settings = new MonitoringSettings(); - configuration.Bind(MonitoringSettings.Position, settings); - services.AddSingleton(settings); + // Read Settings + string? applicationInsightsConnectionString = configuration.GetConnectionString(Constants.ApplicationInsightsConnectionString); + string serviceName = configuration.GetValue(Constants.ServiceName) ?? "IntegrationsWorker"; + MonitoringSettings settings = new MonitoringSettings(); + configuration.Bind(MonitoringSettings.Position, settings); + services.AddSingleton(settings); - // No OpenTelemetryTracing in case of missing ServiceName - if (string.IsNullOrWhiteSpace(serviceName)) return services; - - // Set Custom Open telemetry - services.AddOpenTelemetry().WithTracing(builder => - { - TracerProviderBuilder provider = builder.SetResourceBuilder(ResourceBuilder.CreateDefault() - .AddService(serviceName) - .AddTelemetrySdk() - .AddEnvironmentVariableDetector()) - .AddSource("*"); + // No OpenTelemetryTracing in case of missing ServiceName + if (string.IsNullOrWhiteSpace(serviceName)) return services; - // Remove comment below to enable tracing on console - // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry nuget package - provider.AddMongoDBInstrumentation(); + // Set Custom Open telemetry + services.AddOpenTelemetry().WithTracing(builder => + { + TracerProviderBuilder provider = builder.SetResourceBuilder(ResourceBuilder.CreateDefault() + .AddService(serviceName) + .AddTelemetrySdk() + .AddEnvironmentVariableDetector()) + .AddSource("*"); - // Remove comment below to enable tracing on console - // you should add OpenTelemetry.Exporter.Console nuget package - provider.AddConsoleExporter(); + // Remove comment below to enable tracing on console + // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry NuGet package + provider.AddMongoDBInstrumentation(); + // Remove comment below to enable tracing on console + // you should add OpenTelemetry.Exporter.Console NuGet package + provider.AddConsoleExporter(); - // Check for Azure ApplicationInsights - if (!string.IsNullOrWhiteSpace(applicationInsightsConnectionString)) + // Check for Azure ApplicationInsights. + if (!string.IsNullOrWhiteSpace(applicationInsightsConnectionString)) + { + provider.AddAzureMonitorTraceExporter(o => { - provider.AddAzureMonitorTraceExporter(o => - { - o.ConnectionString = applicationInsightsConnectionString; - }); - } + o.ConnectionString = applicationInsightsConnectionString; + }); + } - provider.AddJaegerExporter(o => + provider.AddJaegerExporter(o => + { + o.AgentHost = settings.Jaeger; + o.AgentPort = 6831; + o.MaxPayloadSizeInBytes = 4096; + o.ExportProcessorType = ExportProcessorType.Batch; + o.BatchExportProcessorOptions = new BatchExportProcessorOptions { - o.AgentHost = settings.Jaeger; - o.AgentPort = 6831; - o.MaxPayloadSizeInBytes = 4096; - o.ExportProcessorType = ExportProcessorType.Batch; - o.BatchExportProcessorOptions = new BatchExportProcessorOptions - { - MaxQueueSize = 2048, - ScheduledDelayMilliseconds = 5000, - ExporterTimeoutMilliseconds = 30000, - MaxExportBatchSize = 512, - }; - }); + MaxQueueSize = 2048, + ScheduledDelayMilliseconds = 5000, + ExporterTimeoutMilliseconds = 30000, + MaxExportBatchSize = 512, + }; }); + }); - return services; - } + return services; } } diff --git a/src/Genocs.Secrets.Vault/Extensions.cs b/src/Genocs.Secrets.Vault/Extensions.cs index 5594ffba..6a01da70 100644 --- a/src/Genocs.Secrets.Vault/Extensions.cs +++ b/src/Genocs.Secrets.Vault/Extensions.cs @@ -25,14 +25,16 @@ public static class Extensions private static readonly ICertificatesService CertificatesService = new CertificatesService(); /// - /// UseVault + /// UseVault. /// - /// The builder + /// The builder. /// /// /// - public static IHostBuilder UseVault(this IHostBuilder builder, string? keyValuePath = null, - string sectionName = SectionName) + public static IHostBuilder UseVault( + this IHostBuilder builder, + string? keyValuePath = null, + string sectionName = SectionName) => builder.ConfigureServices(services => services.AddVault(sectionName)) .ConfigureAppConfiguration((ctx, cfg) => { @@ -53,8 +55,10 @@ public static IHostBuilder UseVault(this IHostBuilder builder, string? keyValueP /// /// /// - public static IWebHostBuilder UseVault(this IWebHostBuilder builder, string? keyValuePath = null, - string sectionName = SectionName) + public static IWebHostBuilder UseVault( + this IWebHostBuilder builder, + string? keyValuePath = null, + string sectionName = SectionName) => builder.ConfigureServices(services => services.AddVault(sectionName)) .ConfigureAppConfiguration((ctx, cfg) => { @@ -81,6 +85,7 @@ private static IServiceCollection AddVault(this IServiceCollection services, str { configuration = serviceProvider.GetRequiredService(); } + var options = new VaultSettings(); configuration.GetSection(sectionName).Bind(options); if (!options.Enabled) @@ -136,11 +141,13 @@ private static void VerifyOptions(VaultSettings options) } } - private static async Task AddVaultAsync(this IConfigurationBuilder builder, VaultSettings options, - string? keyValuePath) + private static async Task AddVaultAsync( + this IConfigurationBuilder builder, + VaultSettings options, + string? keyValuePath) { VerifyOptions(options); - var kvPath = string.IsNullOrWhiteSpace(keyValuePath) ? options.Kv?.Path : keyValuePath; + string? kvPath = string.IsNullOrWhiteSpace(keyValuePath) ? options.Kv?.Path : keyValuePath; var (client, _) = GetClientAndSettings(options); if (!string.IsNullOrWhiteSpace(kvPath) && options.Kv.Enabled) { @@ -148,7 +155,7 @@ private static async Task AddVaultAsync(this IConfigurationBuilder builder, Vaul var keyValueSecrets = new KeyValueSecrets(client, options); var secret = await keyValueSecrets.GetAsync(kvPath); var parser = new JsonParser(); - var json = JsonConvert.SerializeObject(secret); + string json = JsonConvert.SerializeObject(secret); var data = parser.Parse(json); var source = new MemoryConfigurationSource { InitialData = data }; builder.Add(source); @@ -184,8 +191,11 @@ private static async Task AddVaultAsync(this IConfigurationBuilder builder, Vaul } } - private static Task InitLeaseAsync(string key, IVaultClient client, VaultSettings.LeaseSettings options, - IDictionary configuration) + private static Task InitLeaseAsync( + string key, + IVaultClient client, + VaultSettings.LeaseSettings options, + IDictionary configuration) => options.Type.ToLowerInvariant() switch { "activedirectory" => SetActiveDirectorySecretsAsync(key, client, options, configuration), @@ -196,11 +206,14 @@ private static Task InitLeaseAsync(string key, IVaultClient client, VaultSetting _ => Task.CompletedTask }; - private static async Task SetActiveDirectorySecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, IDictionary configuration) + private static async Task SetActiveDirectorySecretsAsync( + string key, + IVaultClient client, + VaultSettings.LeaseSettings options, + IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.ActiveDirectory; - var mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; + string mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; var credentials = await client.V1.Secrets.ActiveDirectory.GetCredentialsAsync(options.RoleName, mountPoint); SetSecrets(key, options, configuration, name, () => (credentials, new Dictionary diff --git a/src/Genocs.Tracing/Jaeger/Extensions.cs b/src/Genocs.Tracing/Jaeger/Extensions.cs index a4f03bd0..4eae6818 100644 --- a/src/Genocs.Tracing/Jaeger/Extensions.cs +++ b/src/Genocs.Tracing/Jaeger/Extensions.cs @@ -14,18 +14,16 @@ namespace Genocs.Tracing.Jaeger; - /// -/// The Open Tracing +/// The Open Tracing. /// public static class Extensions { private static int _initialized; private const string RegistryName = "tracing.jaeger"; - /// - /// Add Jaeger Tracer + /// Add Jaeger Tracer. /// /// /// @@ -38,7 +36,6 @@ public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string secti return builder; } - var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); @@ -55,7 +52,6 @@ public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string secti return builder; } - builder.Services.AddSingleton(sp => { var loggerFactory = sp.GetRequiredService(); diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index 191217ac..d0cc8608 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -21,7 +21,7 @@ public Startup(IConfiguration configuration) { Configuration = configuration; } - + public void ConfigureServices(IServiceCollection services) { services.AddScoped(); @@ -45,7 +45,7 @@ public void ConfigureServices(IServiceCollection services) .AddSecurity() .AddWebApi() .Build(); - + services.AddAuthorization(options => { options.AddPolicy("authenticatedUser", policy => @@ -61,6 +61,8 @@ public void ConfigureServices(IServiceCollection services) .WithHeaders("Content-Type", "Authorization"); }); }); + + services.AddHealthChecks(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) @@ -90,6 +92,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) await context.Response.WriteAsync(context.RequestServices.GetService()?.Name ?? "Service"); }); endpoints.MapReverseProxy(); + + endpoints.MapHealthChecks("/healthz"); }); } } diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index bb23d735..9e26e220 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -21,6 +21,7 @@ using Genocs.Persistence.Redis; using Genocs.Secrets.Vault; using Genocs.Tracing; +using Genocs.Metrics.AppMetrics; using Genocs.Tracing.Jaeger; using Genocs.Tracing.Jaeger.RabbitMQ; using Genocs.WebApi; @@ -57,6 +58,7 @@ .AddFabio() .AddOpenTelemetry() .AddJaeger() + .AddMetrics() .AddMongo() .AddMongoRepository("orders") .AddCommandHandlers() From 3d49180fd5bfa4d07f7297b852bee83f2b000849 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 7 Dec 2023 16:00:49 +0100 Subject: [PATCH 022/104] Documentation, updated packages --- Directory.Build.props | 2 +- genocs.sln | 8 ++ src/Genocs.Auth/Genocs.Auth.csproj | 5 +- .../Genocs.Core.UnitTests.csproj | 3 +- src/Genocs.Core/Genocs.Core.csproj | 4 +- .../Genocs.HTTP.RestEase.csproj | 1 - src/Genocs.Logging/Extensions.cs | 26 ++-- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- src/Genocs.Logging/LoggingService.cs | 5 +- src/Genocs.Logging/Options/AzureSettings.cs | 10 +- src/Genocs.Logging/Options/ConsoleSettings.cs | 4 +- src/Genocs.Logging/Options/ElkSettings.cs | 14 +++ .../Options/LocalFileSettings.cs | 14 +++ src/Genocs.Logging/Options/LoggerSettings.cs | 13 ++ src/Genocs.Logging/Options/LokiSettings.cs | 20 +-- src/Genocs.Logging/Options/MongoSettings.cs | 12 ++ src/Genocs.Logging/Options/SeqSettings.cs | 4 +- src/Genocs.Monitoring/Constants.cs | 12 +- .../Options/MonitoringSettings.cs | 27 ++-- src/Genocs.Monitoring/README.md | 4 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 5 +- .../Extensions/MongoDbExtensions.cs | 108 ++++++++-------- .../Options/MongoDbSettings.cs | 85 ++++++------- src/Genocs.Persistence.MongoDb/README.md | 2 +- .../_docs/README_NUGET.md | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 2 +- src/Genocs.Tracing/Extensions.cs | 116 ++++++++++-------- src/Genocs.Tracing/Genocs.Tracing.csproj | 3 +- src/Genocs.Tracing/Jaeger/Extensions.cs | 16 +-- .../Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs | 15 ++- .../Genocs.WebApi.Swagger.csproj | 2 +- .../Genocs.Orders.WebApi/appsettings.json | 4 +- 32 files changed, 319 insertions(+), 231 deletions(-) create mode 100644 src/Genocs.Logging/Options/MongoSettings.cs diff --git a/Directory.Build.props b/Directory.Build.props index 88b9512c..9de369d9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/genocs.sln b/genocs.sln index 38feed0d..d2e4264d 100644 --- a/genocs.sln +++ b/genocs.sln @@ -83,10 +83,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Common", "src\Genocs EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Solution Items", "_Solution Items", "{51A2E158-4686-4764-91D5-3CDDD06280D4}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig demo-docker-compose.yml = demo-docker-compose.yml demo-webapi.dockerfile = demo-webapi.dockerfile demo-worker.dockerfile = demo-worker.dockerfile + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + dotnet.ruleset = dotnet.ruleset + global.json = global.json + launchSettings.json = launchSettings.json + Makefile = Makefile README.md = README.md + stylecop.json = stylecop.json EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OrdersService", "OrdersService", "{80862789-8B42-4878-AC10-9CFF06A7313C}" diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 3fcc2d52..90259a2e 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -59,14 +59,13 @@ - - + - + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index d0778a8d..2e7c5b63 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -5,8 +5,9 @@ false false + - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 9b070bbb..9b44b568 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -4,7 +4,7 @@ netstandard2.1;net6.0;net7.0;net8.0 Genocs.Core Genocs.Core - Genocs.Core + Genocs.Core 10.0 true 5.0.0 @@ -21,7 +21,7 @@ git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README.md - Nove to NET8 + Updated to NET8 True latest diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 19248746..78509196 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -1,6 +1,5 @@  - net6.0;net7.0;net8.0 Genocs.HTTP.RestEase diff --git a/src/Genocs.Logging/Extensions.cs b/src/Genocs.Logging/Extensions.cs index 9654982f..76fe5817 100644 --- a/src/Genocs.Logging/Extensions.cs +++ b/src/Genocs.Logging/Extensions.cs @@ -20,10 +20,11 @@ public static class Extensions { internal static LoggingLevelSwitch LoggingLevelSwitch = new(); - public static IHostBuilder UseLogging(this IHostBuilder hostBuilder, - Action? configure = null, - string? loggerSectionName = null, - string? appSectionName = null) + public static IHostBuilder UseLogging( + this IHostBuilder hostBuilder, + Action? configure = null, + string? loggerSectionName = null, + string? appSectionName = null) => hostBuilder .ConfigureServices(services => services.AddSingleton()) .UseSerilog((context, loggerConfiguration) => @@ -45,13 +46,16 @@ public static IHostBuilder UseLogging(this IHostBuilder hostBuilder, configure?.Invoke(context, loggerConfiguration); }); - - public static IEndpointConventionBuilder MapLogLevelHandler(this IEndpointRouteBuilder builder, - string endpointRoute = "~/logging/level") + public static IEndpointConventionBuilder MapLogLevelHandler( + this IEndpointRouteBuilder builder, + string endpointRoute = "~/logging/level") => builder.MapPost(endpointRoute, LevelSwitch); - private static void MapOptions(LoggerSettings loggerOptions, AppSettings appOptions, - LoggerConfiguration loggerConfiguration, string environmentName) + private static void MapOptions( + LoggerSettings loggerOptions, + AppSettings appOptions, + LoggerConfiguration loggerConfiguration, + string environmentName) { LoggingLevelSwitch.MinimumLevel = GetLogEventLevel(loggerOptions.Level); @@ -100,7 +104,7 @@ private static void Configure(LoggerConfiguration loggerConfiguration, LoggerSet // local file system if (fileOptions.Enabled) { - var path = string.IsNullOrWhiteSpace(fileOptions.Path) ? "logs/logs.txt" : fileOptions.Path; + string path = string.IsNullOrWhiteSpace(fileOptions.Path) ? "logs/logs.txt" : fileOptions.Path; if (!Enum.TryParse(fileOptions.Interval, true, out var interval)) { interval = RollingInterval.Day; @@ -129,7 +133,7 @@ private static void Configure(LoggerConfiguration loggerConfiguration, LoggerSet // seq if (seqOptions.Enabled) { - loggerConfiguration.WriteTo.Seq(seqOptions.Url, apiKey: seqOptions.ApiKey); + loggerConfiguration.WriteTo.Seq(seqOptions.Url!, apiKey: seqOptions.ApiKey); } // loki diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index c9f5adb3..d6b289fb 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.Logging/LoggingService.cs b/src/Genocs.Logging/LoggingService.cs index c9b6b3f8..bd535b59 100644 --- a/src/Genocs.Logging/LoggingService.cs +++ b/src/Genocs.Logging/LoggingService.cs @@ -6,5 +6,6 @@ public void SetLoggingLevel(string logEventLevel) => Extensions.LoggingLevelSwitch.MinimumLevel = Extensions.GetLogEventLevel(logEventLevel); } - -public class LoggingService : ILoggingService { } \ No newline at end of file +public class LoggingService : ILoggingService +{ +} \ No newline at end of file diff --git a/src/Genocs.Logging/Options/AzureSettings.cs b/src/Genocs.Logging/Options/AzureSettings.cs index ae3d43ec..387881f8 100644 --- a/src/Genocs.Logging/Options/AzureSettings.cs +++ b/src/Genocs.Logging/Options/AzureSettings.cs @@ -1,11 +1,17 @@ namespace Genocs.Logging.Options; - /// -/// Azure application insights logging settings +/// Azure application insights logging settings. /// public class AzureSettings { + /// + /// It define whether the Azure application insights logger and tracing are enabled or not. + /// public bool Enabled { get; set; } + + /// + /// The Azure application insights connection string. + /// public string? ConnectionString { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Logging/Options/ConsoleSettings.cs b/src/Genocs.Logging/Options/ConsoleSettings.cs index b41102ff..a647aa26 100644 --- a/src/Genocs.Logging/Options/ConsoleSettings.cs +++ b/src/Genocs.Logging/Options/ConsoleSettings.cs @@ -1,12 +1,12 @@ namespace Genocs.Logging.Options; /// -/// Console Settings +/// Console Settings. /// public class ConsoleSettings { /// - /// It define whether the console logger and tracing are enabled or not + /// It define whether the console logger and tracing are enabled or not. /// public bool Enabled { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Logging/Options/ElkSettings.cs b/src/Genocs.Logging/Options/ElkSettings.cs index ce911d24..b67d082d 100644 --- a/src/Genocs.Logging/Options/ElkSettings.cs +++ b/src/Genocs.Logging/Options/ElkSettings.cs @@ -1,9 +1,23 @@ namespace Genocs.Logging.Options; +/// +/// Elasticsearch Settings. +/// public class ElkSettings { + /// + /// It define whether the Elasticsearch logger and tracing are enabled or not. + /// public bool Enabled { get; set; } + + /// + /// It define whether the Elasticsearch authentication is enabled or not. + /// public bool BasicAuthEnabled { get; set; } + + /// + /// The Elasticsearch Url. + /// public string? Url { get; set; } public string? Username { get; set; } public string? Password { get; set; } diff --git a/src/Genocs.Logging/Options/LocalFileSettings.cs b/src/Genocs.Logging/Options/LocalFileSettings.cs index 9d362ff9..bc5d0993 100644 --- a/src/Genocs.Logging/Options/LocalFileSettings.cs +++ b/src/Genocs.Logging/Options/LocalFileSettings.cs @@ -1,8 +1,22 @@ namespace Genocs.Logging.Options; +/// +/// File settings for local file logging. +/// public class LocalFileSettings { + /// + /// If enabled, local file logging is enabled. + /// public bool Enabled { get; set; } + + /// + /// The path to the local file. + /// public string? Path { get; set; } + + /// + /// The interval to roll the file. it uses the same values as Serilog.Sinks.File. + /// public string? Interval { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Logging/Options/LoggerSettings.cs b/src/Genocs.Logging/Options/LoggerSettings.cs index 8d69c4e6..e5ac5aa5 100644 --- a/src/Genocs.Logging/Options/LoggerSettings.cs +++ b/src/Genocs.Logging/Options/LoggerSettings.cs @@ -20,9 +20,22 @@ public class LoggerSettings public LocalFileSettings? File { get; set; } public ElkSettings? Elk { get; set; } public SeqSettings? Seq { get; set; } + + /// + /// Loki logging settings. + /// public LokiSettings? Loki { get; set; } + + /// + /// Azure application insights logging settings. + /// public AzureSettings? Azure { get; set; } + /// + /// MongoDb logging settings. + /// + public MongoSettings? Mongo { get; set; } + public IDictionary? MinimumLevelOverrides { get; set; } public IEnumerable? ExcludePaths { get; set; } public IEnumerable? ExcludeProperties { get; set; } diff --git a/src/Genocs.Logging/Options/LokiSettings.cs b/src/Genocs.Logging/Options/LokiSettings.cs index 264f3876..9c19d209 100644 --- a/src/Genocs.Logging/Options/LokiSettings.cs +++ b/src/Genocs.Logging/Options/LokiSettings.cs @@ -1,7 +1,7 @@ namespace Genocs.Logging.Options; /// -/// Relevant options for the Serilog Loki sink +/// Relevant options for the Serilog Loki sink. /// /// Not all options have been included as some have been covered by Genocs.Logging already. /// The sink has reasonable defaults for the unused options. @@ -22,38 +22,42 @@ /// TextFormatter /// HttpClient /// CreateLevelLabel -/// -/// +/// /// public class LokiSettings { /// - /// Whether or not to enable Loki Logging + /// Whether or not to enable Loki Logging. /// public bool Enabled { get; set; } /// - /// The Uri at which the Loki instance can be found + /// The Uri at which the Loki instance can be found. /// public string? Url { get; set; } + /// /// The maximum number of events to post in a single batch. Default value is 1000. /// public int? BatchPostingLimit { get; set; } + /// - /// The maximum number of events stored in the queue in memory, waiting to be posted over + /// The maximum number of events stored in the queue in memory, waiting to be posted over. /// public int? QueueLimit { get; set; } + /// /// The time to wait between checking for event batches. Default value is 2 seconds. /// public TimeSpan? Period { get; set; } + /// - /// Username used for Grafana Loki authorization + /// Username used for Grafana Loki authorization. /// public string? LokiUsername { get; set; } + /// - /// Password used for Grafana Loki authorization + /// Password used for Grafana Loki authorization. /// public string? LokiPassword { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Logging/Options/MongoSettings.cs b/src/Genocs.Logging/Options/MongoSettings.cs new file mode 100644 index 00000000..a8e2e47b --- /dev/null +++ b/src/Genocs.Logging/Options/MongoSettings.cs @@ -0,0 +1,12 @@ +namespace Genocs.Logging.Options; + +/// +/// MongoDb logging settings. +/// +public class MongoSettings +{ + /// + /// It define whether the MongoDb logger and tracing are enabled or not. + /// + public bool Enabled { get; set; } +} \ No newline at end of file diff --git a/src/Genocs.Logging/Options/SeqSettings.cs b/src/Genocs.Logging/Options/SeqSettings.cs index 68512b91..26432556 100644 --- a/src/Genocs.Logging/Options/SeqSettings.cs +++ b/src/Genocs.Logging/Options/SeqSettings.cs @@ -3,6 +3,6 @@ namespace Genocs.Logging.Options; public class SeqSettings { public bool Enabled { get; set; } - public string Url { get; set; } - public string ApiKey { get; set; } + public string? Url { get; set; } + public string? ApiKey { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Monitoring/Constants.cs b/src/Genocs.Monitoring/Constants.cs index e8180ba5..ab6a549e 100644 --- a/src/Genocs.Monitoring/Constants.cs +++ b/src/Genocs.Monitoring/Constants.cs @@ -1,9 +1,7 @@ -namespace Genocs.Monitoring +namespace Genocs.Monitoring; + +internal static class Constants { - internal static class Constants - { - public const string ApplicationInsightsConnectionString = "ApplicationInsights"; - public const string MongoDbConnectionString = "MongoDb"; - public const string ServiceName = "AppSettings:ServiceName"; - } + public const string ApplicationInsightsConnectionString = "ApplicationInsights"; + public const string ServiceName = "AppSettings:ServiceName"; } diff --git a/src/Genocs.Monitoring/Options/MonitoringSettings.cs b/src/Genocs.Monitoring/Options/MonitoringSettings.cs index cfaa026e..6d0ea9d2 100644 --- a/src/Genocs.Monitoring/Options/MonitoringSettings.cs +++ b/src/Genocs.Monitoring/Options/MonitoringSettings.cs @@ -1,20 +1,17 @@ -namespace Genocs.Monitoring.Options +namespace Genocs.Monitoring.Options; + +/// +/// The monitoring settings. +/// +public class MonitoringSettings { /// - /// The monitoring settings + /// The static position. /// - public class MonitoringSettings - { - /// - /// The static position - /// - public const string Position = "Monitoring"; + public const string Position = "Monitoring"; - /// - /// Jaeger url - /// - public string Jaeger { get; set; } = "localhost"; - } + /// + /// Jaeger url. + /// + public string Jaeger { get; set; } = "localhost"; } - - diff --git a/src/Genocs.Monitoring/README.md b/src/Genocs.Monitoring/README.md index 8bbebb85..4ee8ba10 100644 --- a/src/Genocs.Monitoring/README.md +++ b/src/Genocs.Monitoring/README.md @@ -36,7 +36,7 @@ Following are the project settings needed to enable monitoring ## Release notes ### [2023-03-04] 2.0.1 -- Updated nuget packages +- Updated NuGet packages ### [2023-03-04] 2.0.0 - Revisited @@ -51,7 +51,7 @@ Following are the project settings needed to enable monitoring - Moved to netstandart ### [2023-01-01] 1.0.0-rc2.0 -- Refactory and standardization +- Refactor and standardization diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 118510b4..51f3108f 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -6,10 +6,11 @@ false Genocs + - + - + diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs index 93968790..d418b605 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs @@ -17,23 +17,23 @@ namespace Genocs.Persistence.MongoDb.Extensions; /// -/// The MongoDb Extensions +/// The MongoDb Extensions. /// public static class MongoDbExtensions { // Helpful when dealing with integration testing private static bool _conventionsRegistered; - private const string RegistryName = "persistence.mongoDb"; /// - /// + /// It allows to add support for MongoDb. /// - /// The Genocs builder - /// - /// - /// - /// The Genocs builder - public static IGenocsBuilder AddMongo(this IGenocsBuilder builder, + /// The Genocs builder. + /// The section name. + /// The seeder name. + /// Defines if setup the MongoDB Conventions. + /// The Genocs builder. + public static IGenocsBuilder AddMongo( + this IGenocsBuilder builder, string sectionName = MongoDbSettings.Position, Type? seederType = null, bool registerConventions = true) @@ -48,39 +48,46 @@ public static IGenocsBuilder AddMongo(this IGenocsBuilder builder, } /// - /// Setup MongoDb support + /// It allows to add support for MongoDb. /// - /// The Genocs builder - /// - /// - /// - /// The Genocs builder - public static IGenocsBuilder AddMongo(this IGenocsBuilder builder, Func buildOptions, Type? seederType = null, bool registerConventions = true) + /// The Genocs builder. + /// The Genocs builder. + /// The seeder name. + /// Defines if setup the MongoDB Conventions. + /// The Genocs builder. + public static IGenocsBuilder AddMongo( + this IGenocsBuilder builder, + Func buildOptions, + Type? seederType = null, + bool registerConventions = true) { var mongoOptions = buildOptions(new MongoDbOptionsBuilder()).Build(); return builder.AddMongo(mongoOptions, seederType, registerConventions); } /// - /// Setup MongoDb support + /// Setup MongoDb support. /// - /// The Genocs builder - /// The settings + /// The Genocs builder. + /// The settings. /// /// - /// The Genocs builder - public static IGenocsBuilder AddMongo(this IGenocsBuilder builder, MongoDbSettings mongoOptions, - Type? seederType = null, bool registerConventions = true) + /// The Genocs builder. + public static IGenocsBuilder AddMongo( + this IGenocsBuilder builder, + MongoDbSettings mongoOptions, + Type? seederType = null, + bool registerConventions = true) { - if (!builder.TryRegister(RegistryName)) + if (!builder.TryRegister(MongoDbSettings.Position)) { return builder; } if (mongoOptions.SetRandomDatabaseSuffix) { - var suffix = $"{Guid.NewGuid():N}"; + string suffix = $"{Guid.NewGuid():N}"; Console.WriteLine($"Setting a random MongoDB database suffix: '{suffix}'."); mongoOptions.Database = $"{mongoOptions.Database}_{suffix}"; } @@ -131,15 +138,16 @@ public static IGenocsBuilder AddMongo(this IGenocsBuilder builder, MongoDbSettin } /// - /// Adds a MongoDb repository to the DI container. Using Genocs builder support + /// Adds a MongoDb repository to the DI container. Using Genocs builder support. /// - /// The name of the entity - /// The kind of identifier - /// The Genocs builder - /// The collection name where to store data - /// The Genocs builder - public static IGenocsBuilder AddMongoRepository(this IGenocsBuilder builder, - string collectionName) + /// The name of the entity. + /// The kind of identifier. + /// The Genocs builder. + /// The collection name where to store data. + /// The Genocs builder. + public static IGenocsBuilder AddMongoRepository( + this IGenocsBuilder builder, + string collectionName) where TEntity : IIdentifiable { builder.Services.AddTransient>(sp => @@ -151,17 +159,17 @@ public static IGenocsBuilder AddMongoRepository(this IGe return builder; } - /// - /// Add MongoDb support + /// Add MongoDb support. /// - /// The Genocs builder - /// The Genocs builder - /// The Genocs builder - /// The Genocs builder - public static IGenocsBuilder AddMongoFast(this IGenocsBuilder builder, - string sectionName = MongoDbSettings.Position, - bool registerConventions = true) + /// The Genocs builder. + /// The Genocs builder. + /// The Genocs builder. + /// The Genocs builder. + public static IGenocsBuilder AddMongoFast( + this IGenocsBuilder builder, + string sectionName = MongoDbSettings.Position, + bool registerConventions = true) { if (string.IsNullOrWhiteSpace(sectionName)) @@ -190,14 +198,16 @@ public static IGenocsBuilder AddMongoFast(this IGenocsBuilder builder, } /// - /// Register all the default MongoDb repository + /// Register all the default MongoDb repository. /// - /// The Genocs builder - /// Assembly to scan - /// Kind of ServiceLifetime - /// The Genocs builder - public static IGenocsBuilder RegisterMongoRepositories(this IGenocsBuilder builder, Assembly assembly, - ServiceLifetime lifetime = ServiceLifetime.Transient) + /// The Genocs builder. + /// Assembly to scan. + /// Kind of ServiceLifetime. + /// The Genocs builder. + public static IGenocsBuilder RegisterMongoRepositories( + this IGenocsBuilder builder, + Assembly assembly, + ServiceLifetime lifetime = ServiceLifetime.Transient) { builder.Services .Scan(s => s.FromAssemblyDependencies(assembly) diff --git a/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs b/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs index 20f34923..6dc46179 100644 --- a/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs +++ b/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs @@ -1,60 +1,55 @@ using System.ComponentModel; -namespace Genocs.Persistence.MongoDb.Options +namespace Genocs.Persistence.MongoDb.Options; + +/// +/// MongoDb database Settings. +/// +public class MongoDbSettings { /// - /// MongoDb database Settings + /// Default Section name. /// - public class MongoDbSettings - { - /// - /// Default Section name - /// - public const string Position = "mongodb"; - - /// - /// The Database connection string - /// - public string ConnectionString { get; set; } = default!; - - /// - /// The database name where the data will be stored - /// - public string Database { get; set; } = default!; - - /// - /// Toggle database tracing - /// - public bool EnableTracing { get; set; } + public const string Position = "mongoDb"; + /// + /// The Database connection string. + /// + public string ConnectionString { get; set; } = default!; - /// - /// It defines if the database seed is applied - /// - public bool Seed { get; set; } - + /// + /// The database name where the data will be stored. + /// + public string Database { get; set; } = default!; - /// - /// It defines if random database name suffix is added - /// - [Description("Might be helpful for the integration testing.")] - public bool SetRandomDatabaseSuffix { get; set; } + /// + /// Toggle database tracing. + /// + public bool EnableTracing { get; set; } + /// + /// It defines if the database seed is applied. + /// + public bool Seed { get; set; } - /// - /// Check if the MongoDbSettings object contains valid data - /// - /// MongoDbSettings object - /// return true if valid otherwise false - public static bool IsValid(MongoDbSettings settings) - { - if (settings is null) return false; + /// + /// It defines if random database name suffix is added. + /// + [Description("Might be helpful for the integration testing.")] + public bool SetRandomDatabaseSuffix { get; set; } - if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; - if (string.IsNullOrWhiteSpace(settings.Database)) return false; + /// + /// Check if the MongoDbSettings object contains valid data. + /// + /// MongoDbSettings object. + /// return true if valid otherwise false. + public static bool IsValid(MongoDbSettings settings) + { + if (settings is null) return false; - return true; + if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; + if (string.IsNullOrWhiteSpace(settings.Database)) return false; - } + return true; } } diff --git a/src/Genocs.Persistence.MongoDb/README.md b/src/Genocs.Persistence.MongoDb/README.md index 0e0463a5..ab91c582 100644 --- a/src/Genocs.Persistence.MongoDb/README.md +++ b/src/Genocs.Persistence.MongoDb/README.md @@ -23,7 +23,7 @@ Please check the GitHub repository getting more info. Following is about how to setup **MongoDb** ``` json - "mongodb": { + "mongoDb": { "ConnectionString": "mongodb://localhost", "Database": "demo_database", "EnableTracing": false diff --git a/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md b/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md index 51e3f8ef..ab91c582 100644 --- a/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md +++ b/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md @@ -23,7 +23,7 @@ Please check the GitHub repository getting more info. Following is about how to setup **MongoDb** ``` json - "MongoDb": { + "mongoDb": { "ConnectionString": "mongodb://localhost", "Database": "demo_database", "EnableTracing": false diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 96078a67..3cc63f45 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -7,7 +7,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index 0345f959..beb99dfb 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -23,7 +23,7 @@ public static class Extensions /// /// Custom settings for OpenTelemetry. /// - /// The genocs builder. + /// The Genocs builder. /// The builder. public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) { @@ -41,73 +41,81 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) // Set Custom Open telemetry services.AddOpenTelemetry().WithTracing(x => { -/* - Action appResourceBuilder = - resource => resource - .AddDetector(new ContainerResourceDetector()); - - builder.Services.AddOpenTelemetry() - .ConfigureResource(appResourceBuilder) - .WithTracing(tracerBuilder => tracerBuilder - .AddRedisInstrumentation( - cartStore.GetConnection(), - options => options.SetVerboseDatabaseStatements = true) - .AddAspNetCoreInstrumentation() - .AddGrpcClientInstrumentation() - .AddHttpClientInstrumentation() - .AddOtlpExporter()) - .WithMetrics(meterBuilder => meterBuilder - .AddRuntimeInstrumentation() - .AddAspNetCoreInstrumentation() - .AddOtlpExporter()); -*/ - TracerProviderBuilder provider = x.SetResourceBuilder(ResourceBuilder.CreateDefault() - .AddService(appOptions.Service) - .AddTelemetrySdk() - .AddEnvironmentVariableDetector()) - .AddSource("*"); - - // TODO> add flag to enable feature MongoDB.Driver.Core.Extensions.OpenTelemetry - provider.AddMongoDBInstrumentation(); + .AddService(appOptions.Service) + .AddTelemetrySdk() + .AddEnvironmentVariableDetector()) + .AddSource("*"); var loggerOptions = builder.GetOptions(LoggerSettings.Position); - // Check for Console config - if (loggerOptions.Console != null && loggerOptions.Console.Enabled) + // No OpenTelemetryTracing in case of missing LoggerSettings + if (loggerOptions != null) { - // OpenTelemetry.Exporter.Console NuGet package - provider.AddConsoleExporter(); - } + if (loggerOptions.Mongo != null && loggerOptions.Mongo.Enabled) + { + // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry NuGet package + provider.AddMongoDBInstrumentation(); + } - // Check for Azure ApplicationInsights config - if (loggerOptions.Azure != null && loggerOptions.Azure.Enabled) - { - provider.AddAzureMonitorTraceExporter(o => + // Check for Console config + if (loggerOptions.Console != null && loggerOptions.Console.Enabled) { - o.ConnectionString = loggerOptions.Azure.ConnectionString; - }); + // you should add OpenTelemetry.Exporter.Console NuGet package + provider.AddConsoleExporter(); + } + + // Check for Azure ApplicationInsights config + if (loggerOptions.Azure != null && loggerOptions.Azure.Enabled) + { + provider.AddAzureMonitorTraceExporter(o => + { + o.ConnectionString = loggerOptions.Azure.ConnectionString; + }); + } } var jaegerOptions = builder.GetOptions(JaegerSettings.Position); if (jaegerOptions != null && jaegerOptions.Enabled) { - //provider.AddJaegerExporter(o => - //{ - // o.AgentHost = jaegerOptions.UdpHost; - // o.AgentPort = jaegerOptions.UdpPort; - // o.MaxPayloadSizeInBytes = jaegerOptions.MaxPacketSize; - // o.ExportProcessorType = ExportProcessorType.Batch; - // o.BatchExportProcessorOptions = new BatchExportProcessorOptions - // { - // MaxQueueSize = 2048, - // ScheduledDelayMilliseconds = 5000, - // ExporterTimeoutMilliseconds = 30000, - // MaxExportBatchSize = 512, - // }; - //}); + + provider.AddJaegerExporter(o => + { + o.AgentHost = jaegerOptions.UdpHost; + o.AgentPort = jaegerOptions.UdpPort; + o.MaxPayloadSizeInBytes = jaegerOptions.MaxPacketSize; + o.ExportProcessorType = ExportProcessorType.Batch; + o.BatchExportProcessorOptions = new BatchExportProcessorOptions + { + MaxQueueSize = 2048, + ScheduledDelayMilliseconds = 5000, + ExporterTimeoutMilliseconds = 30000, + MaxExportBatchSize = 512, + }; + }); } + + /* + Action appResourceBuilder = + resource => resource + .AddDetector(new ContainerResourceDetector()); + + builder.Services.AddOpenTelemetry() + .ConfigureResource(appResourceBuilder) + .WithTracing(tracerBuilder => tracerBuilder + .AddRedisInstrumentation( + cartStore.GetConnection(), + options => options.SetVerboseDatabaseStatements = true) + .AddAspNetCoreInstrumentation() + .AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation() + .AddOtlpExporter()) + .WithMetrics(meterBuilder => meterBuilder + .AddRuntimeInstrumentation() + .AddAspNetCoreInstrumentation() + .AddOtlpExporter()); + */ }); return builder; diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 2bbea06c..3d25858b 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -58,9 +58,10 @@ - + + diff --git a/src/Genocs.Tracing/Jaeger/Extensions.cs b/src/Genocs.Tracing/Jaeger/Extensions.cs index 4eae6818..664f1c6a 100644 --- a/src/Genocs.Tracing/Jaeger/Extensions.cs +++ b/src/Genocs.Tracing/Jaeger/Extensions.cs @@ -55,8 +55,8 @@ public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string secti builder.Services.AddSingleton(sp => { var loggerFactory = sp.GetRequiredService(); - var maxPacketSize = options.MaxPacketSize <= 0 ? 64967 : options.MaxPacketSize; - var senderType = string.IsNullOrWhiteSpace(options.Sender) ? "udp" : options.Sender?.ToLowerInvariant(); + int maxPacketSize = options.MaxPacketSize <= 0 ? 64967 : options.MaxPacketSize; + string? senderType = string.IsNullOrWhiteSpace(options.Sender) ? "udp" : options.Sender?.ToLowerInvariant(); ISender sender = senderType switch { "http" => BuildHttpSender(options.HttpSender), @@ -132,12 +132,12 @@ public static IApplicationBuilder UseJaeger(this IApplicationBuilder app) private static ISampler GetSampler(JaegerSettings options) { - switch (options.Sampler) + return options.Sampler switch { - case "const": return new ConstSampler(true); - case "rate": return new RateLimitingSampler(options.MaxTracesPerSecond); - case "probabilistic": return new ProbabilisticSampler(options.SamplingRate); - default: return new ConstSampler(true); - } + "const" => new ConstSampler(true), + "rate" => new RateLimitingSampler(options.MaxTracesPerSecond), + "probabilistic" => new ProbabilisticSampler(options.SamplingRate), + _ => new ConstSampler(true), + }; } } \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs b/src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs index b4504082..5ce191a8 100644 --- a/src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs +++ b/src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs @@ -19,14 +19,17 @@ public JaegerPlugin(ITracer tracer, RabbitMQOptions options) _spanContextHeader = options.GetSpanContextHeader(); } - public override async Task HandleAsync(object message, object correlationContext, - BasicDeliverEventArgs args) + public override async Task HandleAsync( + object message, + object correlationContext, + BasicDeliverEventArgs args) { - var messageName = message.GetType().Name.Underscore(); - var messageId = args.BasicProperties.MessageId; - var spanContext = string.Empty; + string messageName = message.GetType().Name.Underscore(); + string messageId = args.BasicProperties.MessageId; + string spanContext = string.Empty; + if (args.BasicProperties.Headers is { } && - args.BasicProperties.Headers.TryGetValue(_spanContextHeader, out var spanContextHeader) && + args.BasicProperties.Headers.TryGetValue(_spanContextHeader, out object? spanContextHeader) && spanContextHeader is byte[] spanContextBytes) { spanContext = Encoding.UTF8.GetString(spanContextBytes); diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 254f9b9e..7e8f8fed 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0;net7.0;net8.0 Genocs.WebApi.Swagger Genocs.WebApi.Swagger Genocs.WebApi.Swagger diff --git a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json index aae8e655..4aaf4cbc 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json +++ b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json @@ -60,10 +60,10 @@ "metrics": { "enabled": true, "influxEnabled": false, - "prometheusEnabled": true, + "prometheusEnabled": false, + "prometheusFormatter": null, "influxUrl": "http://localhost:8086", "database": "test", - "env": "local", "interval": 5 }, "mongodb": { From 9ffe8612bf90808a2584c3a62feb1128be2d65de Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 7 Dec 2023 16:32:09 +0100 Subject: [PATCH 023/104] Updated project structure --- src/Genocs.Auth/Genocs.Auth.csproj | 4 ++-- src/Genocs.Common/Genocs.Common.csproj | 6 +++--- src/Genocs.Core.Demo.WebApi/Program.cs | 5 +---- src/Genocs.Core.Demo.Worker/appsettings.json | 4 ++-- src/Genocs.Core/Genocs.Core.csproj | 4 ++-- src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj | 4 ++-- src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj | 4 ++-- src/Genocs.HTTP/Genocs.HTTP.csproj | 4 ++-- .../Genocs.LoadBalancing.Fabio.csproj | 4 ++-- .../CQRS/Decorators/CommandHandlerLoggingDecorator.cs | 3 ++- src/Genocs.Logging/Genocs.Logging.csproj | 4 ++-- .../Genocs.MessageBrokers.Outbox.MongoDB.csproj | 4 ++-- .../Genocs.MessageBrokers.Outbox.csproj | 4 ++-- .../Genocs.MessageBrokers.RabbitMQ.csproj | 4 ++-- src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj | 4 ++-- src/Genocs.Metrics/Genocs.Metrics.csproj | 4 ++-- src/Genocs.Monitoring/Genocs.Monitoring.csproj | 6 +++--- .../Genocs.Persistence.MongoDb.csproj | 4 ++-- .../Genocs.Persistence.Redis.csproj | 6 +++--- src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj | 4 ++-- src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj | 4 ++-- src/Genocs.Security/Genocs.Security.csproj | 4 ++-- src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj | 4 ++-- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 6 ++++-- src/Genocs.Tracing/Genocs.Tracing.csproj | 4 ++-- src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj | 4 ++-- src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj | 4 ++-- src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj | 4 ++-- src/Genocs.WebApi/Genocs.WebApi.csproj | 6 +++--- src/apps/api-gateway/Genocs.APIGateway/Startup.cs | 2 +- src/apps/api-gateway/Genocs.APIGateway/appsettings.json | 2 +- src/apps/identity/Genocs.Identities.WebApi/appsettings.json | 2 +- src/apps/orders/Genocs.Orders.WebApi/Program.cs | 3 +-- src/apps/orders/Genocs.Orders.WebApi/appsettings.json | 2 +- src/apps/products/Genocs.Products.WebApi/appsettings.json | 6 +++--- src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json | 2 +- 36 files changed, 72 insertions(+), 73 deletions(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 90259a2e..2a5afec9 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -5,14 +5,14 @@ Genocs.Auth Genocs.Auth Genocs.Auth + The authorization library useful to build .NET Core projects. + The authorization library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The authorization library useful to build .NET Core projects. - The authorization library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index fa608135..f1c0bc79 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -5,14 +5,14 @@ Genocs.Common Genocs.Common Genocs.Common + The commons components library useful to build .NET Core projects. + The commons components library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The commons components library useful to build .NET Core projects. - The commons components library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library @@ -40,5 +40,5 @@ \ - + diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index 670a448e..d51bbe01 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -17,12 +17,10 @@ .WriteTo.Console() .CreateLogger(); - var builder = WebApplication.CreateBuilder(args); builder.Host .UseLogging(); -// .UseVault(); // add services to DI container var services = builder.Services; @@ -75,7 +73,6 @@ .AllowAnyHeader() .AllowCredentials()); - app.UseHttpsRedirection(); app.UseRouting(); @@ -84,7 +81,7 @@ app.MapControllers(); -app.MapHealthChecks("/healthz"); +app.MapHealthChecks("/hc"); app.Run(); diff --git a/src/Genocs.Core.Demo.Worker/appsettings.json b/src/Genocs.Core.Demo.Worker/appsettings.json index 62530ab2..1993b991 100644 --- a/src/Genocs.Core.Demo.Worker/appsettings.json +++ b/src/Genocs.Core.Demo.Worker/appsettings.json @@ -87,7 +87,7 @@ "Token" ], "console": { - "enabled": true + "enabled": false }, "elk": { "enabled": false, @@ -105,7 +105,7 @@ }, "azure": { "enabled": false, - "connectionString": "" + "connectionString": null }, "tags": {} }, diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 9b44b568..0f732b03 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -5,14 +5,14 @@ Genocs.Core Genocs.Core Genocs.Core + The base library to build .NET Core projects. + The base library to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The base library to build .NET Core projects. - The base library to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 58360ef2..74416868 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -5,14 +5,14 @@ Genocs.Discovery.Consul Genocs.Discovery.Consul Genocs.Discovery.Consul + The service discovery by Consul library useful to build .NET Core projects. + The service discovery by Consul library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The service discovery by Consul library useful to build .NET Core projects. - The service discovery by Consul library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 78509196..7e61a45b 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -5,14 +5,14 @@ Genocs.HTTP.RestEase Genocs.HTTP.RestEase Genocs.HTTP.RestEase + The http support library useful to build .NET Core projects. + The http support library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The http support library useful to build .NET Core projects. - The http support library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 8472b903..e06ba814 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -5,14 +5,14 @@ Genocs.HTTP Genocs.HTTP Genocs.HTTP + The http support library useful to build .NET Core projects. + The http support library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The http support library useful to build .NET Core projects. - The http support library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 112ba4a3..a3d28122 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -5,14 +5,14 @@ Genocs.LoadBalancing.Fabio Genocs.LoadBalancing.Fabio Genocs.LoadBalancing.Fabio + The load balacer based on Fabio library useful to build .NET Core projects. + The load balacer based on Fabio library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The load balacer based on Fabio library useful to build .NET Core projects. - The load balacer based on Fabio library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Logging/CQRS/Decorators/CommandHandlerLoggingDecorator.cs b/src/Genocs.Logging/CQRS/Decorators/CommandHandlerLoggingDecorator.cs index 2b9b9f18..2c0182a0 100644 --- a/src/Genocs.Logging/CQRS/Decorators/CommandHandlerLoggingDecorator.cs +++ b/src/Genocs.Logging/CQRS/Decorators/CommandHandlerLoggingDecorator.cs @@ -66,6 +66,7 @@ private void Log(TCommand command, string message, bool isError = false) private class EmptyMessageToLogTemplateMapper : IMessageToLogTemplateMapper { - public HandlerLogTemplate? Map(TMessage message) where TMessage : class => null; + public HandlerLogTemplate? Map(TMessage message) + where TMessage : class => null; } } \ No newline at end of file diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index d6b289fb..c42283c1 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -5,14 +5,14 @@ Genocs.Logging Genocs.Logging Genocs.Logging + The logging library useful to build .NET Core projects. + The logging library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The logging library useful to build .NET Core projects. - The logging library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 7e5e75aa..2a5c634e 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -5,14 +5,14 @@ Genocs.MessageBrokers.Outbox.MongoDB Genocs.MessageBrokers.Outbox.MongoDB Genocs.MessageBrokers.Outbox.MongoDB + The message brokers outbox MongoDB interface library useful to build .NET Core projects. + The message brokers MongoDB outbox interface library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The message brokers outbox MongoDB interface library useful to build .NET Core projects. - The message brokers MongoDB outbox interface library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 71108981..7f8e0281 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -5,14 +5,14 @@ Genocs.MessageBrokers.Outbox Genocs.MessageBrokers.Outbox Genocs.MessageBrokers.Outbox + The message brokers outbox interface library useful to build .NET Core projects. + The message brokers outbox interface library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The message brokers outbox interface library useful to build .NET Core projects. - The message brokers outbox interface library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 1b7fffb1..dacd4bfe 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -5,14 +5,14 @@ Genocs.MessageBrokers.RabbitMQ Genocs.MessageBrokers.RabbitMQ Genocs.MessageBrokers.RabbitMQ + The message brokers RabbitMQ interface library useful to build .NET Core projects. + The message brokers RabbitMQ outbox interface library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The message brokers RabbitMQ interface library useful to build .NET Core projects. - The message brokers RabbitMQ outbox interface library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 5d2d59d4..a09c5597 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -5,14 +5,14 @@ Genocs.MessageBrokers Genocs.MessageBrokers Genocs.MessageBrokers + The message brokers interface library useful to build .NET Core projects. + The message brokers interface library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The message brokers interface library useful to build .NET Core projects. - The message brokers interface library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index d79747be..48f58a62 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -5,14 +5,14 @@ Genocs.Metrics Genocs.Metrics Genocs.Metrics + The metrics interface library useful to build .NET Core projects. + The metrics interface library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The metrics interface library useful to build .NET Core projects. - The metrics interface library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 4866c69a..34f8e5a1 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -4,15 +4,15 @@ net6.0;net7.0;net8.0 Genocs.Monitoring Genocs.Monitoring - Genocs.Monitoring + Genocs.Monitoring + Telemetry and Tracing library. + Telemetry and Tracing library. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - Telemetry and Tracing library. - Telemetry and Tracing library. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 8abaaccd..d145e756 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -5,14 +5,14 @@ Genocs.Persistence.MongoDb Genocs.Persistence.MongoDb Genocs.Persistence.MongoDb + The Persistence MongoDB Library. + The library containing base repository pattern to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The Persistence MongoDB Library. - The library containing base repository pattern to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index f7705a8d..88a96133 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -4,15 +4,15 @@ net6.0;net7.0;net8.0 Genocs.Persistence.Redis Genocs.Persistence.Redis - Genocs.Persistence.Redis + Genocs.Persistence.Redis + The Persistence Redis Library. + The library containing base repository pattern to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The Persistence Redis Library. - The library containing base repository pattern to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 5938e46d..9bba8647 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -5,14 +5,14 @@ Genocs.QueryBuilder Genocs.QueryBuilder Genocs.QueryBuilder + The Persistence Agnostic Query Builder Library. + The persistence agnostic query builder library. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The Persistence Agnostic Query Builder Library. - The persistence agnostic query builder library. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 7726dc90..9de89b50 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -5,14 +5,14 @@ Genocs.Secrets.Vault Genocs.Secrets.Vault Genocs.Secrets.Vault + The Genocs Secrets Vault library + The Genocs Secrets Vault library 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The Genocs Secrets Vault library - The Genocs Secrets Vault library Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index b8fb77f6..c47d4229 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -5,14 +5,14 @@ Genocs.Security Genocs.Security Genocs.Security + The Genocs Security library + The Genocs Security library 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The Genocs Security library - The Genocs Security library Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index c8902c12..cbac4eb2 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -5,14 +5,14 @@ Genocs.ServiceBusAzure Genocs.ServiceBusAzure Genocs.ServiceBusAzure + The low level library to use Azure Service Bus. + The low level library to use Azure Service Bus. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The low level library to use Azure Service Bus. - The low level library to use Azure Service Bus. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index ff212e70..dfc2c3eb 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -3,14 +3,16 @@ net6.0;net7.0;net8.0 Genocs.Tracing.Jaeger.RabbitMQ + Genocs.Tracing.Jaeger.RabbitMQ + Genocs.Tracing.Jaeger.RabbitMQ + The load balacer based on Fabio library useful to build .NET Core projects. + The load balacer based on Fabio library useful to build .NET Core projects. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The load balacer based on Fabio library useful to build .NET Core projects. - The load balacer based on Fabio library useful to build .NET Core projects. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 3d25858b..a4756ef1 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -5,14 +5,14 @@ Genocs.Tracing Genocs.Tracing Genocs.Tracing + The tracing library to use Azure Service Bus. + The tracing library to use Azure Service Bus. 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The tracing library to use Azure Service Bus. - The tracing library to use Azure Service Bus. Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 2aaacf42..e7e62541 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -5,14 +5,14 @@ Genocs.WebApi.CQRS Genocs.WebApi.CQRS Genocs.WebApi.CQRS + The web api CORS library + The web api CORS library 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The web api CORS library - The web api CORS library Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index f5eaff5b..b1cb0fde 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -5,14 +5,14 @@ Genocs.WebApi.Security Genocs.WebApi.Security Genocs.WebApi.Security + The web api Security library + The web api Security library 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The web api Security library - The web api Security library Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 7e8f8fed..99821695 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -5,14 +5,14 @@ Genocs.WebApi.Swagger Genocs.WebApi.Swagger Genocs.WebApi.Swagger + The web api Swagger library + The web api Swagger library 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The web api Swagger library - The web api Swagger library Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 4ee8058d..cb8cae7d 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -4,15 +4,15 @@ net6.0;net7.0;net8.0 Genocs.WebApi Genocs.WebApi - Genocs.WebApi + Genocs.WebApi + The web api library + The web api library 10.0 true 5.0.0 5.0.0 Nocco Giovanni Emanuele Genocs - The web api library - The web api library Genocs 2023 LICENSE https://github.com/Genocs/genocs-library diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index d0cc8608..11a962b5 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -93,7 +93,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) }); endpoints.MapReverseProxy(); - endpoints.MapHealthChecks("/healthz"); + endpoints.MapHealthChecks("/hc"); }); } } diff --git a/src/apps/api-gateway/Genocs.APIGateway/appsettings.json b/src/apps/api-gateway/Genocs.APIGateway/appsettings.json index 4183191b..3d4010c7 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/appsettings.json +++ b/src/apps/api-gateway/Genocs.APIGateway/appsettings.json @@ -49,7 +49,7 @@ "Token" ], "console": { - "enabled": true + "enabled": false }, "elk": { "enabled": false, diff --git a/src/apps/identity/Genocs.Identities.WebApi/appsettings.json b/src/apps/identity/Genocs.Identities.WebApi/appsettings.json index 79f7ff97..e08e5fc8 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/appsettings.json +++ b/src/apps/identity/Genocs.Identities.WebApi/appsettings.json @@ -73,7 +73,7 @@ "Token" ], "console": { - "enabled": true + "enabled": false }, "elk": { "enabled": false, diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index 9e26e220..a93ab27c 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -98,5 +98,4 @@ app.Run(); -Log.CloseAndFlush(); - +Log.CloseAndFlush(); \ No newline at end of file diff --git a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json index 4aaf4cbc..f84e4046 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json +++ b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json @@ -35,7 +35,7 @@ "excludePaths": ["/ping", "/metrics"], "level": "information", "console": { - "enabled": true + "enabled": false }, "file": { "enabled": true, diff --git a/src/apps/products/Genocs.Products.WebApi/appsettings.json b/src/apps/products/Genocs.Products.WebApi/appsettings.json index 0e4f6b37..1b89b8c0 100644 --- a/src/apps/products/Genocs.Products.WebApi/appsettings.json +++ b/src/apps/products/Genocs.Products.WebApi/appsettings.json @@ -34,7 +34,7 @@ "excludePaths": [ "/ping", "/metrics" ], "level": "information", "console": { - "enabled": true + "enabled": false }, "file": { "enabled": true, @@ -42,7 +42,7 @@ "interval": "day" }, "seq": { - "enabled": true, + "enabled": false, "url": "http://localhost:5341", "token": "secret" } @@ -59,7 +59,7 @@ "metrics": { "enabled": true, "influxEnabled": false, - "prometheusEnabled": true, + "prometheusEnabled": false, "influxUrl": "http://localhost:8086", "database": "test", "env": "local", diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json b/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json index 85e29164..bd12c5fb 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json +++ b/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json @@ -73,7 +73,7 @@ ], "level": "information", "console": { - "enabled": true + "enabled": false }, "file": { "enabled": true, From a8bad21f6c199b726de89167f740bac1c85fcd6f Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 7 Dec 2023 16:45:21 +0100 Subject: [PATCH 024/104] Disabled Monitoring --- src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Core.Demo.Worker/Program.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 3bdb8728..73ec70e3 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index 6e538c4d..03bcee15 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -7,7 +7,7 @@ using Genocs.Core.Demo.Worker.Consumers; using Genocs.Core.Demo.Worker.Handlers; using Genocs.Logging; -using Genocs.Monitoring; +using Genocs.Tracing; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Persistence.MongoDb.Repositories; using Genocs.Persistence.MongoDb.Repositories.Clean; @@ -38,12 +38,12 @@ services .AddGenocs(hostContext.Configuration) + .AddOpenTelemetry() .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()); // It registers the repositories that has been overridden. No need in case of standard repository ConfigureMassTransit(services, hostContext.Configuration); - services.AddCustomOpenTelemetry(hostContext.Configuration); }) .Build(); From 9ad67419409742bcad1f383a1f9f5219f9ccfb7a Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 20 Dec 2023 17:27:44 +0100 Subject: [PATCH 025/104] Minor fix --- genocs.sln | 6 ----- .../Controllers/ServiceBusController.cs | 1 - .../Genocs.Core.Demo.WebApi.csproj | 15 ++++++++--- src/Genocs.Core.Demo.WebApi/Program.cs | 6 ++--- .../Genocs.Core.Demo.Worker.csproj | 15 ++++++++--- src/Genocs.Discovery.Consul/IConsulService.cs | 2 +- .../IConsulServicesRegistry.cs | 2 +- .../ConsulServiceNotFoundException.cs | 8 +++--- .../Services/ConsulService.cs | 8 +++--- .../Services/ConsulServicesRegistry.cs | 4 +-- src/Genocs.HTTP.RestEase/Extensions.cs | 26 ++++++++++++------- .../Serializers/QueryParamSerializer.cs | 13 ++++++---- src/Genocs.HTTP/IHttpClient.cs | 15 +++++------ 13 files changed, 69 insertions(+), 52 deletions(-) diff --git a/genocs.sln b/genocs.sln index d2e4264d..9d353690 100644 --- a/genocs.sln +++ b/genocs.sln @@ -29,8 +29,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Core.Demo.Domain", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Core.Demo.Infrastructure", "src\Genocs.Core.Demo.Infrastructure\Genocs.Core.Demo.Infrastructure.csproj", "{FA01671E-9778-4581-9CD3-4A0651DBC7D7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Monitoring", "src\Genocs.Monitoring\Genocs.Monitoring.csproj", "{14F46B52-6C3E-40CC-A18F-1A1E8FA9E6F3}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.QueryBuilder", "src\Genocs.QueryBuilder\Genocs.QueryBuilder.csproj", "{2F9F9EF1-031D-433A-816D-49372AAAAC66}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.QueryBuilder.UnitTests", "src\Genocs.QueryBuilder.UnitTests\Genocs.QueryBuilder.UnitTests.csproj", "{23B5DC61-F78E-42A5-9AA8-AB96DB7C89EC}" @@ -179,10 +177,6 @@ Global {FA01671E-9778-4581-9CD3-4A0651DBC7D7}.Debug|Any CPU.Build.0 = Debug|Any CPU {FA01671E-9778-4581-9CD3-4A0651DBC7D7}.Release|Any CPU.ActiveCfg = Release|Any CPU {FA01671E-9778-4581-9CD3-4A0651DBC7D7}.Release|Any CPU.Build.0 = Release|Any CPU - {14F46B52-6C3E-40CC-A18F-1A1E8FA9E6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {14F46B52-6C3E-40CC-A18F-1A1E8FA9E6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {14F46B52-6C3E-40CC-A18F-1A1E8FA9E6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {14F46B52-6C3E-40CC-A18F-1A1E8FA9E6F3}.Release|Any CPU.Build.0 = Release|Any CPU {2F9F9EF1-031D-433A-816D-49372AAAAC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2F9F9EF1-031D-433A-816D-49372AAAAC66}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F9F9EF1-031D-433A-816D-49372AAAAC66}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs index 2b4d2d63..90604ce3 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs @@ -22,7 +22,6 @@ public ServiceBusController(ILogger logger, IAzureServiceB _azureServiceBusTopic = azureServiceBusTopic; } - [HttpPost("SendToQueueAzureServiceBusQueue")] [Consumes(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 767607a9..8d67b977 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -9,6 +9,18 @@ ..\.. + + + + + + + + + + + + @@ -18,9 +30,6 @@ - - - diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index d51bbe01..bdbe0b05 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -1,7 +1,7 @@ using Genocs.Core.Builders; using Genocs.Core.Demo.WebApi.Infrastructure.Extensions; using Genocs.Logging; -using Genocs.Monitoring; +using Genocs.Tracing; using Genocs.Persistence.MongoDb.Extensions; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; @@ -27,6 +27,7 @@ services .AddGenocs(builder.Configuration) + .AddOpenTelemetry() .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()); @@ -54,9 +55,6 @@ services.AddOptions(); -// Set Custom Open telemetry -services.AddCustomOpenTelemetry(builder.Configuration); - var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 73ec70e3..34da5164 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -9,6 +9,18 @@ ..\.. + + + + + + + + + + + + @@ -19,9 +31,6 @@ - - - diff --git a/src/Genocs.Discovery.Consul/IConsulService.cs b/src/Genocs.Discovery.Consul/IConsulService.cs index d9209754..9c405e4e 100644 --- a/src/Genocs.Discovery.Consul/IConsulService.cs +++ b/src/Genocs.Discovery.Consul/IConsulService.cs @@ -6,5 +6,5 @@ public interface IConsulService { Task RegisterServiceAsync(ServiceRegistration registration); Task DeregisterServiceAsync(string id); - Task> GetServiceAgentsAsync(string service = null); + Task> GetServiceAgentsAsync(string? service = null); } \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/IConsulServicesRegistry.cs b/src/Genocs.Discovery.Consul/IConsulServicesRegistry.cs index 33e7fac7..5cbaebe8 100644 --- a/src/Genocs.Discovery.Consul/IConsulServicesRegistry.cs +++ b/src/Genocs.Discovery.Consul/IConsulServicesRegistry.cs @@ -4,5 +4,5 @@ namespace Genocs.Discovery.Consul; public interface IConsulServicesRegistry { - Task GetAsync(string name); + Task GetAsync(string name); } \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceNotFoundException.cs b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceNotFoundException.cs index 4e8d151a..4fa720f8 100644 --- a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceNotFoundException.cs +++ b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceNotFoundException.cs @@ -1,16 +1,16 @@ -using System; - namespace Genocs.Discovery.Consul.MessageHandlers; internal sealed class ConsulServiceNotFoundException : Exception { public string ServiceName { get; set; } - public ConsulServiceNotFoundException(string serviceName) : this(string.Empty, serviceName) + public ConsulServiceNotFoundException(string serviceName) + : this(string.Empty, serviceName) { } - public ConsulServiceNotFoundException(string message, string serviceName) : base(message) + public ConsulServiceNotFoundException(string message, string serviceName) + : base(message) { ServiceName = serviceName; } diff --git a/src/Genocs.Discovery.Consul/Services/ConsulService.cs b/src/Genocs.Discovery.Consul/Services/ConsulService.cs index 4ca5ae45..0f32f333 100644 --- a/src/Genocs.Discovery.Consul/Services/ConsulService.cs +++ b/src/Genocs.Discovery.Consul/Services/ConsulService.cs @@ -6,8 +6,8 @@ namespace Genocs.Discovery.Consul.Services; internal sealed class ConsulService : IConsulService { - private static readonly StringContent EmptyRequest = GetPayload(new { }); private const string Version = "v1"; + private static readonly StringContent EmptyRequest = GetPayload(new { }); private readonly HttpClient _client; public ConsulService(HttpClient client) @@ -21,16 +21,16 @@ public Task RegisterServiceAsync(ServiceRegistration regist public Task DeregisterServiceAsync(string id) => _client.PutAsync(GetEndpoint($"agent/service/deregister/{id}"), EmptyRequest); - public async Task> GetServiceAgentsAsync(string service = null) + public async Task> GetServiceAgentsAsync(string? service = null) { - var filter = string.IsNullOrWhiteSpace(service) ? string.Empty : $"?filter=Service==\"{service}\""; + string filter = string.IsNullOrWhiteSpace(service) ? string.Empty : $"?filter=Service==\"{service}\""; var response = await _client.GetAsync(GetEndpoint($"agent/services{filter}")); if (!response.IsSuccessStatusCode) { return new Dictionary(); } - var content = await response.Content.ReadAsStringAsync(); + string content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize>(content); } diff --git a/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs b/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs index c8e3e277..78df40b9 100644 --- a/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs +++ b/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs @@ -13,7 +13,7 @@ public ConsulServicesRegistry(IConsulService consulService) _consulService = consulService; } - public async Task GetAsync(string name) + public async Task GetAsync(string name) { var services = await _consulService.GetServiceAgentsAsync(name); if (!services.Any()) @@ -33,7 +33,7 @@ public async Task GetAsync(string name) return GetService(services, name); } - private ServiceAgent GetService(IDictionary services, string name) + private ServiceAgent? GetService(IDictionary services, string name) { switch (services.Count) { diff --git a/src/Genocs.HTTP.RestEase/Extensions.cs b/src/Genocs.HTTP.RestEase/Extensions.cs index 26591664..70020773 100644 --- a/src/Genocs.HTTP.RestEase/Extensions.cs +++ b/src/Genocs.HTTP.RestEase/Extensions.cs @@ -51,8 +51,11 @@ public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, st => builder.AddServiceClient(serviceName, options, b => b.AddFabio(fabioOptions, consulOptions, httpClientOptions)); - private static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, - RestEaseSettings options, Action registerFabio) + private static IGenocsBuilder AddServiceClient( + this IGenocsBuilder builder, + string serviceName, + RestEaseSettings options, + Action registerFabio) where T : class { if (!builder.TryRegister(RegistryName)) @@ -60,7 +63,7 @@ private static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, s return builder; } - var clientName = typeof(T).ToString(); + string clientName = typeof(T).ToString(); switch (options.LoadBalancer?.ToLowerInvariant()) { @@ -82,17 +85,19 @@ private static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, s return builder; } - private static void ConfigureDefaultClient(IServiceCollection services, string clientName, - string serviceName, RestEaseSettings options) + private static void ConfigureDefaultClient( + IServiceCollection services, + string clientName, + string serviceName, + RestEaseSettings options) { services.AddHttpClient(clientName, client => { - var service = options.Services.SingleOrDefault(s => s.Name.Equals(serviceName, - StringComparison.InvariantCultureIgnoreCase)); + var service = options.Services.SingleOrDefault(s => s.Name.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase)); + if (service is null) { - throw new RestEaseServiceNotFoundException($"RestEase service: '{serviceName}' was not found.", - serviceName); + throw new RestEaseServiceNotFoundException($"RestEase service: '{serviceName}' was not found.", serviceName); } client.BaseAddress = new UriBuilder @@ -104,7 +109,8 @@ private static void ConfigureDefaultClient(IServiceCollection services, string c }); } - private static void ConfigureForwarder(IServiceCollection services, string clientName) where T : class + private static void ConfigureForwarder(IServiceCollection services, string clientName) + where T : class { services.AddTransient(c => new RestClient(c.GetRequiredService().CreateClient(clientName)) { diff --git a/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs b/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs index 46159da2..6b929112 100644 --- a/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs +++ b/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs @@ -52,24 +52,27 @@ private Dictionary GetPropertiesDeepRecursive(object obj, string if (obj is IEnumerable collection) { int i = 0; - foreach (var item in collection) + foreach (object? item in collection) { dict = dict.Concat(GetPropertiesDeepRecursive(item, $"{name}[{i++}]")).ToDictionary(e => e.Key, e => e.Value); } + return dict; } var properties = obj.GetType().GetProperties(); - //If the prefix won't be empty, then it is needed to specify [Query(null)]. - //Otherwise, the query string will contain the query name e.g. 'query.page' instead of just 'page'. - //var prefix = string.IsNullOrWhiteSpace(name) ? string.Empty : $"{name}."; - var prefix = string.Empty; + + // If the prefix won't be empty, then it is needed to specify [Query(null)]. + // Otherwise, the query string will contain the query name e.g. 'query.page' instead of just 'page'. + // var prefix = string.IsNullOrWhiteSpace(name) ? string.Empty : $"{name}."; + string prefix = string.Empty; foreach (var prop in properties) { dict = dict .Concat(GetPropertiesDeepRecursive(prop.GetValue(obj, null), $"{prefix}{prop.Name}")) .ToDictionary(e => e.Key, e => e.Value); } + return dict; } } \ No newline at end of file diff --git a/src/Genocs.HTTP/IHttpClient.cs b/src/Genocs.HTTP/IHttpClient.cs index 9438b666..568bae1e 100644 --- a/src/Genocs.HTTP/IHttpClient.cs +++ b/src/Genocs.HTTP/IHttpClient.cs @@ -2,9 +2,8 @@ namespace Genocs.HTTP; - /// -/// The Genocs HTTP client +/// The Genocs HTTP client. /// public interface IHttpClient { @@ -36,23 +35,23 @@ public interface IHttpClient Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null); /// - /// Send the request and return the result + /// Send the request and return the result. /// - /// + /// The type to be send. /// /// /// Task> SendResultAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null); /// - /// Set the headers for the HTTP client + /// Set the headers for the HTTP client. /// - /// The headers dictionary + /// The headers dictionary. void SetHeaders(IDictionary headers); /// - /// Set the headers for the HTTP client + /// Set the headers for the HTTP client. /// - /// The headers action delegate + /// The headers action delegate. void SetHeaders(Action headers); } \ No newline at end of file From 9ff8abbd28df412a5e8e34b4d6e5fc26bda2046b Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 26 Dec 2023 19:17:30 +0100 Subject: [PATCH 026/104] Updated Nuget Packages --- Directory.Build.props | 2 +- .../Genocs.Core.Demo.WebApi.csproj | 2 +- .../Genocs.Core.Demo.Worker.csproj | 2 +- .../Genocs.Core.UnitTests.csproj | 4 +- .../Extensions/DictionaryExtensions.cs | 134 ++++----- .../Extensions/EnumerableExtensions.cs | 110 ++++--- src/Genocs.Core/Collections/TypeList.cs | 228 +++++++-------- .../Entities/EntityNotFoundException.cs | 6 +- .../Repositories/TableMappingAttribute.cs | 27 +- src/Genocs.Logging/Options/LoggerSettings.cs | 6 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 4 +- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +- src/Genocs.QueryBuilder/Constants.cs | 111 ++++---- .../DynamicQueryBuilder.cs | 268 +++++++++--------- src/Genocs.QueryBuilder/Expression.String.cs | 160 ++++++----- src/Genocs.QueryBuilder/QueryItem.cs | 8 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 4 +- src/Genocs.Tracing/Genocs.Tracing.csproj | 4 +- 21 files changed, 538 insertions(+), 552 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9de369d9..21248176 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,7 +18,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 8d67b977..0dde951c 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 34da5164..19dfa7d5 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 2e7c5b63..ca43f1f3 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs b/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs index e69a577f..21b5938c 100644 --- a/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs @@ -1,80 +1,80 @@ -namespace Genocs.Core.Collections.Extensions -{ - using System; - using System.Collections.Generic; +using System; +using System.Collections.Generic; + +namespace Genocs.Core.Collections.Extensions; + +/// +/// Extension methods for Dictionary. +/// +public static class DictionaryExtensions +{ /// - /// Extension methods for Dictionary. + /// This method is used to try to get a value in a dictionary if it does exists. /// - public static class DictionaryExtensions + /// Type of the value + /// The collection object + /// Key + /// Value of the key (or default value if key not exists) + /// True if key does exists in the dictionary + internal static bool TryGetValue(this IDictionary dictionary, string key, out T value) { - /// - /// This method is used to try to get a value in a dictionary if it does exists. - /// - /// Type of the value - /// The collection object - /// Key - /// Value of the key (or default value if key not exists) - /// True if key does exists in the dictionary - internal static bool TryGetValue(this IDictionary dictionary, string key, out T value) + object valueObj; + if (dictionary.TryGetValue(key, out valueObj) && valueObj is T) { - object valueObj; - if (dictionary.TryGetValue(key, out valueObj) && valueObj is T) - { - value = (T)valueObj; - return true; - } - - value = default(T); - return false; + value = (T)valueObj; + return true; } - /// - /// Gets a value from the dictionary with given key. Returns default value if can not find. - /// - /// Dictionary to check and get - /// Key to find the value - /// Type of the key - /// Type of the value - /// Value if found, default if can not found. - public static TValue GetOrDefault(this IDictionary dictionary, TKey key) - { - TValue obj; - return dictionary.TryGetValue(key, out obj) ? obj : default(TValue); - } + value = default(T); + return false; + } - /// - /// Gets a value from the dictionary with given key. Returns default value if can not find. - /// - /// Dictionary to check and get - /// Key to find the value - /// A factory method used to create the value if not found in the dictionary - /// Type of the key - /// Type of the value - /// Value if found, default if can not found. - public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) - { - TValue obj; - if (dictionary.TryGetValue(key, out obj)) - { - return obj; - } + /// + /// Gets a value from the dictionary with given key. Returns default value if can not find. + /// + /// Dictionary to check and get + /// Key to find the value + /// Type of the key + /// Type of the value + /// Value if found, default if can not found. + public static TValue GetOrDefault(this IDictionary dictionary, TKey key) + { + TValue obj; + return dictionary.TryGetValue(key, out obj) ? obj : default(TValue); + } - return dictionary[key] = factory(key); - } - - /// - /// Gets a value from the dictionary with given key. Returns default value if can not find. - /// - /// Dictionary to check and get - /// Key to find the value - /// A factory method used to create the value if not found in the dictionary - /// Type of the key - /// Type of the value - /// Value if found, default if can not found. - public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) + /// + /// Gets a value from the dictionary with given key. Returns default value if can not find. + /// + /// Dictionary to check and get + /// Key to find the value + /// A factory method used to create the value if not found in the dictionary + /// Type of the key + /// Type of the value + /// Value if found, default if can not found. + public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) + { + TValue obj; + if (dictionary.TryGetValue(key, out obj)) { - return dictionary.GetOrAdd(key, k => factory()); + return obj; } + + return dictionary[key] = factory(key); + } + + /// + /// Gets a value from the dictionary with given key. Returns default value if can not find. + /// + /// Dictionary to check and get + /// Key to find the value + /// A factory method used to create the value if not found in the dictionary + /// Type of the key + /// Type of the value + /// Value if found, default if can not found. + public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) + { + return dictionary.GetOrAdd(key, k => factory()); } } \ No newline at end of file diff --git a/src/Genocs.Core/Collections/Extensions/EnumerableExtensions.cs b/src/Genocs.Core/Collections/Extensions/EnumerableExtensions.cs index cd71be8e..29f0c7e7 100644 --- a/src/Genocs.Core/Collections/Extensions/EnumerableExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/EnumerableExtensions.cs @@ -1,66 +1,60 @@ -namespace Genocs.Core.Collections.Extensions -{ - using System; - using System.Collections.Generic; - using System.Linq; - +namespace Genocs.Core.Collections.Extensions; - /// - /// Extension methods for . +/// +/// Extension methods for . +/// +public static class EnumerableExtensions +{ + /// + /// Concatenates the members of a constructed collection of type System.String, using the specified separator between each member. + /// This is a shortcut for string.Join(...) /// - public static class EnumerableExtensions + /// A collection that contains the strings to concatenate. + /// The string to use as a separator. separator is included in the returned string only if values has more than one element. + /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty. + public static string JoinAsString(this IEnumerable source, string separator) { - /// - /// Concatenates the members of a constructed collection of type System.String, using the specified separator between each member. - /// This is a shortcut for string.Join(...) - /// - /// A collection that contains the strings to concatenate. - /// The string to use as a separator. separator is included in the returned string only if values has more than one element. - /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty. - public static string JoinAsString(this IEnumerable source, string separator) - { - return string.Join(separator, source); - } + return string.Join(separator, source); + } - /// - /// Concatenates the members of a collection, using the specified separator between each member. - /// This is a shortcut for string.Join(...) - /// - /// A collection that contains the objects to concatenate. - /// The string to use as a separator. separator is included in the returned string only if values has more than one element. - /// The type of the members of values. - /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty. - public static string JoinAsString(this IEnumerable source, string separator) - { - return string.Join(separator, source); - } + /// + /// Concatenates the members of a collection, using the specified separator between each member. + /// This is a shortcut for string.Join(...) + /// + /// A collection that contains the objects to concatenate. + /// The string to use as a separator. separator is included in the returned string only if values has more than one element. + /// The type of the members of values. + /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty. + public static string JoinAsString(this IEnumerable source, string separator) + { + return string.Join(separator, source); + } - /// - /// Filters a by given predicate if given condition is true. - /// - /// Enumerable to apply filtering - /// A boolean value - /// Predicate to filter the enumerable - /// Filtered or not filtered enumerable based on - public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) - { - return condition - ? source.Where(predicate) - : source; - } + /// + /// Filters a by given predicate if given condition is true. + /// + /// Enumerable to apply filtering. + /// A boolean value. + /// Predicate to filter the enumerable. + /// Filtered or not filtered enumerable based on . + public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) + { + return condition + ? source.Where(predicate) + : source; + } - /// - /// Filters a by given predicate if given condition is true. - /// - /// Enumerable to apply filtering - /// A boolean value - /// Predicate to filter the enumerable - /// Filtered or not filtered enumerable based on - public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) - { - return condition - ? source.Where(predicate) - : source; - } + /// + /// Filters a by given predicate if given condition is true. + /// + /// Enumerable to apply filtering. + /// A boolean value. + /// Predicate to filter the enumerable. + /// Filtered or not filtered enumerable based on . + public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate) + { + return condition + ? source.Where(predicate) + : source; } } diff --git a/src/Genocs.Core/Collections/TypeList.cs b/src/Genocs.Core/Collections/TypeList.cs index 727b1b1d..32d6f57e 100644 --- a/src/Genocs.Core/Collections/TypeList.cs +++ b/src/Genocs.Core/Collections/TypeList.cs @@ -1,143 +1,143 @@ -namespace Genocs.Core.Collections +using System.Collections; +using System.Reflection; + +namespace Genocs.Core.Collections; + +/// +/// A shortcut for to use object as base type. +/// +public class TypeList : TypeList, ITypeList { - using System; - using System.Collections; - using System.Collections.Generic; - using System.Reflection; +} +/// +/// Extends to add restriction a specific base type. +/// +/// Base Type of s in this list +public class TypeList : ITypeList +{ /// - /// A shortcut for to use object as base type. + /// Gets the count. /// - public class TypeList : TypeList, ITypeList - { - } + /// The count. + public int Count { get { return _typeList.Count; } } /// - /// Extends to add restriction a specific base type. + /// Gets a value indicating whether this instance is read only. /// - /// Base Type of s in this list - public class TypeList : ITypeList - { - /// - /// Gets the count. - /// - /// The count. - public int Count { get { return _typeList.Count; } } - - /// - /// Gets a value indicating whether this instance is read only. - /// - /// true if this instance is read only; otherwise, false. - public bool IsReadOnly { get { return false; } } - - /// - /// Gets or sets the at the specified index. - /// - /// Index. - public Type this[int index] + /// true if this instance is read only; otherwise, false. + public bool IsReadOnly { get { return false; } } + + /// + /// Gets or sets the at the specified index. + /// + /// Index. + public Type this[int index] + { + get { return _typeList[index]; } + set { - get { return _typeList[index]; } - set - { - CheckType(value); - _typeList[index] = value; - } + CheckType(value); + _typeList[index] = value; } + } - private readonly List _typeList; + private readonly List _typeList; - /// - /// Creates a new object. - /// - public TypeList() - { - _typeList = new List(); - } + /// + /// Creates a new object. + /// + public TypeList() + { + _typeList = new List(); + } - /// - public void Add() where T : TBaseType - { - _typeList.Add(typeof(T)); - } + /// + public void Add() + where T : TBaseType + { + _typeList.Add(typeof(T)); + } - /// - public void Add(Type item) - { - CheckType(item); - _typeList.Add(item); - } + /// + public void Add(Type item) + { + CheckType(item); + _typeList.Add(item); + } - /// - public void Insert(int index, Type item) - { - _typeList.Insert(index, item); - } + /// + public void Insert(int index, Type item) + { + _typeList.Insert(index, item); + } - /// - public int IndexOf(Type item) - { - return _typeList.IndexOf(item); - } + /// + public int IndexOf(Type item) + { + return _typeList.IndexOf(item); + } - /// - public bool Contains() where T : TBaseType - { - return Contains(typeof(T)); - } + /// + public bool Contains() + where T : TBaseType + { + return Contains(typeof(T)); + } - /// - public bool Contains(Type item) - { - return _typeList.Contains(item); - } + /// + public bool Contains(Type item) + { + return _typeList.Contains(item); + } - /// - public void Remove() where T : TBaseType - { - _typeList.Remove(typeof(T)); - } + /// + public void Remove() + where T : TBaseType + { + _typeList.Remove(typeof(T)); + } - /// - public bool Remove(Type item) - { - return _typeList.Remove(item); - } + /// + public bool Remove(Type item) + { + return _typeList.Remove(item); + } - /// - public void RemoveAt(int index) - { - _typeList.RemoveAt(index); - } + /// + public void RemoveAt(int index) + { + _typeList.RemoveAt(index); + } - /// - public void Clear() - { - _typeList.Clear(); - } + /// + public void Clear() + { + _typeList.Clear(); + } - /// - public void CopyTo(Type[] array, int arrayIndex) - { - _typeList.CopyTo(array, arrayIndex); - } + /// + public void CopyTo(Type[] array, int arrayIndex) + { + _typeList.CopyTo(array, arrayIndex); + } - /// - public IEnumerator GetEnumerator() - { - return _typeList.GetEnumerator(); - } + /// + public IEnumerator GetEnumerator() + { + return _typeList.GetEnumerator(); + } - IEnumerator IEnumerable.GetEnumerator() - { - return _typeList.GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() + { + return _typeList.GetEnumerator(); + } - private static void CheckType(Type item) + private static void CheckType(Type item) + { + if (!typeof(TBaseType).GetTypeInfo().IsAssignableFrom(item)) { - if (!typeof(TBaseType).GetTypeInfo().IsAssignableFrom(item)) - { - throw new ArgumentException("Given item is not type of " + typeof(TBaseType).AssemblyQualifiedName, "item"); - } + throw new ArgumentException("Given item is not type of " + typeof(TBaseType).AssemblyQualifiedName, "item"); } } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs index f5fd0b4a..28a83399 100644 --- a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs +++ b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs @@ -35,7 +35,7 @@ public EntityNotFoundException(SerializationInfo serializationInfo, StreamingCon { } - + /// /// Creates a new object. /// @@ -68,8 +68,8 @@ public EntityNotFoundException(string message) /// /// Creates a new object. /// - /// Exception message - /// Inner exception + /// Exception message. + /// Inner exception. public EntityNotFoundException(string message, Exception innerException) : base(message, innerException) { diff --git a/src/Genocs.Core/Domain/Repositories/TableMappingAttribute.cs b/src/Genocs.Core/Domain/Repositories/TableMappingAttribute.cs index a971d42c..ee57d19b 100644 --- a/src/Genocs.Core/Domain/Repositories/TableMappingAttribute.cs +++ b/src/Genocs.Core/Domain/Repositories/TableMappingAttribute.cs @@ -1,19 +1,18 @@ -namespace Genocs.Core.Domain.Repositories +namespace Genocs.Core.Domain.Repositories; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] +public class TableMappingAttribute : Attribute { - [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct)] - public class TableMappingAttribute : System.Attribute - { - /// - /// The Collection/Table name - /// - public string Name { get; set; } + /// + /// The Collection/Table name. + /// + public string Name { get; set; } - public double version; + public readonly double Version; - public TableMappingAttribute(string tableName) - { - Name = tableName; - version = 1.0; - } + public TableMappingAttribute(string tableName) + { + Name = tableName; + Version = 1.0; } } diff --git a/src/Genocs.Logging/Options/LoggerSettings.cs b/src/Genocs.Logging/Options/LoggerSettings.cs index e5ac5aa5..a604ae66 100644 --- a/src/Genocs.Logging/Options/LoggerSettings.cs +++ b/src/Genocs.Logging/Options/LoggerSettings.cs @@ -2,19 +2,19 @@ namespace Genocs.Logging.Options; /// -/// Logger Settings +/// Logger Settings. /// public class LoggerSettings { /// - /// Default section name + /// Default section name. /// public const string Position = "logger"; public string? Level { get; set; } /// - /// The Console Logging and tracing Settings + /// The Console Logging and tracing Settings. /// public ConsoleSettings? Console { get; set; } public LocalFileSettings? File { get; set; } diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index dacd4bfe..f34920a2 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -52,7 +52,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 48f58a62..8f9dfcf1 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -78,7 +78,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 51f3108f..c6e850c4 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -12,8 +12,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 88a96133..cb25bde3 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 4517b19e..812247f4 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -14,8 +14,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.QueryBuilder/Constants.cs b/src/Genocs.QueryBuilder/Constants.cs index 5671e3e0..2b73c2ea 100644 --- a/src/Genocs.QueryBuilder/Constants.cs +++ b/src/Genocs.QueryBuilder/Constants.cs @@ -1,59 +1,58 @@ -namespace Genocs.QueryBuilder +namespace Genocs.QueryBuilder; + +/// +/// Query constants. +/// +public static class Constants +{ + /// + /// Default date format. + /// + public const string DATE_FORMAT = "yyyy-MM-dd"; + + /// + /// Default filtering date. + /// + public const string DATE_FILTERING = "UpdatedAt"; + + /// + /// Default property name. + /// + public const string DEFAULT_PROPERY_NAME = "IsDefault"; +} + +/// +/// Query operator types. +/// +public enum QueryOperator { /// - /// Query constants - /// - public static class Constants - { - /// - /// Default date format - /// - public const string DATE_FORMAT = "yyyy-MM-dd"; - - /// - /// Default filtering date - /// - public const string DATE_FILTERING = "UpdatedAt"; - - /// - /// Default property name - /// - public const string DEFAULT_PROPERY_NAME = "IsDefault"; - } - - /// - /// Query operator types - /// - public enum QueryOperator - { - /// - /// GreaterThan - /// - GreaterThan, - - /// - /// GreaterThanOrEqual - /// - GreaterThanOrEqual, - - /// - /// Equal - /// - Equal, - - /// - /// NotEqual - /// - NotEqual, - - /// - /// LessThan - /// - LessThan, - - /// - /// LessThanOrEqual - /// - LessThanOrEqual - } + /// GreaterThan. + /// + GreaterThan, + + /// + /// GreaterThanOrEqual. + /// + GreaterThanOrEqual, + + /// + /// Equal. + /// + Equal, + + /// + /// NotEqual. + /// + NotEqual, + + /// + /// LessThan. + /// + LessThan, + + /// + /// LessThanOrEqual. + /// + LessThanOrEqual } \ No newline at end of file diff --git a/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs b/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs index 32820599..a486bcbd 100644 --- a/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs +++ b/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs @@ -1,170 +1,164 @@ -using System; -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; -namespace Genocs.QueryBuilder +namespace Genocs.QueryBuilder; + +/// +/// DynamicQueryBuilder. +/// +public class DynamicQueryBuilder { + #region Private static members + private static readonly string AndOperator = " and "; + private static readonly string OrOperator = " or "; + private static readonly string GtOperator = " gt "; + private static readonly string LtOperator = " lt "; + private static readonly string GtEOperator = " gte "; + private static readonly string LtEOperator = " lte "; + + private static readonly string NotOperator = " not "; + + private static readonly string[] StringSeparators = new string[] { AndOperator, OrOperator, LtOperator, GtOperator, GtEOperator, LtEOperator }; + #endregion + /// - /// DynamicQueryBuilder + /// Builds the advanced search expression tree. + /// This enables dynamic query on Following attributes + /// MemberId, FirstName, LastName, Employer, Email, Address.City. + /// It can be enabled on other fields as well, but i have just restricted as a sample ot these set of fields. /// - public class DynamicQueryBuilder + /// The type of the source. + /// The search term. + /// The search. + /// + public static Expression> BuildAdvancedSearchExpressionTree(List searchItems, string sourceName) { - #region Private static members - private static readonly string AndOperator = " and "; - private static readonly string OrOperator = " or "; - private static readonly string GtOperator = " gt "; - private static readonly string LtOperator = " lt "; - private static readonly string GtEOperator = " gte "; - private static readonly string LtEOperator = " lte "; - - private static readonly string NotOperator = " not "; - - private static readonly string[] stringSeparators = new string[] { AndOperator, OrOperator, LtOperator, GtOperator, GtEOperator, LtEOperator }; - #endregion - - - /// - /// Builds the advanced search expression tree. - /// This enables dynamic query on Following attributes - /// MemberId, FirstName, LastName, Employer, Email, Address.City. - /// It can be enabled on other fields as well, but i have just restricted as a sample ot these set of fields. - /// - /// The type of the source. - /// The search term. - /// The search. - /// - public static Expression> BuildAdvancedSearchExpressionTree(List searchItems, string sourceName) + ParameterExpression pe = Expression.Parameter(typeof(TSource), sourceName); + Expression searchExpression = null; + + foreach (var searchItem in searchItems) { - ParameterExpression pe = Expression.Parameter(typeof(TSource), sourceName); - Expression searchExpression = null; + Expression expression = ExpressionBuilder(searchItem, pe); - foreach (var searchItem in searchItems) - { - Expression expression = ExpressionBuilder(searchItem, pe); + // If you want to apply OR + // searchExpression = searchExpression == null ? expression : Expression.OrElse(searchExpression, expression); - // If you want to apply OR - //searchExpression = searchExpression == null ? expression : Expression.OrElse(searchExpression, expression); + // If you want to apply AND + searchExpression = searchExpression == null ? expression : Expression.AndAlso(searchExpression, expression); + } - // If you want to apply AND - searchExpression = searchExpression == null ? expression : Expression.AndAlso(searchExpression, expression); - } + return Expression.Lambda>(searchExpression, pe); + } - return Expression.Lambda>(searchExpression, pe); - } + /// + /// Builds the advanced search expression tree. + /// This enables dynamic query on a single item. + /// + /// The type of the source. + /// The search term. + /// The search. + /// + public static Expression> BuildAdvancedSearchExpressionTree(QueryItem searchItem, string sourceName) + { + ParameterExpression pe = Expression.Parameter(typeof(TSource), sourceName); + Expression searchExpression = ExpressionBuilder(searchItem, pe); + return Expression.Lambda>(searchExpression, pe); + } + private static Expression ExpressionBuilder(QueryItem searchItem, ParameterExpression pe) + { + string[] results = searchItem.PropertyValue.Split(StringSeparators, StringSplitOptions.RemoveEmptyEntries); + var operatorIndexes = GetListOfSortedOperatorIndexes(searchItem.PropertyValue); - /// - /// Builds the advanced search expression tree. - /// This enables dynamic query on a single item - /// - /// The type of the source. - /// The search term. - /// The search. - /// - public static Expression> BuildAdvancedSearchExpressionTree(QueryItem searchItem, string sourceName) + Expression expression; + switch (searchItem.PropertyType.ToLower().Trim()) { - ParameterExpression pe = Expression.Parameter(typeof(TSource), sourceName); - Expression searchExpression = ExpressionBuilder(searchItem, pe); - return Expression.Lambda>(searchExpression, pe); + case "string": + expression = QueryBuilder.ExpressionBuilder.GetExpressionString(results, searchItem.PropertyValue, searchItem.PropertyName, operatorIndexes, pe, searchItem.ParentCanBeNull); + break; + case "int": + expression = QueryBuilder.ExpressionBuilder.GetExpressionInt(results, searchItem.PropertyName, searchItem.OperatorType, pe); + break; + case "numeric": + expression = QueryBuilder.ExpressionBuilder.GetExpressionNumeric(results, searchItem.PropertyName, searchItem.OperatorType, pe); + break; + case "date": + expression = QueryBuilder.ExpressionBuilder.GetExpressionDate(results, searchItem.PropertyName, searchItem.OperatorType, pe); + break; + case "bool": + expression = QueryBuilder.ExpressionBuilder.GetExpressionBool(results, searchItem.PropertyName, pe); + break; + default: + expression = QueryBuilder.ExpressionBuilder.GetExpressionString(results, searchItem.PropertyValue, searchItem.PropertyName, operatorIndexes, pe, searchItem.ParentCanBeNull); + break; } - private static Expression ExpressionBuilder(QueryItem searchItem, ParameterExpression pe) - { - string[] results = searchItem.PropertyValue.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); - var operatorIndexes = GetListOfSortedOperatorIndexes(searchItem.PropertyValue); + return expression; - Expression expression; - switch (searchItem.PropertyType.ToLower().Trim()) - { - case "string": - expression = QueryBuilder.ExpressionBuilder.GetExpressionString(results, searchItem.PropertyValue, searchItem.PropertyName, operatorIndexes, pe, searchItem.ParentCanBeNull); - break; - case "int": - expression = QueryBuilder.ExpressionBuilder.GetExpressionInt(results, searchItem.PropertyName, searchItem.OperatorType, pe); - break; - case "numeric": - expression = QueryBuilder.ExpressionBuilder.GetExpressionNumeric(results, searchItem.PropertyName, searchItem.OperatorType, pe); - break; - case "date": - expression = QueryBuilder.ExpressionBuilder.GetExpressionDate(results, searchItem.PropertyName, searchItem.OperatorType, pe); - break; - case "bool": - expression = QueryBuilder.ExpressionBuilder.GetExpressionBool(results, searchItem.PropertyName, pe); - break; - default: - expression = QueryBuilder.ExpressionBuilder.GetExpressionString(results, searchItem.PropertyValue, searchItem.PropertyName, operatorIndexes, pe, searchItem.ParentCanBeNull); - break; - } - - return expression; + } - } + /// + /// Gets the list of sorted operator indexes. + /// + /// The input. + /// + private static List GetListOfSortedOperatorIndexes(string input) + { + input = input.ToLower(); + string[] result = input.Split(StringSeparators, StringSplitOptions.RemoveEmptyEntries); + List operatorIndexes = new List(); + var andOperatorIndexes = AllIndexesOf(input, StringSeparators[0]); + var orOperatorIndexes = AllIndexesOf(input, StringSeparators[1]); - /// - /// Gets the list of sorted operator indexes. - /// - /// The input. - /// - private static List GetListOfSortedOperatorIndexes(string input) + if (andOperatorIndexes.Count > 0) { - input = input.ToLower(); - string[] result = input.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); + operatorIndexes.AddRange(andOperatorIndexes); + } - List operatorIndexes = new List(); - var andOperatorIndexes = AllIndexesOf(input, stringSeparators[0]); - var orOperatorIndexes = AllIndexesOf(input, stringSeparators[1]); + if (orOperatorIndexes.Count > 0) + { + operatorIndexes.AddRange(orOperatorIndexes); + } - if (andOperatorIndexes.Count > 0) - { - operatorIndexes.AddRange(andOperatorIndexes); - } + if (operatorIndexes.Count > 0) + { + var sorterOperatorIndexes = operatorIndexes.ToList().OrderBy(v => v.Index).ToList(); + } - if (orOperatorIndexes.Count > 0) - { - operatorIndexes.AddRange(orOperatorIndexes); - } + return operatorIndexes; + } - if (operatorIndexes.Count > 0) - { - var sorterOperatorIndexes = operatorIndexes.ToList().OrderBy(v => v.Index).ToList(); - } - return operatorIndexes; + /// + /// All the indexes of. + /// + /// The string. + /// The value. + /// + /// the string to find may not be empty value. + private static List AllIndexesOf(string str, string value) + { + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("the string to find may not be empty", "value"); } - /// - /// All the indexes of. - /// - /// The string. - /// The value. - /// - /// the string to find may not be empty;value - private static List AllIndexesOf(string str, string value) + List indexes = new List(); + for (int index = 0; ; index += value.Length) { - if (string.IsNullOrWhiteSpace(value)) + index = str.IndexOf(value, index); + if (index == -1) + return indexes; + indexes.Add(new OperatorIndexes { - throw new ArgumentException("the string to find may not be empty", "value"); - } - - List indexes = new List(); - for (int index = 0; ; index += value.Length) - { - index = str.IndexOf(value, index); - if (index == -1) - return indexes; - indexes.Add(new OperatorIndexes - { - Index = index, - Operator = value - }); - } + Index = index, + Operator = value + }); } } +} - internal class OperatorIndexes - { - public int Index { get; set; } - public string Operator { get; set; } - } +internal class OperatorIndexes +{ + public int Index { get; set; } + public string Operator { get; set; } } \ No newline at end of file diff --git a/src/Genocs.QueryBuilder/Expression.String.cs b/src/Genocs.QueryBuilder/Expression.String.cs index 221332bc..8e040f8f 100644 --- a/src/Genocs.QueryBuilder/Expression.String.cs +++ b/src/Genocs.QueryBuilder/Expression.String.cs @@ -1,104 +1,102 @@ -using System; -using System.Collections.Generic; using System.Linq.Expressions; -namespace Genocs.QueryBuilder +namespace Genocs.QueryBuilder; + +/// +/// ExpressionBuilder class. +/// +public static partial class ExpressionBuilder { /// - /// ExpressionBuilder class + /// Gets the expression. /// - public static partial class ExpressionBuilder + /// The type of the source. + /// The search terms. + /// The keyword. + /// Name of the property. + /// The operator indexes. + /// The pe. + /// if set to true [add parent object null check]. + /// + internal static Expression GetExpressionString( + string[] searchTerms, + string keyword, + string propertyName, + List operatorIndexes, + ParameterExpression pe, + bool addParentObjectNullCheck) { - /// - /// Gets the expression. - /// - /// The type of the source. - /// The search terms. - /// The keyword. - /// Name of the property. - /// The operator indexes. - /// The pe. - /// if set to true [add parent object null check]. - /// - internal static Expression GetExpressionString(string[] searchTerms, - string keyword, - string propertyName, - List operatorIndexes, - ParameterExpression pe, - bool addParentObjectNullCheck) + // Compose the expression tree that represents the parameter to the predicate. + Expression propertyExp = pe; + string[] members = propertyName.Split('.'); + foreach (string member in members) { - // Compose the expression tree that represents the parameter to the predicate. - Expression propertyExp = pe; - string[] members = propertyName.Split('.'); - foreach (var member in members) - { - propertyExp = Expression.PropertyOrField(propertyExp, member); - } + propertyExp = Expression.PropertyOrField(propertyExp, member); + } - Expression searchExpression = null; - Expression finalExpression = null; - Expression nullorEmptyCheck = null; + Expression? searchExpression = null; + Expression? finalExpression = null; + Expression? nullOrEmptyCheck = null; - MethodCallExpression left = Expression.Call(propertyExp, typeof(string).GetMethod("ToLower", Type.EmptyTypes)); + MethodCallExpression left = Expression.Call(propertyExp, typeof(string).GetMethod("ToLower", Type.EmptyTypes)); - var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); + var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); - for (int count = 0; count < searchTerms.Length; count++) + for (int count = 0; count < searchTerms.Length; count++) + { + string searchTerm = searchTerms[count].ToLower(); + searchTerm = searchTerm.Replace("*", string.Empty); + searchTerm = searchTerm.Replace("\"", string.Empty); + Expression rightExpression; + Expression methodCallExpression; + if (searchTerm.Contains(NotOperator.TrimStart())) { - var searchTerm = searchTerms[count].ToLower(); - searchTerm = searchTerm.Replace("*", string.Empty); - searchTerm = searchTerm.Replace("\"", string.Empty); - Expression rightExpression; - Expression methodCallExpresssion; - if (searchTerm.Contains(NotOperator.TrimStart())) - { - searchTerm = searchTerm.Replace(NotOperator.TrimStart(), string.Empty).Trim(); - rightExpression = Expression.Constant(searchTerm); - methodCallExpresssion = Expression.Call(left, method, rightExpression); - methodCallExpresssion = Expression.Not(methodCallExpresssion); - } - else - { - rightExpression = Expression.Constant(searchTerm); - methodCallExpresssion = Expression.Call(left, method, rightExpression); - } - - if (count == 0) - { - searchExpression = methodCallExpresssion; - } - else - { - var conditionOperator = operatorIndexes[count - 1].Operator.Trim(); - switch (conditionOperator) - { - case "and": - searchExpression = Expression.AndAlso(searchExpression, methodCallExpresssion); - break; - case "or": - searchExpression = Expression.OrElse(searchExpression, methodCallExpresssion); - break; - default: - break; - } - } + searchTerm = searchTerm.Replace(NotOperator.TrimStart(), string.Empty).Trim(); + rightExpression = Expression.Constant(searchTerm); + methodCallExpression = Expression.Call(left, method, rightExpression); + methodCallExpression = Expression.Not(methodCallExpression); + } + else + { + rightExpression = Expression.Constant(searchTerm); + methodCallExpression = Expression.Call(left, method, rightExpression); } - if (addParentObjectNullCheck) + if (count == 0) { - //Add Null check for nested Object before checking the value of the property. - var nullCheck = Expression.NotEqual(Expression.PropertyOrField(pe, members[0]), Expression.Constant(null, typeof(object))); - nullorEmptyCheck = Expression.Not(Expression.Call(typeof(string), typeof(string).GetMethod("IsNullOrEmpty").Name, null, propertyExp)); - finalExpression = Expression.AndAlso(nullCheck, nullorEmptyCheck); - finalExpression = Expression.AndAlso(finalExpression, searchExpression); + searchExpression = methodCallExpression; } else { - nullorEmptyCheck = Expression.Not(Expression.Call(typeof(string), typeof(string).GetMethod("IsNullOrEmpty").Name, null, propertyExp)); - finalExpression = Expression.AndAlso(nullorEmptyCheck, searchExpression); + string conditionOperator = operatorIndexes[count - 1].Operator.Trim(); + switch (conditionOperator) + { + case "and": + searchExpression = Expression.AndAlso(searchExpression, methodCallExpression); + break; + case "or": + searchExpression = Expression.OrElse(searchExpression, methodCallExpression); + break; + default: + break; + } } + } - return finalExpression; + if (addParentObjectNullCheck) + { + // Add Null check for nested Object before checking the value of the property. + var nullCheck = Expression.NotEqual(Expression.PropertyOrField(pe, members[0]), Expression.Constant(null, typeof(object))); + nullOrEmptyCheck = Expression.Not(Expression.Call(typeof(string), typeof(string).GetMethod("IsNullOrEmpty").Name, null, propertyExp)); + finalExpression = Expression.AndAlso(nullCheck, nullOrEmptyCheck); + finalExpression = Expression.AndAlso(finalExpression, searchExpression); } + else + { + nullOrEmptyCheck = Expression.Not(Expression.Call(typeof(string), typeof(string).GetMethod("IsNullOrEmpty").Name, null, propertyExp)); + finalExpression = Expression.AndAlso(nullOrEmptyCheck, searchExpression); + } + + return finalExpression; } } \ No newline at end of file diff --git a/src/Genocs.QueryBuilder/QueryItem.cs b/src/Genocs.QueryBuilder/QueryItem.cs index 51b5466f..1ea52faf 100644 --- a/src/Genocs.QueryBuilder/QueryItem.cs +++ b/src/Genocs.QueryBuilder/QueryItem.cs @@ -1,11 +1,12 @@ namespace Genocs.QueryBuilder; /// -/// The QueryItem class +/// The QueryItem class. /// public class QueryItem { - public QueryItem(string propertyName, + public QueryItem( + string propertyName, string propertyValue, string propertyType = "string", QueryOperator operatorType = QueryOperator.Equal) @@ -16,7 +17,8 @@ public QueryItem(string propertyName, OperatorType = operatorType; } - public QueryItem(string propertyName, + public QueryItem( + string propertyName, string propertyValue, bool parentCanBeNull, string propertyType = "string", diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 3cc63f45..0dbd8904 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index a4756ef1..facc38eb 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -60,9 +60,9 @@ - + - + From 8efd5aed4024a46dcc5e14f3bf22bd063c336d59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 04:16:06 +0000 Subject: [PATCH 027/104] Bump Moq from 4.20.69 to 4.20.70 Bumps [Moq](https://github.com/moq/moq) from 4.20.69 to 4.20.70. - [Release notes](https://github.com/moq/moq/releases) - [Changelog](https://github.com/devlooped/moq/blob/main/CHANGELOG.md) - [Commits](https://github.com/moq/moq/compare/v4.20.69...v4.20.70) --- updated-dependencies: - dependency-name: Moq dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Genocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index c6e850c4..7392ed96 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -11,7 +11,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 812247f4..f2006bdc 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -12,7 +12,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + From d620e5d6d9a9d4a5abac0dde8ad3aeef3e2c42a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 03:41:33 +0000 Subject: [PATCH 028/104] Bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets Bumps Microsoft.VisualStudio.Azure.Containers.Tools.Targets from 1.19.5 to 1.19.6. --- updated-dependencies: - dependency-name: Microsoft.VisualStudio.Azure.Containers.Tools.Targets dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 19dfa7d5..a934501b 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -24,7 +24,7 @@ - + From 9eb35fad767602a64d4dbf06439ed8c7bca5de5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 03:42:37 +0000 Subject: [PATCH 029/104] Bump prometheus-net from 5.0.2 to 8.2.1 Bumps [prometheus-net](https://github.com/prometheus-net/prometheus-net) from 5.0.2 to 8.2.1. - [Release notes](https://github.com/prometheus-net/prometheus-net/releases) - [Changelog](https://github.com/prometheus-net/prometheus-net/blob/master/History) - [Commits](https://github.com/prometheus-net/prometheus-net/compare/v5.0.2...v8.2.1) --- updated-dependencies: - dependency-name: prometheus-net dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 8f9dfcf1..d33bf381 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -74,7 +74,7 @@ - + From 9d334d3912729647466c7f6d3424158a018d555f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 03:44:35 +0000 Subject: [PATCH 030/104] Bump Polly from 8.2.0 to 8.2.1 Bumps [Polly](https://github.com/App-vNext/Polly) from 8.2.0 to 8.2.1. - [Release notes](https://github.com/App-vNext/Polly/releases) - [Changelog](https://github.com/App-vNext/Polly/blob/main/CHANGELOG.md) - [Commits](https://github.com/App-vNext/Polly/compare/8.2.0...8.2.1) --- updated-dependencies: - dependency-name: Polly dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index e06ba814..72516c60 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index f34920a2..8d270ec5 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -51,7 +51,7 @@ - + From cd58c28d68e059fb6fb83db7d34debcdee5ee1b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 18:45:33 +0000 Subject: [PATCH 031/104] Bump System.IdentityModel.Tokens.Jwt in /src/Genocs.Auth Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 7.0.3 to 7.1.2. - [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases) - [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md) - [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/7.0.3...7.1.2) --- updated-dependencies: - dependency-name: System.IdentityModel.Tokens.Jwt dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/Genocs.Auth/Genocs.Auth.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 2a5afec9..4bc84788 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -65,7 +65,7 @@ - + From 9f04ab59052556b3f27aa3b377b08ed2b3e5e4b8 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 23 Jan 2024 20:21:24 +0100 Subject: [PATCH 032/104] Updated packages --- Directory.Build.props | 2 +- src/Genocs.Auth/Genocs.Auth.csproj | 4 +- src/Genocs.Auth/README.md | 19 ++++ src/Genocs.Common/Genocs.Common.csproj | 4 +- src/Genocs.Common/README.md | 19 ++++ .../Genocs.Core.UnitTests.csproj | 2 +- src/Genocs.Core/Genocs.Core.csproj | 6 +- src/Genocs.Core/README.md | 19 ++++ .../Genocs.Discovery.Consul.csproj | 2 +- src/Genocs.Discovery.Consul/README.md | 22 ++++ .../Genocs.HTTP.RestEase.csproj | 2 +- src/Genocs.HTTP.RestEase/README.md | 19 ++++ .../EmptyCorrelationContextFactory.cs | 2 +- src/Genocs.HTTP/EmptyCorrelationIdFactory.cs | 2 +- src/Genocs.HTTP/Extensions.cs | 15 ++- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- src/Genocs.HTTP/GenocsHttpClient.cs | 107 +++++++++--------- .../GenocsLoggingScopeHttpMessageHandler.cs | 46 ++++---- src/Genocs.HTTP/ICorrelationIdFactory.cs | 6 +- src/Genocs.HTTP/IHttpClientSerializer.cs | 2 +- src/Genocs.HTTP/Options/HttpClientSettings.cs | 6 +- .../SystemTextJsonHttpClientSerializer.cs | 4 +- .../Genocs.LoadBalancing.Fabio.csproj | 2 +- src/Genocs.LoadBalancing.Fabio/README.md | 19 ++++ src/Genocs.Logging/Genocs.Logging.csproj | 6 +- src/Genocs.Logging/README.md | 19 ++++ ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 2 +- .../README.md | 19 ++++ .../Genocs.MessageBrokers.Outbox.csproj | 2 +- src/Genocs.MessageBrokers.Outbox/README.md | 19 ++++ .../Extensions.cs | 4 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- src/Genocs.MessageBrokers.RabbitMQ/README.md | 19 ++++ .../Genocs.MessageBrokers.csproj | 2 +- src/Genocs.MessageBrokers/README.md | 19 ++++ .../Builders/MetricsOptionsBuilder.cs | 6 +- src/Genocs.Metrics/AppMetrics/Extensions.cs | 62 +++++----- .../AppMetrics/IMetricsOptionsBuilder.cs | 4 +- .../MetricsSettings.cs} | 6 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- src/Genocs.Metrics/Prometheus/Extensions.cs | 7 +- .../Prometheus/Internals/PrometheusJob.cs | 13 ++- .../Internals/PrometheusMiddleware.cs | 9 +- .../Prometheus/Options/PrometheusSettings.cs | 27 +++++ .../Prometheus/PrometheusOptions.cs | 11 -- src/Genocs.Metrics/README.md | 23 +++- .../Genocs.Monitoring.csproj | 2 +- src/Genocs.Monitoring/README.md | 22 ++++ ...enocs.Persistence.MongoDB.UnitTests.csproj | 4 +- .../Genocs.Persistence.MongoDb.csproj | 4 +- src/Genocs.Persistence.MongoDb/README.md | 22 ++++ .../_docs/README_NUGET.md | 22 ++++ .../Genocs.Persistence.Redis.csproj | 4 +- src/Genocs.Persistence.Redis/README.md | 19 ++++ .../Genocs.QueryBuilder.UnitTests.csproj | 4 +- .../Genocs.QueryBuilder.csproj | 2 +- src/Genocs.QueryBuilder/README.md | 19 ++++ .../Genocs.Secrets.Vault.csproj | 2 +- .../Options/VaultSettings.cs | 25 ++-- src/Genocs.Secrets.Vault/README.md | 19 ++++ src/Genocs.Security/Genocs.Security.csproj | 2 +- src/Genocs.Security/README.md | 19 ++++ .../Genocs.ServiceBusAzure.UnitTests.csproj | 2 +- .../Genocs.ServiceBusAzure.csproj | 4 +- src/Genocs.ServiceBusAzure/README.md | 19 ++++ .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 2 +- src/Genocs.Tracing.Jaeger.RabbitMQ/README.md | 19 ++++ src/Genocs.Tracing/Genocs.Tracing.csproj | 4 +- src/Genocs.Tracing/README.md | 19 ++++ .../Genocs.WebApi.CQRS.csproj | 2 +- src/Genocs.WebApi.CQRS/README.md | 19 ++++ .../Genocs.WebApi.Security.csproj | 2 +- src/Genocs.WebApi.Security/README.md | 19 ++++ .../Genocs.WebApi.Swagger.csproj | 2 +- src/Genocs.WebApi.Swagger/README.md | 19 ++++ src/Genocs.WebApi/Genocs.WebApi.csproj | 2 +- src/Genocs.WebApi/README.md | 19 ++++ 77 files changed, 747 insertions(+), 213 deletions(-) rename src/Genocs.Metrics/AppMetrics/{MetricsOptions.cs => Options/MetricsSettings.cs} (91%) create mode 100644 src/Genocs.Metrics/Prometheus/Options/PrometheusSettings.cs delete mode 100644 src/Genocs.Metrics/Prometheus/PrometheusOptions.cs diff --git a/Directory.Build.props b/Directory.Build.props index 21248176..115be95f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 4bc84788..eab733fd 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git @@ -65,7 +65,7 @@ - + diff --git a/src/Genocs.Auth/README.md b/src/Genocs.Auth/README.md index fbd670e5..bb642339 100644 --- a/src/Genocs.Auth/README.md +++ b/src/Genocs.Auth/README.md @@ -37,6 +37,25 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index f1c0bc79..3ce81b20 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + netstandard2.1;net6.0;net7.0;net8.0 Genocs.Common Genocs.Common Genocs.Common @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.Common/README.md b/src/Genocs.Common/README.md index a40658e7..db3b92d4 100644 --- a/src/Genocs.Common/README.md +++ b/src/Genocs.Common/README.md @@ -15,6 +15,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index ca43f1f3..822be4c7 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -8,7 +8,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 0f732b03..e1e67708 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git @@ -57,12 +57,12 @@ - + - + diff --git a/src/Genocs.Core/README.md b/src/Genocs.Core/README.md index 66ce6efb..2683d26d 100644 --- a/src/Genocs.Core/README.md +++ b/src/Genocs.Core/README.md @@ -15,6 +15,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 74416868..d1b22aa1 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.Discovery.Consul/README.md b/src/Genocs.Discovery.Consul/README.md index a9b80e9f..6ffbc96c 100644 --- a/src/Genocs.Discovery.Consul/README.md +++ b/src/Genocs.Discovery.Consul/README.md @@ -15,6 +15,28 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-10-13] 5.0.0-preview.5.0 - Added [editorconfig](https://editorconfig.org/) - Added StyleCop diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 7e61a45b..ebc40049 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.HTTP.RestEase/README.md b/src/Genocs.HTTP.RestEase/README.md index 782ef191..6ffbc96c 100644 --- a/src/Genocs.HTTP.RestEase/README.md +++ b/src/Genocs.HTTP.RestEase/README.md @@ -15,6 +15,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.HTTP/EmptyCorrelationContextFactory.cs b/src/Genocs.HTTP/EmptyCorrelationContextFactory.cs index aa3b6133..cc9cbb7b 100644 --- a/src/Genocs.HTTP/EmptyCorrelationContextFactory.cs +++ b/src/Genocs.HTTP/EmptyCorrelationContextFactory.cs @@ -2,5 +2,5 @@ namespace Genocs.HTTP; internal class EmptyCorrelationContextFactory : ICorrelationContextFactory { - public string Create() => default; + public string Create() => default!; } \ No newline at end of file diff --git a/src/Genocs.HTTP/EmptyCorrelationIdFactory.cs b/src/Genocs.HTTP/EmptyCorrelationIdFactory.cs index 75f26d6f..574c9375 100644 --- a/src/Genocs.HTTP/EmptyCorrelationIdFactory.cs +++ b/src/Genocs.HTTP/EmptyCorrelationIdFactory.cs @@ -3,7 +3,7 @@ namespace Genocs.HTTP; internal class EmptyCorrelationIdFactory : ICorrelationIdFactory { /// - /// CorrelationIdFactory, empty implementation + /// CorrelationIdFactory, empty implementation. /// /// public string? Create() => default; diff --git a/src/Genocs.HTTP/Extensions.cs b/src/Genocs.HTTP/Extensions.cs index 699a5819..13238b93 100644 --- a/src/Genocs.HTTP/Extensions.cs +++ b/src/Genocs.HTTP/Extensions.cs @@ -8,7 +8,7 @@ namespace Genocs.HTTP; /// -/// The HTTP client extensions +/// The HTTP client extensions. /// public static class Extensions { @@ -16,10 +16,12 @@ public static class Extensions private const string RegistryName = "http.client"; private const string ClientName = "genocs"; - - public static IGenocsBuilder AddHttpClient(this IGenocsBuilder builder, string clientName = ClientName, - IEnumerable? maskedRequestUrlParts = null, string sectionName = SectionName, - Action? httpClientBuilder = null) + public static IGenocsBuilder AddHttpClient( + this IGenocsBuilder builder, + string clientName = ClientName, + IEnumerable? maskedRequestUrlParts = null, + string sectionName = SectionName, + Action? httpClientBuilder = null) { if (string.IsNullOrWhiteSpace(sectionName)) { @@ -79,7 +81,8 @@ public static void RemoveHttpClient(this IGenocsBuilder builder) { var registryType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()) .SingleOrDefault(t => t.Name == "HttpClientMappingRegistry"); - var registry = builder.Services.SingleOrDefault(s => s.ServiceType == registryType)?.ImplementationInstance; + + object? registry = builder.Services.SingleOrDefault(s => s.ServiceType == registryType)?.ImplementationInstance; var registrations = registry?.GetType().GetProperty("TypedClientRegistrations"); var clientRegistrations = registrations?.GetValue(registry) as IDictionary; clientRegistrations?.Remove(typeof(IHttpClient)); diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 72516c60..dc627bbb 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.HTTP/GenocsHttpClient.cs b/src/Genocs.HTTP/GenocsHttpClient.cs index 6437f934..c407de2a 100644 --- a/src/Genocs.HTTP/GenocsHttpClient.cs +++ b/src/Genocs.HTTP/GenocsHttpClient.cs @@ -6,7 +6,7 @@ namespace Genocs.HTTP; /// -/// The Genocs Http Client +/// The Genocs Http Client. /// public class GenocsHttpClient : IHttpClient { @@ -15,106 +15,103 @@ public class GenocsHttpClient : IHttpClient private readonly HttpClientSettings _options; private readonly IHttpClientSerializer _serializer; - public GenocsHttpClient(HttpClient client, HttpClientSettings options, IHttpClientSerializer serializer, - ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) + public GenocsHttpClient( + HttpClient client, + HttpClientSettings options, + IHttpClientSerializer serializer, + ICorrelationContextFactory correlationContextFactory, + ICorrelationIdFactory correlationIdFactory) { _client = client; _options = options; _serializer = serializer; if (!string.IsNullOrWhiteSpace(_options.CorrelationContextHeader)) { - var correlationContext = correlationContextFactory.Create(); - _client.DefaultRequestHeaders.TryAddWithoutValidation(_options.CorrelationContextHeader, - correlationContext); + string correlationContext = correlationContextFactory.Create(); + _client.DefaultRequestHeaders.TryAddWithoutValidation( + _options.CorrelationContextHeader, + correlationContext); } if (!string.IsNullOrWhiteSpace(_options.CorrelationIdHeader)) { - var correlationId = correlationIdFactory.Create(); - _client.DefaultRequestHeaders.TryAddWithoutValidation(_options.CorrelationIdHeader, - correlationId); + string? correlationId = correlationIdFactory.Create(); + _client.DefaultRequestHeaders.TryAddWithoutValidation( + _options.CorrelationIdHeader, + correlationId); } } public virtual Task GetAsync(string uri) => SendAsync(uri, Method.Get); - public virtual Task GetAsync(string uri, IHttpClientSerializer serializer = null) + public virtual Task GetAsync(string uri, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Get, serializer: serializer); - public Task> GetResultAsync(string uri, IHttpClientSerializer serializer = null) + public Task> GetResultAsync(string uri, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Get, serializer: serializer); - public virtual Task PostAsync(string uri, object data = null, - IHttpClientSerializer serializer = null) + public virtual Task PostAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Post, GetJsonPayload(data, serializer)); public Task PostAsync(string uri, HttpContent content) => SendAsync(uri, Method.Post, content); - public virtual Task PostAsync(string uri, object data = null, IHttpClientSerializer serializer = null) + public virtual Task PostAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Post, GetJsonPayload(data, serializer)); - public Task PostAsync(string uri, HttpContent content, IHttpClientSerializer serializer = null) + public Task PostAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Post, content, serializer); - public Task> PostResultAsync(string uri, object data = null, - IHttpClientSerializer serializer = null) + public Task> PostResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Post, GetJsonPayload(data, serializer), serializer); - public Task> PostResultAsync(string uri, HttpContent content, - IHttpClientSerializer serializer = null) + public Task> PostResultAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Post, content, serializer); - public virtual Task PutAsync(string uri, object data = null, - IHttpClientSerializer serializer = null) + public virtual Task PutAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Put, GetJsonPayload(data, serializer)); public Task PutAsync(string uri, HttpContent content) => SendAsync(uri, Method.Put, content); - public virtual Task PutAsync(string uri, object data = null, IHttpClientSerializer serializer = null) + public virtual Task PutAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Put, GetJsonPayload(data, serializer), serializer); - public Task PutAsync(string uri, HttpContent content, IHttpClientSerializer serializer = null) + public Task PutAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Put, content, serializer); - public Task> PutResultAsync(string uri, object data = null, - IHttpClientSerializer serializer = null) + public Task> PutResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Put, GetJsonPayload(data, serializer), serializer); - public Task> PutResultAsync(string uri, HttpContent content, - IHttpClientSerializer serializer = null) + public Task> PutResultAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Put, content, serializer); - public Task PatchAsync(string uri, object data = null, - IHttpClientSerializer serializer = null) + public Task PatchAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Patch, GetJsonPayload(data, serializer)); public Task PatchAsync(string uri, HttpContent content) => SendAsync(uri, Method.Patch, content); - public Task PatchAsync(string uri, object data = null, IHttpClientSerializer serializer = null) + public Task PatchAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Patch, GetJsonPayload(data, serializer)); - public Task PatchAsync(string uri, HttpContent content, IHttpClientSerializer serializer = null) + public Task PatchAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Patch, content, serializer); - public Task> PatchResultAsync(string uri, object data = null, - IHttpClientSerializer serializer = null) + public Task> PatchResultAsync(string uri, object? data = null, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Patch, GetJsonPayload(data, serializer)); - public Task> PatchResultAsync(string uri, HttpContent content, - IHttpClientSerializer serializer = null) + public Task> PatchResultAsync(string uri, HttpContent content, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Patch, content, serializer); public virtual Task DeleteAsync(string uri) => SendAsync(uri, Method.Delete); - public Task DeleteAsync(string uri, IHttpClientSerializer serializer = null) + public Task DeleteAsync(string uri, IHttpClientSerializer? serializer = null) => SendAsync(uri, Method.Delete, serializer: serializer); - public Task> DeleteResultAsync(string uri, IHttpClientSerializer serializer = null) + public Task> DeleteResultAsync(string uri, IHttpClientSerializer? serializer = null) => SendResultAsync(uri, Method.Delete, serializer: serializer); public Task SendAsync(HttpRequestMessage request) @@ -122,7 +119,7 @@ public Task SendAsync(HttpRequestMessage request) .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(() => _client.SendAsync(request)); - public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer serializer = null) + public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null) => Policy.Handle() .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(async () => @@ -130,7 +127,7 @@ public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer se var response = await _client.SendAsync(request); if (!response.IsSuccessStatusCode) { - return default; + return default!; } var stream = await response.Content.ReadAsStreamAsync(); @@ -138,8 +135,7 @@ public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer se return await DeserializeJsonFromStream(stream, serializer); }); - public Task> SendResultAsync(HttpRequestMessage request, - IHttpClientSerializer serializer = null) + public Task> SendResultAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null) => Policy.Handle() .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(async () => @@ -147,7 +143,7 @@ public Task> SendResultAsync(HttpRequestMessage request, var response = await _client.SendAsync(request); if (!response.IsSuccessStatusCode) { - return new HttpResult(default, response); + return new HttpResult(default!, response); } var stream = await response.Content.ReadAsStreamAsync(); @@ -176,13 +172,12 @@ public void SetHeaders(IDictionary headers) public void SetHeaders(Action headers) => headers?.Invoke(_client.DefaultRequestHeaders); - protected virtual async Task SendAsync(string uri, Method method, HttpContent content = null, - IHttpClientSerializer serializer = null) + protected virtual async Task SendAsync(string uri, Method method, HttpContent? content = null, IHttpClientSerializer? serializer = null) { var response = await SendAsync(uri, method, content); if (!response.IsSuccessStatusCode) { - return default; + return default!; } var stream = await response.Content.ReadAsStreamAsync(); @@ -190,13 +185,16 @@ protected virtual async Task SendAsync(string uri, Method method, HttpCont return await DeserializeJsonFromStream(stream, serializer); } - protected virtual async Task> SendResultAsync(string uri, Method method, - HttpContent content = null, IHttpClientSerializer serializer = null) + protected virtual async Task> SendResultAsync( + string uri, + Method method, + HttpContent? content = null, + IHttpClientSerializer? serializer = null) { var response = await SendAsync(uri, method, content); if (!response.IsSuccessStatusCode) { - return new HttpResult(default, response); + return new HttpResult(default!, response); } var stream = await response.Content.ReadAsStreamAsync(); @@ -205,18 +203,17 @@ protected virtual async Task> SendResultAsync(string uri, Metho return new HttpResult(result, response); } - protected virtual Task SendAsync(string uri, Method method, HttpContent content = null) + protected virtual Task SendAsync(string uri, Method method, HttpContent? content = null) => Policy.Handle() .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(() => { - var requestUri = uri.StartsWith("http") ? uri : $"http://{uri}"; + string requestUri = uri.StartsWith("http") ? uri : $"http://{uri}"; return GetResponseAsync(requestUri, method, content); }); - protected virtual Task GetResponseAsync(string uri, Method method, - HttpContent content = null) + protected virtual Task GetResponseAsync(string uri, Method method, HttpContent? content = null) => method switch { Method.Get => _client.GetAsync(uri), @@ -227,7 +224,7 @@ protected virtual Task GetResponseAsync(string uri, Method _ => throw new InvalidOperationException($"Unsupported HTTP method: {method}") }; - protected StringContent GetJsonPayload(object data, IHttpClientSerializer serializer = null) + protected StringContent? GetJsonPayload(object? data, IHttpClientSerializer? serializer = null) { if (data is null) { @@ -244,11 +241,11 @@ protected StringContent GetJsonPayload(object data, IHttpClientSerializer serial return content; } - protected async Task DeserializeJsonFromStream(Stream stream, IHttpClientSerializer serializer = null) + protected async Task DeserializeJsonFromStream(Stream stream, IHttpClientSerializer? serializer = null) { if (stream is null || stream.CanRead is false) { - return default; + return default!; } serializer ??= _serializer; diff --git a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs index 69231530..529f245f 100644 --- a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs +++ b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs @@ -21,8 +21,7 @@ public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientSettings o : options.RequestMasking.MaskTemplate; } - protected override async Task SendAsync(HttpRequestMessage request, - CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request is null) { @@ -47,31 +46,30 @@ private static class EventIds public static readonly EventId PipelineEnd = new(101, "RequestPipelineEnd"); } - private static readonly Func _beginRequestPipelineScope = - LoggerMessage.DefineScope( - "HTTP {HttpMethod} {Uri}"); + private static readonly Func _beginRequestPipelineScope = + LoggerMessage.DefineScope("HTTP {HttpMethod} {Uri}"); private static readonly Action _requestPipelineStart = - LoggerMessage.Define( - LogLevel.Information, - EventIds.PipelineStart, - "Start processing HTTP request {HttpMethod} {Uri}"); - - private static readonly Action _requestPipelineEnd = - LoggerMessage.Define( - LogLevel.Information, - EventIds.PipelineEnd, - "End processing HTTP request - {StatusCode}"); - - public static IDisposable BeginRequestPipelineScope(ILogger logger, HttpRequestMessage request, - ISet maskedRequestUrlParts, string maskTemplate) + LoggerMessage.Define(LogLevel.Information, EventIds.PipelineStart, "Start processing HTTP request {HttpMethod} {Uri}"); + + private static readonly Action _requestPipelineEnd = + LoggerMessage.Define(LogLevel.Information, EventIds.PipelineEnd, "End processing HTTP request - {StatusCode}"); + + public static IDisposable BeginRequestPipelineScope( + ILogger logger, + HttpRequestMessage request, + ISet maskedRequestUrlParts, + string maskTemplate) { var uri = MaskUri(request.RequestUri, maskedRequestUrlParts, maskTemplate); return _beginRequestPipelineScope(logger, request.Method, uri); } - public static void RequestPipelineStart(ILogger logger, HttpRequestMessage request, - ISet maskedRequestUrlParts, string maskTemplate) + public static void RequestPipelineStart( + ILogger logger, + HttpRequestMessage request, + ISet maskedRequestUrlParts, + string maskTemplate) { var uri = MaskUri(request.RequestUri, maskedRequestUrlParts, maskTemplate); _requestPipelineStart(logger, request.Method, uri, null); @@ -82,16 +80,16 @@ public static void RequestPipelineEnd(ILogger logger, HttpResponseMessage respon _requestPipelineEnd(logger, response.StatusCode, null); } - private static Uri MaskUri(Uri uri, ISet maskedRequestUrlParts, string maskTemplate) + private static Uri? MaskUri(Uri? uri, ISet maskedRequestUrlParts, string maskTemplate) { if (!maskedRequestUrlParts.Any()) { return uri; } - var requestUri = uri.OriginalString; - var hasMatch = false; - foreach (var part in maskedRequestUrlParts) + string? requestUri = uri?.OriginalString; + bool hasMatch = false; + foreach (string part in maskedRequestUrlParts) { if (string.IsNullOrWhiteSpace(part)) { diff --git a/src/Genocs.HTTP/ICorrelationIdFactory.cs b/src/Genocs.HTTP/ICorrelationIdFactory.cs index d516564f..4580c4dc 100644 --- a/src/Genocs.HTTP/ICorrelationIdFactory.cs +++ b/src/Genocs.HTTP/ICorrelationIdFactory.cs @@ -1,13 +1,13 @@ namespace Genocs.HTTP; /// -/// Generic CorrelationId Factory interface +/// Generic CorrelationId Factory interface. /// public interface ICorrelationIdFactory { /// - /// Create a correlationId + /// Create a correlationId. /// /// - string? Create(); + string Create(); } \ No newline at end of file diff --git a/src/Genocs.HTTP/IHttpClientSerializer.cs b/src/Genocs.HTTP/IHttpClientSerializer.cs index f95e6517..2bba0792 100644 --- a/src/Genocs.HTTP/IHttpClientSerializer.cs +++ b/src/Genocs.HTTP/IHttpClientSerializer.cs @@ -3,5 +3,5 @@ public interface IHttpClientSerializer { string Serialize(T value); - ValueTask DeserializeAsync(Stream stream); + ValueTask DeserializeAsync(Stream stream); } \ No newline at end of file diff --git a/src/Genocs.HTTP/Options/HttpClientSettings.cs b/src/Genocs.HTTP/Options/HttpClientSettings.cs index d42d35ef..8c775602 100644 --- a/src/Genocs.HTTP/Options/HttpClientSettings.cs +++ b/src/Genocs.HTTP/Options/HttpClientSettings.cs @@ -6,8 +6,8 @@ namespace Genocs.HTTP.Options; public class HttpClientSettings { /// - /// It defines if set consul as service discovery or fabio as load balancer. - /// Allowed values are: consul, fabio + /// It defines if set consul as service discovery or Fabio as load balancer. + /// Allowed values are: consul, Fabio. /// public string? Type { get; set; } @@ -19,7 +19,7 @@ public class HttpClientSettings /// /// It defines the list of services to be registered. /// - public IDictionary Services { get; set; } + public IDictionary? Services { get; set; } public RequestMaskingSettings RequestMasking { get; set; } public bool RemoveCharsetFromContentType { get; set; } public string CorrelationContextHeader { get; set; } diff --git a/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs b/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs index c66665e2..accab9d4 100644 --- a/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs +++ b/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs @@ -7,7 +7,7 @@ public class SystemTextJsonHttpClientSerializer : IHttpClientSerializer { private readonly JsonSerializerOptions _options; - public SystemTextJsonHttpClientSerializer(JsonSerializerOptions options = null) + public SystemTextJsonHttpClientSerializer(JsonSerializerOptions? options = null) { _options = options ?? new JsonSerializerOptions { @@ -20,5 +20,5 @@ public SystemTextJsonHttpClientSerializer(JsonSerializerOptions options = null) public string Serialize(T value) => JsonSerializer.Serialize(value, _options); - public ValueTask DeserializeAsync(Stream stream) => JsonSerializer.DeserializeAsync(stream, _options); + public ValueTask DeserializeAsync(Stream stream) => JsonSerializer.DeserializeAsync(stream, _options); } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index a3d28122..9300fa11 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.LoadBalancing.Fabio/README.md b/src/Genocs.LoadBalancing.Fabio/README.md index 782ef191..6ffbc96c 100644 --- a/src/Genocs.LoadBalancing.Fabio/README.md +++ b/src/Genocs.LoadBalancing.Fabio/README.md @@ -15,6 +15,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index c42283c1..7b61f72a 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git @@ -51,7 +51,7 @@ - + @@ -60,7 +60,7 @@ - + diff --git a/src/Genocs.Logging/README.md b/src/Genocs.Logging/README.md index 0f7a9e47..3c23f07b 100644 --- a/src/Genocs.Logging/README.md +++ b/src/Genocs.Logging/README.md @@ -22,6 +22,25 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 2a5c634e..05c831d0 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md b/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 7f8e0281..85bf7181 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.MessageBrokers.Outbox/README.md b/src/Genocs.MessageBrokers.Outbox/README.md index d1b09884..f1a3ae5a 100644 --- a/src/Genocs.MessageBrokers.Outbox/README.md +++ b/src/Genocs.MessageBrokers.Outbox/README.md @@ -26,6 +26,25 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs index e34149aa..18093103 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs @@ -28,8 +28,8 @@ public static class Extensions /// /// AddRabbitMq extension method. /// - /// - /// + /// The builder. + /// the default section name. /// /// /// diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 8d270ec5..e9428587 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.MessageBrokers.RabbitMQ/README.md b/src/Genocs.MessageBrokers.RabbitMQ/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/README.md +++ b/src/Genocs.MessageBrokers.RabbitMQ/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index a09c5597..cdc92fba 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.MessageBrokers/README.md b/src/Genocs.MessageBrokers/README.md index d9e79ee9..38b40df2 100644 --- a/src/Genocs.MessageBrokers/README.md +++ b/src/Genocs.MessageBrokers/README.md @@ -33,6 +33,25 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs index d3ab3fc7..ffd23f2e 100644 --- a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs +++ b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs @@ -1,8 +1,10 @@ +using Genocs.Metrics.AppMetrics.Options; + namespace Genocs.Metrics.AppMetrics.Builders; internal sealed class MetricsOptionsBuilder : IMetricsOptionsBuilder { - private readonly MetricsOptions _options = new(); + private readonly MetricsSettings _options = new(); public IMetricsOptionsBuilder Enable(bool enabled) { @@ -52,6 +54,6 @@ public IMetricsOptionsBuilder WithTags(IDictionary tags) return this; } - public MetricsOptions Build() + public MetricsSettings Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index facb15b8..446ebf52 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -8,6 +8,7 @@ using Genocs.Core.Builders; using Genocs.Metrics.AppMetrics; using Genocs.Metrics.AppMetrics.Builders; +using Genocs.Metrics.AppMetrics.Options; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -18,14 +19,17 @@ namespace Genocs.Metrics.AppMetrics; public static class Extensions { - private static bool _initialized; private const string MetricsSectionName = "metrics"; private const string AppSectionName = "app"; private const string RegistryName = "metrics.metrics"; + private static bool _initialized; + [Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] - public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, - string metricsSectionName = MetricsSectionName, string appSectionName = AppSectionName) + public static IGenocsBuilder AddMetrics( + this IGenocsBuilder builder, + string metricsSectionName = MetricsSectionName, + string appSectionName = AppSectionName) { if (string.IsNullOrWhiteSpace(metricsSectionName)) { @@ -37,15 +41,17 @@ public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, appSectionName = AppSettings.Position; } - var metricsOptions = builder.GetOptions(metricsSectionName); + var metricsOptions = builder.GetOptions(metricsSectionName); var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); } [Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] - public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, - Func buildOptions, string appSectionName = AppSectionName) + public static IGenocsBuilder AddMetrics( + this IGenocsBuilder builder, + Func buildOptions, + string appSectionName = AppSectionName) { if (string.IsNullOrWhiteSpace(appSectionName)) { @@ -59,8 +65,10 @@ public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, } [Description("For the time being it sets Kestrel's and IIS ServerOptions AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] - public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, MetricsOptions metricsOptions, - AppSettings appOptions) + public static IGenocsBuilder AddMetrics( + this IGenocsBuilder builder, + MetricsSettings metricsOptions, + AppSettings appOptions) { builder.Services.AddSingleton(metricsOptions); if (!builder.TryRegister(RegistryName) || !metricsOptions.Enabled || _initialized) @@ -78,9 +86,9 @@ public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, MetricsOpti return; } - tags.TryGetValue("app", out var app); - tags.TryGetValue("env", out var env); - tags.TryGetValue("server", out var server); + tags.TryGetValue("app", out string? app); + tags.TryGetValue("env", out string? env); + tags.TryGetValue("server", out string? server); cfg.AddAppTag(string.IsNullOrWhiteSpace(app) ? appOptions.Service : app); cfg.AddEnvTag(string.IsNullOrWhiteSpace(env) ? null : env); cfg.AddServerTag(string.IsNullOrWhiteSpace(server) ? null : server); @@ -139,7 +147,22 @@ public static IGenocsBuilder AddMetrics(this IGenocsBuilder builder, MetricsOpti return builder; } - private static MetricsWebHostOptions GetMetricsWebHostOptions(MetricsOptions metricsOptions) + public static IApplicationBuilder UseMetrics(this IApplicationBuilder app) + { + MetricsOptions options; + using (var scope = app.ApplicationServices.CreateScope()) + { + options = scope.ServiceProvider.GetRequiredService(); + } + + return !options.Enabled + ? app + : app.UseHealthAllEndpoints() + .UseMetricsAllEndpoints() + .UseMetricsAllMiddleware(); + } + + private static MetricsWebHostOptions GetMetricsWebHostOptions(MetricsSettings metricsOptions) { var options = new MetricsWebHostOptions(); @@ -170,19 +193,4 @@ private static MetricsWebHostOptions GetMetricsWebHostOptions(MetricsOptions met return options; } - - public static IApplicationBuilder UseMetrics(this IApplicationBuilder app) - { - MetricsOptions options; - using (var scope = app.ApplicationServices.CreateScope()) - { - options = scope.ServiceProvider.GetRequiredService(); - } - - return !options.Enabled - ? app - : app.UseHealthAllEndpoints() - .UseMetricsAllEndpoints() - .UseMetricsAllMiddleware(); - } } \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs index cfbaf375..dff0200c 100644 --- a/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs +++ b/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs @@ -1,3 +1,5 @@ +using Genocs.Metrics.AppMetrics.Options; + namespace Genocs.Metrics.AppMetrics; public interface IMetricsOptionsBuilder @@ -10,5 +12,5 @@ public interface IMetricsOptionsBuilder IMetricsOptionsBuilder WithDatabase(string database); IMetricsOptionsBuilder WithInterval(int interval); IMetricsOptionsBuilder WithTags(IDictionary tags); - MetricsOptions Build(); + MetricsSettings Build(); } \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/MetricsOptions.cs b/src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs similarity index 91% rename from src/Genocs.Metrics/AppMetrics/MetricsOptions.cs rename to src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs index 41095f89..19f0144c 100644 --- a/src/Genocs.Metrics/AppMetrics/MetricsOptions.cs +++ b/src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs @@ -1,9 +1,9 @@ -namespace Genocs.Metrics.AppMetrics; +namespace Genocs.Metrics.AppMetrics.Options; /// -/// The MetricsOptions class. +/// The MetricsSettings class. /// -public class MetricsOptions +public class MetricsSettings { /// /// Default section name. diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index d33bf381..ae3db412 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.Metrics/Prometheus/Extensions.cs b/src/Genocs.Metrics/Prometheus/Extensions.cs index a5f744ad..0e7e4bec 100644 --- a/src/Genocs.Metrics/Prometheus/Extensions.cs +++ b/src/Genocs.Metrics/Prometheus/Extensions.cs @@ -1,5 +1,6 @@ using Genocs.Core.Builders; using Genocs.Metrics.Prometheus.Internals; +using Genocs.Metrics.Prometheus.Options; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Prometheus; @@ -11,7 +12,7 @@ public static class Extensions { public static IGenocsBuilder AddPrometheus(this IGenocsBuilder builder) { - var prometheusOptions = builder.GetOptions("prometheus"); + var prometheusOptions = builder.GetOptions("prometheus"); builder.Services.AddSingleton(prometheusOptions); if (!prometheusOptions.Enabled) { @@ -27,13 +28,13 @@ public static IGenocsBuilder AddPrometheus(this IGenocsBuilder builder) public static IApplicationBuilder UsePrometheus(this IApplicationBuilder app) { - var options = app.ApplicationServices.GetRequiredService(); + var options = app.ApplicationServices.GetRequiredService(); if (!options.Enabled) { return app; } - var endpoint = string.IsNullOrWhiteSpace(options.Endpoint) ? "/metrics" : + string endpoint = string.IsNullOrWhiteSpace(options.Endpoint) ? "/metrics" : options.Endpoint.StartsWith("/") ? options.Endpoint : $"/{options.Endpoint}"; return app diff --git a/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs b/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs index 5aab3ed1..ac4f209e 100644 --- a/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs +++ b/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs @@ -1,27 +1,28 @@ -using Microsoft.Extensions.Hosting; +using Genocs.Metrics.Prometheus.Options; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Prometheus.DotNetRuntime; namespace Genocs.Metrics.Prometheus.Internals; /// -/// The PrometheusJob that fetch metrix for Prometheus +/// The PrometheusJob that fetch metrics for Prometheus. /// internal sealed class PrometheusJob : IHostedService { - private IDisposable? _collector; private readonly ILogger _logger; private readonly bool _enabled; + private IDisposable? _collector; /// - /// Default PrometheusJob Constructor + /// Default PrometheusJob Constructor. /// /// /// - public PrometheusJob(PrometheusOptions options, ILogger logger) + public PrometheusJob(PrometheusSettings options, ILogger logger) { _enabled = options.Enabled; - _logger = logger; + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger.LogInformation($"Prometheus integration is {(_enabled ? "enabled" : "disabled")}."); } diff --git a/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs b/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs index 624538eb..e4b90a57 100644 --- a/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs +++ b/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Http; +using Genocs.Metrics.Prometheus.Options; +using Microsoft.AspNetCore.Http; namespace Genocs.Metrics.Prometheus.Internals; @@ -6,9 +7,9 @@ internal sealed class PrometheusMiddleware : IMiddleware { private readonly ISet _allowedHosts; private readonly string _endpoint; - private readonly string _apiKey; + private readonly string? _apiKey; - public PrometheusMiddleware(PrometheusOptions options) + public PrometheusMiddleware(PrometheusSettings options) { _allowedHosts = new HashSet(options.AllowedHosts ?? Array.Empty()); _endpoint = string.IsNullOrWhiteSpace(options.Endpoint) ? "/metrics" : @@ -34,7 +35,7 @@ public Task InvokeAsync(HttpContext context, RequestDelegate next) return next(context); } - var host = context.Request.Host.Host; + string host = context.Request.Host.Host; if (_allowedHosts.Contains(host)) { return next(context); diff --git a/src/Genocs.Metrics/Prometheus/Options/PrometheusSettings.cs b/src/Genocs.Metrics/Prometheus/Options/PrometheusSettings.cs new file mode 100644 index 00000000..c8c68104 --- /dev/null +++ b/src/Genocs.Metrics/Prometheus/Options/PrometheusSettings.cs @@ -0,0 +1,27 @@ +namespace Genocs.Metrics.Prometheus.Options; + +/// +/// The Prometheus Setting definition. +/// +public class PrometheusSettings +{ + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } + + /// + /// The Prometheus endpoint. + /// + public string? Endpoint { get; set; } + + /// + /// The Prometheus ApiKey. + /// + public string? ApiKey { get; set; } + + /// + /// The Prometheus AllowedHosts. + /// + public IEnumerable? AllowedHosts { get; set; } +} \ No newline at end of file diff --git a/src/Genocs.Metrics/Prometheus/PrometheusOptions.cs b/src/Genocs.Metrics/Prometheus/PrometheusOptions.cs deleted file mode 100644 index f962e198..00000000 --- a/src/Genocs.Metrics/Prometheus/PrometheusOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Genocs.Metrics.Prometheus; - -public class PrometheusOptions -{ - public bool Enabled { get; set; } - public string Endpoint { get; set; } - public string ApiKey { get; set; } - public IEnumerable AllowedHosts { get; set; } -} \ No newline at end of file diff --git a/src/Genocs.Metrics/README.md b/src/Genocs.Metrics/README.md index 93568a5e..98dc7734 100644 --- a/src/Genocs.Metrics/README.md +++ b/src/Genocs.Metrics/README.md @@ -1,12 +1,12 @@ # .NET Core Base library This package contains a set of base functionalities designed by Genocs. -The libraries are built using .NET standard 2.1. +The libraries are built using .NET8 ## Description -Core NuGet package contains general purpose functionalities to be used on DDD services. +Genocs.Metrics NuGet package contains general purpose functionalities to be used on DDD services. ## Support @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 34f8e5a1..98a95250 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.Monitoring/README.md b/src/Genocs.Monitoring/README.md index 4ee8ba10..d21b702d 100644 --- a/src/Genocs.Monitoring/README.md +++ b/src/Genocs.Monitoring/README.md @@ -35,6 +35,28 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-03-04] 2.0.1 - Updated NuGet packages diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 7392ed96..8163801f 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -9,10 +9,10 @@ - + - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index d145e756..d757e07a 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/README.md b/src/Genocs.Persistence.MongoDb/README.md index ab91c582..a1a01d8b 100644 --- a/src/Genocs.Persistence.MongoDb/README.md +++ b/src/Genocs.Persistence.MongoDb/README.md @@ -32,6 +32,28 @@ Following is about how to setup **MongoDb** ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-03-11] 3.4.0 - Updated to Genocs.Core 3.0.0 diff --git a/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md b/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md index ab91c582..a1a01d8b 100644 --- a/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md +++ b/src/Genocs.Persistence.MongoDb/_docs/README_NUGET.md @@ -32,6 +32,28 @@ Following is about how to setup **MongoDb** ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + +### [2023-11-25] 5.0.0 +- Moved to NET8 + ### [2023-03-11] 3.4.0 - Updated to Genocs.Core 3.0.0 diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index cb25bde3..d062bc70 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/README.md b/src/Genocs.Persistence.Redis/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.Persistence.Redis/README.md +++ b/src/Genocs.Persistence.Redis/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index f2006bdc..8197dc8e 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 9bba8647..541174a7 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.QueryBuilder/README.md b/src/Genocs.QueryBuilder/README.md index 782ef191..6ffbc96c 100644 --- a/src/Genocs.QueryBuilder/README.md +++ b/src/Genocs.QueryBuilder/README.md @@ -15,6 +15,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 9de89b50..281bf019 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.Secrets.Vault/Options/VaultSettings.cs b/src/Genocs.Secrets.Vault/Options/VaultSettings.cs index ccff724f..9d0bf271 100644 --- a/src/Genocs.Secrets.Vault/Options/VaultSettings.cs +++ b/src/Genocs.Secrets.Vault/Options/VaultSettings.cs @@ -1,18 +1,17 @@ namespace Genocs.Secrets.Vault.Options; - /// -/// The vault Setting definition +/// The vault Setting definition. /// public class VaultSettings { public bool Enabled { get; set; } - public string Url { get; set; } - public string Key { get; set; } - public string AuthType { get; set; } - public string Token { get; set; } - public string Username { get; set; } - public string Password { get; set; } + public string? Url { get; set; } + public string? Key { get; set; } + public string? AuthType { get; set; } + public string? Token { get; set; } + public string? Username { get; set; } + public string? Password { get; set; } public bool RevokeLeaseOnShutdown { get; set; } public int RenewalsInterval { get; set; } public KeyValueSettings Kv { get; set; } @@ -23,17 +22,17 @@ public class KeyValueSettings { public bool Enabled { get; set; } public int EngineVersion { get; set; } = 2; - public string MountPoint { get; set; } = "kv"; - public string Path { get; set; } + public string? MountPoint { get; set; } = "kv"; + public string? Path { get; set; } public int? Version { get; set; } } public class LeaseSettings { public bool Enabled { get; set; } - public string Type { get; set; } - public string RoleName { get; set; } - public string MountPoint { get; set; } + public string? Type { get; set; } + public string? RoleName { get; set; } + public string? MountPoint { get; set; } public bool AutoRenewal { get; set; } public IDictionary Templates { get; set; } } diff --git a/src/Genocs.Secrets.Vault/README.md b/src/Genocs.Secrets.Vault/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.Secrets.Vault/README.md +++ b/src/Genocs.Secrets.Vault/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index c47d4229..63807237 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.Security/README.md b/src/Genocs.Security/README.md index c78df224..221b7883 100644 --- a/src/Genocs.Security/README.md +++ b/src/Genocs.Security/README.md @@ -15,6 +15,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 0dbd8904..625336b5 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -8,7 +8,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index cbac4eb2..364a2c6e 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git @@ -53,7 +53,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/README.md b/src/Genocs.ServiceBusAzure/README.md index f74281c4..06093b27 100644 --- a/src/Genocs.ServiceBusAzure/README.md +++ b/src/Genocs.ServiceBusAzure/README.md @@ -33,6 +33,25 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index dfc2c3eb..e757e910 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md b/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md index 782ef191..6ffbc96c 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md @@ -15,6 +15,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index facc38eb..7715409b 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git @@ -63,7 +63,7 @@ - + diff --git a/src/Genocs.Tracing/README.md b/src/Genocs.Tracing/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.Tracing/README.md +++ b/src/Genocs.Tracing/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index e7e62541..11512a6e 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.WebApi.CQRS/README.md b/src/Genocs.WebApi.CQRS/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.WebApi.CQRS/README.md +++ b/src/Genocs.WebApi.CQRS/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index b1cb0fde..50b7437e 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.WebApi.Security/README.md b/src/Genocs.WebApi.Security/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.WebApi.Security/README.md +++ b/src/Genocs.WebApi.Security/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 99821695..ae9fa8d4 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.WebApi.Swagger/README.md b/src/Genocs.WebApi.Swagger/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.WebApi.Swagger/README.md +++ b/src/Genocs.WebApi.Swagger/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index cb8cae7d..7a0ab5ff 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -13,7 +13,7 @@ 5.0.0 Nocco Giovanni Emanuele Genocs - Genocs 2023 + Genocs 2024 LICENSE https://github.com/Genocs/genocs-library https://github.com/Genocs/genocs-library.git diff --git a/src/Genocs.WebApi/README.md b/src/Genocs.WebApi/README.md index 93568a5e..cf06bc9b 100644 --- a/src/Genocs.WebApi/README.md +++ b/src/Genocs.WebApi/README.md @@ -16,6 +16,25 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + ### [2023-11-25] 5.0.0 - Moved to NET8 From c58e4a2be076f22bec1dcad16a4f4a05a8865203 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 23 Jan 2024 22:07:43 +0100 Subject: [PATCH 033/104] updates for 2024 --- .travis.yml | 4 ++-- LICENSE | 2 +- README.md | 34 +++++++++++----------------------- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6df0ef1a..8cc7e1c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,10 @@ language: csharp mono: none sudo: required dist: xenial -dotnet: 7.0.100 +dotnet: 8.0.0 branches: only: - - master + - main #- develop before_script: - chmod -R a+x scripts diff --git a/LICENSE b/LICENSE index b5d2cb0b..e9e6d445 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Genocs Services +Copyright (c) 2024 Genocs Services Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 2f8e5045..96ea5a65 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,7 @@ # Genocs .NET library - -This repo contains a set of libraries designed by Genocs. The libraries are built using .NET6 and .NET7. +This repo contains a set of libraries designed by Genocs. The library is built on top of .NET8. Packages are available on [NuGet Genocs](https://www.nuget.org/profiles/gioema_nocco). @@ -67,20 +66,21 @@ You will use ***Docker compose*** to setup the infrastructure components. ``` bash +cd ./containers # Setup the infrastructure -docker-compose -f ./containers/infrastructure-bare.yml --env-file ./containers/.env --project-name genocs-app up -d -docker-compose -f ./containers/infrastructure-monitoring.yml --env-file ./containers/.env --project-name genocs-app up -d -docker-compose -f ./containers/infrastructure-scaling.yml --env-file ./containers/.env --project-name genocs-app up -d -docker-compose -f ./containers/infrastructure-security.yml --env-file ./containers/.env --project-name genocs-app up -d +docker compose -f ./infrastructure-bare.yml --env-file ./.env --project-name genocs up -d +docker compose -f ./infrastructure-monitoring.yml --env-file ./.env --project-name genocs up -d +docker compose -f ./infrastructure-scaling.yml --env-file ./.env --project-name genocs up -d +docker compose -f ./infrastructure-security.yml --env-file ./.env --project-name genocs up -d # Use this file only in case you want to setup sqlserver database (no need if you use postgres) -docker-compose -f ./containers/infrastructure-sqlserver.yml --env-file ./containers/.env --project-name genocs-app up -d +docker compose -f ./infrastructure-sqlserver.yml --env-file ./.env --project-name genocs up -d # Use this file only in case you want to setup elk stack -docker-compose -f ./containers/infrastructure-elk.yml --env-file ./containers/.env --project-name genocs-app up -d +docker compose -f ./infrastructure-elk.yml --env-file ./.env --project-name genocs up -d # Use this file only in case you want to setup AI ML components prepared by Genocs -docker-compose -f ./containers/infrastructure-ml.yml --env-file ./containers/.env --project-name genocs-app up -d +docker compose -f ./infrastructure-ml.yml --env-file ./.env --project-name genocs up -d ``` `infrastructure-bare.yml` allows to install the basic infrastructure components. Basic components are the [RabbitMQ](https://rabbitmq.com), [Redis](https://redis.io), [Mongo](https://mongodb.com), [Postgres](https://www.postgresql.org/). @@ -128,21 +128,13 @@ networks: Remember to add the network configuration inside your docker compose file to setup the network, before running the containers. -``` yml -networks: - genocs: - name: genocs-network - external: true - driver: bridge -``` ## ***Kubernetes cluster*** You can setup the application inside a Kubernetes cluster. -Check the repo [enterprise-containers](https://github.com/Genocs/enterprise-containers) to setup a Kubernetes cluster. - -Inside the repo you can find scripts, configuration files and documentation to setup a cluster from scratch. +Check the repo [enterprise-containers](https://github.com/Genocs/enterprise-containers) to setup a Kubernetes cluster. +There you can find scripts, configuration files and documentation to setup a cluster from scratch. ## **Libraries** You can find a full documentation on: @@ -435,7 +427,6 @@ Take a look inside **./src/apps** folder. There you can find a full-fledged appl In that way you can test the entire flow. - ### How to BUILD & RUN the application The build and run process can be done by using docker-compose @@ -500,9 +491,6 @@ You can deploy Demo Application with one click in Heroku, Microsoft Azure, or Go [](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fheartexlabs%2Flabel-studio%2Fmaster%2Fazuredeploy.json) [](https://deploy.cloud.run) - - - ## License This project is licensed with the [MIT license](LICENSE). From 3d4c17e0e501d9174160f01569d2523472085a04 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 8 Feb 2024 18:53:33 +0100 Subject: [PATCH 034/104] Added documentation and more control over types --- Directory.Build.props | 2 +- .../DisabledAuthenticationPolicyEvaluator.cs | 14 +- src/Genocs.Auth/Extensions.cs | 20 +- src/Genocs.Auth/Genocs.Auth.csproj | 2 +- src/Genocs.Auth/IJwtHandler.cs | 29 +-- src/Genocs.Auth/JsonWebToken.cs | 5 +- src/Genocs.Auth/JsonWebTokenPayload.cs | 10 +- src/Genocs.Auth/JwtAuthAttribute.cs | 3 +- src/Genocs.Common/Genocs.Common.csproj | 4 +- .../Genocs.Core.UnitTests.csproj | 2 +- .../Commands/Dispatchers/CommandDispatcher.cs | 38 ++- src/Genocs.Core/CQRS/Commands/Extensions.cs | 15 +- src/Genocs.Core/CQRS/Commands/ICommand.cs | 13 +- .../CQRS/Commands/ICommandDispatcher.cs | 31 ++- .../CQRS/Commands/ICommandHandler.cs | 32 ++- src/Genocs.Core/CQRS/Commons/Extensions.cs | 16 +- src/Genocs.Core/CQRS/Commons/IDispatcher.cs | 69 +++-- .../CQRS/Commons/InMemoryDispatcher.cs | 27 +- .../Events/Dispatchers/EventDispatcher.cs | 27 +- src/Genocs.Core/CQRS/Events/Extensions.cs | 10 +- src/Genocs.Core/CQRS/Events/IEvent.cs | 2 +- .../CQRS/Events/IEventDispatcher.cs | 12 +- src/Genocs.Core/CQRS/Events/IEventHandler.cs | 8 +- src/Genocs.Core/CQRS/Events/IRejectedEvent.cs | 11 +- src/Genocs.Core/CQRS/Events/RejectedEvent.cs | 30 ++- .../Queries/Dispatchers/QueryDispatcher.cs | 62 +++-- src/Genocs.Core/CQRS/Queries/Extensions.cs | 6 +- src/Genocs.Core/CQRS/Queries/IPagedFilter.cs | 30 ++- src/Genocs.Core/CQRS/Queries/IPagedQuery.cs | 41 ++- src/Genocs.Core/CQRS/Queries/IQuery.cs | 27 +- .../CQRS/Queries/IQueryDispatcher.cs | 51 ++-- src/Genocs.Core/CQRS/Queries/IQueryHandler.cs | 33 ++- .../CQRS/Queries/PagedQueryBase.cs | 41 ++- .../CQRS/Queries/PagedQueryWithFilter.cs | 17 +- src/Genocs.Core/CQRS/Queries/PagedResult.cs | 39 +-- .../CQRS/Queries/PagedResultBase.cs | 80 +++--- src/Genocs.Core/CQRS/Queries/Request.cs | 21 +- src/Genocs.Core/Collections/ITypeList.cs | 59 +++-- src/Genocs.Core/Collections/TypeList.cs | 6 +- .../Entities/Auditing/AuditedAggregateRoot.cs | 82 +++--- .../Domain/Entities/Auditing/AuditedEntity.cs | 82 +++--- .../Auditing/CreationAuditedAggregateRoot.cs | 89 ++++--- .../Entities/Auditing/EntityAuditingHelper.cs | 188 +++++++------- .../Auditing/FullAuditedAggregateRoot.cs | 104 ++++---- .../Entities/Auditing/FullAuditedEntity.cs | 104 ++++---- .../Domain/Entities/Auditing/IFullAudited.cs | 31 ++- .../Entities/Auditing/IHasCreationTime.cs | 23 +- .../Entities/Auditing/IHasDeletionTime.cs | 21 +- src/Genocs.Core/Domain/Entities/Entity.cs | 7 +- .../IRepositoryOfTEntityAndTPrimaryKey.cs | 10 +- .../Repositories/ISupportsExplicitLoading.cs | 39 ++- .../Domain/Repositories/RepositoryBase.cs | 8 +- src/Genocs.Core/Exceptions/GenocsException.cs | 13 +- src/Genocs.Core/Extensions/Encryption.cs | 22 +- .../Extensions/ExceptionExtensions.cs | 2 +- .../Extensions/ObjectExtensions.cs | 81 +++--- .../Extensions/StringExtensions.cs | 236 +++++++++--------- src/Genocs.Core/Genocs.Core.csproj | 6 +- src/Genocs.Discovery.Consul/Extensions.cs | 26 +- .../ConsulServiceDiscoveryMessageHandler.cs | 37 +-- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 4 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- src/Genocs.MessageBrokers/IBusPublisher.cs | 10 +- src/Genocs.MessageBrokers/MessageAttribute.cs | 17 +- .../MessageProperties.cs | 8 +- src/Genocs.Metrics/AppMetrics/Extensions.cs | 1 - ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 6 +- .../Repositories/IMongoDbSeeder.cs | 2 +- .../Repositories/IMongoSessionFactory.cs | 2 +- .../Repositories/Mentor/MongoRepository.cs | 18 +- .../Genocs.QueryBuilder.UnitTests.csproj | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 2 +- src/Genocs.Tracing/Genocs.Tracing.csproj | 2 +- 75 files changed, 1102 insertions(+), 1134 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 115be95f..dfc912e7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs b/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs index 9723b386..85cc1ab8 100644 --- a/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs +++ b/src/Genocs.Auth/DisabledAuthenticationPolicyEvaluator.cs @@ -17,8 +17,11 @@ internal sealed class DisabledAuthenticationPolicyEvaluator : IPolicyEvaluator /// public Task AuthenticateAsync(AuthorizationPolicy policy, HttpContext context) { - var authenticationTicket = new AuthenticationTicket(new ClaimsPrincipal(), - new AuthenticationProperties(), JwtBearerDefaults.AuthenticationScheme); + var authenticationTicket = new AuthenticationTicket( + new ClaimsPrincipal(), + new AuthenticationProperties(), + JwtBearerDefaults.AuthenticationScheme); + return Task.FromResult(AuthenticateResult.Success(authenticationTicket)); } @@ -30,8 +33,11 @@ public Task AuthenticateAsync(AuthorizationPolicy policy, Ht /// /// /// - public Task AuthorizeAsync(AuthorizationPolicy policy, - AuthenticateResult authenticationResult, HttpContext context, object resource) + public Task AuthorizeAsync( + AuthorizationPolicy policy, + AuthenticateResult authenticationResult, + HttpContext context, + object resource) { return Task.FromResult(PolicyAuthorizationResult.Success()); } diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index eaeb7a6e..bd55671a 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -71,28 +71,28 @@ private static IGenocsBuilder AddJwt(this IGenocsBuilder builder, JwtOptions opt tokenValidationParameters.AuthenticationType = options.AuthenticationType; } - var hasCertificate = false; + bool hasCertificate = false; if (options.Certificate is not null) { X509Certificate2 certificate = null; - var password = options.Certificate.Password; - var hasPassword = !string.IsNullOrWhiteSpace(password); + string password = options.Certificate.Password; + bool hasPassword = !string.IsNullOrWhiteSpace(password); if (!string.IsNullOrWhiteSpace(options.Certificate.Location)) { certificate = hasPassword ? new X509Certificate2(options.Certificate.Location, password) : new X509Certificate2(options.Certificate.Location); - var keyType = certificate.HasPrivateKey ? "with private key" : "with public key only"; + string keyType = certificate.HasPrivateKey ? "with private key" : "with public key only"; Console.WriteLine($"Loaded X.509 certificate from location: '{options.Certificate.Location}' {keyType}."); } if (!string.IsNullOrWhiteSpace(options.Certificate.RawData)) { - var rawData = Convert.FromBase64String(options.Certificate.RawData); + byte[] rawData = Convert.FromBase64String(options.Certificate.RawData); certificate = hasPassword ? new X509Certificate2(rawData, password) : new X509Certificate2(rawData); - var keyType = certificate.HasPrivateKey ? "with private key" : "with public key only"; + string keyType = certificate.HasPrivateKey ? "with private key" : "with public key only"; Console.WriteLine($"Loaded X.509 certificate from raw data {keyType}."); } @@ -105,7 +105,7 @@ private static IGenocsBuilder AddJwt(this IGenocsBuilder builder, JwtOptions opt hasCertificate = true; tokenValidationParameters.IssuerSigningKey = new X509SecurityKey(certificate); - var actionType = certificate.HasPrivateKey ? "issuing" : "validating"; + string actionType = certificate.HasPrivateKey ? "issuing" : "validating"; Console.WriteLine($"Using X.509 certificate for {actionType} tokens."); } } @@ -117,7 +117,7 @@ private static IGenocsBuilder AddJwt(this IGenocsBuilder builder, JwtOptions opt options.Algorithm = SecurityAlgorithms.HmacSha256; } - var rawKey = Encoding.UTF8.GetBytes(options.IssuerSigningKey); + byte[] rawKey = Encoding.UTF8.GetBytes(options.IssuerSigningKey); tokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(rawKey); Console.WriteLine("Using symmetric encryption for issuing tokens."); } @@ -167,12 +167,12 @@ public static IApplicationBuilder UseAccessTokenValidator(this IApplicationBuild } /// -/// DateExtensions extension method +/// DateExtensions extension method. /// internal static class DateExtensions { /// - /// ToTimestamp support function + /// ToTimestamp support function. /// /// /// diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index eab733fd..8e08a3f7 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -65,7 +65,7 @@ - + diff --git a/src/Genocs.Auth/IJwtHandler.cs b/src/Genocs.Auth/IJwtHandler.cs index 45f3706a..5720e6fa 100644 --- a/src/Genocs.Auth/IJwtHandler.cs +++ b/src/Genocs.Auth/IJwtHandler.cs @@ -1,27 +1,28 @@ namespace Genocs.Auth; /// -/// IJwtHandler interface definition +/// IJwtHandler interface definition. /// public interface IJwtHandler { /// - /// It allows to create a new JsonWebToken + /// It allows to create a new JsonWebToken. /// - /// The userId - /// The role - /// The audience - /// The claims - /// The JsonWebToken just created - JsonWebToken CreateToken(string userId, - string? role = null, - string? audience = null, - IDictionary>? claims = null); + /// The userId. + /// The role. + /// The audience. + /// The claims. + /// The JsonWebToken just created. + JsonWebToken CreateToken( + string userId, + string? role = null, + string? audience = null, + IDictionary>? claims = null); /// - /// Get the JsonWebTokenPayload from the accessToken + /// Get the JsonWebTokenPayload from the accessToken. /// - /// The access token string value - /// The JsonWebTokenPayload + /// The access token string value. + /// The JsonWebTokenPayload. JsonWebTokenPayload? GetTokenPayload(string accessToken); } \ No newline at end of file diff --git a/src/Genocs.Auth/JsonWebToken.cs b/src/Genocs.Auth/JsonWebToken.cs index 6a3a6b66..bdf2eefc 100644 --- a/src/Genocs.Auth/JsonWebToken.cs +++ b/src/Genocs.Auth/JsonWebToken.cs @@ -1,6 +1,5 @@ namespace Genocs.Auth; - /// /// The JSON Web Token definition. /// @@ -15,7 +14,7 @@ public class JsonWebToken /// Gets or sets the refresh token. /// public string? RefreshToken { get; set; } - + /// /// Gets or sets the access token expiration. /// @@ -34,5 +33,5 @@ public class JsonWebToken /// /// The claims. /// - public IDictionary>? Claims { get; set; } + public IDictionary>? Claims { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Auth/JsonWebTokenPayload.cs b/src/Genocs.Auth/JsonWebTokenPayload.cs index 68dfe0f4..b3dcfdc1 100644 --- a/src/Genocs.Auth/JsonWebTokenPayload.cs +++ b/src/Genocs.Auth/JsonWebTokenPayload.cs @@ -1,27 +1,27 @@ namespace Genocs.Auth; /// -/// The JsonWebToken payload +/// The JsonWebToken payload. /// public class JsonWebTokenPayload { /// - /// The subject + /// The subject. /// public string? Subject { get; set; } /// - /// The Identity Role + /// The Identity Role. /// public string? Role { get; set; } /// - /// The expiration ticks + /// The expiration ticks. /// public long Expires { get; set; } /// - /// List of claims + /// List of claims. /// public IDictionary>? Claims { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Auth/JwtAuthAttribute.cs b/src/Genocs.Auth/JwtAuthAttribute.cs index c3b4715e..96439a83 100644 --- a/src/Genocs.Auth/JwtAuthAttribute.cs +++ b/src/Genocs.Auth/JwtAuthAttribute.cs @@ -4,7 +4,8 @@ public class JwtAuthAttribute : AuthAttribute { public const string AuthenticationScheme = "Bearer"; - public JwtAuthAttribute(string policy = "") : base(AuthenticationScheme, policy) + public JwtAuthAttribute(string policy = "") + : base(AuthenticationScheme, policy) { } } \ No newline at end of file diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 3ce81b20..71b4167a 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -5,8 +5,8 @@ Genocs.Common Genocs.Common Genocs.Common - The commons components library useful to build .NET Core projects. - The commons components library useful to build .NET Core projects. + The Genocs Library - Common components. + The common components to build .NET Core projects along with Genocs Library. 10.0 true 5.0.0 diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 822be4c7..5a325f34 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -7,7 +7,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core/CQRS/Commands/Dispatchers/CommandDispatcher.cs b/src/Genocs.Core/CQRS/Commands/Dispatchers/CommandDispatcher.cs index c5ae356a..86b1f6cf 100644 --- a/src/Genocs.Core/CQRS/Commands/Dispatchers/CommandDispatcher.cs +++ b/src/Genocs.Core/CQRS/Commands/Dispatchers/CommandDispatcher.cs @@ -1,26 +1,22 @@ -namespace Genocs.Core.CQRS.Commands.Dispatchers -{ - using Genocs.Core.CQRS.Commands; - using Microsoft.Extensions.DependencyInjection; - using System; - using System.Threading; - using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; - /// - /// CommandDispatcher implementation - /// - internal sealed class CommandDispatcher : ICommandDispatcher - { - private readonly IServiceProvider _serviceProvider; +namespace Genocs.Core.CQRS.Commands.Dispatchers; - public CommandDispatcher(IServiceProvider serviceProvider) - => _serviceProvider = serviceProvider; +/// +/// CommandDispatcher implementation. +/// +internal sealed class CommandDispatcher : ICommandDispatcher +{ + private readonly IServiceProvider _serviceProvider; - public async Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand - { - await using var scope = _serviceProvider.CreateAsyncScope(); - var handler = scope.ServiceProvider.GetRequiredService>(); - await handler.HandleAsync(command, cancellationToken); - } + public CommandDispatcher(IServiceProvider serviceProvider) + => _serviceProvider = serviceProvider; + + public async Task SendAsync(T command, CancellationToken cancellationToken = default) + where T : class, ICommand + { + await using var scope = _serviceProvider.CreateAsyncScope(); + var handler = scope.ServiceProvider.GetRequiredService>(); + await handler.HandleAsync(command, cancellationToken); } } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Commands/Extensions.cs b/src/Genocs.Core/CQRS/Commands/Extensions.cs index a9a15b37..84cc6b25 100644 --- a/src/Genocs.Core/CQRS/Commands/Extensions.cs +++ b/src/Genocs.Core/CQRS/Commands/Extensions.cs @@ -6,15 +6,15 @@ namespace Genocs.Core.CQRS.Commands; /// -/// Extension method +/// Extension methods. /// public static class Extensions { /// - /// AddCommandHandlers + /// Add all the Command handlers to the DI container. /// - /// - /// + /// The builder. + /// The builder to be used for chaining pattern. public static IGenocsBuilder AddCommandHandlers(this IGenocsBuilder builder) { builder.Services.Scan(s => @@ -28,14 +28,13 @@ public static IGenocsBuilder AddCommandHandlers(this IGenocsBuilder builder) } /// - /// AddInMemoryCommandDispatcher + /// Add the In Memory command dispatcher to the DI container. /// - /// - /// + /// The builder. + /// The builder to be used for chaining pattern. public static IGenocsBuilder AddInMemoryCommandDispatcher(this IGenocsBuilder builder) { builder.Services.AddSingleton(); return builder; - } } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Commands/ICommand.cs b/src/Genocs.Core/CQRS/Commands/ICommand.cs index 1e359e23..cc3cbe15 100644 --- a/src/Genocs.Core/CQRS/Commands/ICommand.cs +++ b/src/Genocs.Core/CQRS/Commands/ICommand.cs @@ -1,9 +1,8 @@ -namespace Genocs.Core.CQRS.Commands +namespace Genocs.Core.CQRS.Commands; + +/// +/// CQRS command interface +/// +public interface ICommand { - /// - /// CQRS command interface - /// - public interface ICommand - { - } } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs b/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs index 4b8076c6..a4a64469 100644 --- a/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs +++ b/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs @@ -1,20 +1,19 @@ -namespace Genocs.Core.CQRS.Commands -{ - using System.Threading; - using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; + +namespace Genocs.Core.CQRS.Commands; +/// +/// Command dispatcher interface +/// +public interface ICommandDispatcher +{ /// - /// Command dispatcher interface + /// SendAsync /// - public interface ICommandDispatcher - { - /// - /// SendAsync - /// - /// - /// - /// - /// - Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand; - } + /// + /// + /// + /// + Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand; } diff --git a/src/Genocs.Core/CQRS/Commands/ICommandHandler.cs b/src/Genocs.Core/CQRS/Commands/ICommandHandler.cs index 6c5f9c61..7e90ec19 100644 --- a/src/Genocs.Core/CQRS/Commands/ICommandHandler.cs +++ b/src/Genocs.Core/CQRS/Commands/ICommandHandler.cs @@ -1,34 +1,32 @@ namespace Genocs.Core.CQRS.Commands; -using System.Threading; -using System.Threading.Tasks; - /// -/// CQRS command handler interface +/// CQRS command handler interface. /// -/// -public interface ICommandHandler where TCommand : class, ICommand +/// The type of command. +public interface ICommandHandler + where TCommand : class, ICommand { /// - /// HandleAsync + /// HandleAsync. /// - /// - /// - /// + /// The command + /// The Cancellation token. + /// Async Task. Task HandleAsync(TCommand command, CancellationToken cancellationToken = default); } - /// -/// Legacy CQRS command handler interface +/// Legacy CQRS command handler interface. /// -/// -public interface ICommandHandlerLegacy where T : ICommand +/// The type of command. +public interface ICommandHandlerLegacy + where T : ICommand { /// - /// Legacy HandleAsync + /// Legacy HandleAsync. /// - /// - /// + /// The command. + /// Async Task. Task HandleCommand(T @command); } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Commons/Extensions.cs b/src/Genocs.Core/CQRS/Commons/Extensions.cs index 88cd514e..014e8e6c 100644 --- a/src/Genocs.Core/CQRS/Commons/Extensions.cs +++ b/src/Genocs.Core/CQRS/Commons/Extensions.cs @@ -10,20 +10,20 @@ namespace Genocs.Core.CQRS.Commons; /// -/// Extension helper to handle the whole set of Dispatcher +/// Extension helper to handle the whole set of Dispatcher. /// public static class Extensions { /// - /// AddHandlers implementation + /// AddHandlers implementation. /// - /// - /// + /// The service collection. + /// Name of the project. /// public static IServiceCollection AddHandlers(this IServiceCollection services, string project) { var assemblies = AppDomain.CurrentDomain.GetAssemblies() - .Where(x => x.FullName != null && x.FullName.Contains(project)) + .Where(x => x.FullName != null && x.FullName.Contains(project)) .ToArray(); services.Scan(s => s.FromAssemblies(assemblies) @@ -48,10 +48,10 @@ public static IServiceCollection AddHandlers(this IServiceCollection services, s } /// - /// AddDispatchers Implementation + /// AddDispatchers Implementation. /// - /// - /// + /// The service collection. + /// The service collection to be used for chaining pattern. public static IServiceCollection AddDispatchers(this IServiceCollection services) => services .AddSingleton() diff --git a/src/Genocs.Core/CQRS/Commons/IDispatcher.cs b/src/Genocs.Core/CQRS/Commons/IDispatcher.cs index fbdec5fa..cca50975 100644 --- a/src/Genocs.Core/CQRS/Commons/IDispatcher.cs +++ b/src/Genocs.Core/CQRS/Commons/IDispatcher.cs @@ -1,41 +1,40 @@ -namespace Genocs.Core.CQRS.Commons -{ - using Genocs.Core.CQRS.Commands; - using Genocs.Core.CQRS.Events; - using Genocs.Core.CQRS.Queries; - using System.Threading; - using System.Threading.Tasks; +using Genocs.Core.CQRS.Commands; +using Genocs.Core.CQRS.Events; +using Genocs.Core.CQRS.Queries; + +namespace Genocs.Core.CQRS.Commons; +/// +/// Generic dispatcher interface. +/// +public interface IDispatcher +{ /// - /// Generic dispatcher interface + /// Generic command sender. /// - public interface IDispatcher - { - /// - /// Generic command sender - /// - /// - /// - /// - /// - Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand; + /// + /// + /// + /// + Task SendAsync(T command, CancellationToken cancellationToken = default) + where T : class, ICommand; - /// - /// Generic event publisher - /// - /// - /// - /// - /// - Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent; + /// + /// Generic event publisher + /// + /// + /// + /// + /// + Task PublishAsync(T @event, CancellationToken cancellationToken = default) + where T : class, IEvent; - /// - /// Generic query fetcher - /// - /// - /// - /// - /// - Task QueryAsync(IQuery query, CancellationToken cancellationToken = default); - } + /// + /// Generic query fetcher. + /// + /// + /// + /// + /// + Task QueryAsync(IQuery query, CancellationToken cancellationToken = default); } diff --git a/src/Genocs.Core/CQRS/Commons/InMemoryDispatcher.cs b/src/Genocs.Core/CQRS/Commons/InMemoryDispatcher.cs index c3c872ca..609ac04f 100644 --- a/src/Genocs.Core/CQRS/Commons/InMemoryDispatcher.cs +++ b/src/Genocs.Core/CQRS/Commons/InMemoryDispatcher.cs @@ -1,14 +1,11 @@ -namespace Genocs.Core.CQRS.Commons; - -using Genocs.Core.CQRS.Commands; +using Genocs.Core.CQRS.Commands; using Genocs.Core.CQRS.Events; using Genocs.Core.CQRS.Queries; -using System.Threading; -using System.Threading.Tasks; +namespace Genocs.Core.CQRS.Commons; /// -/// The class name will be renamed!!! +/// The class name will be renamed. /// internal sealed class InMemoryDispatcher : IDispatcher { @@ -16,18 +13,22 @@ internal sealed class InMemoryDispatcher : IDispatcher private readonly IEventDispatcher _eventDispatcher; private readonly IQueryDispatcher _queryDispatcher; - public InMemoryDispatcher(ICommandDispatcher commandDispatcher, IEventDispatcher eventDispatcher, - IQueryDispatcher queryDispatcher) + public InMemoryDispatcher( + ICommandDispatcher commandDispatcher, + IEventDispatcher eventDispatcher, + IQueryDispatcher queryDispatcher) { - _commandDispatcher = commandDispatcher; - _eventDispatcher = eventDispatcher; - _queryDispatcher = queryDispatcher; + _commandDispatcher = commandDispatcher ?? throw new ArgumentNullException(nameof(commandDispatcher)); + _eventDispatcher = eventDispatcher ?? throw new ArgumentNullException(nameof(eventDispatcher)); + _queryDispatcher = queryDispatcher ?? throw new ArgumentNullException(nameof(queryDispatcher)); } - public Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand + public Task SendAsync(T command, CancellationToken cancellationToken = default) + where T : class, ICommand => _commandDispatcher.SendAsync(command, cancellationToken); - public Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent + public Task PublishAsync(T @event, CancellationToken cancellationToken = default) + where T : class, IEvent => _eventDispatcher.PublishAsync(@event, cancellationToken); public Task QueryAsync(IQuery query, CancellationToken cancellationToken = default) diff --git a/src/Genocs.Core/CQRS/Events/Dispatchers/EventDispatcher.cs b/src/Genocs.Core/CQRS/Events/Dispatchers/EventDispatcher.cs index edccd1cb..cdea3890 100644 --- a/src/Genocs.Core/CQRS/Events/Dispatchers/EventDispatcher.cs +++ b/src/Genocs.Core/CQRS/Events/Dispatchers/EventDispatcher.cs @@ -1,20 +1,31 @@ -namespace Genocs.Core.CQRS.Events.Dispatchers; - -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Genocs.Core.CQRS.Events; using Microsoft.Extensions.DependencyInjection; +namespace Genocs.Core.CQRS.Events.Dispatchers; + +/// +/// The event dispatcher is responsible for dispatching events to their respective handlers. +/// internal sealed class EventDispatcher : IEventDispatcher { private readonly IServiceProvider _serviceProvider; + /// + /// standard constructor. + /// + /// The service provider. public EventDispatcher(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; - public async Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent + /// + /// The event dispatcher is responsible for dispatching events to their respective handlers. + /// + /// The type of the event to publish. + /// The event object instance. + /// The cancellation token. + /// The event cannot be null. + /// Async task. + public async Task PublishAsync(T @event, CancellationToken cancellationToken = default) + where T : class, IEvent { if (@event is null) { diff --git a/src/Genocs.Core/CQRS/Events/Extensions.cs b/src/Genocs.Core/CQRS/Events/Extensions.cs index b845280b..db9d35dc 100644 --- a/src/Genocs.Core/CQRS/Events/Extensions.cs +++ b/src/Genocs.Core/CQRS/Events/Extensions.cs @@ -6,12 +6,12 @@ namespace Genocs.Core.CQRS.Events; /// -/// CQRS events extensions +/// CQRS events extensions. /// public static class Extensions { /// - /// AddEventHandlers + /// AddEventHandlers. /// /// /// @@ -29,7 +29,7 @@ public static IGenocsBuilder AddEventHandlers(this IGenocsBuilder builder) /// - /// AddInMemoryEventDispatcher + /// AddInMemoryEventDispatcher. /// /// /// @@ -40,7 +40,7 @@ public static IGenocsBuilder AddInMemoryEventDispatcher(this IGenocsBuilder buil } /// - /// AddEventHandlers + /// AddEventHandlers. /// /// /// @@ -57,7 +57,7 @@ public static IServiceCollection AddEventHandlers(this IServiceCollection servic } /// - /// AddInMemoryEventDispatcher + /// AddInMemoryEventDispatcher. /// /// /// diff --git a/src/Genocs.Core/CQRS/Events/IEvent.cs b/src/Genocs.Core/CQRS/Events/IEvent.cs index 4ea82680..c61433d7 100644 --- a/src/Genocs.Core/CQRS/Events/IEvent.cs +++ b/src/Genocs.Core/CQRS/Events/IEvent.cs @@ -1,7 +1,7 @@ namespace Genocs.Core.CQRS.Events; /// -/// The CQRS event interface that defines a generic event used for integration tasks +/// The CQRS event interface that defines a generic event used for integration tasks. /// public interface IEvent { diff --git a/src/Genocs.Core/CQRS/Events/IEventDispatcher.cs b/src/Genocs.Core/CQRS/Events/IEventDispatcher.cs index 3b3d7b20..9d9ae905 100644 --- a/src/Genocs.Core/CQRS/Events/IEventDispatcher.cs +++ b/src/Genocs.Core/CQRS/Events/IEventDispatcher.cs @@ -1,19 +1,17 @@ namespace Genocs.Core.CQRS.Events; -using System.Threading; -using System.Threading.Tasks; - /// -/// The CQRS event dispatcher interface used to publish an integration event +/// The CQRS event dispatcher interface used to publish an integration event. /// public interface IEventDispatcher { /// - /// It allows to Publish an integration event Async + /// It allows to Publish an integration event Async. /// - /// + /// The Type of the event. /// /// /// - Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent; + Task PublishAsync(T @event, CancellationToken cancellationToken = default) + where T : class, IEvent; } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Events/IEventHandler.cs b/src/Genocs.Core/CQRS/Events/IEventHandler.cs index f636e7fb..5308d394 100644 --- a/src/Genocs.Core/CQRS/Events/IEventHandler.cs +++ b/src/Genocs.Core/CQRS/Events/IEventHandler.cs @@ -1,10 +1,7 @@ namespace Genocs.Core.CQRS.Events; -using System.Threading; -using System.Threading.Tasks; - /// -/// Generic interface for CQRS Event handler +/// Generic interface for CQRS Event handler. /// /// public interface IEventHandler where TEvent : class, IEvent @@ -18,7 +15,6 @@ public interface IEventHandler where TEvent : class, IEvent Task HandleAsync(TEvent @event, CancellationToken cancellationToken = default); } - /// /// Legacy Event handler interface definition /// @@ -26,7 +22,7 @@ public interface IEventHandler where TEvent : class, IEvent public interface IEventHandlerLegacy where T : IEvent { /// - /// Legacy event handler place holder + /// Legacy event handler place holder. /// /// /// diff --git a/src/Genocs.Core/CQRS/Events/IRejectedEvent.cs b/src/Genocs.Core/CQRS/Events/IRejectedEvent.cs index 22e1f9e0..9fbae293 100644 --- a/src/Genocs.Core/CQRS/Events/IRejectedEvent.cs +++ b/src/Genocs.Core/CQRS/Events/IRejectedEvent.cs @@ -1,8 +1,7 @@ -namespace Genocs.Core.CQRS.Events +namespace Genocs.Core.CQRS.Events; + +public interface IRejectedEvent : IEvent { - public interface IRejectedEvent : IEvent - { - string Reason { get; } - string Code { get; } - } + string Reason { get; } + string Code { get; } } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Events/RejectedEvent.cs b/src/Genocs.Core/CQRS/Events/RejectedEvent.cs index 11109941..7d2f82d4 100644 --- a/src/Genocs.Core/CQRS/Events/RejectedEvent.cs +++ b/src/Genocs.Core/CQRS/Events/RejectedEvent.cs @@ -1,21 +1,19 @@ -namespace Genocs.Core.CQRS.Events -{ - using System.Text.Json.Serialization; +using System.Text.Json.Serialization; - public class RejectedEvent : IRejectedEvent - { - public string Reason { get; } - public string Code { get; } +namespace Genocs.Core.CQRS.Events; - [JsonConstructor] - public RejectedEvent(string reason, string code) - { - Reason = reason; - Code = code; - } +public class RejectedEvent : IRejectedEvent +{ + public string Reason { get; } + public string Code { get; } - public static IRejectedEvent For(string name) - => new RejectedEvent($"There was an error when executing: " + - $"{name}", $"{name}_error"); + [JsonConstructor] + public RejectedEvent(string reason, string code) + { + Reason = reason; + Code = code; } + + public static IRejectedEvent For(string name) + => new RejectedEvent($"There was an error when executing: " + $"{name}", $"{name}_error"); } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/Dispatchers/QueryDispatcher.cs b/src/Genocs.Core/CQRS/Queries/Dispatchers/QueryDispatcher.cs index 999262df..4e1fadd5 100644 --- a/src/Genocs.Core/CQRS/Queries/Dispatchers/QueryDispatcher.cs +++ b/src/Genocs.Core/CQRS/Queries/Dispatchers/QueryDispatcher.cs @@ -1,46 +1,42 @@ -namespace Genocs.Core.CQRS.Queries.Dispatchers +using Microsoft.Extensions.DependencyInjection; + +namespace Genocs.Core.CQRS.Queries.Dispatchers; + +internal sealed class QueryDispatcher : IQueryDispatcher { - using System; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Extensions.DependencyInjection; + private readonly IServiceProvider _serviceProvider; - internal sealed class QueryDispatcher : IQueryDispatcher + public QueryDispatcher(IServiceProvider serviceProvider) { - private readonly IServiceProvider _serviceProvider; + _serviceProvider = serviceProvider; + } - public QueryDispatcher(IServiceProvider serviceProvider) + public async Task QueryAsync(IQuery query, CancellationToken cancellationToken = default) + { + if (query is null) { - _serviceProvider = serviceProvider; + throw new InvalidOperationException("Query cannot be null."); } - public async Task QueryAsync(IQuery query, CancellationToken cancellationToken = default) - { - if (query is null) - { - throw new InvalidOperationException("Query cannot be null."); - } - - await using var scope = _serviceProvider.CreateAsyncScope(); - var handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult)); - var handler = scope.ServiceProvider.GetRequiredService(handlerType); + await using var scope = _serviceProvider.CreateAsyncScope(); + var handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult)); + object handler = scope.ServiceProvider.GetRequiredService(handlerType); - var method = handlerType.GetMethod(nameof(IQueryHandler, TResult>.HandleAsync)); - if (method is null) - { - throw new InvalidOperationException($"Query handler for '{typeof(TResult).Name}' is invalid."); - } + var method = handlerType.GetMethod(nameof(IQueryHandler, TResult>.HandleAsync)); + if (method is null) + { + throw new InvalidOperationException($"Query handler for '{typeof(TResult).Name}' is invalid."); + } - return await (Task)method.Invoke(handler, new object[] { query, cancellationToken }); + return await (Task)method.Invoke(handler, new object[] { query, cancellationToken }); - } + } - public async Task QueryAsync(TQuery query, CancellationToken cancellationToken = default) - where TQuery : class, IQuery - { - using var scope = _serviceProvider.CreateScope(); - var handler = scope.ServiceProvider.GetRequiredService>(); - return await handler.HandleAsync(query, cancellationToken); - } + public async Task QueryAsync(TQuery query, CancellationToken cancellationToken = default) + where TQuery : class, IQuery + { + using var scope = _serviceProvider.CreateScope(); + var handler = scope.ServiceProvider.GetRequiredService>(); + return await handler.HandleAsync(query, cancellationToken); } } diff --git a/src/Genocs.Core/CQRS/Queries/Extensions.cs b/src/Genocs.Core/CQRS/Queries/Extensions.cs index aa026f06..16024689 100644 --- a/src/Genocs.Core/CQRS/Queries/Extensions.cs +++ b/src/Genocs.Core/CQRS/Queries/Extensions.cs @@ -6,12 +6,12 @@ namespace Genocs.Core.CQRS.Queries; /// -/// +/// Extension helper class for CQRS Queries. /// public static class Extensions { /// - /// AddQueryHandlers + /// AddQueryHandlers. /// /// /// @@ -28,7 +28,7 @@ public static IGenocsBuilder AddQueryHandlers(this IGenocsBuilder builder) } /// - /// AddInMemoryQueryDispatcher + /// AddInMemoryQueryDispatcher. /// /// /// diff --git a/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs b/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs index 72ea7a99..8c47cba2 100644 --- a/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs +++ b/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs @@ -1,20 +1,18 @@ -namespace Genocs.Core.CQRS.Queries -{ - using System.Collections.Generic; +namespace Genocs.Core.CQRS.Queries; +/// +/// The paged filter interface. +/// +/// +/// +public interface IPagedFilter + where TQuery : IQuery +{ /// - /// The paged filter interface + /// Filter /// - /// - /// - public interface IPagedFilter where TQuery : IQuery - { - /// - /// Filter - /// - /// - /// - /// - PagedResult Filter(IEnumerable values, TQuery query); - } + /// + /// + /// + PagedResult Filter(IEnumerable values, TQuery query); } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/IPagedQuery.cs b/src/Genocs.Core/CQRS/Queries/IPagedQuery.cs index d8b9f5e1..ffd6fd89 100644 --- a/src/Genocs.Core/CQRS/Queries/IPagedQuery.cs +++ b/src/Genocs.Core/CQRS/Queries/IPagedQuery.cs @@ -1,28 +1,27 @@ -namespace Genocs.Core.CQRS.Queries +namespace Genocs.Core.CQRS.Queries; + +/// +/// Query for pagination. +/// +public interface IPagedQuery : IQuery { /// - /// Query for pagination + /// Page to query zero indexed. /// - public interface IPagedQuery : IQuery - { - /// - /// Page to query zero indexed - /// - int Page { get; } + int Page { get; } - /// - /// Number of results. Aka page size - /// - int Results { get; } + /// + /// Number of results. Aka page size. + /// + int Results { get; } - /// - /// The field used to order by - /// - string? OrderBy { get; } + /// + /// The field used to order by. + /// + string? OrderBy { get; } - /// - /// Type of order. It could be ASC or DESC - /// - string? SortOrder { get; } - } + /// + /// Type of order. It could be ASC or DESC. + /// + string? SortOrder { get; } } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/IQuery.cs b/src/Genocs.Core/CQRS/Queries/IQuery.cs index 4b0cfd95..ba1ea122 100644 --- a/src/Genocs.Core/CQRS/Queries/IQuery.cs +++ b/src/Genocs.Core/CQRS/Queries/IQuery.cs @@ -1,17 +1,16 @@ -namespace Genocs.Core.CQRS.Queries +namespace Genocs.Core.CQRS.Queries; + +/// +/// Generic interface for query. +/// +public interface IQuery { - /// - /// Generic interface for query. - /// - public interface IQuery - { - } +} - /// - /// Generic interface for type - /// - /// - public interface IQuery : IQuery - { - } +/// +/// Generic interface for type. +/// +/// +public interface IQuery : IQuery +{ } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs b/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs index eb5f3ca5..49cfab52 100644 --- a/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs +++ b/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs @@ -1,31 +1,30 @@ -namespace Genocs.Core.CQRS.Queries -{ - using System.Threading.Tasks; - using System.Threading; +using System.Threading.Tasks; +using System.Threading; + +namespace Genocs.Core.CQRS.Queries; +/// +/// The query dispatcher interface. +/// +public interface IQueryDispatcher +{ /// - /// The query dispatcher interface + /// QueryAsync. /// - public interface IQueryDispatcher - { - /// - /// QueryAsync - /// - /// - /// - /// - /// - Task QueryAsync(IQuery query, CancellationToken cancellationToken = default); + /// The result type. + /// The query. + /// The Cancellation token. + /// The query result. + Task QueryAsync(IQuery query, CancellationToken cancellationToken = default); - /// - /// QueryAsync - /// - /// - /// - /// - /// - /// - Task QueryAsync(TQuery query, CancellationToken cancellationToken = default) - where TQuery : class, IQuery; - } + /// + /// QueryAsync. + /// + /// The type of the query. + /// The result. + /// The query object instance. + /// The cancellation token. + /// The query result. + Task QueryAsync(TQuery query, CancellationToken cancellationToken = default) + where TQuery : class, IQuery; } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs b/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs index f05d4858..2ec99250 100644 --- a/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs +++ b/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs @@ -1,21 +1,20 @@ -namespace Genocs.Core.CQRS.Queries -{ - using System.Threading.Tasks; - using System.Threading; +using System.Threading.Tasks; +using System.Threading; + +namespace Genocs.Core.CQRS.Queries; +/// +/// The query handler interface. +/// +/// +/// +public interface IQueryHandler where TQuery : class, IQuery +{ /// - /// The query handler interface + /// HandleAsync /// - /// - /// - public interface IQueryHandler where TQuery : class, IQuery - { - /// - /// HandleAsync - /// - /// - /// - /// - Task HandleAsync(TQuery query, CancellationToken cancellationToken = default); - } + /// + /// + /// + Task HandleAsync(TQuery query, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/PagedQueryBase.cs b/src/Genocs.Core/CQRS/Queries/PagedQueryBase.cs index 43e90b9f..f518a21e 100644 --- a/src/Genocs.Core/CQRS/Queries/PagedQueryBase.cs +++ b/src/Genocs.Core/CQRS/Queries/PagedQueryBase.cs @@ -1,28 +1,27 @@ -namespace Genocs.Core.CQRS.Queries +namespace Genocs.Core.CQRS.Queries; + +/// +/// The paged query result. +/// +public abstract class PagedQueryBase : IPagedQuery { /// - /// The paged query result + /// The zero based page index. /// - public abstract class PagedQueryBase : IPagedQuery - { - /// - /// The zero based page index - /// - public int Page { get; set; } + public int Page { get; set; } - /// - /// Number of results. Aka page size - /// - public int Results { get; set; } + /// + /// Number of results. Aka page size. + /// + public int Results { get; set; } - /// - /// The field used to order by - /// - public string? OrderBy { get; set; } + /// + /// The field used to order by. + /// + public string? OrderBy { get; set; } - /// - /// Type of order. It could be ASC or DESC - /// - public string? SortOrder { get; set; } - } + /// + /// Type of order. It could be ASC or DESC. + /// + public string? SortOrder { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/PagedQueryWithFilter.cs b/src/Genocs.Core/CQRS/Queries/PagedQueryWithFilter.cs index 2c4ebac3..03fdaf18 100644 --- a/src/Genocs.Core/CQRS/Queries/PagedQueryWithFilter.cs +++ b/src/Genocs.Core/CQRS/Queries/PagedQueryWithFilter.cs @@ -1,13 +1,12 @@ -namespace Genocs.Core.CQRS.Queries +namespace Genocs.Core.CQRS.Queries; + +/// +/// Paged query extension with Filter. +/// +public class PagedQueryWithFilter : PagedQueryBase { /// - /// Paged query extension with Filter + /// The filter. /// - public class PagedQueryWithFilter : PagedQueryBase - { - /// - /// The filter - /// - public string FilterBy { get; set; } = string.Empty; - } + public string FilterBy { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/PagedResult.cs b/src/Genocs.Core/CQRS/Queries/PagedResult.cs index 2620f2d2..e501d3ae 100644 --- a/src/Genocs.Core/CQRS/Queries/PagedResult.cs +++ b/src/Genocs.Core/CQRS/Queries/PagedResult.cs @@ -24,11 +24,11 @@ protected PagedResult() /// /// Standard constructor. /// - /// - /// - /// - /// - /// + /// The list of items. + /// Zero based current page. + /// Number of results within the page. + /// Total number of pages. + /// Total number of results. [JsonConstructor] protected PagedResult( IEnumerable items, @@ -44,19 +44,19 @@ protected PagedResult( /// /// Create helper. /// - /// - /// - /// - /// - /// - /// + /// The list of items. + /// Zero based current page. + /// Number of results within the page. + /// Total number of pages. + /// Total number of results. + /// The paged results. public static PagedResult Create( IEnumerable items, int currentPage, int resultsPerPage, int totalPages, long totalResults) - => new PagedResult(items, currentPage, resultsPerPage, totalPages, totalResults); + => new(items, currentPage, resultsPerPage, totalPages, totalResults); /// /// From helper. @@ -67,15 +67,16 @@ public static PagedResult Create( public static PagedResult From( PagedResultBase result, IEnumerable items) - => new PagedResult( - items, - result.CurrentPage, - result.ResultsPerPage, - result.TotalPages, - result.TotalResults); + => new( + items, + result.CurrentPage, + result.ResultsPerPage, + result.TotalPages, + result.TotalResults); /// /// Static helper to get Empty result. /// - public static PagedResult Empty => new PagedResult(); + public static PagedResult Empty + => new(); } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/PagedResultBase.cs b/src/Genocs.Core/CQRS/Queries/PagedResultBase.cs index 79dec7f1..b9a8a5e2 100644 --- a/src/Genocs.Core/CQRS/Queries/PagedResultBase.cs +++ b/src/Genocs.Core/CQRS/Queries/PagedResultBase.cs @@ -1,51 +1,49 @@ -namespace Genocs.Core.CQRS.Queries +namespace Genocs.Core.CQRS.Queries; + +/// +/// The page result base class. +/// +public abstract class PagedResultBase { /// - /// The page result base class + /// Returned zero index page. /// - public abstract class PagedResultBase - { - /// - /// Returned zero index page - /// - public int CurrentPage { get; } + public int CurrentPage { get; } - /// - /// Number of returned results. Aka page size - /// - public int ResultsPerPage { get; } + /// + /// Number of returned results. Aka page size. + /// + public int ResultsPerPage { get; } - /// - /// Number of pages - /// - public int TotalPages { get; } + /// + /// Number of pages. + /// + public int TotalPages { get; } - /// - /// Total number of results - /// - public long TotalResults { get; } + /// + /// Total number of results. + /// + public long TotalResults { get; } - /// - /// Default constructor - /// - protected PagedResultBase() - { - } + /// + /// Default constructor. + /// + protected PagedResultBase() + { + } - /// - /// Standard constructor - /// - /// - /// - /// - /// - protected PagedResultBase(int currentPage, int resultsPerPage, - int totalPages, long totalResults) - { - CurrentPage = currentPage > totalPages ? totalPages : currentPage; - ResultsPerPage = resultsPerPage; - TotalPages = totalPages; - TotalResults = totalResults; - } + /// + /// Standard constructor. + /// + /// + /// + /// + /// + protected PagedResultBase(int currentPage, int resultsPerPage, int totalPages, long totalResults) + { + CurrentPage = currentPage > totalPages ? totalPages : currentPage; + ResultsPerPage = resultsPerPage; + TotalPages = totalPages; + TotalResults = totalResults; } } \ No newline at end of file diff --git a/src/Genocs.Core/CQRS/Queries/Request.cs b/src/Genocs.Core/CQRS/Queries/Request.cs index 97ddc21d..08c620d8 100644 --- a/src/Genocs.Core/CQRS/Queries/Request.cs +++ b/src/Genocs.Core/CQRS/Queries/Request.cs @@ -1,16 +1,15 @@ -namespace Genocs.Core.CQRS.Queries +namespace Genocs.Core.CQRS.Queries; + +public interface ISearchRequest { - public interface ISearchRequest - { - string q { get; set; } + string q { get; set; } - int MaxItems { get; set; } - } + int MaxItems { get; set; } +} - public class SearchRequest : ISearchRequest - { - public string q { get; set; } = string.Empty; +public class SearchRequest : ISearchRequest +{ + public string q { get; set; } = string.Empty; - public int MaxItems { get; set; } = 10; - } + public int MaxItems { get; set; } = 10; } diff --git a/src/Genocs.Core/Collections/ITypeList.cs b/src/Genocs.Core/Collections/ITypeList.cs index be8fad3d..0756221b 100644 --- a/src/Genocs.Core/Collections/ITypeList.cs +++ b/src/Genocs.Core/Collections/ITypeList.cs @@ -1,39 +1,38 @@ -namespace Genocs.Core.Collections +namespace Genocs.Core.Collections; + +/// +/// A shortcut for to use object as base type. +/// +public interface ITypeList : ITypeList { - using System; - using System.Collections.Generic; +} + +/// +/// Extends to add restriction a specific base type. +/// +/// Base Type of s in this list. +public interface ITypeList : IList +{ /// - /// A shortcut for to use object as base type. + /// Adds a type to list. /// - public interface ITypeList : ITypeList - { - - } + /// The type of the param. + void Add() + where T : TBaseType; /// - /// Extends to add restriction a specific base type. + /// Checks if a type exists in the list. /// - /// Base Type of s in this list - public interface ITypeList : IList - { - /// - /// Adds a type to list. - /// - /// Type - void Add() where T : TBaseType; + /// The type of the param. + /// True when the list contains the item otherwise False. + bool Contains() + where T : TBaseType; - /// - /// Checks if a type exists in the list. - /// - /// Type - /// - bool Contains() where T : TBaseType; - - /// - /// Removes a type from list - /// - /// - void Remove() where T : TBaseType; - } + /// + /// Removes a type from list. + /// + /// The type of the param. + void Remove() + where T : TBaseType; } \ No newline at end of file diff --git a/src/Genocs.Core/Collections/TypeList.cs b/src/Genocs.Core/Collections/TypeList.cs index 32d6f57e..4662cf86 100644 --- a/src/Genocs.Core/Collections/TypeList.cs +++ b/src/Genocs.Core/Collections/TypeList.cs @@ -34,7 +34,11 @@ public class TypeList : ITypeList /// Index. public Type this[int index] { - get { return _typeList[index]; } + get + { + return _typeList[index]; + } + set { CheckType(value); diff --git a/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs index 00113b4e..4433ee83 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs @@ -1,54 +1,52 @@ -namespace Genocs.Core.Domain.Entities.Auditing +using System.ComponentModel.DataAnnotations.Schema; + +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// A shortcut of for most used primary key type (). +/// +[Serializable] +public abstract class AuditedAggregateRoot : AuditedAggregateRoot { - using System; - using System.ComponentModel.DataAnnotations.Schema; +} + +/// +/// This class can be used to simplify implementing for aggregate roots. +/// +/// Type of the primary key of the entity +[Serializable] +public abstract class AuditedAggregateRoot : CreationAuditedAggregateRoot, IAudited +{ /// - /// A shortcut of for most used primary key type (). + /// Last modification date of this entity. /// - [Serializable] - public abstract class AuditedAggregateRoot : AuditedAggregateRoot - { - - } + public virtual DateTime? LastModificationTime { get; set; } /// - /// This class can be used to simplify implementing for aggregate roots. + /// Last modifier user of this entity. /// - /// Type of the primary key of the entity - [Serializable] - public abstract class AuditedAggregateRoot : CreationAuditedAggregateRoot, IAudited - { - /// - /// Last modification date of this entity. - /// - public virtual DateTime? LastModificationTime { get; set; } - - /// - /// Last modifier user of this entity. - /// - public virtual long? LastModifierUserId { get; set; } - } + public virtual long? LastModifierUserId { get; set; } +} +/// +/// This class can be used to simplify implementing for aggregate roots. +/// +/// Type of the primary key of the entity. +/// Type of the user. +[Serializable] +public abstract class AuditedAggregateRoot : AuditedAggregateRoot, IAudited + where TUser : IEntity +{ /// - /// This class can be used to simplify implementing for aggregate roots. + /// Reference to the creator user of this entity. /// - /// Type of the primary key of the entity - /// Type of the user - [Serializable] - public abstract class AuditedAggregateRoot : AuditedAggregateRoot, IAudited - where TUser : IEntity - { - /// - /// Reference to the creator user of this entity. - /// - [ForeignKey("CreatorUserId")] - public virtual TUser CreatorUser { get; set; } + [ForeignKey("CreatorUserId")] + public virtual TUser? CreatorUser { get; set; } - /// - /// Reference to the last modifier user of this entity. - /// - [ForeignKey("LastModifierUserId")] - public virtual TUser LastModifierUser { get; set; } - } + /// + /// Reference to the last modifier user of this entity. + /// + [ForeignKey("LastModifierUserId")] + public virtual TUser? LastModifierUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs index b240ffdc..ea77a34c 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs @@ -1,54 +1,52 @@ -namespace Genocs.Core.Domain.Entities.Auditing +using System.ComponentModel.DataAnnotations.Schema; + +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// A shortcut of for most used primary key type (). +/// +[Serializable] +public abstract class AuditedEntity : AuditedEntity, IEntity { - using System; - using System.ComponentModel.DataAnnotations.Schema; +} + +/// +/// This class can be used to simplify implementing . +/// +/// Type of the primary key of the entity. +[Serializable] +public abstract class AuditedEntity : CreationAuditedEntity, IAudited +{ /// - /// A shortcut of for most used primary key type (). + /// Last modification date of this entity. /// - [Serializable] - public abstract class AuditedEntity : AuditedEntity, IEntity - { - - } + public virtual DateTime? LastModificationTime { get; set; } /// - /// This class can be used to simplify implementing . + /// Last modifier user of this entity. /// - /// Type of the primary key of the entity - [Serializable] - public abstract class AuditedEntity : CreationAuditedEntity, IAudited - { - /// - /// Last modification date of this entity. - /// - public virtual DateTime? LastModificationTime { get; set; } - - /// - /// Last modifier user of this entity. - /// - public virtual long? LastModifierUserId { get; set; } - } + public virtual long? LastModifierUserId { get; set; } +} +/// +/// This class can be used to simplify implementing . +/// +/// Type of the primary key of the entity. +/// Type of the user. +[Serializable] +public abstract class AuditedEntity : AuditedEntity, IAudited + where TUser : IEntity +{ /// - /// This class can be used to simplify implementing . + /// Reference to the creator user of this entity. /// - /// Type of the primary key of the entity - /// Type of the user - [Serializable] - public abstract class AuditedEntity : AuditedEntity, IAudited - where TUser : IEntity - { - /// - /// Reference to the creator user of this entity. - /// - [ForeignKey("CreatorUserId")] - public virtual TUser CreatorUser { get; set; } + [ForeignKey("CreatorUserId")] + public virtual TUser? CreatorUser { get; set; } - /// - /// Reference to the last modifier user of this entity. - /// - [ForeignKey("LastModifierUserId")] - public virtual TUser LastModifierUser { get; set; } - } + /// + /// Reference to the last modifier user of this entity. + /// + [ForeignKey("LastModifierUserId")] + public virtual TUser? LastModifierUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs index bf60ca63..3dd1a8f7 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs @@ -1,59 +1,56 @@ -namespace Genocs.Core.Domain.Entities.Auditing +using System.ComponentModel.DataAnnotations.Schema; + +// using Genocs.Timing; + +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// A shortcut of for most used primary key type (). +/// +[Serializable] +public abstract class CreationAuditedAggregateRoot : CreationAuditedAggregateRoot +{ +} + +/// +/// This class can be used to simplify implementing for aggregate roots. +/// +/// Type of the primary key of the entity. +[Serializable] +public abstract class CreationAuditedAggregateRoot : AggregateRoot, ICreationAudited { - using System; - using System.ComponentModel.DataAnnotations.Schema; - //using Genocs.Timing; + /// + /// Creation time of this entity. + /// + public virtual DateTime CreationTime { get; set; } /// - /// A shortcut of for most used primary key type (). + /// Creator of this entity. /// - [Serializable] - public abstract class CreationAuditedAggregateRoot : CreationAuditedAggregateRoot - { - - } + public virtual long? CreatorUserId { get; set; } /// - /// This class can be used to simplify implementing for aggregate roots. + /// Constructor. /// - /// Type of the primary key of the entity - [Serializable] - public abstract class CreationAuditedAggregateRoot : AggregateRoot, ICreationAudited + protected CreationAuditedAggregateRoot() { - /// - /// Creation time of this entity. - /// - public virtual DateTime CreationTime { get; set; } - - /// - /// Creator of this entity. - /// - public virtual long? CreatorUserId { get; set; } - - /// - /// Constructor. - /// - protected CreationAuditedAggregateRoot() - { - //CreationTime = Clock.Now; // Manage timezone - CreationTime = DateTime.Now; - - } + // CreationTime = Clock.Now; // Manage timezone + CreationTime = DateTime.Now; } +} +/// +/// This class can be used to simplify implementing for aggregate roots. +/// +/// Type of the primary key of the entity. +/// Type of the user. +[Serializable] +public abstract class CreationAuditedAggregateRoot : CreationAuditedAggregateRoot, ICreationAudited + where TUser : IEntity +{ /// - /// This class can be used to simplify implementing for aggregate roots. + /// Reference to the creator user of this entity. /// - /// Type of the primary key of the entity - /// Type of the user - [Serializable] - public abstract class CreationAuditedAggregateRoot : CreationAuditedAggregateRoot, ICreationAudited - where TUser : IEntity - { - /// - /// Reference to the creator user of this entity. - /// - [ForeignKey("CreatorUserId")] - public virtual TUser CreatorUser { get; set; } - } + [ForeignKey("CreatorUserId")] + public virtual TUser? CreatorUser { get; set; } } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs index 10c0bfbf..d02e6c0e 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs @@ -1,120 +1,120 @@ -namespace Genocs.Core.Domain.Entities.Auditing +// using Genocs.Timing; +// using Genocs.Core.Configuration.Startup; +// using Genocs.Core.MultiTenancy; +using Genocs.Core.Extensions; + +namespace Genocs.Core.Domain.Entities.Auditing; + +public static class EntityAuditingHelper { - //using Genocs.Timing; - using System; - //using Genocs.Core.Configuration.Startup; - //using Genocs.Core.MultiTenancy; - using Genocs.Core.Extensions; + public static void SetCreationAuditProperties( - public static class EntityAuditingHelper + // IMultiTenancyConfig multiTenancyConfig, + object entityAsObj, + int? tenantId, + long? userId) { - public static void SetCreationAuditProperties( - //IMultiTenancyConfig multiTenancyConfig, - object entityAsObj, - int? tenantId, - long? userId) + var entityWithCreationTime = entityAsObj as IHasCreationTime; + if (entityWithCreationTime == null) { - var entityWithCreationTime = entityAsObj as IHasCreationTime; - if (entityWithCreationTime == null) - { - //Object does not implement IHasCreationTime - return; - } + // Object does not implement IHasCreationTime + return; + } - if (entityWithCreationTime.CreationTime == default(DateTime)) - { - //entityWithCreationTime.CreationTime = Clock.Now; - entityWithCreationTime.CreationTime = DateTime.Now; + if (entityWithCreationTime.CreationTime == default(DateTime)) + { + // entityWithCreationTime.CreationTime = Clock.Now; + entityWithCreationTime.CreationTime = DateTime.Now; - } + } - if (!(entityAsObj is ICreationAudited)) - { - //Object does not implement ICreationAudited - return; - } + if (!(entityAsObj is ICreationAudited)) + { + // Object does not implement ICreationAudited + return; + } - if (!userId.HasValue) - { - //Unknown user - return; - } + if (!userId.HasValue) + { + // Unknown user + return; + } - var entity = entityAsObj as ICreationAudited; - if (entity.CreatorUserId != null) - { - //CreatorUserId is already set - return; - } + var entity = entityAsObj as ICreationAudited; + if (entity.CreatorUserId != null) + { + // CreatorUserId is already set + return; + } - //if (multiTenancyConfig?.IsEnabled == true) - //{ - // if (MultiTenancyHelper.IsMultiTenantEntity(entity) && - // !MultiTenancyHelper.IsTenantEntity(entity, tenantId)) - // { - // //A tenant entitiy is created by host or a different tenant - // return; - // } - - // if (tenantId.HasValue && MultiTenancyHelper.IsHostEntity(entity)) - // { - // //Tenant user created a host entity - // return; - // } - //} - - //Finally, set CreatorUserId! - entity.CreatorUserId = userId; + //if (multiTenancyConfig?.IsEnabled == true) + //{ + // if (MultiTenancyHelper.IsMultiTenantEntity(entity) && + // !MultiTenancyHelper.IsTenantEntity(entity, tenantId)) + // { + // //A tenant entitiy is created by host or a different tenant + // return; + // } + + // if (tenantId.HasValue && MultiTenancyHelper.IsHostEntity(entity)) + // { + // //Tenant user created a host entity + // return; + // } + //} + + //Finally, set CreatorUserId! + entity.CreatorUserId = userId; + } + + public static void SetModificationAuditProperties( + //IMultiTenancyConfig multiTenancyConfig, + object entityAsObj, + int? tenantId, + long? userId) + { + if (entityAsObj is IHasModificationTime) + { + //entityAsObj.As().LastModificationTime = Clock.Now; + entityAsObj.As().LastModificationTime = DateTime.Now; } - public static void SetModificationAuditProperties( - //IMultiTenancyConfig multiTenancyConfig, - object entityAsObj, - int? tenantId, - long? userId) + if (!(entityAsObj is IModificationAudited)) { - if (entityAsObj is IHasModificationTime) - { - //entityAsObj.As().LastModificationTime = Clock.Now; - entityAsObj.As().LastModificationTime = DateTime.Now; - } + //Entity does not implement IModificationAudited + return; + } - if (!(entityAsObj is IModificationAudited)) - { - //Entity does not implement IModificationAudited - return; - } + var entity = entityAsObj.As(); - var entity = entityAsObj.As(); + if (userId == null) + { + //Unknown user + entity.LastModifierUserId = null; + return; + } - if (userId == null) + /* + if (multiTenancyConfig?.IsEnabled == true) + { + if (MultiTenancyHelper.IsMultiTenantEntity(entity) && + !MultiTenancyHelper.IsTenantEntity(entity, tenantId)) { - //Unknown user + //A tenant entitiy is modified by host or a different tenant entity.LastModifierUserId = null; return; } - /* - if (multiTenancyConfig?.IsEnabled == true) + if (tenantId.HasValue && MultiTenancyHelper.IsHostEntity(entity)) { - if (MultiTenancyHelper.IsMultiTenantEntity(entity) && - !MultiTenancyHelper.IsTenantEntity(entity, tenantId)) - { - //A tenant entitiy is modified by host or a different tenant - entity.LastModifierUserId = null; - return; - } - - if (tenantId.HasValue && MultiTenancyHelper.IsHostEntity(entity)) - { - //Tenant user modified a host entity - entity.LastModifierUserId = null; - return; - } + //Tenant user modified a host entity + entity.LastModifierUserId = null; + return; } - */ - //Finally, set LastModifierUserId! - entity.LastModifierUserId = userId; } + */ + + // Finally, set LastModifierUserId! + entity.LastModifierUserId = userId; } } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs index c09c5654..c7027a8b 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs @@ -1,68 +1,66 @@ -namespace Genocs.Core.Domain.Entities.Auditing +using System.ComponentModel.DataAnnotations.Schema; + +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// A shortcut of for most used primary key type (). +/// +[Serializable] +public abstract class FullAuditedAggregateRoot : FullAuditedAggregateRoot { - using System; - using System.ComponentModel.DataAnnotations.Schema; +} + +/// +/// Implements to be a base class for full-audited aggregate roots. +/// +/// Type of the primary key of the entity. +[Serializable] +public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot, IFullAudited +{ /// - /// A shortcut of for most used primary key type (). + /// Is this entity Deleted? /// - [Serializable] - public abstract class FullAuditedAggregateRoot : FullAuditedAggregateRoot - { - - } + public virtual bool IsDeleted { get; set; } /// - /// Implements to be a base class for full-audited aggregate roots. + /// Which user deleted this entity? /// - /// Type of the primary key of the entity - [Serializable] - public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot, IFullAudited - { - /// - /// Is this entity Deleted? - /// - public virtual bool IsDeleted { get; set; } - - /// - /// Which user deleted this entity? - /// - public virtual long? DeleterUserId { get; set; } + public virtual long? DeleterUserId { get; set; } - /// - /// Deletion time of this entity. - /// - public virtual DateTime? DeletionTime { get; set; } - } + /// + /// Deletion time of this entity. + /// + public virtual DateTime? DeletionTime { get; set; } +} +/// +/// Implements to be a base class for full-audited aggregate roots. +/// +/// Type of the primary key of the entity. +/// Type of the user. +[Serializable] +public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot, IFullAudited + where TUser : IEntity +{ /// - /// Implements to be a base class for full-audited aggregate roots. + /// Is this entity Deleted? /// - /// Type of the primary key of the entity - /// Type of the user - [Serializable] - public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot, IFullAudited - where TUser : IEntity - { - /// - /// Is this entity Deleted? - /// - public virtual bool IsDeleted { get; set; } + public virtual bool IsDeleted { get; set; } - /// - /// Reference to the deleter user of this entity. - /// - [ForeignKey("DeleterUserId")] - public virtual TUser DeleterUser { get; set; } + /// + /// Reference to the deleter user of this entity. + /// + [ForeignKey("DeleterUserId")] + public virtual TUser DeleterUser { get; set; } - /// - /// Which user deleted this entity? - /// - public virtual long? DeleterUserId { get; set; } + /// + /// Which user deleted this entity? + /// + public virtual long? DeleterUserId { get; set; } - /// - /// Deletion time of this entity. - /// - public virtual DateTime? DeletionTime { get; set; } - } + /// + /// Deletion time of this entity. + /// + public virtual DateTime? DeletionTime { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs index 774135a5..03f72eb4 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs @@ -1,68 +1,66 @@ -namespace Genocs.Core.Domain.Entities.Auditing +using System.ComponentModel.DataAnnotations.Schema; + +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// A shortcut of for most used primary key type (). +/// +[Serializable] +public abstract class FullAuditedEntity : FullAuditedEntity, IEntity { - using System; - using System.ComponentModel.DataAnnotations.Schema; +} + +/// +/// Implements to be a base class for full-audited entities. +/// +/// Type of the primary key of the entity +[Serializable] +public abstract class FullAuditedEntity : AuditedEntity, IFullAudited +{ /// - /// A shortcut of for most used primary key type (). + /// Is this entity Deleted? /// - [Serializable] - public abstract class FullAuditedEntity : FullAuditedEntity, IEntity - { - - } + public virtual bool IsDeleted { get; set; } /// - /// Implements to be a base class for full-audited entities. + /// Which user deleted this entity? /// - /// Type of the primary key of the entity - [Serializable] - public abstract class FullAuditedEntity : AuditedEntity, IFullAudited - { - /// - /// Is this entity Deleted? - /// - public virtual bool IsDeleted { get; set; } - - /// - /// Which user deleted this entity? - /// - public virtual long? DeleterUserId { get; set; } + public virtual long? DeleterUserId { get; set; } - /// - /// Deletion time of this entity. - /// - public virtual DateTime? DeletionTime { get; set; } - } + /// + /// Deletion time of this entity. + /// + public virtual DateTime? DeletionTime { get; set; } +} +/// +/// Implements to be a base class for full-audited entities. +/// +/// Type of the primary key of the entity +/// Type of the user +[Serializable] +public abstract class FullAuditedEntity : AuditedEntity, IFullAudited + where TUser : IEntity +{ /// - /// Implements to be a base class for full-audited entities. + /// Is this entity Deleted? /// - /// Type of the primary key of the entity - /// Type of the user - [Serializable] - public abstract class FullAuditedEntity : AuditedEntity, IFullAudited - where TUser : IEntity - { - /// - /// Is this entity Deleted? - /// - public virtual bool IsDeleted { get; set; } + public virtual bool IsDeleted { get; set; } - /// - /// Reference to the deleter user of this entity. - /// - [ForeignKey("DeleterUserId")] - public virtual TUser DeleterUser { get; set; } + /// + /// Reference to the deleter user of this entity. + /// + [ForeignKey("DeleterUserId")] + public virtual TUser DeleterUser { get; set; } - /// - /// Which user deleted this entity? - /// - public virtual long? DeleterUserId { get; set; } + /// + /// Which user deleted this entity? + /// + public virtual long? DeleterUserId { get; set; } - /// - /// Deletion time of this entity. - /// - public virtual DateTime? DeletionTime { get; set; } - } + /// + /// Deletion time of this entity. + /// + public virtual DateTime? DeletionTime { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs index 720cc2c1..3cce8e74 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs @@ -1,20 +1,19 @@ -namespace Genocs.Core.Domain.Entities.Auditing +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// This interface ads to for a fully audited entity. +/// +public interface IFullAudited : IAudited, IDeletionAudited { - /// - /// This interface ads to for a fully audited entity. - /// - public interface IFullAudited : IAudited, IDeletionAudited - { - - } + +} - /// - /// Adds navigation properties to interface for user. - /// - /// Type of the user - public interface IFullAudited : IAudited, IFullAudited, IDeletionAudited - where TUser : IEntity - { +/// +/// Adds navigation properties to interface for user. +/// +/// Type of the user +public interface IFullAudited : IAudited, IFullAudited, IDeletionAudited + where TUser : IEntity +{ - } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs index 7aae3621..660e0003 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs @@ -1,16 +1,15 @@ -namespace Genocs.Core.Domain.Entities.Auditing -{ - using System; +namespace Genocs.Core.Domain.Entities.Auditing; + +using System; +/// +/// An entity can implement this interface if of this entity must be stored. +/// is automatically set when saving to database. +/// +public interface IHasCreationTime +{ /// - /// An entity can implement this interface if of this entity must be stored. - /// is automatically set when saving to database. + /// Creation time of this entity. /// - public interface IHasCreationTime - { - /// - /// Creation time of this entity. - /// - DateTime CreationTime { get; set; } - } + DateTime CreationTime { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs b/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs index bcf30abe..450bfc1b 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs @@ -1,16 +1,13 @@ -namespace Genocs.Core.Domain.Entities.Auditing -{ - using System; +namespace Genocs.Core.Domain.Entities.Auditing; +/// +/// An entity can implement this interface if of this entity must be stored. +/// is automatically set when deleting . +/// +public interface IHasDeletionTime : ISoftDelete +{ /// - /// An entity can implement this interface if of this entity must be stored. - /// is automatically set when deleting . + /// Deletion time of this entity. /// - public interface IHasDeletionTime : ISoftDelete - { - /// - /// Deletion time of this entity. - /// - DateTime? DeletionTime { get; set; } - } + DateTime? DeletionTime { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Entity.cs b/src/Genocs.Core/Domain/Entities/Entity.cs index 644df88c..3cbf8de7 100644 --- a/src/Genocs.Core/Domain/Entities/Entity.cs +++ b/src/Genocs.Core/Domain/Entities/Entity.cs @@ -1,5 +1,4 @@ using System.Reflection; -// using Genocs.Extensions; namespace Genocs.Core.Domain.Entities; @@ -23,15 +22,15 @@ public abstract class Entity : IEntity /// /// Unique identifier for this entity. /// - public virtual TPrimaryKey Id { get; set; } + public virtual TPrimaryKey? Id { get; set; } /// /// Checks if this entity is transient (it has not an Id). /// - /// True, if this entity is transient + /// True, if this entity is transient. public virtual bool IsTransient() { - if (EqualityComparer.Default.Equals(Id, default(TPrimaryKey))) + if (EqualityComparer.Default.Equals(Id, default)) { return true; } diff --git a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs index 82283219..3ebe15a4 100644 --- a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs @@ -95,33 +95,33 @@ public interface IRepositoryOfEntity : IRepository /// Primary key of the entity to get. /// Entity or null. - TEntity FirstOrDefault(TIdentifiable id); + TEntity? FirstOrDefault(TIdentifiable id); /// /// Gets an entity with given primary key or null if not found. /// /// Primary key of the entity to get. /// Entity or null. - Task FirstOrDefaultAsync(TIdentifiable id); + Task FirstOrDefaultAsync(TIdentifiable id); /// /// Gets an entity with given predicate or null if not found. /// /// Predicate to filter entities. - TEntity FirstOrDefault(Expression> predicate); + TEntity? FirstOrDefault(Expression> predicate); /// /// Gets an entity with given predicate or null if not found. /// /// Predicate to filter entities. - Task FirstOrDefaultAsync(Expression> predicate); + Task FirstOrDefaultAsync(Expression> predicate); /// /// Creates an entity with given primary key without database access. /// /// Primary key of the entity to load. /// Entity. - TEntity Load(TIdentifiable id); + TEntity? Load(TIdentifiable id); #endregion diff --git a/src/Genocs.Core/Domain/Repositories/ISupportsExplicitLoading.cs b/src/Genocs.Core/Domain/Repositories/ISupportsExplicitLoading.cs index c847bbbd..f74dc875 100644 --- a/src/Genocs.Core/Domain/Repositories/ISupportsExplicitLoading.cs +++ b/src/Genocs.Core/Domain/Repositories/ISupportsExplicitLoading.cs @@ -1,25 +1,20 @@ -namespace Genocs.Core.Domain.Repositories -{ - using System; - using System.Collections.Generic; - using System.Linq.Expressions; - using System.Threading; - using System.Threading.Tasks; - using Genocs.Core.Domain.Entities; +using Genocs.Core.Domain.Entities; +using System.Linq.Expressions; + +namespace Genocs.Core.Domain.Repositories; - public interface ISupportsExplicitLoading - where TEntity : class, IEntity - { - Task EnsureCollectionLoadedAsync( - TEntity entity, - Expression>> collectionExpression, - CancellationToken cancellationToken) - where TProperty : class; +public interface ISupportsExplicitLoading + where TEntity : class, IEntity +{ + Task EnsureCollectionLoadedAsync( + TEntity entity, + Expression>> collectionExpression, + CancellationToken cancellationToken) + where TProperty : class; - Task EnsurePropertyLoadedAsync( - TEntity entity, - Expression> propertyExpression, - CancellationToken cancellationToken) - where TProperty : class; - } + Task EnsurePropertyLoadedAsync( + TEntity entity, + Expression> propertyExpression, + CancellationToken cancellationToken) + where TProperty : class; } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs index 73df5ee8..58e998a2 100644 --- a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs +++ b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs @@ -102,22 +102,22 @@ public virtual Task SingleAsync(Expression> predica return Task.FromResult(Single(predicate)); } - public virtual TEntity FirstOrDefault(TPrimaryKey id) + public virtual TEntity? FirstOrDefault(TPrimaryKey id) { return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id)); } - public virtual Task FirstOrDefaultAsync(TPrimaryKey id) + public virtual Task FirstOrDefaultAsync(TPrimaryKey id) { return Task.FromResult(FirstOrDefault(id)); } - public virtual TEntity FirstOrDefault(Expression> predicate) + public virtual TEntity? FirstOrDefault(Expression> predicate) { return GetAll().FirstOrDefault(predicate); } - public virtual Task FirstOrDefaultAsync(Expression> predicate) + public virtual Task FirstOrDefaultAsync(Expression> predicate) { return Task.FromResult(FirstOrDefault(predicate)); } diff --git a/src/Genocs.Core/Exceptions/GenocsException.cs b/src/Genocs.Core/Exceptions/GenocsException.cs index 1a687054..ef7cdc27 100644 --- a/src/Genocs.Core/Exceptions/GenocsException.cs +++ b/src/Genocs.Core/Exceptions/GenocsException.cs @@ -1,8 +1,8 @@ -namespace Genocs.Core.Exceptions; +using System.Runtime.Serialization; -using System; +namespace Genocs.Core.Exceptions; -/* Unmerged change from project 'Genocs.Core (netstandard2.1)' +/* Unmerged change from project 'Genocs.Core (netstandard2.0)' Before: using System.Runtime.Serialization; After: @@ -11,7 +11,6 @@ using Genocs.Core; using Genocs.Core.Exceptions; */ -using System.Runtime.Serialization; /// /// Base exception type for those are thrown by Genocs system for Genocs specific exceptions. @@ -39,7 +38,7 @@ public GenocsException(SerializationInfo serializationInfo, StreamingContext con /// /// Creates a new object. /// - /// Exception message + /// Exception message. public GenocsException(string message) : base(message) { @@ -49,8 +48,8 @@ public GenocsException(string message) /// /// Creates a new object. /// - /// Exception message - /// Inner exception + /// Exception message. + /// Inner exception. public GenocsException(string message, Exception innerException) : base(message, innerException) { diff --git a/src/Genocs.Core/Extensions/Encryption.cs b/src/Genocs.Core/Extensions/Encryption.cs index 4452e8c9..86e7b477 100644 --- a/src/Genocs.Core/Extensions/Encryption.cs +++ b/src/Genocs.Core/Extensions/Encryption.cs @@ -3,8 +3,7 @@ namespace Genocs.Core.Extensions; - -//https://github.com/dotnet/corefx/issues/23686 +// https://github.com/dotnet/corefx/issues/23686 public static class Encryption { @@ -21,14 +20,14 @@ public static void FromXmlFile(this RSA rsa, string xmlFilePath) { switch (node.Name) { - case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; + case "Modulus": parameters.Modulus = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; + case "Exponent": parameters.Exponent = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; + case "P": parameters.P = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; + case "Q": parameters.Q = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; + case "DP": parameters.DP = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; + case "DQ": parameters.DQ = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; + case "InverseQ": parameters.InverseQ = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; + case "D": parameters.D = string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText); break; } } } @@ -53,7 +52,6 @@ public static void ToXmlFile(this RSA rsa, bool includePrivateParameters, string parameters.DP != null ? Convert.ToBase64String(parameters.DP) : null, parameters.DQ != null ? Convert.ToBase64String(parameters.DQ) : null, parameters.InverseQ != null ? Convert.ToBase64String(parameters.InverseQ) : null, - parameters.D != null ? Convert.ToBase64String(parameters.D) : null) - ); + parameters.D != null ? Convert.ToBase64String(parameters.D) : null)); } } diff --git a/src/Genocs.Core/Extensions/ExceptionExtensions.cs b/src/Genocs.Core/Extensions/ExceptionExtensions.cs index 46eca4e0..e1c267db 100644 --- a/src/Genocs.Core/Extensions/ExceptionExtensions.cs +++ b/src/Genocs.Core/Extensions/ExceptionExtensions.cs @@ -11,7 +11,7 @@ public static class ExceptionExtensions /// Uses method to re-throws exception /// while preserving stack trace. /// - /// Exception to be re-thrown + /// Exception to be re-thrown. public static void ReThrow(this Exception exception) { ExceptionDispatchInfo.Capture(exception).Throw(); diff --git a/src/Genocs.Core/Extensions/ObjectExtensions.cs b/src/Genocs.Core/Extensions/ObjectExtensions.cs index 5b31ea58..518d32f5 100644 --- a/src/Genocs.Core/Extensions/ObjectExtensions.cs +++ b/src/Genocs.Core/Extensions/ObjectExtensions.cs @@ -1,53 +1,50 @@ -namespace Genocs.Core.Extensions +using System.ComponentModel; +using System.Globalization; + +namespace Genocs.Core.Extensions; + +/// +/// Extension methods for all objects. +/// +public static class ObjectExtensions { - using System; - using System.Globalization; - using System.Linq; - using System.ComponentModel; + /// + /// Used to simplify and beautify casting an object to a type. + /// + /// Type to be casted. + /// Object to cast. + /// Casted object. + public static T As(this object obj) + where T : class + { + return (T)obj; + } /// - /// Extension methods for all objects. + /// Converts given object to a value type using method. /// - public static class ObjectExtensions + /// Object to be converted. + /// Type of the target object. + /// Converted object + public static T To(this object obj) + where T : struct { - /// - /// Used to simplify and beautify casting an object to a type. - /// - /// Type to be casted - /// Object to cast - /// Casted object - public static T As(this object obj) - where T : class + if (typeof(T) == typeof(Guid)) { - return (T)obj; + return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(obj.ToString()); } - /// - /// Converts given object to a value type using method. - /// - /// Object to be converted - /// Type of the target object - /// Converted object - public static T To(this object obj) - where T : struct - { - if (typeof(T) == typeof(Guid)) - { - return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(obj.ToString()); - } - - return (T)Convert.ChangeType(obj, typeof(T), CultureInfo.InvariantCulture); - } + return (T)Convert.ChangeType(obj, typeof(T), CultureInfo.InvariantCulture); + } - /// - /// Check if an item is in a list. - /// - /// Item to check - /// List of items - /// Type of the items - public static bool IsIn(this T item, params T[] list) - { - return list.Contains(item); - } + /// + /// Check if an item is in a list. + /// + /// Item to check. + /// List of items. + /// Type of the items. + public static bool IsIn(this T item, params T[] list) + { + return list.Contains(item); } } diff --git a/src/Genocs.Core/Extensions/StringExtensions.cs b/src/Genocs.Core/Extensions/StringExtensions.cs index 10d5c3ca..b85987a3 100644 --- a/src/Genocs.Core/Extensions/StringExtensions.cs +++ b/src/Genocs.Core/Extensions/StringExtensions.cs @@ -14,7 +14,7 @@ public static class StringExtensions /// /// Adds a char to end of given string if it does not ends with the char. /// - public static string EnsureEndsWith(this string str, char c) + public static string? EnsureEndsWith(this string? str, char c) { return EnsureEndsWith(str, c, StringComparison.Ordinal); } @@ -22,11 +22,11 @@ public static string EnsureEndsWith(this string str, char c) /// /// Adds a char to end of given string if it does not ends with the char. /// - public static string EnsureEndsWith(this string str, char c, StringComparison comparisonType) + public static string? EnsureEndsWith(this string? str, char c, StringComparison comparisonType) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - throw new ArgumentNullException(nameof(str)); + return str; } if (str.EndsWith(c.ToString(), comparisonType)) @@ -40,11 +40,11 @@ public static string EnsureEndsWith(this string str, char c, StringComparison co /// /// Adds a char to end of given string if it does not ends with the char. /// - public static string EnsureEndsWith(this string str, char c, bool ignoreCase, CultureInfo culture) + public static string? EnsureEndsWith(this string? str, char c, bool ignoreCase, CultureInfo culture) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - throw new ArgumentNullException(nameof(str)); + return str; } if (str.EndsWith(c.ToString(culture), ignoreCase, culture)) @@ -58,7 +58,7 @@ public static string EnsureEndsWith(this string str, char c, bool ignoreCase, Cu /// /// Adds a char to beginning of given string if it does not starts with the char. /// - public static string EnsureStartsWith(this string str, char c) + public static string? EnsureStartsWith(this string? str, char c) { return EnsureStartsWith(str, c, StringComparison.Ordinal); } @@ -66,11 +66,11 @@ public static string EnsureStartsWith(this string str, char c) /// /// Adds a char to beginning of given string if it does not starts with the char. /// - public static string EnsureStartsWith(this string str, char c, StringComparison comparisonType) + public static string? EnsureStartsWith(this string? str, char c, StringComparison comparisonType) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - throw new ArgumentNullException(nameof(str)); + return str; } if (str.StartsWith(c.ToString(), comparisonType)) @@ -84,11 +84,11 @@ public static string EnsureStartsWith(this string str, char c, StringComparison /// /// Adds a char to beginning of given string if it does not starts with the char. /// - public static string EnsureStartsWith(this string str, char c, bool ignoreCase, CultureInfo culture) + public static string? EnsureStartsWith(this string? str, char c, bool ignoreCase, CultureInfo culture) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - throw new ArgumentNullException("str"); + return str; } if (str.StartsWith(c.ToString(culture), ignoreCase, culture)) @@ -102,13 +102,13 @@ public static string EnsureStartsWith(this string str, char c, bool ignoreCase, /// /// Gets a substring of a string from beginning of the string. /// - /// Thrown if is null - /// Thrown if is bigger that string's length - public static string Left(this string str, int len) + /// Thrown if is null. + /// Thrown if is bigger that string's length. + public static string? Left(this string? str, int len) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - throw new ArgumentNullException("str"); + return str; } if (str.Length < len) @@ -116,32 +116,34 @@ public static string Left(this string str, int len) throw new ArgumentException("len argument can not be bigger than given string's length!"); } - return str.Substring(0, len); + return str[..len]; } /// /// Converts line endings in the string to . /// - public static string NormalizeLineEndings(this string str) + public static string? NormalizeLineEndings(this string? str) { + if (string.IsNullOrWhiteSpace(str)) + { + return str; + } + return str.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine); } /// - /// Gets index of nth occurence of a char in a string. + /// Gets index of nth occurrence of a char in a string. /// - /// source string to be searched - /// Char to search in - /// Count of the occurence + /// source string to be searched. + /// Char to search in . + /// Count of the occurrence. public static int NthIndexOf(this string str, char c, int n) { - if (str == null) - { - throw new ArgumentNullException(nameof(str)); - } + if (string.IsNullOrEmpty(str)) throw new ArgumentException("String can not be null or empty!", nameof(str)); - var count = 0; - for (var i = 0; i < str.Length; i++) + int count = 0; + for (int i = 0; i < str.Length; i++) { if (str[i] != c) { @@ -163,17 +165,12 @@ public static int NthIndexOf(this string str, char c, int n) /// /// The string. /// one or more postfix. - /// Modified string or the same string if it has not any of given postfixes - public static string RemovePostFix(this string str, params string[] postFixes) + /// Modified string or the same string if it has not any of given postfixes. + public static string? RemovePostFix(this string? str, params string[] postFixes) { - if (str == null) - { - return null; - } - - if (str == string.Empty) + if (string.IsNullOrWhiteSpace(str)) { - return string.Empty; + return str; } if (postFixes.IsNullOrEmpty()) @@ -181,7 +178,7 @@ public static string RemovePostFix(this string str, params string[] postFixes) return str; } - foreach (var postFix in postFixes) + foreach (string postFix in postFixes) { if (str.EndsWith(postFix)) { @@ -198,17 +195,12 @@ public static string RemovePostFix(this string str, params string[] postFixes) /// /// The string. /// one or more prefix. - /// Modified string or the same string if it has not any of given prefixes - public static string RemovePreFix(this string str, params string[] preFixes) + /// Modified string or the same string if it has not any of given prefixes. + public static string? RemovePreFix(this string? str, params string[] preFixes) { - if (str == null) - { - return null; - } - - if (str == string.Empty) + if (string.IsNullOrWhiteSpace(str)) { - return string.Empty; + return str; } if (preFixes.IsNullOrEmpty()) @@ -216,7 +208,7 @@ public static string RemovePreFix(this string str, params string[] preFixes) return str; } - foreach (var preFix in preFixes) + foreach (string preFix in preFixes) { if (str.StartsWith(preFix)) { @@ -230,13 +222,13 @@ public static string RemovePreFix(this string str, params string[] preFixes) /// /// Gets a substring of a string from end of the string. /// - /// Thrown if is null - /// Thrown if is bigger that string's length - public static string Right(this string str, int len) + /// Thrown if is null.exception> + /// Thrown if is bigger that string's length. + public static string? Right(this string? str, int len) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - throw new ArgumentNullException("str"); + return str; } if (str.Length < len) @@ -282,10 +274,10 @@ public static string[] SplitToLines(this string str, StringSplitOptions options) /// /// Converts PascalCase string to camelCase string. /// - /// String to convert - /// Invariant culture - /// camelCase of the string - public static string ToCamelCase(this string str, bool invariantCulture = true) + /// String to convert. + /// Invariant culture. + /// camelCase of the string. + public static string? ToCamelCase(this string? str, bool invariantCulture = true) { if (string.IsNullOrWhiteSpace(str)) { @@ -303,10 +295,10 @@ public static string ToCamelCase(this string str, bool invariantCulture = true) /// /// Converts PascalCase string to camelCase string in specified culture. /// - /// String to convert - /// An object that supplies culture-specific casing rules - /// camelCase of the string - public static string ToCamelCase(this string str, CultureInfo culture) + /// String to convert. + /// An object that supplies culture-specific casing rules. + /// camelCase of the string. + public static string? ToCamelCase(this string? str, CultureInfo culture) { if (string.IsNullOrWhiteSpace(str)) { @@ -318,7 +310,7 @@ public static string ToCamelCase(this string str, CultureInfo culture) return str.ToLower(culture); } - return char.ToLower(str[0], culture) + str.Substring(1); + return char.ToLower(str[0], culture) + str[1..]; } /// @@ -326,8 +318,8 @@ public static string ToCamelCase(this string str, CultureInfo culture) /// Example: "ThisIsSampleSentence" is converted to "This is a sample sentence". /// /// String to convert. - /// Invariant culture - public static string ToSentenceCase(this string str, bool invariantCulture = false) + /// Invariant culture. + public static string? ToSentenceCase(this string? str, bool invariantCulture = false) { if (string.IsNullOrWhiteSpace(str)) { @@ -347,7 +339,7 @@ public static string ToSentenceCase(this string str, bool invariantCulture = fal /// /// String to convert. /// An object that supplies culture-specific casing rules. - public static string ToSentenceCase(this string str, CultureInfo culture) + public static string? ToSentenceCase(this string? str, CultureInfo culture) { if (string.IsNullOrWhiteSpace(str)) { @@ -360,62 +352,54 @@ public static string ToSentenceCase(this string str, CultureInfo culture) /// /// Converts string to enum value. /// - /// Type of enum - /// String value to convert - /// Returns enum object - public static T ToEnum(this string value) + /// Type of enum. + /// String value to convert. + /// Returns enum object. + public static T ToEnum(this string? str) where T : struct { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + if (string.IsNullOrEmpty(str)) throw new ArgumentException("String can not be null or empty!", nameof(str)); - return (T)Enum.Parse(typeof(T), value); + return (T)Enum.Parse(typeof(T), str); } /// /// Converts string to enum value. /// - /// Type of enum - /// String value to convert - /// Ignore case - /// Returns enum object - public static T ToEnum(this string value, bool ignoreCase) + /// Type of enum. + /// String value to convert. + /// Ignore case. + /// Returns enum object. + public static T ToEnum(this string? str, bool ignoreCase) where T : struct { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + if (string.IsNullOrEmpty(str)) throw new ArgumentException("String can not be null or empty!", nameof(str)); - return (T)Enum.Parse(typeof(T), value, ignoreCase); + return (T)Enum.Parse(typeof(T), str, ignoreCase); } public static string ToMd5(this string str) { - using (var md5 = MD5.Create()) - { - var inputBytes = Encoding.UTF8.GetBytes(str); - var hashBytes = md5.ComputeHash(inputBytes); + using var md5 = MD5.Create(); + byte[] inputBytes = Encoding.UTF8.GetBytes(str); + byte[] hashBytes = md5.ComputeHash(inputBytes); - var sb = new StringBuilder(); - foreach (var hashByte in hashBytes) - { - sb.Append(hashByte.ToString("X2")); - } - - return sb.ToString(); + var sb = new StringBuilder(); + foreach (byte hashByte in hashBytes) + { + sb.Append(hashByte.ToString("X2")); } + + return sb.ToString(); } /// /// Converts camelCase string to PascalCase string. /// - /// String to convert - /// Invariant culture - /// PascalCase of the string - public static string ToPascalCase(this string str, bool invariantCulture = true) + /// String to convert. + /// Invariant culture. + /// PascalCase of the string. + public static string? ToPascalCase(this string? str, bool invariantCulture = true) { if (string.IsNullOrWhiteSpace(str)) { @@ -424,7 +408,7 @@ public static string ToPascalCase(this string str, bool invariantCulture = true) if (str.Length == 1) { - return invariantCulture ? str.ToUpperInvariant(): str.ToUpper(); + return invariantCulture ? str.ToUpperInvariant() : str.ToUpper(); } return (invariantCulture ? char.ToUpperInvariant(str[0]) : char.ToUpper(str[0])) + str.Substring(1); @@ -433,10 +417,10 @@ public static string ToPascalCase(this string str, bool invariantCulture = true) /// /// Converts camelCase string to PascalCase string in specified culture. /// - /// String to convert - /// An object that supplies culture-specific casing rules - /// PascalCase of the string - public static string ToPascalCase(this string str, CultureInfo culture) + /// String to convert. + /// An object that supplies culture-specific casing rules. + /// PascalCase of the string. + public static string? ToPascalCase(this string? str, CultureInfo culture) { if (string.IsNullOrWhiteSpace(str)) { @@ -454,12 +438,12 @@ public static string ToPascalCase(this string str, CultureInfo culture) /// /// Gets a substring of a string from beginning of the string if it exceeds maximum length. /// - /// Thrown if is null - public static string Truncate(this string str, int maxLength) + /// Truncated string if it is too long, otherwise the entire string. + public static string? Truncate(this string? str, int maxLength) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - return null; + return str; } if (str.Length <= maxLength) @@ -475,8 +459,8 @@ public static string Truncate(this string str, int maxLength) /// It adds a "..." postfix to end of the string if it's truncated. /// Returning string can not be longer than maxLength. /// - /// Thrown if is null - public static string TruncateWithPostfix(this string str, int maxLength) + /// Thrown if is null. + public static string? TruncateWithPostfix(this string? str, int maxLength) { return TruncateWithPostfix(str, maxLength, "..."); } @@ -486,15 +470,14 @@ public static string TruncateWithPostfix(this string str, int maxLength) /// It adds given to end of the string if it's truncated. /// Returning string can not be longer than maxLength. /// - /// Thrown if is null - public static string TruncateWithPostfix(this string str, int maxLength, string postfix) + public static string? TruncateWithPostfix(this string? str, int maxLength, string postfix) { - if (str == null) + if (string.IsNullOrWhiteSpace(str)) { - return null; + return str; } - if (str == string.Empty || maxLength == 0) + if (maxLength == 0) { return string.Empty; } @@ -513,11 +496,18 @@ public static string TruncateWithPostfix(this string str, int maxLength, string } /// - /// Helper method + /// Helper method. It's used to convert a string to snake case. /// - /// - /// - public static string Underscore(this string value) - => string.Concat(value.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x : x.ToString())) + /// The input string. + /// The output result. + public static string? Underscore(this string? str) + { + if (string.IsNullOrWhiteSpace(str)) + { + return str; + } + + return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x : x.ToString())) .ToLowerInvariant(); + } } \ No newline at end of file diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index e1e67708..b417032f 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -5,8 +5,8 @@ Genocs.Core Genocs.Core Genocs.Core - The base library to build .NET Core projects. - The base library to build .NET Core projects. + The Genocs Library - Core components. + The core components to build .NET Core projects along with Genocs Library. 10.0 true 5.0.0 @@ -58,7 +58,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Extensions.cs b/src/Genocs.Discovery.Consul/Extensions.cs index 81353d8d..ac934f94 100644 --- a/src/Genocs.Discovery.Consul/Extensions.cs +++ b/src/Genocs.Discovery.Consul/Extensions.cs @@ -17,8 +17,10 @@ public static class Extensions private const string SectionName = "consul"; private const string RegistryName = "discovery.consul"; - public static IGenocsBuilder AddConsul(this IGenocsBuilder builder, string sectionName = SectionName, - string httpClientSectionName = "httpClient") + public static IGenocsBuilder AddConsul( + this IGenocsBuilder builder, + string sectionName = SectionName, + string httpClientSectionName = "httpClient") { if (string.IsNullOrWhiteSpace(sectionName)) { @@ -30,15 +32,19 @@ public static IGenocsBuilder AddConsul(this IGenocsBuilder builder, string secti return builder.AddConsul(consulOptions, httpClientOptions); } - public static IGenocsBuilder AddConsul(this IGenocsBuilder builder, - Func buildOptions, HttpClientSettings httpClientOptions) + public static IGenocsBuilder AddConsul( + this IGenocsBuilder builder, + Func buildOptions, + HttpClientSettings httpClientOptions) { var options = buildOptions(new ConsulOptionsBuilder()).Build(); return builder.AddConsul(options, httpClientOptions); } - public static IGenocsBuilder AddConsul(this IGenocsBuilder builder, ConsulSettings options, - HttpClientSettings httpClientOptions) + public static IGenocsBuilder AddConsul( + this IGenocsBuilder builder, + ConsulSettings options, + HttpClientSettings httpClientOptions) { builder.Services.AddSingleton(options); if (!options.Enabled || !builder.TryRegister(RegistryName)) @@ -68,7 +74,7 @@ public static IGenocsBuilder AddConsul(this IGenocsBuilder builder, ConsulSettin return builder; } - public static void AddConsulHttpClient(this IGenocsBuilder builder, string clientName, string serviceName) + public static void AddConsulHttpClient(this IGenocsBuilder builder, string clientName, string? serviceName) => builder.Services.AddHttpClient(clientName) .AddHttpMessageHandler(c => new ConsulServiceDiscoveryMessageHandler( c.GetRequiredService(), @@ -77,8 +83,8 @@ public static void AddConsulHttpClient(this IGenocsBuilder builder, string clien private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulSettings options) { - var enabled = options.Enabled; - var consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); + bool enabled = options.Enabled; + string? consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); if (!string.IsNullOrWhiteSpace(consulEnabled)) { enabled = consulEnabled is "true" or "1"; @@ -132,7 +138,7 @@ private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBui pingEndpoint = pingEndpoint.Substring(0, pingEndpoint.Length - 1); } - var scheme = options.Address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) + string scheme = options.Address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase) ? string.Empty : "http://"; var check = new ServiceCheck diff --git a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs index f9b9e9d4..162f57a7 100644 --- a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs +++ b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs @@ -6,11 +6,14 @@ internal sealed class ConsulServiceDiscoveryMessageHandler : DelegatingHandler { private readonly IConsulServicesRegistry _servicesRegistry; private readonly ConsulSettings _options; - private readonly string _serviceName; + private readonly string? _serviceName; private readonly bool? _overrideRequestUri; - public ConsulServiceDiscoveryMessageHandler(IConsulServicesRegistry servicesRegistry, - ConsulSettings options, string serviceName = null, bool? overrideRequestUri = null) + public ConsulServiceDiscoveryMessageHandler( + IConsulServicesRegistry servicesRegistry, + ConsulSettings options, + string? serviceName = null, + bool? overrideRequestUri = null) { if (string.IsNullOrWhiteSpace(options.Url)) { @@ -23,11 +26,12 @@ public ConsulServiceDiscoveryMessageHandler(IConsulServicesRegistry servicesRegi _overrideRequestUri = overrideRequestUri; } - protected override async Task SendAsync(HttpRequestMessage request, - CancellationToken cancellationToken) + protected override async Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) { var uri = GetUri(request); - var serviceName = string.IsNullOrWhiteSpace(_serviceName) ? uri.Host : _serviceName; + string serviceName = string.IsNullOrWhiteSpace(_serviceName) ? uri.Host : _serviceName; return await SendAsync(request, serviceName, uri, cancellationToken); } @@ -40,8 +44,11 @@ private Uri GetUri(HttpRequestMessage request) $"{request.RequestUri.Scheme}://{_serviceName}/{request.RequestUri.Host}{request.RequestUri.PathAndQuery}") : request.RequestUri; - private async Task SendAsync(HttpRequestMessage request, - string serviceName, Uri uri, CancellationToken cancellationToken) + private async Task SendAsync( + HttpRequestMessage request, + string serviceName, + Uri uri, + CancellationToken cancellationToken) { if (!_options.Enabled) { @@ -53,15 +60,13 @@ private async Task SendAsync(HttpRequestMessage request, return await base.SendAsync(request, cancellationToken); } - private async Task GetRequestUriAsync(HttpRequestMessage request, - string serviceName, Uri uri) + private async Task GetRequestUriAsync( + HttpRequestMessage request, + string serviceName, + Uri uri) { - var service = await _servicesRegistry.GetAsync(serviceName); - if (service is null) - { - throw new ConsulServiceNotFoundException($"Consul service: '{serviceName}' was not found.", - serviceName); - } + var service = await _servicesRegistry.GetAsync(serviceName) + ?? throw new ConsulServiceNotFoundException($"Consul service: '{serviceName}' was not found.", serviceName); if (!_options.SkipLocalhostDockerDnsReplace) { diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index dc627bbb..634d8971 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 7b61f72a..b2e2a65e 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -55,12 +55,12 @@ - + - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index e9428587..a31d1c59 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.MessageBrokers/IBusPublisher.cs b/src/Genocs.MessageBrokers/IBusPublisher.cs index 5fc4da13..c0e995c8 100644 --- a/src/Genocs.MessageBrokers/IBusPublisher.cs +++ b/src/Genocs.MessageBrokers/IBusPublisher.cs @@ -2,6 +2,12 @@ namespace Genocs.MessageBrokers; public interface IBusPublisher { - Task PublishAsync(T message, string? messageId = null, string? correlationId = null, string? spanContext = null, - object? messageContext = null, IDictionary? headers = null) where T : class; + Task PublishAsync( + T message, + string? messageId = null, + string? correlationId = null, + string? spanContext = null, + object? messageContext = null, + IDictionary? headers = null) + where T : class; } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers/MessageAttribute.cs b/src/Genocs.MessageBrokers/MessageAttribute.cs index 2d30ccd6..9ddc4186 100644 --- a/src/Genocs.MessageBrokers/MessageAttribute.cs +++ b/src/Genocs.MessageBrokers/MessageAttribute.cs @@ -7,34 +7,37 @@ namespace Genocs.MessageBrokers; public class MessageAttribute : Attribute { /// - /// The Exchange name + /// The Exchange name. /// public string? Exchange { get; } /// - /// The Routing Key + /// The Routing Key. /// public string? RoutingKey { get; } /// - /// The Queue name + /// The Queue name. /// public string? Queue { get; } /// - /// External + /// External. /// public bool External { get; } /// - /// ctor + /// ctor. /// /// /// /// /// - public MessageAttribute(string? exchange = null, string? routingKey = null, string? queue = null, - bool external = false) + public MessageAttribute( + string? exchange = null, + string? routingKey = null, + string? queue = null, + bool external = false) { Exchange = exchange; RoutingKey = routingKey; diff --git a/src/Genocs.MessageBrokers/MessageProperties.cs b/src/Genocs.MessageBrokers/MessageProperties.cs index e22baab9..f50360f8 100644 --- a/src/Genocs.MessageBrokers/MessageProperties.cs +++ b/src/Genocs.MessageBrokers/MessageProperties.cs @@ -1,11 +1,9 @@ -using System.Collections.Generic; - namespace Genocs.MessageBrokers; public class MessageProperties : IMessageProperties { - public string MessageId { get; set; } - public string CorrelationId { get; set; } + public string? MessageId { get; set; } + public string? CorrelationId { get; set; } public long Timestamp { get; set; } - public IDictionary Headers { get; set; } + public IDictionary? Headers { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index 446ebf52..4829b458 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -24,7 +24,6 @@ public static class Extensions private const string RegistryName = "metrics.metrics"; private static bool _initialized; - [Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 8163801f..01a9d147 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index d757e07a..cabe4f22 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -6,7 +6,7 @@ Genocs.Persistence.MongoDb Genocs.Persistence.MongoDb The Persistence MongoDB Library. - The library containing base repository pattern to build .NET Core projects. + The Genocs Library .NET Core to be used with MongoDB as persistence datalayer.. 10.0 true 5.0.0 @@ -19,9 +19,9 @@ https://github.com/Genocs/genocs-library.git icon.png git - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + mongodb aggregate architecture boilerplate repository-patterns domain-driven-design dotnet-core microservice microservices solid solid-principles README.md - Moved to NET7.0 + Moved to NET8.0 True latest diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs index 50445be5..7c1b0129 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs @@ -11,6 +11,6 @@ public interface IMongoDbSeeder /// Database Seed. /// /// The database. - /// + /// The async Task Task SeedAsync(IMongoDatabase database); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs index b6b4c6a2..2e9d7599 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoSessionFactory.cs @@ -10,6 +10,6 @@ public interface IMongoSessionFactory /// /// Create a new session. /// - /// The ClientSessionHandle. + /// The async ClientSessionHandle. Task CreateAsync(); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs index 2bb18e98..3bee0d81 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs @@ -127,10 +127,10 @@ public async Task SingleAsync(Expression> predicate return await result.SingleAsync(); } - public TEntity FirstOrDefault(TIdentifiable id) + public TEntity? FirstOrDefault(TIdentifiable id) => Collection.Find(c => c.Id.Equals(id)).FirstOrDefault(); - public async Task FirstOrDefaultAsync(TIdentifiable id) + public async Task FirstOrDefaultAsync(TIdentifiable id) { var result = await Collection.FindAsync(c => c.Id.Equals(id)); return await result.FirstOrDefaultAsync(); @@ -139,13 +139,13 @@ public async Task FirstOrDefaultAsync(TIdentifiable id) public TEntity FirstOrDefault(Expression> predicate) => Collection.Find(predicate).FirstOrDefault(); - public async Task FirstOrDefaultAsync(Expression> predicate) + public async Task FirstOrDefaultAsync(Expression> predicate) { var result = await Collection.FindAsync(predicate); return await result.FirstOrDefaultAsync(); } - public TEntity Load(TIdentifiable id) + public TEntity? Load(TIdentifiable id) => FirstOrDefault(id); public TEntity Insert(TEntity entity) @@ -168,13 +168,13 @@ public async Task InsertAndGetIdAsync(TEntity entity) public TEntity InsertOrUpdate(TEntity entity) { - Collection.ReplaceOne(c => c.Id.Equals(entity.Id), entity, new ReplaceOptions { IsUpsert = true }); + Collection.ReplaceOne(c => c.Id!.Equals(entity.Id), entity, new ReplaceOptions { IsUpsert = true }); return entity; } public async Task InsertOrUpdateAsync(TEntity entity) { - await Collection.ReplaceOneAsync(c => c.Id.Equals(entity.Id), entity, new ReplaceOptions { IsUpsert = true }); + await Collection.ReplaceOneAsync(c => c.Id!.Equals(entity.Id), entity, new ReplaceOptions { IsUpsert = true }); return entity; } @@ -186,7 +186,7 @@ public async Task InsertOrUpdateAndGetIdAsync(TEntity entity) public TEntity Update(TEntity entity) { - Collection.ReplaceOne(c => c.Id.Equals(entity.Id), entity); + Collection.ReplaceOne(c => c.Id!.Equals(entity.Id), entity); return entity; } @@ -223,7 +223,7 @@ public void Delete(TIdentifiable id) throw new ArgumentNullException(nameof(id)); } - Collection.DeleteOne(c => c.Id.Equals(id)); + Collection.DeleteOne(c => c.Id!.Equals(id)); } public void Delete(Expression> predicate) @@ -262,7 +262,7 @@ public async Task LongCountAsync(Expression> predicate async Task IRepositoryOfEntity.UpdateAsync(TEntity entity) { - await UpdateAsync(entity, e => e.Id.Equals(entity.Id)); + await UpdateAsync(entity, e => e.Id!.Equals(entity.Id)); return entity; } } \ No newline at end of file diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 8197dc8e..38d45961 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -11,7 +11,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 625336b5..5684f0e2 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -7,7 +7,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 7715409b..fecefc8e 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -58,7 +58,7 @@ - + From 02c2be7978110755596ff81f95f108b6b8c61f0b Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 9 Feb 2024 19:27:06 +0100 Subject: [PATCH 035/104] Setup configuration --- .../Framework/LogContextMiddleware.cs | 2 +- src/apps/orders/Genocs.Orders.WebApi/Program.cs | 3 +-- .../orders/Genocs.Orders.WebApi/appsettings.json | 8 +++++--- .../products/Genocs.Products.WebApi/Program.cs | 6 +++--- .../appsettings.Docker.json | 4 ++-- .../Genocs.Products.WebApi/appsettings.json | 15 +++++++++------ src/apps/signalr/Genocs.SignalR.WebApi/Program.cs | 11 +++++------ .../Genocs.SignalR.WebApi/appsettings.json | 2 +- 8 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/LogContextMiddleware.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/LogContextMiddleware.cs index 7d306530..a1fe66e6 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/LogContextMiddleware.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/LogContextMiddleware.cs @@ -13,7 +13,7 @@ public LogContextMiddleware(CorrelationIdFactory correlationIdFactory) public async Task InvokeAsync(HttpContext context, RequestDelegate next) { - var correlationId = _correlationIdFactory.Create(); + string correlationId = _correlationIdFactory.Create(); using (LogContext.PushProperty("CorrelationId", correlationId)) { await next(context); diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index a93ab27c..4df10ce6 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -10,6 +10,7 @@ using Genocs.MessageBrokers.Outbox; using Genocs.MessageBrokers.Outbox.MongoDB; using Genocs.MessageBrokers.RabbitMQ; +using Genocs.Metrics.AppMetrics; using Genocs.Metrics.Prometheus; using Genocs.Orders.WebApi; using Genocs.Orders.WebApi.Commands; @@ -21,7 +22,6 @@ using Genocs.Persistence.Redis; using Genocs.Secrets.Vault; using Genocs.Tracing; -using Genocs.Metrics.AppMetrics; using Genocs.Tracing.Jaeger; using Genocs.Tracing.Jaeger.RabbitMQ; using Genocs.WebApi; @@ -40,7 +40,6 @@ .WriteTo.Console() .CreateLogger(); - var builder = WebApplication.CreateBuilder(args); builder.Host diff --git a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json index f84e4046..d04f618c 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json +++ b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json @@ -32,7 +32,7 @@ }, "logger": { "applicationName": "orders-service", - "excludePaths": ["/ping", "/metrics"], + "excludePaths": [ "/ping", "/metrics" ], "level": "information", "console": { "enabled": false @@ -64,6 +64,7 @@ "prometheusFormatter": null, "influxUrl": "http://localhost:8086", "database": "test", + "env": "local", "interval": 5 }, "mongodb": { @@ -91,7 +92,8 @@ "virtualHost": "/", "port": 5672, "hostnames": [ - "localhost", "rabbitmq" + "localhost", + "rabbitmq" ], "requestedConnectionTimeout": "00:00:30", "requestedHeartbeat": "00:01:00", @@ -142,7 +144,7 @@ "certificate": { "enabled": true, "header": "Certificate", - "allowedHosts": ["localhost", "order"] + "allowedHosts": [ "localhost", "order" ] } }, "vault": { diff --git a/src/apps/products/Genocs.Products.WebApi/Program.cs b/src/apps/products/Genocs.Products.WebApi/Program.cs index 1000f458..684c6646 100644 --- a/src/apps/products/Genocs.Products.WebApi/Program.cs +++ b/src/apps/products/Genocs.Products.WebApi/Program.cs @@ -9,6 +9,7 @@ using Genocs.MessageBrokers.Outbox; using Genocs.MessageBrokers.Outbox.MongoDB; using Genocs.MessageBrokers.RabbitMQ; +using Genocs.Metrics.AppMetrics; using Genocs.Metrics.Prometheus; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Persistence.Redis; @@ -37,7 +38,6 @@ .WriteTo.Console() .CreateLogger(); - var builder = WebApplication.CreateBuilder(args); builder.Host @@ -55,6 +55,7 @@ .AddFabio() .AddOpenTelemetry() .AddJaeger() + .AddMetrics() .AddMongo() .AddMongoRepository("products") .AddCommandHandlers() @@ -94,5 +95,4 @@ app.Run(); -Log.CloseAndFlush(); - +Log.CloseAndFlush(); \ No newline at end of file diff --git a/src/apps/products/Genocs.Products.WebApi/appsettings.Docker.json b/src/apps/products/Genocs.Products.WebApi/appsettings.Docker.json index 639155ea..b68c544e 100644 --- a/src/apps/products/Genocs.Products.WebApi/appsettings.Docker.json +++ b/src/apps/products/Genocs.Products.WebApi/appsettings.Docker.json @@ -8,7 +8,7 @@ }, "fabio": { "enabled": true, - "url": "http://localhost:9999", + "url": "http://fabio:9999", "service": "products-service" }, "logger": { @@ -30,7 +30,7 @@ "influxEnabled": true, "prometheusEnabled": true, "influxUrl": "http://influxdb:8086", - "env" :"docker" + "env": "docker" }, "prometheus": { "enabled": true diff --git a/src/apps/products/Genocs.Products.WebApi/appsettings.json b/src/apps/products/Genocs.Products.WebApi/appsettings.json index 1b89b8c0..f91c5997 100644 --- a/src/apps/products/Genocs.Products.WebApi/appsettings.json +++ b/src/apps/products/Genocs.Products.WebApi/appsettings.json @@ -11,7 +11,7 @@ "enabled": false, "url": "http://localhost:8500", "service": "products-service", - "address": "docker.for.win.localhost", + "address": "localhost", "port": "5002", "pingEnabled": true, "pingEndpoint": "ping", @@ -21,7 +21,8 @@ "fabio": { "enabled": false, "url": "http://localhost:9999", - "service": "products-service" + "service": "products-service", + "requestRetries": 3 }, "httpClient": { "type": "", @@ -42,7 +43,7 @@ "interval": "day" }, "seq": { - "enabled": false, + "enabled": true, "url": "http://localhost:5341", "token": "secret" } @@ -60,6 +61,7 @@ "enabled": true, "influxEnabled": false, "prometheusEnabled": false, + "prometheusFormatter": null, "influxUrl": "http://localhost:8086", "database": "test", "env": "local", @@ -69,7 +71,7 @@ "connectionString": "mongodb://localhost:27017", "database": "products-service", "seed": false, - "enableTracing" : true + "enableTracing": true }, "prometheus": { "enabled": false @@ -90,7 +92,8 @@ "virtualHost": "/", "port": 5672, "hostnames": [ - "localhost", "rabbitmq" + "localhost", + "rabbitmq" ], "requestedConnectionTimeout": "00:00:30", "requestedHeartbeat": "00:01:00", @@ -141,7 +144,7 @@ "certificate": { "enabled": true, "header": "Certificate", - "allowedHosts": [ "localhost" ,"product"] + "allowedHosts": [ "localhost", "product" ] } }, "vault": { diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs index eb7b9a00..6ddbe92a 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs @@ -7,6 +7,7 @@ using Genocs.MessageBrokers.Outbox; using Genocs.MessageBrokers.Outbox.MongoDB; using Genocs.MessageBrokers.RabbitMQ; +using Genocs.Metrics.AppMetrics; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Secrets.Vault; using Genocs.SignalR.WebApi.Commands; @@ -31,7 +32,6 @@ .WriteTo.Console() .CreateLogger(); - var builder = WebApplication.CreateBuilder(args); builder.Host @@ -51,6 +51,7 @@ .AddErrorHandler() .AddOpenTelemetry() .AddJaeger() + .AddMetrics() .AddMongo() .AddCommandHandlers() .AddEventHandlers() @@ -67,12 +68,12 @@ var app = builder.Build(); - app.UseGenocs() .UserCorrelationContextLogging() .UseErrorHandler() .UseRouting() - .UseEndpoints(r => { + .UseEndpoints(r => + { r.MapControllers(); r.MapHub("/notificationHub"); }) @@ -80,13 +81,11 @@ .Get("", ctx => ctx.Response.WriteAsync("SignalR Service")) .Get("ping", ctx => ctx.Response.WriteAsync("pong")) .Post("notifications", - afterDispatch: (cmd, ctx) => ctx.Response.Created($"notifications/{cmd.NotificationId}")) - ) + afterDispatch: (cmd, ctx) => ctx.Response.Created($"notifications/{cmd.NotificationId}"))) .UseJaeger() .UseSwaggerDocs() .UseRabbitMq(); - app.UseHttpsRedirection(); app.UseStaticFiles(); diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json b/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json index bd12c5fb..85b6c681 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json +++ b/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json @@ -87,7 +87,7 @@ } }, "metrics": { - "enabled": false, + "enabled": true, "influxEnabled": false, "prometheusEnabled": false, "influxUrl": "http://localhost:8086", From 99ac6373f8774c73de507419425b9840928f5fde Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Mon, 19 Feb 2024 21:52:04 +0100 Subject: [PATCH 036/104] Reverted reference framework --- Directory.Build.props | 2 +- src/Genocs.Auth/Genocs.Auth.csproj | 2 +- src/Genocs.Common/Genocs.Common.csproj | 2 +- .../Genocs.Core.UnitTests.csproj | 4 +-- src/Genocs.Core/Genocs.Core.csproj | 26 +++++++++---------- .../Genocs.Discovery.Consul.csproj | 2 +- .../Genocs.HTTP.RestEase.csproj | 2 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Genocs.LoadBalancing.Fabio.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 2 +- .../Genocs.MessageBrokers.Outbox.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- .../Genocs.MessageBrokers.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- .../Genocs.Monitoring.csproj | 2 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 4 +-- .../Genocs.Persistence.MongoDb.csproj | 4 +-- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +-- .../Genocs.Secrets.Vault.csproj | 2 +- src/Genocs.Security/Genocs.Security.csproj | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 4 +-- .../Genocs.ServiceBusAzure.csproj | 2 +- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 2 +- src/Genocs.Tracing/Genocs.Tracing.csproj | 2 +- .../Genocs.WebApi.CQRS.csproj | 2 +- .../Genocs.WebApi.Security.csproj | 2 +- .../Genocs.WebApi.Swagger.csproj | 2 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 2 +- 30 files changed, 46 insertions(+), 48 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index dfc912e7..e545ebbb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 8e08a3f7..5509a98e 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Auth Genocs.Auth Genocs.Auth diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 71b4167a..0ae4fc34 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -1,7 +1,7 @@  - netstandard2.1;net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0;netstandard2.1 Genocs.Common Genocs.Common Genocs.Common diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 5a325f34..d08f8706 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index b417032f..2a958ba8 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -1,7 +1,7 @@  - netstandard2.1;net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0;netstandard2.1 Genocs.Core Genocs.Core Genocs.Core @@ -49,23 +49,12 @@ - - - - - - - - - - - - + @@ -73,8 +62,17 @@ - + + + + + + + + + + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index d1b22aa1..89e6fd98 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Discovery.Consul Genocs.Discovery.Consul Genocs.Discovery.Consul diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index ebc40049..41f78a71 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.HTTP.RestEase Genocs.HTTP.RestEase Genocs.HTTP.RestEase diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 634d8971..09f77df5 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.HTTP Genocs.HTTP Genocs.HTTP diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 9300fa11..c2ba5fcd 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.LoadBalancing.Fabio Genocs.LoadBalancing.Fabio Genocs.LoadBalancing.Fabio diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index b2e2a65e..4fc3c4e0 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Logging Genocs.Logging Genocs.Logging diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 05c831d0..63769706 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.MessageBrokers.Outbox.MongoDB Genocs.MessageBrokers.Outbox.MongoDB Genocs.MessageBrokers.Outbox.MongoDB diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 85bf7181..07edad63 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.MessageBrokers.Outbox Genocs.MessageBrokers.Outbox Genocs.MessageBrokers.Outbox diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index a31d1c59..31aeaf2c 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.MessageBrokers.RabbitMQ Genocs.MessageBrokers.RabbitMQ Genocs.MessageBrokers.RabbitMQ diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index cdc92fba..d40a6c53 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.MessageBrokers Genocs.MessageBrokers Genocs.MessageBrokers diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index ae3db412..57f0f9bb 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Metrics Genocs.Metrics Genocs.Metrics diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 98a95250..d4a1c0b4 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Monitoring Genocs.Monitoring Genocs.Monitoring diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 01a9d147..c45a05ea 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -12,8 +12,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index cabe4f22..f3b24c06 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Persistence.MongoDb Genocs.Persistence.MongoDb Genocs.Persistence.MongoDb @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index d062bc70..fc794cb3 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Persistence.Redis Genocs.Persistence.Redis Genocs.Persistence.Redis diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 38d45961..5cad2f93 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -14,8 +14,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 281bf019..d70d81f6 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Secrets.Vault Genocs.Secrets.Vault Genocs.Secrets.Vault diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 63807237..d9149076 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Security Genocs.Security Genocs.Security diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 5684f0e2..f670d0e1 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 364a2c6e..0683a3ba 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.ServiceBusAzure Genocs.ServiceBusAzure Genocs.ServiceBusAzure diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index e757e910..420baf36 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Tracing.Jaeger.RabbitMQ Genocs.Tracing.Jaeger.RabbitMQ Genocs.Tracing.Jaeger.RabbitMQ diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index fecefc8e..e8196f3c 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.Tracing Genocs.Tracing Genocs.Tracing diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 11512a6e..a1144df4 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.WebApi.CQRS Genocs.WebApi.CQRS Genocs.WebApi.CQRS diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 50b7437e..06635225 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.WebApi.Security Genocs.WebApi.Security Genocs.WebApi.Security diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index ae9fa8d4..74828dae 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.WebApi.Swagger Genocs.WebApi.Swagger Genocs.WebApi.Swagger diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 7a0ab5ff..7f8c6cec 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -1,7 +1,7 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Genocs.WebApi Genocs.WebApi Genocs.WebApi From 0af67b813a1c7d70d5a7b5f0d3fc8fdf5e7071da Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Mon, 19 Feb 2024 22:18:56 +0100 Subject: [PATCH 037/104] Fix --- src/Genocs.Discovery.Consul/Extensions.cs | 6 +-- .../Options/ConsulSettings.cs | 18 +++---- .../Services/ConsulServicesRegistry.cs | 13 ++--- .../Options/RestEaseSettings.cs | 10 ++-- src/Genocs.LoadBalancing.Fabio/Extensions.cs | 2 +- .../Options/FabioSettings.cs | 6 +-- src/Genocs.Security/Services/Encryptor.cs | 2 +- src/Genocs.Security/Services/Hasher.cs | 4 +- src/Genocs.Security/Services/Signer.cs | 8 +-- src/Genocs.WebApi/EndpointsBuilder.cs | 12 ++--- src/Genocs.WebApi/IEndpointsBuilder.cs | 54 ++++++++++--------- .../Genocs.Identities.WebApi/Program.cs | 4 +- 12 files changed, 69 insertions(+), 70 deletions(-) diff --git a/src/Genocs.Discovery.Consul/Extensions.cs b/src/Genocs.Discovery.Consul/Extensions.cs index ac934f94..ecebcb98 100644 --- a/src/Genocs.Discovery.Consul/Extensions.cs +++ b/src/Genocs.Discovery.Consul/Extensions.cs @@ -80,8 +80,7 @@ public static void AddConsulHttpClient(this IGenocsBuilder builder, string clien c.GetRequiredService(), c.GetRequiredService(), serviceName, true)); - private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, - ConsulSettings options) + private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulSettings options) { bool enabled = options.Enabled; string? consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); @@ -97,8 +96,7 @@ private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBui if (string.IsNullOrWhiteSpace(options.Address)) { - throw new ArgumentException("Consul address can not be empty.", - nameof(options.PingEndpoint)); + throw new ArgumentException("Consul address can not be empty.", nameof(options.PingEndpoint)); } builder.Services.AddHttpClient(c => c.BaseAddress = new Uri(options.Url)); diff --git a/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs b/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs index df0c848b..d16f9642 100644 --- a/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs +++ b/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs @@ -3,19 +3,19 @@ namespace Genocs.Discovery.Consul.Options; public class ConsulSettings { public bool Enabled { get; set; } - public string Url { get; set; } - public string Service { get; set; } - public string Address { get; set; } + public string? Url { get; set; } + public string? Service { get; set; } + public string? Address { get; set; } public int Port { get; set; } public bool PingEnabled { get; set; } - public string PingEndpoint { get; set; } - public string PingInterval { get; set; } - public string RemoveAfterInterval { get; set; } - public List Tags { get; set; } - public IDictionary Meta { get; set; } + public string? PingEndpoint { get; set; } + public string? PingInterval { get; set; } + public string? RemoveAfterInterval { get; set; } + public List? Tags { get; set; } + public IDictionary? Meta { get; set; } public bool EnableTagOverride { get; set; } public bool SkipLocalhostDockerDnsReplace { get; set; } - public ConnectSettings Connect { get; set; } + public ConnectSettings? Connect { get; set; } public class ConnectSettings { diff --git a/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs b/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs index 78df40b9..f498ca44 100644 --- a/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs +++ b/src/Genocs.Discovery.Consul/Services/ConsulServicesRegistry.cs @@ -35,15 +35,12 @@ public ConsulServicesRegistry(IConsulService consulService) private ServiceAgent? GetService(IDictionary services, string name) { - switch (services.Count) + return services.Count switch { - case 0: - return null; - case 1: - return services.First().Value; - default: - return ChooseService(services, name); - } + 0 => null, + 1 => services.First().Value, + _ => ChooseService(services, name), + }; } private ServiceAgent ChooseService(IDictionary services, string name) diff --git a/src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs b/src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs index 5c14911b..f5b4c1f3 100644 --- a/src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs +++ b/src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs @@ -2,14 +2,14 @@ namespace Genocs.HTTP.RestEase.Options; public class RestEaseSettings { - public string LoadBalancer { get; set; } - public IEnumerable Services { get; set; } + public string? LoadBalancer { get; set; } + public IEnumerable? Services { get; set; } public class Service { - public string Name { get; set; } - public string Scheme { get; set; } - public string Host { get; set; } + public string? Name { get; set; } + public string? Scheme { get; set; } + public string? Host { get; set; } public int Port { get; set; } } } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Extensions.cs b/src/Genocs.LoadBalancing.Fabio/Extensions.cs index 96c2b1a3..e0e507f9 100644 --- a/src/Genocs.LoadBalancing.Fabio/Extensions.cs +++ b/src/Genocs.LoadBalancing.Fabio/Extensions.cs @@ -99,7 +99,7 @@ private static void UpdateConsulRegistration(this IServiceCollection services, private static List GetFabioTags(string consulService, string fabioService) { - var service = (string.IsNullOrWhiteSpace(fabioService) ? consulService : fabioService) + string service = (string.IsNullOrWhiteSpace(fabioService) ? consulService : fabioService) .ToLowerInvariant(); return new List { $"urlprefix-/{service} strip=/{service}" }; diff --git a/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs b/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs index 8753d710..f7e6d9ab 100644 --- a/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs +++ b/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs @@ -1,12 +1,12 @@ namespace Genocs.LoadBalancing.Fabio.Options; /// -/// The Fabio settings +/// The Fabio settings. /// public class FabioSettings { /// - /// The default Fabio section name + /// The default Fabio section name. /// public const string Position = "fabio"; @@ -16,7 +16,7 @@ public class FabioSettings public bool Enabled { get; set; } /// - /// + /// The service url. /// public string? Url { get; set; } diff --git a/src/Genocs.Security/Services/Encryptor.cs b/src/Genocs.Security/Services/Encryptor.cs index 10f13b43..320feaa7 100644 --- a/src/Genocs.Security/Services/Encryptor.cs +++ b/src/Genocs.Security/Services/Encryptor.cs @@ -19,7 +19,7 @@ public string Encrypt(string data, string key) using var aes = Aes.Create(); aes.Key = Encoding.UTF8.GetBytes(key); - var iv = Convert.ToBase64String(aes.IV); + string iv = Convert.ToBase64String(aes.IV); var transform = aes.CreateEncryptor(aes.Key, aes.IV); using var memoryStream = new MemoryStream(); using var cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write); diff --git a/src/Genocs.Security/Services/Hasher.cs b/src/Genocs.Security/Services/Hasher.cs index 4cd31a14..f299e33a 100644 --- a/src/Genocs.Security/Services/Hasher.cs +++ b/src/Genocs.Security/Services/Hasher.cs @@ -7,9 +7,9 @@ internal sealed class Hasher : IHasher { public string Hash(string data) { - var hash = Hash(Encoding.UTF8.GetBytes(data)); + byte[] hash = Hash(Encoding.UTF8.GetBytes(data)); var builder = new StringBuilder(); - foreach (var @byte in hash) + foreach (byte @byte in hash) { builder.Append(@byte.ToString("x2")); } diff --git a/src/Genocs.Security/Services/Signer.cs b/src/Genocs.Security/Services/Signer.cs index f4de9da4..54de2b1d 100644 --- a/src/Genocs.Security/Services/Signer.cs +++ b/src/Genocs.Security/Services/Signer.cs @@ -18,8 +18,8 @@ public string Sign(object data, X509Certificate2 certificate) throw new ArgumentNullException(nameof(certificate), "Certificate cannot be null."); } - var bytes = JsonSerializer.SerializeToUtf8Bytes(data); - var signature = Sign(bytes, certificate); + byte[] bytes = JsonSerializer.SerializeToUtf8Bytes(data); + byte[] signature = Sign(bytes, certificate); return BitConverter.ToString(signature).Replace("-", string.Empty); } @@ -107,8 +107,8 @@ public bool Verify(byte[] data, X509Certificate2 certificate, byte[] signature, private static byte[] ToByteArray(string hex) { - var bytes = new byte[hex.Length / 2]; - for (var i = 0; i < hex.Length; i += 2) + byte[] bytes = new byte[hex.Length / 2]; + for (int i = 0; i < hex.Length; i += 2) { bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); } diff --git a/src/Genocs.WebApi/EndpointsBuilder.cs b/src/Genocs.WebApi/EndpointsBuilder.cs index 0a55176d..1173be2b 100644 --- a/src/Genocs.WebApi/EndpointsBuilder.cs +++ b/src/Genocs.WebApi/EndpointsBuilder.cs @@ -46,7 +46,7 @@ public IEndpointsBuilder Get(string path, Func? context } public IEndpointsBuilder Get(string path, Func context = null, - Action endpoint = null, bool auth = false, string roles = null, + Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) where TRequest : class { @@ -59,7 +59,7 @@ public IEndpointsBuilder Get(string path, Func context = null, - Action endpoint = null, bool auth = false, string roles = null, + Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) { var builder = _routeBuilder.MapPost(path, ctx => context?.Invoke(ctx)); @@ -71,7 +71,7 @@ public IEndpointsBuilder Post(string path, Func context = nul } public IEndpointsBuilder Post(string path, Func context = null, - Action endpoint = null, bool auth = false, string roles = null, + Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) where T : class { @@ -84,7 +84,7 @@ public IEndpointsBuilder Post(string path, Func context } public IEndpointsBuilder Put(string path, Func context = null, - Action endpoint = null, bool auth = false, string roles = null, + Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) { var builder = _routeBuilder.MapPut(path, ctx => context?.Invoke(ctx)); @@ -96,7 +96,7 @@ public IEndpointsBuilder Put(string path, Func context = null } public IEndpointsBuilder Put(string path, Func context = null, - Action endpoint = null, bool auth = false, string roles = null, + Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) where T : class { @@ -109,7 +109,7 @@ public IEndpointsBuilder Put(string path, Func context } public IEndpointsBuilder Delete(string path, Func context = null, - Action endpoint = null, bool auth = false, string roles = null, + Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) { var builder = _routeBuilder.MapDelete(path, ctx => context?.Invoke(ctx)); diff --git a/src/Genocs.WebApi/IEndpointsBuilder.cs b/src/Genocs.WebApi/IEndpointsBuilder.cs index e7ea4b53..89a49f33 100644 --- a/src/Genocs.WebApi/IEndpointsBuilder.cs +++ b/src/Genocs.WebApi/IEndpointsBuilder.cs @@ -5,35 +5,39 @@ namespace Genocs.WebApi; public interface IEndpointsBuilder { - IEndpointsBuilder Get(string path, - Func? context = null, - Action? endpoint = null, - bool auth = false, - string? roles = null, - params string[] policies); - - IEndpointsBuilder Get(string path, - Func? context = null, - Action? endpoint = null, - bool auth = false, - string? roles = null, - params string[] policies) + IEndpointsBuilder Get( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); + + IEndpointsBuilder Get( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where T : class; - IEndpointsBuilder Get(string path, - Func? context = null, - Action? endpoint = null, - bool auth = false, - string? roles = null, - params string[] policies) + IEndpointsBuilder Get( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where TRequest : class; - IEndpointsBuilder Post(string path, - Func? context = null, - Action? endpoint = null, - bool auth = false, - string? roles = null, - params string[] policies); + IEndpointsBuilder Post( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); IEndpointsBuilder Post(string path, Func? context = null, Action? endpoint = null, bool auth = false, string? roles = null, diff --git a/src/apps/identity/Genocs.Identities.WebApi/Program.cs b/src/apps/identity/Genocs.Identities.WebApi/Program.cs index 1a840d1a..b19e5aa5 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Program.cs +++ b/src/apps/identity/Genocs.Identities.WebApi/Program.cs @@ -36,7 +36,7 @@ app.UseCore(); app.UseDispatcherEndpoints(endpoints => endpoints - .Get("", ctx => ctx.GetAppName()) + .Get(string.Empty, ctx => ctx.GetAppName()) .Post("sign-in", afterDispatch: (cmd, ctx) => { var auth = ctx.RequestServices.GetRequiredService().Get(cmd.Id); @@ -44,7 +44,7 @@ }) .Post("sign-up", afterDispatch: (cmd, ctx) => { - ctx.Response.Headers.Add("user-id", cmd.UserId.ToString()); + ctx.Response.Headers.Append("user-id", cmd.UserId.ToString()); return Task.CompletedTask; }) .Post("access-tokens/revoke", auth: true, roles: "admin") From 3887c171b97543ee47e8e182e63964e6b5f8667e Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 31 Mar 2024 13:54:17 +0200 Subject: [PATCH 038/104] Updated nuget packages to prepare for removing legacy behavior --- Directory.Build.props | 2 +- src/Genocs.Auth/Genocs.Auth.csproj | 2 +- .../Genocs.Core.Demo.WebApi.csproj | 2 +- .../Genocs.Core.Demo.Worker.csproj | 4 +- .../MassTransitConsoleHostedService.cs | 2 +- .../Genocs.Core.UnitTests.csproj | 2 +- src/Genocs.Core/Builders/ServiceId.cs | 2 - .../Extensions/CollectionExtensions.cs | 2 - .../AutoRepositoryTypesAttribute.cs | 2 - .../Extensions/StringExtensions.cs | 4 +- src/Genocs.Core/Genocs.Core.csproj | 4 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 4 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 2 +- .../Genocs.ServiceBusAzure.csproj | 2 +- .../Topics/AzureServiceBusTopic.cs | 43 ++++++++++--------- src/Genocs.WebApi/Extensions.cs | 6 +-- .../orders/Genocs.Orders.WebApi/Program.cs | 2 +- 22 files changed, 47 insertions(+), 52 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index e545ebbb..109e38eb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 5509a98e..b24b556b 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -65,7 +65,7 @@ - + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 0dde951c..9aafbcb6 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index a934501b..6184463e 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs b/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs index 39f50b58..e972d775 100644 --- a/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs +++ b/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs @@ -3,7 +3,7 @@ namespace Genocs.Core.Demo.Worker; /// -/// General purpose worker. Please check the link below for further informations +/// General purpose worker. Please check the link below for further information /// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-7.0&tabs=visual-studio /// public class MassTransitConsoleHostedService : IHostedService diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index d08f8706..a2311542 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -13,7 +13,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Core/Builders/ServiceId.cs b/src/Genocs.Core/Builders/ServiceId.cs index 8a9742c8..6b2200f5 100644 --- a/src/Genocs.Core/Builders/ServiceId.cs +++ b/src/Genocs.Core/Builders/ServiceId.cs @@ -1,7 +1,5 @@ namespace Genocs.Core.Builders; -using System; - internal class ServiceId : IServiceId { public string Id { get; } = $"{Guid.NewGuid():N}"; diff --git a/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs b/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs index edadc987..71ba80bf 100644 --- a/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs @@ -1,7 +1,5 @@ namespace Genocs.Core.Collections.Extensions { - using System; - using System.Collections.Generic; /// /// Extension methods for Collections. diff --git a/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs b/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs index 315403fe..f1734ebd 100644 --- a/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs +++ b/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs @@ -1,7 +1,5 @@ namespace Genocs.Core.Domain.Repositories { - using System; - /// /// Used to define auto-repository types for entities. /// This can be used for DbContext types. diff --git a/src/Genocs.Core/Extensions/StringExtensions.cs b/src/Genocs.Core/Extensions/StringExtensions.cs index b85987a3..5841f1c2 100644 --- a/src/Genocs.Core/Extensions/StringExtensions.cs +++ b/src/Genocs.Core/Extensions/StringExtensions.cs @@ -136,7 +136,7 @@ public static class StringExtensions /// Gets index of nth occurrence of a char in a string. /// /// source string to be searched. - /// Char to search in . + /// Char to search in . /// Count of the occurrence. public static int NthIndexOf(this string str, char c, int n) { @@ -222,7 +222,7 @@ public static int NthIndexOf(this string str, char c, int n) /// /// Gets a substring of a string from end of the string. /// - /// Thrown if is null.exception> + /// Thrown if is null. /// Thrown if is bigger that string's length. public static string? Right(this string? str, int len) { diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 2a958ba8..42fbdfc5 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -70,9 +70,9 @@ - + - + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 09f77df5..8fa7e5bf 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 31aeaf2c..2777cae4 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index c45a05ea..5921d7b5 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index f3b24c06..dae81f0d 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index fc794cb3..cb7c877b 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 5cad2f93..1b30c865 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -13,13 +13,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index f670d0e1..e5d40229 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -13,7 +13,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 0683a3ba..ff1e0031 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -53,7 +53,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs b/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs index 0fe896e5..46367ca4 100644 --- a/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs +++ b/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs @@ -74,9 +74,9 @@ public AzureServiceBusTopic(AzureServiceBusTopicSettings options, public async Task PublishAsync(IEvent @event) { - var eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, ""); - var jsonMessage = JsonConvert.SerializeObject(@event); - var body = Encoding.UTF8.GetBytes(jsonMessage); + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); var message = new Message { @@ -91,9 +91,9 @@ public async Task PublishAsync(IEvent @event) public async Task PublishAsync(IEvent @event, Dictionary filters) { - var eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, ""); - var jsonMessage = JsonConvert.SerializeObject(@event); - var body = Encoding.UTF8.GetBytes(jsonMessage); + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); var message = new Message { @@ -112,9 +112,9 @@ public async Task PublishAsync(IEvent @event, Dictionary filters public async Task ScheduleAsync(IEvent @event, DateTimeOffset offset) { - var eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, ""); - var jsonMessage = JsonConvert.SerializeObject(@event); - var body = Encoding.UTF8.GetBytes(jsonMessage); + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); var message = new Message { @@ -127,9 +127,9 @@ public async Task ScheduleAsync(IEvent @event, DateTimeOffset offset) public async Task ScheduleAsync(IEvent @event, DateTimeOffset offset, Dictionary filters) { - var eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, ""); - var jsonMessage = JsonConvert.SerializeObject(@event); - var body = Encoding.UTF8.GetBytes(jsonMessage); + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); var message = new Message { @@ -156,8 +156,8 @@ public void Subscribe() where T : IEvent where TH : IEventHandlerLegacy { - var eventName = typeof(T).Name.Replace(EVENT_SUFFIX, ""); - var key = typeof(T).Name; + string eventName = typeof(T).Name.Replace(EVENT_SUFFIX, ""); + string key = typeof(T).Name; if (!_handlers.ContainsKey(key)) { _handlers.Add(key, new List()); @@ -168,6 +168,7 @@ public void Subscribe() // Name = eventName //}).GetAwaiter().GetResult(); } + Type handlerType = typeof(TH); if (_handlers[key].Any(s => s.HandlerType == handlerType)) @@ -182,7 +183,6 @@ public void Subscribe() } _handlers[key].Add(SubscriptionInfo.Typed(handlerType)); - } private void RegisterSubscriptionClientMessageHandler() @@ -190,8 +190,8 @@ private void RegisterSubscriptionClientMessageHandler() _subscriptionClient.RegisterMessageHandler( async (message, token) => { - var eventName = $"{message.Label}{EVENT_SUFFIX}"; - var messageData = Encoding.UTF8.GetString(message.Body); + string eventName = $"{message.Label}{EVENT_SUFFIX}"; + string messageData = Encoding.UTF8.GetString(message.Body); // Complete the message so that it is not received again. if (await ProcessEvent(eventName, messageData)) @@ -212,10 +212,9 @@ private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceiv return Task.CompletedTask; } - private async Task ProcessEvent(string eventName, string message) { - var processed = false; + bool processed = false; if (_handlers.ContainsKey(eventName)) { using (var scope = _serviceProvider.CreateScope()) @@ -224,22 +223,24 @@ private async Task ProcessEvent(string eventName, string message) foreach (var subscription in subscriptions) { - var handler = scope.ServiceProvider.GetRequiredService(subscription.HandlerType); + object handler = scope.ServiceProvider.GetRequiredService(subscription.HandlerType); if (handler != null) { var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); - var command = JsonConvert.DeserializeObject(message, eventType); + object command = JsonConvert.DeserializeObject(message, eventType); var concreteType = typeof(IEventHandler<>).MakeGenericType(eventType); await (Task)concreteType.GetMethod("HandleEvent").Invoke(handler, new object[] { command }); } } } + processed = true; } else { _logger.LogError($"Event '{eventName}' do not contains handlers. Check whether Subscribe is set"); } + return processed; } } diff --git a/src/Genocs.WebApi/Extensions.cs b/src/Genocs.WebApi/Extensions.cs index acc4d596..cdbec57e 100644 --- a/src/Genocs.WebApi/Extensions.cs +++ b/src/Genocs.WebApi/Extensions.cs @@ -184,7 +184,7 @@ private static TModel Bind(this TModel model, Expression x.Name.ToLowerInvariant().StartsWith($"<{propertyName}>")); @@ -363,7 +363,7 @@ public static T ReadQuery(this HttpContext context) where T : class { var queryString = HttpUtility.ParseQueryString(request.HttpContext.Request.QueryString.Value); values ??= new RouteValueDictionary(); - foreach (var key in queryString.AllKeys) + foreach (string? key in queryString.AllKeys) { values.TryAdd(key, queryString[key]); } @@ -375,7 +375,7 @@ public static T ReadQuery(this HttpContext context) where T : class return serializer.Deserialize(EmptyJsonObject); } - var serialized = serializer.Serialize(values.ToDictionary(k => k.Key, k => k.Value)) + string? serialized = serializer.Serialize(values.ToDictionary(k => k.Key, k => k.Value)) ?.Replace("\\\"", "\"") .Replace("\"{", "{") .Replace("}\"", "}") diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index 4df10ce6..45e41f78 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -85,7 +85,7 @@ .UseCertificateAuthentication() .UseEndpoints(r => r.MapControllers()) .UseDispatcherEndpoints(endpoints => endpoints - .Get("", ctx => ctx.Response.WriteAsync("Orders Service")) + .Get(string.Empty, ctx => ctx.Response.WriteAsync("Orders Service")) .Get("ping", ctx => ctx.Response.WriteAsync("pong")) .Get("orders/{orderId}") .Post("orders", From 7b8bf5dfb9d5bdb0c8244a52239af7707c290862 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 4 Apr 2024 14:53:54 +0200 Subject: [PATCH 039/104] Updated github action --- .github/workflows/build_and_test.yml | 2 +- .github/workflows/dockerhub-publish.yml | 4 ++-- .github/workflows/nuget-publish.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index c4579a69..5db7cfe0 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml index 8b656b21..4566a8fc 100644 --- a/.github/workflows/dockerhub-publish.yml +++ b/.github/workflows/dockerhub-publish.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x @@ -46,7 +46,7 @@ jobs: run: dotnet pack --no-build --verbosity normal - name: Docker Hub Log in - uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index aa8893aa..b1b9bb80 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x From cc0d47898ac8f705e9cb17837eb5f272d6a77bc2 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 4 May 2024 17:14:40 +0200 Subject: [PATCH 040/104] Refactored code for readability and updated variable types Reformatted several constructors and methods across multiple classes for improved readability, without altering functionality. Explicitly defined variable types in `PublishNotificationHandler`, `ExceptionToResponseMapper`, and `GenocsHub` classes. Changed the return type of `UseSignalR` method in `Extensions.cs` and uncommented code. Updated URL and commented out `start` function in `appV2.js`, adding a console log for successful SignalR connection. --- .../Commands/Handlers/PublishNotificationHandler.cs | 5 +++-- .../Commands/PublishNotification.cs | 1 - .../Events/NotificationPosted.cs | 1 - .../Exceptions/AppException.cs | 3 ++- .../Exceptions/ExceptionToResponseMapper.cs | 4 ++-- .../Genocs.SignalR.WebApi/Framework/Extensions.cs | 13 ++++++------- .../Handlers/OperationUpdatedHandler.cs | 2 +- .../signalr/Genocs.SignalR.WebApi/Hubs/GenocsHub.cs | 2 +- .../Messages/Events/OperationCompleted.cs | 7 +++++-- .../Messages/Events/OperationPending.cs | 7 +++++-- .../Messages/Events/OperationRejected.cs | 10 +++++++--- .../Options/SignalRSettings.cs | 2 +- .../Genocs.SignalR.WebApi/Services/HubService.cs | 6 ++---- .../wwwroot/signalr/js/appV2.js | 8 +++++--- 14 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs index c7413bf9..e328edb7 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs @@ -16,7 +16,8 @@ public class PublishNotificationHandler : ICommandHandler private readonly ITracer _tracer; private readonly IHubContext _hub; - public PublishNotificationHandler(IBusPublisher publisher, + public PublishNotificationHandler( + IBusPublisher publisher, IMessageOutbox outbox, ITracer tracer, ILogger logger, @@ -32,7 +33,7 @@ public PublishNotificationHandler(IBusPublisher publisher, public async Task HandleAsync(PublishNotification command, CancellationToken cancellationToken = default) { _logger.LogInformation($"Created a notification with id: {command.NotificationId}, customer: {command.CustomerId}."); - var spanContext = _tracer.ActiveSpan?.Context.ToString(); + string? spanContext = _tracer.ActiveSpan?.Context.ToString(); var @event = new NotificationPosted(command.NotificationId); // Send the notification diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Commands/PublishNotification.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Commands/PublishNotification.cs index a43fe802..1155fbe9 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Commands/PublishNotification.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Commands/PublishNotification.cs @@ -8,7 +8,6 @@ public class PublishNotification : ICommand public Guid CustomerId { get; } public string Message { get; } - public PublishNotification(Guid notificationId, Guid customerId, string message) { NotificationId = notificationId == Guid.Empty ? Guid.NewGuid() : notificationId; diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Events/NotificationPosted.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Events/NotificationPosted.cs index 105eebca..78d68fa8 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Events/NotificationPosted.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Events/NotificationPosted.cs @@ -5,7 +5,6 @@ public class NotificationPosted public Guid NotificationId { get; } - public NotificationPosted(Guid notificationId) { NotificationId = notificationId; diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/AppException.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/AppException.cs index c2c32bfd..c4bae6e2 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/AppException.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/AppException.cs @@ -2,7 +2,8 @@ public abstract class AppException : Exception { - protected AppException(string message) : base(message) + protected AppException(string message) + : base(message) { } } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs index defa89b8..8ad5af5b 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs @@ -12,7 +12,7 @@ public class ExceptionToResponseMapper : IExceptionToResponseMapper public ExceptionResponse Map(Exception exception) => exception switch { - //DomainException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, + // DomainException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, // HttpStatusCode.BadRequest), AppException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, HttpStatusCode.BadRequest), @@ -28,7 +28,7 @@ private static string GetCode(Exception exception) return code; } - var exceptionCode = exception.GetType().Name.Underscore().Replace("_exception", string.Empty); + string exceptionCode = exception.GetType().Name.Underscore().Replace("_exception", string.Empty); Codes.TryAdd(type, exceptionCode); return exceptionCode; diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs index 6196760c..4339e3f3 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs @@ -20,15 +20,14 @@ public static IGenocsBuilder AddSignalR(this IGenocsBuilder builder) return builder; } - - public static IApplicationBuilder UseSignalR(this IApplicationBuilder builder) + public static IGenocsBuilder UseSignalR(this IGenocsBuilder builder) { - // var options = builder.GetOptions("signalr"); + var options = builder.GetOptions("signalr"); - // if (options is not null) - // { - // builder.Services.AddSingleton(options); - // } + if (options is not null) + { + builder.Services.AddSingleton(options); + } return builder; } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs index 0d0f5f10..34617883 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs @@ -9,7 +9,7 @@ public class OperationUpdatedHandler : IEventHandler, { private readonly IHubService _hubService; - public OperationUpdatedHandler(IHubService hubService) + public OperationUpdatedHandler(IHubService hubService) => _hubService = hubService ?? throw new ArgumentNullException(nameof(hubService)); public async Task HandleAsync(OperationPending @event, CancellationToken cancellationToken = default) diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Hubs/GenocsHub.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Hubs/GenocsHub.cs index d8ae21eb..7567b642 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Hubs/GenocsHub.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Hubs/GenocsHub.cs @@ -27,7 +27,7 @@ public async Task InitializeAsync(string token) return; } - var group = Guid.Parse(payload.Subject).ToUserGroup(); + string group = Guid.Parse(payload.Subject).ToUserGroup(); await Groups.AddToGroupAsync(Context.ConnectionId, group); await ConnectAsync(); } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationCompleted.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationCompleted.cs index e4e5fcc5..66c49b9a 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationCompleted.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationCompleted.cs @@ -13,8 +13,11 @@ public class OperationCompleted : IEvent public string Resource { get; } [JsonConstructor] - public OperationCompleted(Guid id, - Guid userId, string name, string resource) + public OperationCompleted( + Guid id, + Guid userId, + string name, + string resource) { Id = id; UserId = userId; diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationPending.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationPending.cs index b98d0206..53848460 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationPending.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationPending.cs @@ -13,8 +13,11 @@ public class OperationPending : IEvent public string Resource { get; } [JsonConstructor] - public OperationPending(Guid id, - Guid userId, string name, string resource) + public OperationPending( + Guid id, + Guid userId, + string name, + string resource) { Id = id; UserId = userId; diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationRejected.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationRejected.cs index 749ac634..f6055ad6 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationRejected.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Messages/Events/OperationRejected.cs @@ -15,9 +15,13 @@ public class OperationRejected : IEvent public string Message { get; } [JsonConstructor] - public OperationRejected(Guid id, - Guid userId, string name, string resource, - string code, string message) + public OperationRejected( + Guid id, + Guid userId, + string name, + string resource, + string code, + string message) { Id = id; UserId = userId; diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs index 1786da94..1b1572fa 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs @@ -1,7 +1,7 @@ namespace Genocs.SignalR.WebApi.Options; /// -/// The signalR Settings definition +/// The signalR Settings definition. /// public class SignalRSettings { diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs index e81fd8f7..257bdb90 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs @@ -6,10 +6,9 @@ public class HubService : IHubService { private readonly IHubWrapper _hubContextWrapper; - public HubService(IHubWrapper hubContextWrapper) + public HubService(IHubWrapper hubContextWrapper) => _hubContextWrapper = hubContextWrapper ?? throw new ArgumentNullException(nameof(hubContextWrapper)); - public async Task PublishOperationPendingAsync(OperationPending @event) => await _hubContextWrapper.PublishToUserAsync(@event.UserId, "operation_pending", @@ -42,6 +41,5 @@ public async Task PublishOperationRejectedAsync(OperationRejected @event) resource = @event.Resource, code = @event.Code, reason = @event.Message - } - ); + }); } \ No newline at end of file diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/wwwroot/signalr/js/appV2.js b/src/apps/signalr/Genocs.SignalR.WebApi/wwwroot/signalr/js/appV2.js index 1965d07c..488f0c63 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/wwwroot/signalr/js/appV2.js +++ b/src/apps/signalr/Genocs.SignalR.WebApi/wwwroot/signalr/js/appV2.js @@ -6,7 +6,7 @@ const $messages = document.getElementById("messages"); const connection = new signalR.HubConnectionBuilder() - .withUrl("http://localhost:5007/notificationHub") + .withUrl("https://localhost:5014/notificationHub") .configureLogging(signalR.LogLevel.Information) .build(); @@ -20,6 +20,7 @@ } }; + // Start the connection. $connect.onclick = function () { const jwt = $jwt.value; if (!jwt || /\s/g.test(jwt)) { @@ -30,7 +31,8 @@ appendMessage('Connecting to Genocs Hub...'); connection.start() .then(() => { - //connection.invoke('initializeAsync', $jwt.value); + console.log("SignalR Connected."); + connection.invoke('initializeAsync', $jwt.value); }) .catch(err => appendMessage(err)); } @@ -76,5 +78,5 @@ // Start the connection. - start(); + //start(); })(); \ No newline at end of file From 8b9b1b58fe6d618f0621e2412934fa94e412bdf5 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 18 May 2024 12:11:54 +0200 Subject: [PATCH 041/104] Updated multiple packages and improved code readability Updated various NuGet packages across multiple projects, including `Roslynator.Analyzers`, `System.IdentityModel.Tokens.Jwt`, `MassTransit.RabbitMQ`, `Swashbuckle.AspNetCore`, `Microsoft.VisualStudio.Azure.Containers.Tools.Targets`, `xunit`, `Polly`, `SmartFormat.NET`, `MongoDB.Driver`, and `System.Linq.Dynamic.Core`. Added comments to `IHasher.cs`, `IProductServiceClient.cs`, and `ProductServiceClient.cs` for better documentation. Introduced new methods in `Hasher.cs` and refactored `CreateOrderHandler.cs` and `AddWebApiSwaggerDocs` in `Extensions.cs` for improved readability and error handling. Explicitly declared variable types in `Signer.cs`, `JsonParser.cs`, and `Extensions.cs` for better readability. --- Directory.Build.props | 2 +- src/Genocs.Auth/Genocs.Auth.csproj | 2 +- .../Genocs.Core.Demo.WebApi.csproj | 4 +- .../Genocs.Core.Demo.Worker.csproj | 4 +- .../Genocs.Core.UnitTests.csproj | 4 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 4 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 6 +- src/Genocs.Security/IHasher.cs | 31 ++++++++++- src/Genocs.Security/Services/Hasher.cs | 34 ++++++++++++ src/Genocs.Security/Services/Signer.cs | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 4 +- src/Genocs.WebApi.Swagger/Docs/Extensions.cs | 2 +- src/Genocs.WebApi.Swagger/Extensions.cs | 3 +- .../Genocs.WebApi.Swagger.csproj | 10 ++-- src/Genocs.WebApi/Parsers/JsonParser.cs | 2 +- .../Commands/Handlers/CreateOrderHandler.cs | 16 ++++-- .../Services/IProductServiceClient.cs | 8 +-- .../Services/ProductServiceClient.cs | 55 ++++++++++++++----- 22 files changed, 146 insertions(+), 55 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 109e38eb..d79d1a83 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index b24b556b..301e0e21 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -65,7 +65,7 @@ - + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 9aafbcb6..9f5d5442 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -22,9 +22,9 @@ - + - + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 6184463e..397b8065 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index a2311542..fa630a5c 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 8fa7e5bf..e1dacf30 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 4fc3c4e0..1f67fec2 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -60,7 +60,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 2777cae4..5d195cdc 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 5921d7b5..8c92fbf4 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -12,8 +12,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index dae81f0d..021c5b2e 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 1b30c865..9930c703 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -13,9 +13,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Security/IHasher.cs b/src/Genocs.Security/IHasher.cs index d75e5a09..79dded6a 100644 --- a/src/Genocs.Security/IHasher.cs +++ b/src/Genocs.Security/IHasher.cs @@ -1,8 +1,37 @@ namespace Genocs.Security; -// SHA-256 +/// +/// This provides interfaces to the class. +/// public interface IHasher { + /// + /// Generates the hash value of the given data. + /// + /// The data used to create the hash. + /// The hash result as string. string Hash(string data); + + /// + /// Generates the hash value of the given data. + /// + /// The data used to create the hash. + /// The private key used to used to create the hash. + /// The hash result as string. + string Hash(string data, string key); + + /// + /// Generates the hash value of the given data. + /// + /// The data used to create the hash as byte array. + /// The hash result as byte array. byte[] Hash(byte[] data); + + /// + /// Generates the hash value of the given data. + /// + /// The data used to create the hash. + /// The private key used to used to create the hash. + /// The hash result as byte array. + byte[] Hash(byte[] data, byte[] key); } \ No newline at end of file diff --git a/src/Genocs.Security/Services/Hasher.cs b/src/Genocs.Security/Services/Hasher.cs index f299e33a..4f4b6d34 100644 --- a/src/Genocs.Security/Services/Hasher.cs +++ b/src/Genocs.Security/Services/Hasher.cs @@ -28,4 +28,38 @@ public byte[] Hash(byte[] data) return sha256Hash.ComputeHash(data); } + + public byte[] Hash(byte[] data, byte[] key) + { + if (data is null || !data.Any()) + { + throw new ArgumentException("Data to be hashed cannot be empty.", nameof(data)); + } + + if (key is null || !key.Any()) + { + throw new ArgumentException("Key to be hashed cannot be empty.", nameof(key)); + } + + HMACSHA256 sha256Hash = new HMACSHA256(key); + return sha256Hash.ComputeHash(data); + } + + public string Hash(string data, string key) + { + byte[] bytesData = Encoding.Default.GetBytes(data); + byte[] bytesKey = Encoding.Default.GetBytes(key); + + byte[] hash = Hash(bytesData, bytesKey); + + // convert the byte array to a hexadecimal string + var builder = new StringBuilder(); + foreach (byte @byte in hash) + { + builder.Append(@byte.ToString("x2")); + } + + return builder.ToString(); + + } } \ No newline at end of file diff --git a/src/Genocs.Security/Services/Signer.cs b/src/Genocs.Security/Services/Signer.cs index 54de2b1d..7288bb88 100644 --- a/src/Genocs.Security/Services/Signer.cs +++ b/src/Genocs.Security/Services/Signer.cs @@ -41,7 +41,7 @@ public bool Verify(object data, X509Certificate2 certificate, string signature, throw new ArgumentException("Signature cannot be empty.", nameof(signature)); } - var bytes = JsonSerializer.SerializeToUtf8Bytes(data); + byte[] bytes = JsonSerializer.SerializeToUtf8Bytes(data); return Verify(bytes, certificate, ToByteArray(signature), throwException); } diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index e5d40229..44384c56 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs index f77b8564..24d21078 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs @@ -64,7 +64,7 @@ public static IApplicationBuilder UseSwaggerDocs(this IApplicationBuilder builde return builder; } - var routePrefix = string.IsNullOrWhiteSpace(options.RoutePrefix) ? string.Empty : options.RoutePrefix; + string routePrefix = string.IsNullOrWhiteSpace(options.RoutePrefix) ? string.Empty : options.RoutePrefix; builder.UseStaticFiles() .UseSwagger(c => diff --git a/src/Genocs.WebApi.Swagger/Extensions.cs b/src/Genocs.WebApi.Swagger/Extensions.cs index 6fa0f8f8..585d9ceb 100644 --- a/src/Genocs.WebApi.Swagger/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Extensions.cs @@ -19,8 +19,7 @@ public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, s return builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(sectionName)); } - public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, - Func buildOptions) + public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) => builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(buildOptions)); public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, SwaggerOptions options) diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 74828dae..d292b021 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -50,11 +50,11 @@ - - - - - + + + + + diff --git a/src/Genocs.WebApi/Parsers/JsonParser.cs b/src/Genocs.WebApi/Parsers/JsonParser.cs index bf9afeed..c4b84e5f 100644 --- a/src/Genocs.WebApi/Parsers/JsonParser.cs +++ b/src/Genocs.WebApi/Parsers/JsonParser.cs @@ -35,7 +35,7 @@ public IDictionary Parse(string json) private void VisitElement(JsonElement element) { - var isEmpty = true; + bool isEmpty = true; foreach (JsonProperty property in element.EnumerateObject()) { diff --git a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs index cbc1d243..bf191760 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs @@ -18,9 +18,13 @@ public class CreateOrderHandler : ICommandHandler private readonly ILogger _logger; private readonly ITracer _tracer; - public CreateOrderHandler(IMongoRepository repository, IBusPublisher publisher, - IMessageOutbox outbox, IProductServiceClient productServiceClient, ITracer tracer, - ILogger logger) + public CreateOrderHandler( + IMongoRepository repository, + IBusPublisher publisher, + IMessageOutbox outbox, + IProductServiceClient productServiceClient, + ITracer tracer, + ILogger logger) { _repository = repository; _publisher = publisher; @@ -32,7 +36,7 @@ public CreateOrderHandler(IMongoRepository repository, IBusPublishe public async Task HandleAsync(CreateOrder command, CancellationToken cancellationToken = default) { - var exists = await _repository.ExistsAsync(o => o.Id == command.OrderId); + bool exists = await _repository.ExistsAsync(o => o.Id == command.OrderId); if (exists) { throw new InvalidOperationException($"Order with given id: {command.OrderId} already exists!"); @@ -49,10 +53,10 @@ public async Task HandleAsync(CreateOrder command, CancellationToken cancellatio var order = new Order(command.OrderId, command.CustomerId, productDto.UnitPrice); await _repository.AddAsync(order); - + _logger.LogInformation($"Created order '{command.OrderId}' for customer '{command.CustomerId}'."); - var spanContext = _tracer.ActiveSpan?.Context.ToString(); + string? spanContext = _tracer.ActiveSpan?.Context.ToString(); var @event = new OrderCreated(order.Id); if (_outbox.Enabled) { diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/IProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/IProductServiceClient.cs index bd26538f..636fbf4a 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/IProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/IProductServiceClient.cs @@ -3,14 +3,14 @@ namespace Genocs.Orders.WebApi.Services; /// -/// The Product WebApi client definition +/// The Product WebApi client definition. /// public interface IProductServiceClient { /// - /// Get the product based on the productId + /// Get the product based on the productId. /// - /// The ProductId - /// The Product Response + /// The ProductId. + /// The Product Response. Task GetAsync(Guid productId); } \ No newline at end of file diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs index c31bcd90..49f6cdd8 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs @@ -7,9 +7,8 @@ namespace Genocs.Orders.WebApi.Services; - /// -/// The Product WebApi client implementation +/// The Product WebApi client implementation. /// public class ProductServiceClient : IProductServiceClient { @@ -17,43 +16,69 @@ public class ProductServiceClient : IProductServiceClient private readonly string _url; /// - /// The standard constructor + /// The standard constructor. /// - /// - /// + /// The http client. + /// The certification service. /// /// /// - public ProductServiceClient(IHttpClient client, - ICertificatesService certificatesService, + public ProductServiceClient( + IHttpClient client, + ICertificatesService? certificatesService, HttpClientSettings httpClientOptions, VaultSettings vaultOptions, SecurityOptions securityOptions) { - _client = client; - _url = httpClientOptions.Services["products"]; + _client = client ?? throw new ArgumentNullException(nameof(client)); + + + if (httpClientOptions is null) + { + throw new ArgumentNullException(nameof(httpClientOptions)); + } + + if (vaultOptions is null) + { + throw new ArgumentNullException(nameof(vaultOptions)); + } + + if (securityOptions is null) + { + throw new ArgumentNullException(nameof(securityOptions)); + } + + string? url = httpClientOptions?.Services?["products"]; + + if (string.IsNullOrWhiteSpace(url)) + { + throw new Exception("products http client option cannot be null"); + } + + _url = url; + if (!vaultOptions.Enabled || vaultOptions.Pki?.Enabled != true || securityOptions.Certificate?.Enabled != true) { return; } - var certificate = certificatesService.Get(vaultOptions.Pki.RoleName); + var certificate = certificatesService?.Get(vaultOptions.Pki.RoleName); if (certificate is null) { return; } - var header = securityOptions.Certificate.GetHeaderName(); - var certificateData = certificate.GetRawCertDataString(); + string header = securityOptions.Certificate.GetHeaderName(); + string certificateData = certificate.GetRawCertDataString(); _client.SetHeaders(h => h.Add(header, certificateData)); } /// - /// Get the product result based on the productId + /// Get the product result based on the productId. /// - /// The ProductId - /// The Product Response + /// The ProductId. + /// The Product Response. public Task GetAsync(Guid productId) => _client.GetAsync($"{_url}/products/{productId}"); } \ No newline at end of file From cc6bd4df16be8fc76e4f7f68359cb1e6c1ae430e Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 18 May 2024 19:09:22 +0200 Subject: [PATCH 042/104] Updated project dependencies and refactored security settings Updated `Genocs.Core.Demo.WebApi.csproj` to include new project and package references. Added new namespaces to `Program.cs` and chained `UseLogging()` with `UseVault()`. Updated `appsettings.json` with new configuration settings. Comment for `HttpClientSettings` class in `HttpClientSettings.cs` has been updated. Replaced `SecurityOptions` class with `SecuritySettings` in `CertificateMiddleware.cs`, `Extensions.cs`, and `ProductServiceClient.cs`. Removed `SecurityOptions.cs` file. Added new files `ExternalApiController.cs`, `BuilderExtensions.cs`, `ExternalServiceClient.cs`, `IExternalServiceClient.cs`, `ExternalServiceSettings.cs`, and `SecuritySettings.cs`. Added new service `PricingServiceClient` to the DI container in `Extensions.cs` under `Genocs.Products.WebApi`. Updated the constructor in `ProductServiceClient.cs` to include new parameters. --- .../Controllers/ExternalApiController.cs | 40 ++++++ .../Genocs.Core.Demo.WebApi.csproj | 10 ++ .../Extensions/BuilderExtensions.cs | 26 ++++ .../Services/ExternalServiceClient.cs | 118 ++++++++++++++++++ .../Services/IExternalServiceClient.cs | 117 +++++++++++++++++ .../Options/ExternalServiceSettings.cs | 10 ++ src/Genocs.Core.Demo.WebApi/Program.cs | 15 ++- src/Genocs.Core.Demo.WebApi/appsettings.json | 44 ++++++- src/Genocs.HTTP/Options/HttpClientSettings.cs | 2 +- .../CertificateMiddleware.cs | 31 +++-- src/Genocs.WebApi.Security/Extensions.cs | 23 ++-- .../Options/SecuritySettings.cs | 27 ++++ src/Genocs.WebApi.Security/SecurityOptions.cs | 29 ----- .../Services/ProductServiceClient.cs | 14 +-- .../Genocs.Products.WebApi/Extensions.cs | 1 + 15 files changed, 443 insertions(+), 64 deletions(-) create mode 100644 src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs create mode 100644 src/Genocs.WebApi.Security/Options/SecuritySettings.cs delete mode 100644 src/Genocs.WebApi.Security/SecurityOptions.cs diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs new file mode 100644 index 00000000..09e1f052 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs @@ -0,0 +1,40 @@ +using Genocs.Core.Demo.WebApi.Infrastructure.Services; +using MassTransit; +using Microsoft.AspNetCore.Mvc; +using System.Net.Mime; + +namespace Genocs.Core.Demo.WebApi.Controllers; + +[ApiController] +[Route("[controller]")] +public class ExternalApiController : ControllerBase +{ + private readonly IPublishEndpoint _publishEndpoint; + private readonly ILogger _logger; + private readonly IExternalServiceClient _externalServiceClient; + + public ExternalApiController(ILogger logger, IPublishEndpoint publishEndpoint, IExternalServiceClient externalServiceClient) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _publishEndpoint = publishEndpoint ?? throw new ArgumentNullException(nameof(publishEndpoint)); + _externalServiceClient = externalServiceClient ?? throw new ArgumentNullException(nameof(externalServiceClient)); + } + + [HttpGet("")] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(IssuingResponse), StatusCodes.Status200OK)] + public async Task HomeAsync() + { + var request = new IssuingRequest + { + ExternalReference = Guid.NewGuid().ToString(), + Currency = "xxxx", + Amount = 100, + PartnerCode = "xxxx" + }; + + var response = await _externalServiceClient.IssueAsync(request); + + return Ok(response); + } +} diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 9f5d5442..ee5bcaf8 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -11,14 +11,24 @@ + + + + + + + + + + diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs new file mode 100644 index 00000000..9ab3424f --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs @@ -0,0 +1,26 @@ +using Genocs.Core.Builders; +using Genocs.Core.Demo.WebApi.Infrastructure.Services; +using Genocs.Core.Demo.WebApi.Options; +using Genocs.WebApi.Security; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Extensions; + +public static class BuilderExtensions +{ + public static IGenocsBuilder AddServices(this IGenocsBuilder builder) + { + builder.AddCertificateAuthentication(); + + builder.Services.AddTransient(); + + var settings = new ExternalServiceSettings(); + builder.Configuration.GetSection(ExternalServiceSettings.Position).Bind(settings); + + builder.Services.AddSingleton(settings); + + // builder.Services.Configure(builder.Configuration.GetSection(ExternalServiceSettings.Position)); + + return builder; + } + +} diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs new file mode 100644 index 00000000..4f4228bc --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs @@ -0,0 +1,118 @@ +using Genocs.Core.Demo.WebApi.Options; +using Genocs.HTTP; +using Genocs.HTTP.Options; +using Genocs.Secrets.Vault; +using Genocs.Secrets.Vault.Options; +using Genocs.Security; +using Genocs.WebApi.Security; +using Newtonsoft.Json; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The External WebApi client implementation. +/// +public class ExternalServiceClient : IExternalServiceClient +{ + private readonly IHttpClient _client; + private readonly string _url; + private readonly IHasher _hasher; + private readonly ExternalServiceSettings _externalServiceSettings; + + /// + /// The standard constructor. + /// + /// The http client. + /// The Hash service. + /// The http client settings. + /// The certification service. + /// The vault settings. + /// The security settings. + /// The security settings. + public ExternalServiceClient( + IHttpClient client, + IHasher hasher, + HttpClientSettings httpClientSettings, + ICertificatesService certificatesService, + VaultSettings vaultSettings, + SecuritySettings securitySettings, + ExternalServiceSettings externalServiceSettings) + { + _client = client ?? throw new ArgumentNullException(nameof(client)); + _hasher = hasher ?? throw new ArgumentNullException(nameof(hasher)); + _externalServiceSettings = externalServiceSettings ?? throw new ArgumentNullException(nameof(externalServiceSettings)); + + if (httpClientSettings is null) + { + throw new ArgumentNullException(nameof(httpClientSettings)); + } + + if (vaultSettings is null) + { + throw new ArgumentNullException(nameof(vaultSettings)); + } + + if (securitySettings is null) + { + throw new ArgumentNullException(nameof(securitySettings)); + } + + string? url = httpClientSettings?.Services?["ca_issuer"]; + + if (string.IsNullOrWhiteSpace(url)) + { + throw new Exception("products http client settings cannot be null"); + } + + _url = url; + + if (!vaultSettings.Enabled || vaultSettings.Pki?.Enabled != true || + securitySettings.Certificate?.Enabled != true) + { + return; + } + + var certificate = certificatesService?.Get(vaultSettings.Pki.RoleName); + if (certificate is null) + { + return; + } + + string header = securitySettings.Certificate.GetHeaderName(); + string certificateData = certificate.GetRawCertDataString(); + _client.SetHeaders(h => h.Add(header, certificateData)); + } + + private void SetHeaders(string request) + { + string hash = _hasher.Hash(request, _externalServiceSettings.Private); + string headerData = $"Credential={_externalServiceSettings.Public}, Signature={hash}"; + _client.SetHeaders(h => h.TryAddWithoutValidation("Authorization", headerData)); + } + + /// + /// Send a request for gift card issuing. + /// + /// The issuing Request. + /// The issuing Response. + public async Task IssueAsync(IssuingRequest request) + { + string serializedRequest = JsonConvert.SerializeObject(request); + SetHeaders(serializedRequest); + using (var content = new StringContent(serializedRequest, System.Text.Encoding.UTF8, "application/json")) + { + return await _client.PostAsync($"{_url}/redemptions/gift-cards/{_externalServiceSettings.Caller}/direct-issue", content); + } + } + + /// + /// Get the product based on the Caller. + /// + /// The CallerId. + /// The Product Response. + public async Task RedeemAsync(string callerId) + { + // SetHeaders(callerId); + return await _client.PostAsync($"{_url}/redemptions/gift-cards/custom/redeem", new { }); + } +} \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs new file mode 100644 index 00000000..e1d3d077 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs @@ -0,0 +1,117 @@ +using Newtonsoft.Json; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +public class IssuingRequest +{ + [JsonProperty("external_reference")] + public string? ExternalReference; + + [JsonProperty("loyalty_currency")] + public string? Currency; + + [JsonProperty("fiat_amount")] + public decimal Amount; + + [JsonProperty("partner_code")] + public string? PartnerCode; +} + +public class Metadata +{ + public string memberId { get; set; } + public string requestId { get; set; } + public string email { get; set; } +} + +public class IssuingResponse +{ + public Code code { get; set; } + public GiftCard gift_card { get; set; } +} + +public class Code +{ + public string barcode_format { get; set; } + public string barcode_string { get; set; } + public int discount_amount { get; set; } + public object delivery_url { get; set; } + public string expiration_date { get; set; } + public string fiat_amount { get; set; } + public string fiat_balance { get; set; } + public string fiat_currency { get; set; } + public string code { get; set; } + public string id { get; set; } + public IssuanceDetails issuance_details { get; set; } + public string pin { get; set; } + public object redemption_details { get; set; } + public string redemption_status { get; set; } +} + +public class CustomSettingsData +{ +} + +public class GiftCard +{ + public string barcode_format { get; set; } + public List countries { get; set; } + public string currency { get; set; } + public CustomSettingsData custom_settings_data { get; set; } + public string denomination_type { get; set; } + public List denominations { get; set; } + public string description { get; set; } + + //public int discount_value { get; set; } + public string expiration_policy { get; set; } + public string id { get; set; } + public object image { get; set; } + public string maximum_value { get; set; } + public string minimum_value { get; set; } + public string name { get; set; } + public string provider { get; set; } + public string redeem_instructions_html { get; set; } + public string terms_and_conditions_html { get; set; } + public string terms_and_conditions_url { get; set; } + public string type { get; set; } +} + +public class IssuanceDetails +{ + public CustomSettingsData custom_settings_data { get; set; } + public string external_reference { get; set; } + public LoyaltyInformation loyalty_information { get; set; } +// public Metadata metadata { get; set; } + public string original_external_reference { get; set; } + public string original_code { get; set; } + public string partner_code { get; set; } +} + +public class LoyaltyInformation +{ + //public int? loyalty_amount { get; set; } + public string loyalty_currency { get; set; } + public string member_id { get; set; } + public string partner_name { get; set; } +} + +/// +/// The External WebApi client definition. +/// +public interface IExternalServiceClient +{ + /// + /// Send a request for gift card issuing. + /// + /// The issuing Request. + /// The issuing Response. + Task IssueAsync(IssuingRequest request); + + /// + /// Get the product based on the productId. + /// + /// The ProductId. + /// The Product Response. + Task RedeemAsync(string callerId); + +} diff --git a/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs b/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs new file mode 100644 index 00000000..4a73893e --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs @@ -0,0 +1,10 @@ +namespace Genocs.Core.Demo.WebApi.Options; + +public class ExternalServiceSettings +{ + public const string Position = "ExternalService"; + + public string Caller { get; set; } = default!; + public string Private { get; set; } = default!; + public string Public { get; set; } = default!; +} diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index bdbe0b05..cdf71662 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -1,8 +1,11 @@ using Genocs.Core.Builders; using Genocs.Core.Demo.WebApi.Infrastructure.Extensions; +using Genocs.HTTP; using Genocs.Logging; -using Genocs.Tracing; using Genocs.Persistence.MongoDb.Extensions; +using Genocs.Secrets.Vault; +using Genocs.Security; +using Genocs.Tracing; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; using Serilog.Events; @@ -20,16 +23,20 @@ var builder = WebApplication.CreateBuilder(args); builder.Host - .UseLogging(); + .UseLogging() + .UseVault(); -// add services to DI container var services = builder.Services; services .AddGenocs(builder.Configuration) + .AddServices() + .AddHttpClient() .AddOpenTelemetry() .AddMongoFast() - .RegisterMongoRepositories(Assembly.GetExecutingAssembly()); + .RegisterMongoRepositories(Assembly.GetExecutingAssembly()) + .AddSecurity() + .Build(); services.AddCors(); services.AddControllers().AddJsonOptions(x => diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 8bb32dc4..da10cf1c 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -45,5 +45,47 @@ }, "Monitoring": { "Jaeger": "localhost" + }, + "vault": { + "enabled": true, + "url": "http://localhost:8200", + "authType": "token", + "token": "secret", + "username": "user", + "password": "secret", + "kv": { + "enabled": false, + "engineVersion": 2, + "mountPoint": "kv", + "path": "demo-service/settings" + }, + "pki": { + "enabled": false, + "roleName": "products-service", + "commonName": "demo-service.convey.io" + }, + "lease": { + "mongo": { + "type": "database", + "roleName": "demo-service", + "enabled": false, + "autoRenewal": true, + "templates": { + "connectionString": "mongodb://{{username}}:{{password}}@localhost:27017" + } + } + } + }, + "httpClient": { + "type": "", + "retries": 2, + "services": { + "ca_issuer": "<<>>" + } + }, + "externalService": { + "caller": "<<>>", + "public": "<<>>", + "private": "<<>>" } -} \ No newline at end of file +} diff --git a/src/Genocs.HTTP/Options/HttpClientSettings.cs b/src/Genocs.HTTP/Options/HttpClientSettings.cs index 8c775602..42fde541 100644 --- a/src/Genocs.HTTP/Options/HttpClientSettings.cs +++ b/src/Genocs.HTTP/Options/HttpClientSettings.cs @@ -1,7 +1,7 @@ namespace Genocs.HTTP.Options; /// -/// The HttpClientSettings options class. +/// The HttpClient Settings class. /// public class HttpClientSettings { diff --git a/src/Genocs.WebApi.Security/CertificateMiddleware.cs b/src/Genocs.WebApi.Security/CertificateMiddleware.cs index 42c07ed7..d0c02230 100644 --- a/src/Genocs.WebApi.Security/CertificateMiddleware.cs +++ b/src/Genocs.WebApi.Security/CertificateMiddleware.cs @@ -12,15 +12,17 @@ internal sealed class CertificateMiddleware : IMiddleware { private readonly ICertificatePermissionValidator _certificatePermissionValidator; private readonly ILogger _logger; - private readonly SecurityOptions.CertificateOptions _options; + private readonly SecuritySettings.CertificateSettings _options; private readonly HashSet _allowedHosts; - private readonly IDictionary _acl; + private readonly IDictionary _acl; private readonly IDictionary _subjects = new Dictionary(); private readonly bool _validateAcl; private readonly bool _skipRevocationCheck; - public CertificateMiddleware(ICertificatePermissionValidator certificatePermissionValidator, - SecurityOptions options, ILogger logger) + public CertificateMiddleware( + ICertificatePermissionValidator certificatePermissionValidator, + SecuritySettings options, + ILogger logger) { _certificatePermissionValidator = certificatePermissionValidator; _logger = logger; @@ -28,12 +30,13 @@ public CertificateMiddleware(ICertificatePermissionValidator certificatePermissi _allowedHosts = new HashSet(_options.AllowedHosts ?? Array.Empty()); _validateAcl = _options.Acl is not null && _options.Acl.Any(); _skipRevocationCheck = options.Certificate.SkipRevocationCheck; + if (!_validateAcl) { return; } - _acl = new Dictionary(); + _acl = new Dictionary(); foreach (var (key, acl) in _options.Acl) { if (!string.IsNullOrWhiteSpace(acl.ValidIssuer) && !acl.ValidIssuer.StartsWith("CN=")) @@ -41,10 +44,10 @@ public CertificateMiddleware(ICertificatePermissionValidator certificatePermissi acl.ValidIssuer = $"CN={acl.ValidIssuer}"; } - var subject = key.StartsWith("CN=") ? key : $"CN={key}"; + string subject = key.StartsWith("CN=") ? key : $"CN={key}"; if (_options.AllowSubdomains) { - foreach (var domain in options.Certificate.AllowedDomains ?? Enumerable.Empty()) + foreach (string domain in options.Certificate.AllowedDomains ?? Enumerable.Empty()) { _subjects.Add($"{subject}.{domain}", key); } @@ -78,8 +81,8 @@ public Task InvokeAsync(HttpContext context, RequestDelegate next) return next(context); } - SecurityOptions.CertificateOptions.AclOptions acl; - if (_subjects.TryGetValue(certificate.Subject, out var subject)) + SecuritySettings.CertificateSettings.AclSettings acl; + if (_subjects.TryGetValue(certificate.Subject, out string? subject)) { if (!_acl.TryGetValue(subject, out var existingAcl)) { @@ -141,17 +144,19 @@ private bool Verify(X509Certificate2 certificate) RevocationMode = _skipRevocationCheck ? X509RevocationMode.NoCheck : X509RevocationMode.Online, } }; - var chainBuilt = chain.Build(certificate); + + bool chainBuilt = chain.Build(certificate); + foreach (var chainElement in chain.ChainElements) { chainElement.Certificate.Dispose(); } - + if (chainBuilt) { return true; } - + _logger.LogError("Certificate validation failed"); foreach (var chainStatus in chain.ChainStatus) { @@ -163,7 +168,7 @@ private bool Verify(X509Certificate2 certificate) private bool IsAllowedHost(HttpContext context) { - var host = context.Request.Host.Host; + string host = context.Request.Host.Host; if (_allowedHosts.Contains(host)) { return true; diff --git a/src/Genocs.WebApi.Security/Extensions.cs b/src/Genocs.WebApi.Security/Extensions.cs index ed05cd0d..a615b8c6 100644 --- a/src/Genocs.WebApi.Security/Extensions.cs +++ b/src/Genocs.WebApi.Security/Extensions.cs @@ -11,10 +11,12 @@ public static class Extensions private const string SectionName = "security"; private const string RegistryName = "security"; - public static IGenocsBuilder AddCertificateAuthentication(this IGenocsBuilder builder, - string sectionName = SectionName, Type permissionValidatorType = null) + public static IGenocsBuilder AddCertificateAuthentication( + this IGenocsBuilder builder, + string sectionName = SectionName, + Type? permissionValidatorType = null) { - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); if (!builder.TryRegister(RegistryName)) { @@ -34,10 +36,12 @@ public static IGenocsBuilder AddCertificateAuthentication(this IGenocsBuilder bu { builder.Services.AddSingleton(); } - + builder.Services.AddSingleton(); - builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) + builder.Services + .AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(); + builder.Services.AddCertificateForwarding(c => { c.CertificateHeader = options.Certificate.GetHeaderName(); @@ -52,7 +56,7 @@ public static IGenocsBuilder AddCertificateAuthentication(this IGenocsBuilder bu public static IApplicationBuilder UseCertificateAuthentication(this IApplicationBuilder app) { - var options = app.ApplicationServices.GetRequiredService(); + var options = app.ApplicationServices.GetRequiredService(); if (options.Certificate is null || !options.Certificate.Enabled) { return app; @@ -66,9 +70,10 @@ public static IApplicationBuilder UseCertificateAuthentication(this IApplication private static byte[] StringToByteArray(string hex) { - var numberChars = hex.Length; - var bytes = new byte[numberChars / 2]; - for (var i = 0; i < numberChars; i += 2) + int numberChars = hex.Length; + byte[] bytes = new byte[numberChars / 2]; + + for (int i = 0; i < numberChars; i += 2) { bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); } diff --git a/src/Genocs.WebApi.Security/Options/SecuritySettings.cs b/src/Genocs.WebApi.Security/Options/SecuritySettings.cs new file mode 100644 index 00000000..08fb937a --- /dev/null +++ b/src/Genocs.WebApi.Security/Options/SecuritySettings.cs @@ -0,0 +1,27 @@ +namespace Genocs.WebApi.Security; + +public class SecuritySettings +{ + public CertificateSettings? Certificate { get; set; } + + public class CertificateSettings + { + public bool Enabled { get; set; } + public string? Header { get; set; } + public bool AllowSubdomains { get; set; } + public IEnumerable? AllowedDomains { get; set; } + public IEnumerable? AllowedHosts { get; set; } + public IDictionary? Acl { get; set; } + public bool SkipRevocationCheck { get; set; } + + public string GetHeaderName() => string.IsNullOrWhiteSpace(Header) ? "Certificate" : Header; + + public class AclSettings + { + public string? ValidIssuer { get; set; } + public string? ValidThumbprint { get; set; } + public string? ValidSerialNumber { get; set; } + public IEnumerable? Permissions { get; set; } + } + } +} \ No newline at end of file diff --git a/src/Genocs.WebApi.Security/SecurityOptions.cs b/src/Genocs.WebApi.Security/SecurityOptions.cs deleted file mode 100644 index 9a106639..00000000 --- a/src/Genocs.WebApi.Security/SecurityOptions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; - -namespace Genocs.WebApi.Security; - -public class SecurityOptions -{ - public CertificateOptions Certificate { get; set; } - - public class CertificateOptions - { - public bool Enabled { get; set; } - public string Header { get; set; } - public bool AllowSubdomains { get; set; } - public IEnumerable AllowedDomains { get; set; } - public IEnumerable AllowedHosts { get; set; } - public IDictionary Acl { get; set; } - public bool SkipRevocationCheck { get; set; } - - public string GetHeaderName() => string.IsNullOrWhiteSpace(Header) ? "Certificate" : Header; - - public class AclOptions - { - public string ValidIssuer { get; set; } - public string ValidThumbprint { get; set; } - public string ValidSerialNumber { get; set; } - public IEnumerable Permissions { get; set; } - } - } -} \ No newline at end of file diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs index 49f6cdd8..1577cb9b 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs @@ -22,13 +22,13 @@ public class ProductServiceClient : IProductServiceClient /// The certification service. /// /// - /// + /// public ProductServiceClient( IHttpClient client, - ICertificatesService? certificatesService, + ICertificatesService certificatesService, HttpClientSettings httpClientOptions, VaultSettings vaultOptions, - SecurityOptions securityOptions) + SecuritySettings securitySettings) { _client = client ?? throw new ArgumentNullException(nameof(client)); @@ -43,9 +43,9 @@ public ProductServiceClient( throw new ArgumentNullException(nameof(vaultOptions)); } - if (securityOptions is null) + if (securitySettings is null) { - throw new ArgumentNullException(nameof(securityOptions)); + throw new ArgumentNullException(nameof(securitySettings)); } string? url = httpClientOptions?.Services?["products"]; @@ -58,7 +58,7 @@ public ProductServiceClient( _url = url; if (!vaultOptions.Enabled || vaultOptions.Pki?.Enabled != true || - securityOptions.Certificate?.Enabled != true) + securitySettings.Certificate?.Enabled != true) { return; } @@ -69,7 +69,7 @@ public ProductServiceClient( return; } - string header = securityOptions.Certificate.GetHeaderName(); + string header = securitySettings.Certificate.GetHeaderName(); string certificateData = certificate.GetRawCertDataString(); _client.SetHeaders(h => h.Add(header, certificateData)); } diff --git a/src/apps/products/Genocs.Products.WebApi/Extensions.cs b/src/apps/products/Genocs.Products.WebApi/Extensions.cs index d96f63f6..d9119d6b 100644 --- a/src/apps/products/Genocs.Products.WebApi/Extensions.cs +++ b/src/apps/products/Genocs.Products.WebApi/Extensions.cs @@ -8,6 +8,7 @@ public static class Extensions public static IGenocsBuilder AddServices(this IGenocsBuilder builder) { builder.AddCertificateAuthentication(); + // Add here services like API client // builder.Services.AddSingleton(); return builder; From ccaf4a583373155be0186994deea15dcdabfbade Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 19 May 2024 14:56:20 +0200 Subject: [PATCH 043/104] Updated comments, attributes, methods, and dependencies across multiple files This commit includes a wide range of updates across multiple files for better readability, consistency, and null safety. Punctuation was added to comments, `AttributeUsage` was specified, return types and comments were updated, and dependencies were removed or added as needed. The `UserSecretsId` was updated in the project file. A new namespace `Genocs.Core.Demo.WebApi.Infrastructure.Services` was introduced with several new classes for handling requests and responses. These classes are decorated with the `JsonProperty` attribute for JSON serialization and deserialization. Some properties are currently commented out as they are not in use. --- src/Genocs.Common/Types/DecoratorAttribute.cs | 3 +- src/Genocs.Common/Types/HiddenAttribute.cs | 3 +- src/Genocs.Common/Types/IInitializer.cs | 6 +- .../Types/IStartupInitializer.cs | 7 +- src/Genocs.Common/Types/MessageAttribute.cs | 2 +- .../Types/PublicContractAttribute.cs | 2 +- .../Controllers/ExternalApiController.cs | 25 +-- .../Genocs.Core.Demo.WebApi.csproj | 2 +- .../Services/ExternalServiceClient.cs | 47 +----- .../Services/IExternalServiceClient.Models.cs | 151 ++++++++++++++++++ .../Services/IExternalServiceClient.cs | 106 +----------- src/Genocs.Core/Builders/IServiceId.cs | 4 +- .../Extensions/DictionaryExtensions.cs | 58 ++++--- src/Genocs.Core/Collections/TypeList.cs | 7 +- .../Domain/Entities/AggregateRoot.cs | 1 - .../Auditing/CreationAuditedAggregateRoot.cs | 4 +- .../Entities/Auditing/EntityAuditingHelper.cs | 2 +- .../Auditing/FullAuditedAggregateRoot.cs | 2 +- .../Entities/Auditing/FullAuditedEntity.cs | 6 +- .../Entities/EntityNotFoundException.cs | 6 +- src/Genocs.Core/Exceptions/GenocsException.cs | 12 +- .../DynamicQueryBuilder.cs | 2 +- src/Genocs.QueryBuilder/Expression.Bool.cs | 56 ++++--- 23 files changed, 255 insertions(+), 259 deletions(-) create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.Models.cs diff --git a/src/Genocs.Common/Types/DecoratorAttribute.cs b/src/Genocs.Common/Types/DecoratorAttribute.cs index 07794b3e..fdfba28b 100644 --- a/src/Genocs.Common/Types/DecoratorAttribute.cs +++ b/src/Genocs.Common/Types/DecoratorAttribute.cs @@ -1,8 +1,9 @@ namespace Genocs.Common.Types; /// -/// DecoratorAttribute placeholder +/// DecoratorAttribute placeholder. /// +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public class DecoratorAttribute : Attribute { } \ No newline at end of file diff --git a/src/Genocs.Common/Types/HiddenAttribute.cs b/src/Genocs.Common/Types/HiddenAttribute.cs index 70d846fb..69480b4f 100644 --- a/src/Genocs.Common/Types/HiddenAttribute.cs +++ b/src/Genocs.Common/Types/HiddenAttribute.cs @@ -1,8 +1,7 @@ namespace Genocs.Common.Types; - /// -/// It defines whether the attribute is hidden or not +/// It defines whether the attribute is hidden or not. /// [AttributeUsage(AttributeTargets.Property)] public class HiddenAttribute : Attribute diff --git a/src/Genocs.Common/Types/IInitializer.cs b/src/Genocs.Common/Types/IInitializer.cs index a0390f2b..6c9ff8f9 100644 --- a/src/Genocs.Common/Types/IInitializer.cs +++ b/src/Genocs.Common/Types/IInitializer.cs @@ -1,13 +1,13 @@ namespace Genocs.Common.Types; /// -/// Initializer interface definition +/// Initializer interface definition. /// public interface IInitializer { /// - /// Standard initializer + /// Standard initializer. /// - /// + /// The Task. Task InitializeAsync(); } \ No newline at end of file diff --git a/src/Genocs.Common/Types/IStartupInitializer.cs b/src/Genocs.Common/Types/IStartupInitializer.cs index b78123b4..c6061dcb 100644 --- a/src/Genocs.Common/Types/IStartupInitializer.cs +++ b/src/Genocs.Common/Types/IStartupInitializer.cs @@ -1,14 +1,13 @@ namespace Genocs.Common.Types; - /// -/// Startup initializer interface definition +/// Startup initializer interface definition. /// public interface IStartupInitializer : IInitializer { /// - /// It allows to add an initializer + /// It allows to add an initializer. /// - /// + /// The initializer. void AddInitializer(IInitializer initializer); } \ No newline at end of file diff --git a/src/Genocs.Common/Types/MessageAttribute.cs b/src/Genocs.Common/Types/MessageAttribute.cs index c226ccc0..224aa048 100644 --- a/src/Genocs.Common/Types/MessageAttribute.cs +++ b/src/Genocs.Common/Types/MessageAttribute.cs @@ -27,7 +27,7 @@ public class MessageAttribute : Attribute public string QueueType { get; } /// - /// The error + /// The error. /// public string ErrorQueue { get; } diff --git a/src/Genocs.Common/Types/PublicContractAttribute.cs b/src/Genocs.Common/Types/PublicContractAttribute.cs index 9f669695..e3ab8e01 100644 --- a/src/Genocs.Common/Types/PublicContractAttribute.cs +++ b/src/Genocs.Common/Types/PublicContractAttribute.cs @@ -1,7 +1,7 @@ namespace Genocs.Common.Types; /// -/// PublicContractAttribute class +/// PublicContractAttribute class. /// [AttributeUsage(AttributeTargets.Class)] public class PublicContractAttribute : Attribute diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs index 09e1f052..4ed8db0f 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs @@ -1,5 +1,4 @@ using Genocs.Core.Demo.WebApi.Infrastructure.Services; -using MassTransit; using Microsoft.AspNetCore.Mvc; using System.Net.Mime; @@ -9,32 +8,24 @@ namespace Genocs.Core.Demo.WebApi.Controllers; [Route("[controller]")] public class ExternalApiController : ControllerBase { - private readonly IPublishEndpoint _publishEndpoint; private readonly ILogger _logger; private readonly IExternalServiceClient _externalServiceClient; - public ExternalApiController(ILogger logger, IPublishEndpoint publishEndpoint, IExternalServiceClient externalServiceClient) + public ExternalApiController(ILogger logger, IExternalServiceClient externalServiceClient) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _publishEndpoint = publishEndpoint ?? throw new ArgumentNullException(nameof(publishEndpoint)); _externalServiceClient = externalServiceClient ?? throw new ArgumentNullException(nameof(externalServiceClient)); } [HttpGet("")] [Consumes(MediaTypeNames.Application.Json)] - [ProducesResponseType(typeof(IssuingResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] public async Task HomeAsync() - { - var request = new IssuingRequest - { - ExternalReference = Guid.NewGuid().ToString(), - Currency = "xxxx", - Amount = 100, - PartnerCode = "xxxx" - }; - - var response = await _externalServiceClient.IssueAsync(request); + => await Task.Run(() => Ok("done")); - return Ok(response); - } + [HttpPost("")] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(IssuingResponse), StatusCodes.Status200OK)] + public async Task PostIssueAsync(IssuingRequest request) + => Ok(await _externalServiceClient.IssueAsync(request)); } diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index ee5bcaf8..537f6e0a 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -4,7 +4,7 @@ net8.0 false false - __genocs + genocs Linux ..\.. diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs index 4f4228bc..459ebd9c 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs @@ -1,10 +1,7 @@ using Genocs.Core.Demo.WebApi.Options; using Genocs.HTTP; using Genocs.HTTP.Options; -using Genocs.Secrets.Vault; -using Genocs.Secrets.Vault.Options; using Genocs.Security; -using Genocs.WebApi.Security; using Newtonsoft.Json; namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; @@ -25,17 +22,11 @@ public class ExternalServiceClient : IExternalServiceClient /// The http client. /// The Hash service. /// The http client settings. - /// The certification service. - /// The vault settings. - /// The security settings. /// The security settings. public ExternalServiceClient( IHttpClient client, IHasher hasher, HttpClientSettings httpClientSettings, - ICertificatesService certificatesService, - VaultSettings vaultSettings, - SecuritySettings securitySettings, ExternalServiceSettings externalServiceSettings) { _client = client ?? throw new ArgumentNullException(nameof(client)); @@ -47,16 +38,6 @@ public ExternalServiceClient( throw new ArgumentNullException(nameof(httpClientSettings)); } - if (vaultSettings is null) - { - throw new ArgumentNullException(nameof(vaultSettings)); - } - - if (securitySettings is null) - { - throw new ArgumentNullException(nameof(securitySettings)); - } - string? url = httpClientSettings?.Services?["ca_issuer"]; if (string.IsNullOrWhiteSpace(url)) @@ -65,22 +46,6 @@ public ExternalServiceClient( } _url = url; - - if (!vaultSettings.Enabled || vaultSettings.Pki?.Enabled != true || - securitySettings.Certificate?.Enabled != true) - { - return; - } - - var certificate = certificatesService?.Get(vaultSettings.Pki.RoleName); - if (certificate is null) - { - return; - } - - string header = securitySettings.Certificate.GetHeaderName(); - string certificateData = certificate.GetRawCertDataString(); - _client.SetHeaders(h => h.Add(header, certificateData)); } private void SetHeaders(string request) @@ -94,7 +59,7 @@ private void SetHeaders(string request) /// Send a request for gift card issuing. /// /// The issuing Request. - /// The issuing Response. + /// The issuing Response containing the gift card details. public async Task IssueAsync(IssuingRequest request) { string serializedRequest = JsonConvert.SerializeObject(request); @@ -106,13 +71,13 @@ public async Task IssueAsync(IssuingRequest request) } /// - /// Get the product based on the Caller. + /// Get the product based on the productId. /// - /// The CallerId. - /// The Product Response. - public async Task RedeemAsync(string callerId) + /// The redemption request. + /// The redemption Response. + public async Task RedeemAsync(RedemptionRequest request) { // SetHeaders(callerId); - return await _client.PostAsync($"{_url}/redemptions/gift-cards/custom/redeem", new { }); + return await _client.PostAsync($"{_url}/redemptions/gift-cards/custom/redeem", request); } } \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.Models.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.Models.cs new file mode 100644 index 00000000..aeb41244 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.Models.cs @@ -0,0 +1,151 @@ +using Newtonsoft.Json; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The request object for the issuing endpoint. +/// +public class IssuingRequest +{ + [JsonProperty("external_reference")] + public string? ExternalReference; + + [JsonProperty("loyalty_currency")] + public string? Currency; + + [JsonProperty("fiat_amount")] + public decimal Amount; + + [JsonProperty("partner_code")] + public string? PartnerCode; +} + +/// +/// The request object for the redemption endpoint. +/// +public class RedemptionRequest +{ + +} + +public class Metadata +{ + [JsonProperty("memberId")] + public string? MemberId { get; set; } + + [JsonProperty("requestId")] + public string? RequestId { get; set; } + + [JsonProperty("email")] + public string? Email { get; set; } +} + +/// +/// The response object for the issuing endpoint. +/// +public class IssuingResponse +{ + [JsonProperty("code")] + public CodeResponse? Code { get; set; } + + [JsonProperty("gift_card")] + public GiftCard? GiftCard { get; set; } +} + +/// +/// The Code data available in the response object. +/// +public class CodeResponse +{ + [JsonProperty("id")] + public string? Id { get; set; } + + [JsonProperty("code")] + public string? Code { get; set; } + + [JsonProperty("barcode_string")] + public string? Barcode { get; set; } + + [JsonProperty("barcode_format")] + public string? BarcodeFormat { get; set; } + + [JsonProperty("discount_amount")] + public int DiscountAmount { get; set; } + + [JsonProperty("delivery_url")] + public object? DeliveryUrl { get; set; } + + [JsonProperty("expiration_date")] + public string? ExpirationDate { get; set; } + + [JsonProperty("fiat_amount")] + public string? FiatAmount { get; set; } + + [JsonProperty("fiat_balance")] + public string? FiatBalance { get; set; } + + [JsonProperty("fiat_currency")] + public string? FiatCurrency { get; set; } + + [JsonProperty("issuance_details")] + public IssuanceDetails? IssuanceDetails { get; set; } + + [JsonProperty("pin")] + public string? Pin { get; set; } + + [JsonProperty("redemption_details")] + public object? RedemptionDetails { get; set; } + + [JsonProperty("redemption_status")] + public string? RedemptionStatus { get; set; } +} + +public class CustomSettingsData +{ +} + +public class GiftCard +{ + [JsonProperty("barcode_format")] + public string? BarcodeFormat { get; set; } + + public List countries { get; set; } + public string currency { get; set; } + public CustomSettingsData custom_settings_data { get; set; } + public string denomination_type { get; set; } + public List denominations { get; set; } + public string description { get; set; } + + // public int discount_value { get; set; } + public string expiration_policy { get; set; } + public string id { get; set; } + public object image { get; set; } + public string maximum_value { get; set; } + public string minimum_value { get; set; } + public string name { get; set; } + public string provider { get; set; } + public string redeem_instructions_html { get; set; } + public string terms_and_conditions_html { get; set; } + public string terms_and_conditions_url { get; set; } + public string type { get; set; } +} + +public class IssuanceDetails +{ + public CustomSettingsData custom_settings_data { get; set; } + public string external_reference { get; set; } + public LoyaltyInformation loyalty_information { get; set; } + + // public Metadata metadata { get; set; } + public string original_external_reference { get; set; } + public string original_code { get; set; } + public string partner_code { get; set; } +} + +public class LoyaltyInformation +{ + // public int? loyalty_amount { get; set; } + public string loyalty_currency { get; set; } + public string member_id { get; set; } + public string partner_name { get; set; } +} \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs index e1d3d077..443112b0 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IExternalServiceClient.cs @@ -1,99 +1,4 @@ -using Newtonsoft.Json; - -namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; - -public class IssuingRequest -{ - [JsonProperty("external_reference")] - public string? ExternalReference; - - [JsonProperty("loyalty_currency")] - public string? Currency; - - [JsonProperty("fiat_amount")] - public decimal Amount; - - [JsonProperty("partner_code")] - public string? PartnerCode; -} - -public class Metadata -{ - public string memberId { get; set; } - public string requestId { get; set; } - public string email { get; set; } -} - -public class IssuingResponse -{ - public Code code { get; set; } - public GiftCard gift_card { get; set; } -} - -public class Code -{ - public string barcode_format { get; set; } - public string barcode_string { get; set; } - public int discount_amount { get; set; } - public object delivery_url { get; set; } - public string expiration_date { get; set; } - public string fiat_amount { get; set; } - public string fiat_balance { get; set; } - public string fiat_currency { get; set; } - public string code { get; set; } - public string id { get; set; } - public IssuanceDetails issuance_details { get; set; } - public string pin { get; set; } - public object redemption_details { get; set; } - public string redemption_status { get; set; } -} - -public class CustomSettingsData -{ -} - -public class GiftCard -{ - public string barcode_format { get; set; } - public List countries { get; set; } - public string currency { get; set; } - public CustomSettingsData custom_settings_data { get; set; } - public string denomination_type { get; set; } - public List denominations { get; set; } - public string description { get; set; } - - //public int discount_value { get; set; } - public string expiration_policy { get; set; } - public string id { get; set; } - public object image { get; set; } - public string maximum_value { get; set; } - public string minimum_value { get; set; } - public string name { get; set; } - public string provider { get; set; } - public string redeem_instructions_html { get; set; } - public string terms_and_conditions_html { get; set; } - public string terms_and_conditions_url { get; set; } - public string type { get; set; } -} - -public class IssuanceDetails -{ - public CustomSettingsData custom_settings_data { get; set; } - public string external_reference { get; set; } - public LoyaltyInformation loyalty_information { get; set; } -// public Metadata metadata { get; set; } - public string original_external_reference { get; set; } - public string original_code { get; set; } - public string partner_code { get; set; } -} - -public class LoyaltyInformation -{ - //public int? loyalty_amount { get; set; } - public string loyalty_currency { get; set; } - public string member_id { get; set; } - public string partner_name { get; set; } -} +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; /// /// The External WebApi client definition. @@ -104,14 +9,13 @@ public interface IExternalServiceClient /// Send a request for gift card issuing. /// /// The issuing Request. - /// The issuing Response. + /// The issuing Response containing the gift card details. Task IssueAsync(IssuingRequest request); /// /// Get the product based on the productId. /// - /// The ProductId. - /// The Product Response. - Task RedeemAsync(string callerId); - + /// The redemption request. + /// The redemption Response. + Task RedeemAsync(RedemptionRequest request); } diff --git a/src/Genocs.Core/Builders/IServiceId.cs b/src/Genocs.Core/Builders/IServiceId.cs index 41eb29af..7fbec02a 100644 --- a/src/Genocs.Core/Builders/IServiceId.cs +++ b/src/Genocs.Core/Builders/IServiceId.cs @@ -1,12 +1,12 @@ namespace Genocs.Core.Builders; /// -/// The ServiceId interface definition +/// The ServiceId interface definition. /// public interface IServiceId { /// - /// The id of the service as a getter + /// The id of the service as a getter. /// string Id { get; } } \ No newline at end of file diff --git a/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs b/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs index 21b5938c..925839ed 100644 --- a/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/DictionaryExtensions.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; - -namespace Genocs.Core.Collections.Extensions; - +namespace Genocs.Core.Collections.Extensions; /// /// Extension methods for Dictionary. @@ -12,14 +8,14 @@ public static class DictionaryExtensions /// /// This method is used to try to get a value in a dictionary if it does exists. /// - /// Type of the value - /// The collection object - /// Key - /// Value of the key (or default value if key not exists) - /// True if key does exists in the dictionary - internal static bool TryGetValue(this IDictionary dictionary, string key, out T value) + /// Type of the value. + /// The collection object. + /// Key. + /// Value of the key (or default value if key not exists). + /// True if key does exists in the dictionary. + internal static bool TryGetValue(this IDictionary dictionary, string key, out T? value) { - object valueObj; + object? valueObj; if (dictionary.TryGetValue(key, out valueObj) && valueObj is T) { value = (T)valueObj; @@ -33,29 +29,29 @@ internal static bool TryGetValue(this IDictionary dictionary, /// /// Gets a value from the dictionary with given key. Returns default value if can not find. /// - /// Dictionary to check and get - /// Key to find the value - /// Type of the key - /// Type of the value + /// Dictionary to check and get. + /// Key to find the value. + /// Type of the key. + /// Type of the value. /// Value if found, default if can not found. - public static TValue GetOrDefault(this IDictionary dictionary, TKey key) + public static TValue? GetOrDefault(this IDictionary dictionary, TKey key) { - TValue obj; + TValue? obj; return dictionary.TryGetValue(key, out obj) ? obj : default(TValue); } /// /// Gets a value from the dictionary with given key. Returns default value if can not find. /// - /// Dictionary to check and get - /// Key to find the value - /// A factory method used to create the value if not found in the dictionary - /// Type of the key - /// Type of the value + /// Dictionary to check and get. + /// Key to find the value. + /// A factory method used to create the value if not found in the dictionary. + /// Type of the key. + /// Type of the value. /// Value if found, default if can not found. - public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) + public static TValue? GetOrAdd(this IDictionary dictionary, TKey key, Func factory) { - TValue obj; + TValue? obj; if (dictionary.TryGetValue(key, out obj)) { return obj; @@ -67,13 +63,13 @@ public static TValue GetOrAdd(this IDictionary dicti /// /// Gets a value from the dictionary with given key. Returns default value if can not find. /// - /// Dictionary to check and get - /// Key to find the value - /// A factory method used to create the value if not found in the dictionary - /// Type of the key - /// Type of the value + /// Dictionary to check and get. + /// Key to find the value. + /// A factory method used to create the value if not found in the dictionary. + /// Type of the key. + /// Type of the value. /// Value if found, default if can not found. - public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) + public static TValue? GetOrAdd(this IDictionary dictionary, TKey key, Func factory) { return dictionary.GetOrAdd(key, k => factory()); } diff --git a/src/Genocs.Core/Collections/TypeList.cs b/src/Genocs.Core/Collections/TypeList.cs index 4662cf86..0b8013c1 100644 --- a/src/Genocs.Core/Collections/TypeList.cs +++ b/src/Genocs.Core/Collections/TypeList.cs @@ -13,7 +13,7 @@ public class TypeList : TypeList, ITypeList /// /// Extends to add restriction a specific base type. /// -/// Base Type of s in this list +/// Base Type of s in this list. public class TypeList : ITypeList { /// @@ -26,7 +26,10 @@ public class TypeList : ITypeList /// Gets a value indicating whether this instance is read only. /// /// true if this instance is read only; otherwise, false. - public bool IsReadOnly { get { return false; } } + public bool IsReadOnly + { + get { return false; } + } /// /// Gets or sets the at the specified index. diff --git a/src/Genocs.Core/Domain/Entities/AggregateRoot.cs b/src/Genocs.Core/Domain/Entities/AggregateRoot.cs index 61afe498..04a2beaa 100644 --- a/src/Genocs.Core/Domain/Entities/AggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/AggregateRoot.cs @@ -5,7 +5,6 @@ namespace Genocs.Core.Domain.Entities; - public class AggregateRoot : AggregateRoot, IAggregateRoot { diff --git a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs index 3dd1a8f7..66e69619 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs @@ -9,7 +9,7 @@ namespace Genocs.Core.Domain.Entities.Auditing; /// [Serializable] public abstract class CreationAuditedAggregateRoot : CreationAuditedAggregateRoot -{ +{ } /// @@ -34,7 +34,7 @@ public abstract class CreationAuditedAggregateRoot : AggregateRoot< /// protected CreationAuditedAggregateRoot() { - // CreationTime = Clock.Now; // Manage timezone + // CreationTime = Clock.Now; // Manage time zone CreationTime = DateTime.Now; } } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs index d02e6c0e..1c3764ba 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs @@ -9,7 +9,7 @@ public static class EntityAuditingHelper { public static void SetCreationAuditProperties( - // IMultiTenancyConfig multiTenancyConfig, + // IMultiTenancyConfig multiTenancyConfig, object entityAsObj, int? tenantId, long? userId) diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs index c7027a8b..294e3585 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs @@ -24,7 +24,7 @@ public abstract class FullAuditedAggregateRoot : AuditedAggregateRo public virtual bool IsDeleted { get; set; } /// - /// Which user deleted this entity? + /// Which user deleted this entity. /// public virtual long? DeleterUserId { get; set; } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs index 03f72eb4..2d93e380 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs @@ -37,8 +37,8 @@ public abstract class FullAuditedEntity : AuditedEntity /// Implements to be a base class for full-audited entities. /// -/// Type of the primary key of the entity -/// Type of the user +/// Type of the primary key of the entity. +/// Type of the user. [Serializable] public abstract class FullAuditedEntity : AuditedEntity, IFullAudited where TUser : IEntity @@ -55,7 +55,7 @@ public abstract class FullAuditedEntity : AuditedEntity - /// Which user deleted this entity? + /// Which user deleted this entity. /// public virtual long? DeleterUserId { get; set; } diff --git a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs index 28a83399..1fd5c3ea 100644 --- a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs +++ b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs @@ -48,7 +48,7 @@ public EntityNotFoundException(Type entityType, object id) /// /// Creates a new object. /// - public EntityNotFoundException(Type entityType, object id, Exception innerException) + public EntityNotFoundException(Type entityType, object id, Exception? innerException) : base($"There is no such an entity. Entity type: {entityType.FullName}, id: {id}", innerException) { EntityType = entityType; @@ -58,7 +58,7 @@ public EntityNotFoundException(Type entityType, object id, Exception innerExcept /// /// Creates a new object. /// - /// Exception message + /// Exception message. public EntityNotFoundException(string message) : base(message) { @@ -70,7 +70,7 @@ public EntityNotFoundException(string message) /// /// Exception message. /// Inner exception. - public EntityNotFoundException(string message, Exception innerException) + public EntityNotFoundException(string message, Exception? innerException) : base(message, innerException) { diff --git a/src/Genocs.Core/Exceptions/GenocsException.cs b/src/Genocs.Core/Exceptions/GenocsException.cs index ef7cdc27..0c233be5 100644 --- a/src/Genocs.Core/Exceptions/GenocsException.cs +++ b/src/Genocs.Core/Exceptions/GenocsException.cs @@ -2,16 +2,6 @@ namespace Genocs.Core.Exceptions; -/* Unmerged change from project 'Genocs.Core (netstandard2.0)' -Before: - using System.Runtime.Serialization; -After: - using System.Runtime.Serialization; - using Genocs; - using Genocs.Core; - using Genocs.Core.Exceptions; -*/ - /// /// Base exception type for those are thrown by Genocs system for Genocs specific exceptions. /// @@ -50,7 +40,7 @@ public GenocsException(string message) /// /// Exception message. /// Inner exception. - public GenocsException(string message, Exception innerException) + public GenocsException(string message, Exception? innerException) : base(message, innerException) { diff --git a/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs b/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs index a486bcbd..164d0ab4 100644 --- a/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs +++ b/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs @@ -160,5 +160,5 @@ private static List AllIndexesOf(string str, string value) internal class OperatorIndexes { public int Index { get; set; } - public string Operator { get; set; } + public string Operator { get; set; } = default!; } \ No newline at end of file diff --git a/src/Genocs.QueryBuilder/Expression.Bool.cs b/src/Genocs.QueryBuilder/Expression.Bool.cs index 2ec9baf9..43145946 100644 --- a/src/Genocs.QueryBuilder/Expression.Bool.cs +++ b/src/Genocs.QueryBuilder/Expression.Bool.cs @@ -1,43 +1,41 @@ -using System; using System.Linq.Expressions; -namespace Genocs.QueryBuilder +namespace Genocs.QueryBuilder; + +/// +/// The ExpressionBuilder for bool type. +/// +public static partial class ExpressionBuilder { + /// - /// The ExpressionBuilder for bool type + /// Gets the expression. /// - public static partial class ExpressionBuilder + /// The type of the source. + /// The search terms. + /// Name of the property. + /// The pe. + /// + internal static Expression GetExpressionBool(string[] searchTerms, string propertyName, ParameterExpression pe) { - - /// - /// Gets the expression. - /// - /// The type of the source. - /// The search terms. - /// Name of the property. - /// The pe. - /// - internal static Expression GetExpressionBool(string[] searchTerms, string propertyName, ParameterExpression pe) + // Compose the expression tree that represents the parameter to the predicate. + Expression propertyExp = pe; + foreach (string member in propertyName.Split('.')) { - // Compose the expression tree that represents the parameter to the predicate. - Expression propertyExp = pe; - foreach (var member in propertyName.Split('.')) - { - propertyExp = Expression.PropertyOrField(propertyExp, member); - } + propertyExp = Expression.PropertyOrField(propertyExp, member); + } - Expression searchExpression = null; + Expression? searchExpression = null; - MethodCallExpression left = Expression.Call(propertyExp, typeof(bool).GetMethod("ToString", Type.EmptyTypes)); - left = Expression.Call(left, typeof(string).GetMethod("ToLower", Type.EmptyTypes)); + MethodCallExpression left = Expression.Call(propertyExp, typeof(bool).GetMethod("ToString", Type.EmptyTypes)); + left = Expression.Call(left, typeof(string).GetMethod("ToLower", Type.EmptyTypes)); - var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); + var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); - var searchTerm = searchTerms[0].ToLower(); - Expression rightExpression = Expression.Constant(searchTerm); - searchExpression = Expression.Call(left, method, rightExpression); + string searchTerm = searchTerms[0].ToLower(); + Expression rightExpression = Expression.Constant(searchTerm); + searchExpression = Expression.Call(left, method, rightExpression); - return searchExpression; - } + return searchExpression; } } From 762c51f5b8d38ede287938fde6f0f7638eb33f75 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 6 Jun 2024 19:22:17 +0200 Subject: [PATCH 044/104] Refactor code for improved readability and update variable types --- README.md | 5 +- .../Controllers/ExternalApiController.cs | 4 +- .../Extensions/BuilderExtensions.cs | 22 ++++-- src/Genocs.Core.Demo.WebApi/Program.cs | 6 +- src/Genocs.Core.Demo.WebApi/appsettings.json | 17 +++++ src/Genocs.Security/Crc8.cs | 71 +++++++++++++++++++ src/Genocs.Security/Extensions.cs | 9 +++ 7 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 src/Genocs.Security/Crc8.cs diff --git a/README.md b/README.md index 96ea5a65..e8486356 100644 --- a/README.md +++ b/README.md @@ -534,4 +534,7 @@ Become a financial contributor and help me sustain the project. [Support the Pro ## Acknowledgements - [devmentors](https://github.com/devmentors) -- [abp](https://github.com/abpframework) \ No newline at end of file +- [abp](https://github.com/abpframework) + + +- simple changes \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs index 4ed8db0f..40afc2da 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs @@ -18,14 +18,14 @@ public ExternalApiController(ILogger logger, IExternalServiceCli } [HttpGet("")] - [Consumes(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] + [Consumes(MediaTypeNames.Application.Json)] public async Task HomeAsync() => await Task.Run(() => Ok("done")); [HttpPost("")] - [Consumes(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IssuingResponse), StatusCodes.Status200OK)] + [Consumes(MediaTypeNames.Application.Json)] public async Task PostIssueAsync(IssuingRequest request) => Ok(await _externalServiceClient.IssueAsync(request)); } diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs index 9ab3424f..0cdf5260 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs @@ -1,26 +1,40 @@ using Genocs.Core.Builders; using Genocs.Core.Demo.WebApi.Infrastructure.Services; using Genocs.Core.Demo.WebApi.Options; +using Genocs.HTTP; +using Genocs.Security; using Genocs.WebApi.Security; namespace Genocs.Core.Demo.WebApi.Infrastructure.Extensions; public static class BuilderExtensions { - public static IGenocsBuilder AddServices(this IGenocsBuilder builder) + /// + /// Extension method to add application services to the DI container. + /// + /// The Genocs builder. + /// The Genocs builder to be used for chain. + public static IGenocsBuilder AddApplicationServices(this IGenocsBuilder builder) { + // Add the Security services + builder.AddSecurity(); + + // Add the Certification Authentication builder.AddCertificateAuthentication(); - builder.Services.AddTransient(); + // Add the Genocs Http client + builder.AddHttpClient(); + // Add the External Service settings var settings = new ExternalServiceSettings(); builder.Configuration.GetSection(ExternalServiceSettings.Position).Bind(settings); - builder.Services.AddSingleton(settings); + // Add the External Service http Client + builder.Services.AddTransient(); + // builder.Services.Configure(builder.Configuration.GetSection(ExternalServiceSettings.Position)); return builder; } - } diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index cdf71662..74ba2986 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -1,10 +1,8 @@ using Genocs.Core.Builders; using Genocs.Core.Demo.WebApi.Infrastructure.Extensions; -using Genocs.HTTP; using Genocs.Logging; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Secrets.Vault; -using Genocs.Security; using Genocs.Tracing; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; @@ -30,12 +28,10 @@ services .AddGenocs(builder.Configuration) - .AddServices() - .AddHttpClient() .AddOpenTelemetry() .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()) - .AddSecurity() + .AddApplicationServices() .Build(); services.AddCors(); diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index da10cf1c..2af5120a 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -46,6 +46,23 @@ "Monitoring": { "Jaeger": "localhost" }, + "logger": { + "applicationName": "demo-service", + "excludePaths": [ "/ping", "/metrics" ], + "level": "debug", + "console": { + "enabled": true + }, + "file": { + "enabled": true, + "path": "logs/logs.txt", + "interval": "day" + }, + "azure": { + "enabled": false, + "connectionString": "<>" + } + }, "vault": { "enabled": true, "url": "http://localhost:8200", diff --git a/src/Genocs.Security/Crc8.cs b/src/Genocs.Security/Crc8.cs new file mode 100644 index 00000000..6740783f --- /dev/null +++ b/src/Genocs.Security/Crc8.cs @@ -0,0 +1,71 @@ +using System.Text; + +namespace Genocs.Security; + +/// +/// CRC 8-bit checksum calculator. +/// +public static class Crc8 +{ + // x8 + x7 + x6 + x4 + x2 + 1 + private const byte Poly = 0xd5; + + private static readonly byte[] Table = new byte[256]; + + /// + /// Compute the checksum of the byte array. + /// + /// + /// + public static byte ComputeChecksum(params byte[] bytes) + { + byte crc = 0; + if (bytes != null && bytes.Length > 0) + { + foreach (byte b in bytes) + { + crc = Table[crc ^ b]; + } + } + + return crc; + } + + /// + /// Compute the checksum of the string. + /// + /// The string where to calculate the CRC. + /// The Checksum. + /// If the payload is a null, empty or whitespaces string. + public static byte ComputeChecksum(string payload) + { + if (string.IsNullOrWhiteSpace(payload)) + { + throw new ArgumentNullException(nameof(payload)); + } + + byte[] buffer = Encoding.UTF8.GetBytes(payload); + return ComputeChecksum(buffer); + } + + static Crc8() + { + for (int i = 0; i < 256; ++i) + { + int temp = i; + for (int j = 0; j < 8; ++j) + { + if ((temp & 0x80) != 0) + { + temp = (temp << 1) ^ Poly; + } + else + { + temp <<= 1; + } + } + + Table[i] = (byte)temp; + } + } +} diff --git a/src/Genocs.Security/Extensions.cs b/src/Genocs.Security/Extensions.cs index 3e31cd48..eec8bc37 100644 --- a/src/Genocs.Security/Extensions.cs +++ b/src/Genocs.Security/Extensions.cs @@ -6,6 +6,15 @@ namespace Genocs.Security; public static class Extensions { + /// + /// Extension method to add security services to the DI container. + /// The AddSecurity method adds the following services to the DI container: + /// The Encryptor service . + /// The Hasher service . + /// The Signer service . + /// + /// The Genocs builder. + /// The builder to be used for chain. public static IGenocsBuilder AddSecurity(this IGenocsBuilder builder) { builder.Services From 227e9686af3c2f0c036c1546202e3a9d5b998a96 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 12 Jun 2024 18:58:44 +0200 Subject: [PATCH 045/104] Refactor and enhance codebase for clarity - Removed logging configuration from appsettings.Development.json to modify development environment logging levels. - Improved documentation, code readability, and method signatures in GenocsBuilder.cs, IGenocsBuilder.cs, including adding a new method and updating generic constraints. - Enhanced StartupInitializer.cs to prevent duplicate initializers and improved method documentation for clarity. - Made minor adjustments in Extensions.cs for method signature clarity and fixed parameter alignment in InitLeaseAsync. - Updated ICertificatesService.cs and ILeaseService.cs to return nullable types for Get methods, indicating possible null returns. - Adjusted CertificatesIssuer.cs, CertificatesService.cs, and LeaseService.cs to handle nullable return types in Get methods. - Reformatted constructor parameters in VaultHostedService.cs for readability. - Updated constructor signatures in VaultAuthTypeNotSupportedException.cs and VaultException.cs for consistency. - Improved IDispatcher.cs and IDispatcherEndpointsBuilder.cs method signatures and added a new querying method. - Made clarity adjustments in PublicContractsMiddleware.cs and handled potential null values more gracefully. - Cleaned up CertificateMiddleware.cs, DefaultCertificatePermissionValidator.cs, and ICertificatePermissionValidator.cs by removing unnecessary using directives. - Made SwaggerOptions.cs properties nullable to allow for unset possibilities. - Added missing field initialization in WebApiDocumentFilter.cs and adjusted operation determination to handle nullable cases. --- .../appsettings.Development.json | 10 ------- src/Genocs.Core/Builders/GenocsBuilder.cs | 7 ++--- src/Genocs.Core/Builders/IGenocsBuilder.cs | 18 ++++++++----- .../Builders/StartupInitializer.cs | 16 ++++++------ src/Genocs.Secrets.Vault/Extensions.cs | 2 +- .../ICertificatesService.cs | 4 +-- src/Genocs.Secrets.Vault/ILeaseService.cs | 2 +- .../Internals/CertificatesIssuer.cs | 2 +- .../Internals/CertificatesService.cs | 2 +- .../Internals/LeaseService.cs | 2 +- .../Internals/VaultHostedService.cs | 9 +++++-- .../VaultAuthTypeNotSupportedException.cs | 6 +++-- src/Genocs.Secrets.Vault/VaultException.cs | 9 ++++--- src/Genocs.WebApi.CQRS/IDispatcher.cs | 8 ++++-- .../IDispatcherEndpointsBuilder.cs | 26 ++++++++++++------- .../Middlewares/PublicContractsMiddleware.cs | 18 ++++++++----- .../CertificateMiddleware.cs | 6 +---- .../DefaultCertificatePermissionValidator.cs | 3 +-- .../ICertificatePermissionValidator.cs | 3 +-- src/Genocs.WebApi.Swagger/Docs/Extensions.cs | 5 ++-- .../Docs/SwaggerOptions.cs | 8 +++--- .../Filters/WebApiDocumentFilter.cs | 6 +++-- 22 files changed, 94 insertions(+), 78 deletions(-) delete mode 100644 src/Genocs.Core.Demo.WebApi/appsettings.Development.json diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.Development.json b/src/Genocs.Core.Demo.WebApi/appsettings.Development.json deleted file mode 100644 index 12fcb59b..00000000 --- a/src/Genocs.Core.Demo.WebApi/appsettings.Development.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Information", - "Microsoft": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - } -} diff --git a/src/Genocs.Core/Builders/GenocsBuilder.cs b/src/Genocs.Core/Builders/GenocsBuilder.cs index c7972562..59c5b25b 100644 --- a/src/Genocs.Core/Builders/GenocsBuilder.cs +++ b/src/Genocs.Core/Builders/GenocsBuilder.cs @@ -16,7 +16,7 @@ public sealed class GenocsBuilder : IGenocsBuilder IServiceCollection IGenocsBuilder.Services => _services; /// - /// The configuration + /// The configuration. /// public IConfiguration? Configuration { get; } @@ -31,7 +31,7 @@ private GenocsBuilder(IServiceCollection services, IConfiguration? configuration public static IGenocsBuilder Create(IServiceCollection services, IConfiguration? configuration = null) => new GenocsBuilder(services, configuration); - public bool TryRegister(string name) + public bool TryRegister(string name) => _registry.TryAdd(name, true); public void AddBuildAction(Action execute) @@ -44,7 +44,8 @@ public void AddInitializer(IInitializer initializer) startupInitializer.AddInitializer(initializer); }); - public void AddInitializer() where TInitializer : IInitializer + public void AddInitializer() + where TInitializer : IInitializer => AddBuildAction(sp => { var initializer = sp.GetRequiredService(); diff --git a/src/Genocs.Core/Builders/IGenocsBuilder.cs b/src/Genocs.Core/Builders/IGenocsBuilder.cs index 4775fe67..5ec0b17e 100644 --- a/src/Genocs.Core/Builders/IGenocsBuilder.cs +++ b/src/Genocs.Core/Builders/IGenocsBuilder.cs @@ -5,33 +5,37 @@ namespace Genocs.Core.Builders; /// -/// The Application builder +/// The Application builder. /// public interface IGenocsBuilder { /// - /// Get the service collection + /// Get the service collection. /// IServiceCollection Services { get; } /// - /// Get the configuration + /// Get the configuration. /// IConfiguration Configuration { get; } /// - /// try to register a service by name + /// try to register a service by name. /// - /// Name of the service trying to register + /// Name of the service trying to register. /// bool TryRegister(string name); /// - /// Build the actions based on the service provider + /// Build the actions based on the service provider. /// /// void AddBuildAction(Action execute); + void AddInitializer(IInitializer initializer); - void AddInitializer() where TInitializer : IInitializer; + + void AddInitializer() + where TInitializer : IInitializer; + IServiceProvider Build(); } \ No newline at end of file diff --git a/src/Genocs.Core/Builders/StartupInitializer.cs b/src/Genocs.Core/Builders/StartupInitializer.cs index 5ec96c38..fdba6116 100644 --- a/src/Genocs.Core/Builders/StartupInitializer.cs +++ b/src/Genocs.Core/Builders/StartupInitializer.cs @@ -1,33 +1,33 @@ using Genocs.Common.Types; +using Genocs.Core.Collections.Extensions; namespace Genocs.Core.Builders; /// -/// StartupInitializer implementation +/// StartupInitializer implementation. /// public class StartupInitializer : IStartupInitializer { private readonly IList _initializers = new List(); - /// - /// Add new initializer if not present + /// Add new initializer if not present. /// - /// + /// The initializer to be added. public void AddInitializer(IInitializer initializer) { - if (initializer is null || _initializers.Contains(initializer)) + if (initializer is null) { return; } - _initializers.Add(initializer); + _initializers.AddIfNotContains(initializer); } /// - /// Run the initializer + /// Run the initializer. /// - /// + /// The task. public async Task InitializeAsync() { foreach (var initializer in _initializers) diff --git a/src/Genocs.Secrets.Vault/Extensions.cs b/src/Genocs.Secrets.Vault/Extensions.cs index 6a01da70..914de108 100644 --- a/src/Genocs.Secrets.Vault/Extensions.cs +++ b/src/Genocs.Secrets.Vault/Extensions.cs @@ -195,7 +195,7 @@ private static Task InitLeaseAsync( string key, IVaultClient client, VaultSettings.LeaseSettings options, - IDictionary configuration) + IDictionary configuration) => options.Type.ToLowerInvariant() switch { "activedirectory" => SetActiveDirectorySecretsAsync(key, client, options, configuration), diff --git a/src/Genocs.Secrets.Vault/ICertificatesService.cs b/src/Genocs.Secrets.Vault/ICertificatesService.cs index 29cf0077..52d4db47 100644 --- a/src/Genocs.Secrets.Vault/ICertificatesService.cs +++ b/src/Genocs.Secrets.Vault/ICertificatesService.cs @@ -3,11 +3,11 @@ namespace Genocs.Secrets.Vault; /// -/// The Certification Service implementation +/// The Certification Service interface definition. /// public interface ICertificatesService { IReadOnlyDictionary All { get; } - X509Certificate2 Get(string name); + X509Certificate2? Get(string name); void Set(string name, X509Certificate2 certificate); } \ No newline at end of file diff --git a/src/Genocs.Secrets.Vault/ILeaseService.cs b/src/Genocs.Secrets.Vault/ILeaseService.cs index 339b0057..c8013f01 100644 --- a/src/Genocs.Secrets.Vault/ILeaseService.cs +++ b/src/Genocs.Secrets.Vault/ILeaseService.cs @@ -3,6 +3,6 @@ namespace Genocs.Secrets.Vault; public interface ILeaseService { IReadOnlyDictionary All { get; } - LeaseData Get(string key); + LeaseData? Get(string key); void Set(string key, LeaseData data); } \ No newline at end of file diff --git a/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs b/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs index 5bcf4e09..ef83211d 100644 --- a/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs +++ b/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs @@ -55,7 +55,7 @@ await _client.V1.Secrets.PKI.GetCredentialsAsync(_options.RoleName, return certificate; } - var privateKey = Convert.FromBase64String(credentials.Data.PrivateKeyContent + byte[] privateKey = Convert.FromBase64String(credentials.Data.PrivateKeyContent .Replace("-----BEGIN RSA PRIVATE KEY-----", string.Empty) .Replace("-----END RSA PRIVATE KEY-----", string.Empty)); diff --git a/src/Genocs.Secrets.Vault/Internals/CertificatesService.cs b/src/Genocs.Secrets.Vault/Internals/CertificatesService.cs index e25d5baf..11bde0b0 100644 --- a/src/Genocs.Secrets.Vault/Internals/CertificatesService.cs +++ b/src/Genocs.Secrets.Vault/Internals/CertificatesService.cs @@ -10,7 +10,7 @@ internal sealed class CertificatesService : ICertificatesService public IReadOnlyDictionary All => Certificates; - public X509Certificate2 Get(string name) => Certificates.TryGetValue(name, out var cert) ? cert : null; + public X509Certificate2? Get(string name) => Certificates.TryGetValue(name, out var cert) ? cert : null; public void Set(string name, X509Certificate2 certificate) { diff --git a/src/Genocs.Secrets.Vault/Internals/LeaseService.cs b/src/Genocs.Secrets.Vault/Internals/LeaseService.cs index 9f4b1802..51cbeac8 100644 --- a/src/Genocs.Secrets.Vault/Internals/LeaseService.cs +++ b/src/Genocs.Secrets.Vault/Internals/LeaseService.cs @@ -9,7 +9,7 @@ internal sealed class LeaseService : ILeaseService public IReadOnlyDictionary All => Secrets; - public LeaseData Get(string key) => Secrets.TryGetValue(key, out var data) ? data : null; + public LeaseData? Get(string key) => Secrets.TryGetValue(key, out var data) ? data : null; public void Set(string key, LeaseData data) { diff --git a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs index f7f708f4..94023818 100644 --- a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs +++ b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs @@ -15,8 +15,13 @@ internal sealed class VaultHostedService : BackgroundService private readonly ILogger _logger; private readonly int _interval; - public VaultHostedService(IVaultClient client, ILeaseService leaseService, ICertificatesIssuer certificatesIssuer, - ICertificatesService certificatesService, VaultSettings options, ILogger logger) + public VaultHostedService( + IVaultClient client, + ILeaseService leaseService, + ICertificatesIssuer certificatesIssuer, + ICertificatesService certificatesService, + VaultSettings options, + ILogger logger) { _client = client; _leaseService = leaseService; diff --git a/src/Genocs.Secrets.Vault/VaultAuthTypeNotSupportedException.cs b/src/Genocs.Secrets.Vault/VaultAuthTypeNotSupportedException.cs index a2505571..f6c5e488 100644 --- a/src/Genocs.Secrets.Vault/VaultAuthTypeNotSupportedException.cs +++ b/src/Genocs.Secrets.Vault/VaultAuthTypeNotSupportedException.cs @@ -4,11 +4,13 @@ internal sealed class VaultAuthTypeNotSupportedException : Exception { public string AuthType { get; set; } - public VaultAuthTypeNotSupportedException(string authType) : this(string.Empty, authType) + public VaultAuthTypeNotSupportedException(string authType) + : this(string.Empty, authType) { } - public VaultAuthTypeNotSupportedException(string message, string authType) : base(message) + public VaultAuthTypeNotSupportedException(string message, string authType) + : base(message) { AuthType = authType; } diff --git a/src/Genocs.Secrets.Vault/VaultException.cs b/src/Genocs.Secrets.Vault/VaultException.cs index 1330034b..3f272f85 100644 --- a/src/Genocs.Secrets.Vault/VaultException.cs +++ b/src/Genocs.Secrets.Vault/VaultException.cs @@ -4,15 +4,18 @@ internal sealed class VaultException : Exception { public string Key { get; } - public VaultException(string key) : this(null, key) + public VaultException(string key) + : this(null, key) { } - public VaultException(Exception? innerException, string key) : this(string.Empty, innerException, key) + public VaultException(Exception? innerException, string key) + : this(string.Empty, innerException, key) { } - public VaultException(string message, Exception? innerException, string key) : base(message, innerException) + public VaultException(string message, Exception? innerException, string key) + : base(message, innerException) { Key = key; } diff --git a/src/Genocs.WebApi.CQRS/IDispatcher.cs b/src/Genocs.WebApi.CQRS/IDispatcher.cs index d7c817de..a8dbaf8f 100644 --- a/src/Genocs.WebApi.CQRS/IDispatcher.cs +++ b/src/Genocs.WebApi.CQRS/IDispatcher.cs @@ -6,7 +6,11 @@ namespace Genocs.WebApi.CQRS; public interface IDispatcher { - Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand; - Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent; + Task SendAsync(T command, CancellationToken cancellationToken = default) + where T : class, ICommand; + + Task PublishAsync(T @event, CancellationToken cancellationToken = default) + where T : class, IEvent; + Task QueryAsync(IQuery query, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs b/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs index a048339f..0e1ed123 100644 --- a/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs +++ b/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs @@ -7,15 +7,23 @@ namespace Genocs.WebApi.CQRS; public interface IDispatcherEndpointsBuilder { - IDispatcherEndpointsBuilder Get(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies); - - IDispatcherEndpointsBuilder Get(string path, - Func? beforeDispatch = null, - Func? afterDispatch = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) where TQuery : class, IQuery; + IDispatcherEndpointsBuilder Get( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); + + IDispatcherEndpointsBuilder Get( + string path, + Func? beforeDispatch = null, + Func? afterDispatch = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) + where TQuery : class, IQuery; IDispatcherEndpointsBuilder Post(string path, Func? context = null, Action? endpoint = null, bool auth = false, string? roles = null, diff --git a/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs b/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs index e7a2a25a..ace00b60 100644 --- a/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs +++ b/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs @@ -27,8 +27,7 @@ public class PublicContractsMiddleware private static int _initialized; private static string _serializedContracts = "{}"; - public PublicContractsMiddleware(RequestDelegate next, string endpoint, Type attributeType, - bool attributeRequired) + public PublicContractsMiddleware(RequestDelegate next, string endpoint, Type attributeType, bool attributeRequired) { _next = next; _endpoint = endpoint; @@ -68,15 +67,20 @@ private void Load(Type attributeType) foreach (var command in contracts.Where(t => typeof(ICommand).IsAssignableFrom(t))) { - var instance = command.GetDefaultInstance(); - var name = instance.GetType().Name; + object? instance = command.GetDefaultInstance(); + string? name = instance?.GetType().Name; - if (Contracts.Commands.ContainsKey(name)) + if (!string.IsNullOrWhiteSpace(name) && instance != null) { - throw new InvalidOperationException($"Command: '{name}' already exists."); + + if (Contracts.Commands.ContainsKey(name)) + { + throw new InvalidOperationException($"Command: '{name}' already exists."); + } + + Contracts.Commands[name] = instance; } - Contracts.Commands[name] = instance; } foreach (var @event in contracts.Where(t => typeof(IEvent).IsAssignableFrom(t) && diff --git a/src/Genocs.WebApi.Security/CertificateMiddleware.cs b/src/Genocs.WebApi.Security/CertificateMiddleware.cs index d0c02230..ea5e18d8 100644 --- a/src/Genocs.WebApi.Security/CertificateMiddleware.cs +++ b/src/Genocs.WebApi.Security/CertificateMiddleware.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; +using System.Security.Cryptography.X509Certificates; namespace Genocs.WebApi.Security; diff --git a/src/Genocs.WebApi.Security/DefaultCertificatePermissionValidator.cs b/src/Genocs.WebApi.Security/DefaultCertificatePermissionValidator.cs index f5deed44..753271d7 100644 --- a/src/Genocs.WebApi.Security/DefaultCertificatePermissionValidator.cs +++ b/src/Genocs.WebApi.Security/DefaultCertificatePermissionValidator.cs @@ -1,6 +1,5 @@ -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Http; +using System.Security.Cryptography.X509Certificates; namespace Genocs.WebApi.Security; diff --git a/src/Genocs.WebApi.Security/ICertificatePermissionValidator.cs b/src/Genocs.WebApi.Security/ICertificatePermissionValidator.cs index 578a6b80..8e0ccf12 100644 --- a/src/Genocs.WebApi.Security/ICertificatePermissionValidator.cs +++ b/src/Genocs.WebApi.Security/ICertificatePermissionValidator.cs @@ -1,6 +1,5 @@ -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Http; +using System.Security.Cryptography.X509Certificates; namespace Genocs.WebApi.Security; diff --git a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs index 24d21078..b752a211 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs @@ -22,8 +22,7 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, string return builder.AddSwaggerDocs(options); } - public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, - Func buildOptions) + public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) { var options = buildOptions(new SwaggerOptionsBuilder()).Build(); return builder.AddSwaggerDocs(options); @@ -88,7 +87,7 @@ public static IApplicationBuilder UseSwaggerDocs(this IApplicationBuilder builde } /// - /// Replaces leading double forward slash caused by an empty route prefix + /// Replaces leading double forward slash caused by an empty route prefix. /// /// /// diff --git a/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs b/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs index 68a333aa..30e30d6c 100644 --- a/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs @@ -4,10 +4,10 @@ public class SwaggerOptions { public bool Enabled { get; set; } public bool ReDocEnabled { get; set; } - public string Name { get; set; } - public string Title { get; set; } - public string Version { get; set; } - public string RoutePrefix { get; set; } + public string? Name { get; set; } + public string? Title { get; set; } + public string? Version { get; set; } + public string? RoutePrefix { get; set; } public bool IncludeSecurity { get; set; } public bool SerializeAsOpenApiV2 { get; set; } } \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs b/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs index c088ae44..c6c4e570 100644 --- a/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs +++ b/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs @@ -7,11 +7,13 @@ namespace Genocs.WebApi.Swagger.Filters; internal sealed class WebApiDocumentFilter : IDocumentFilter { - private readonly WebApiEndpointDefinitions _definitions; private const string InBody = "body"; private const string InQuery = "query"; - private readonly Func _getOperation = (item, path) => + private readonly WebApiEndpointDefinitions _definitions; + + + private readonly Func _getOperation = (item, path) => { switch (path) { From bd2a025418302d032c93219388bc542c9c4b9409 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 12 Jun 2024 21:31:55 +0200 Subject: [PATCH 046/104] Integrate Azure Key Vault & Update Packages - Updated `Roslynator.Analyzers` package from `4.12.3` to `4.12.4`. - Added `Genocs.Secrets.AzureKeyVault` project to `genocs.sln`. - Modified `HomeController.cs`: removed and added using directives, introduced a new constructor and `GetSecret` action method. - Updated `Genocs.Core.Demo.WebApi.csproj`: replaced `Genocs.Secrets.Vault` with `Genocs.Secrets.AzureKeyVault`, removed `Serilog.Sinks.ApplicationInsights`. - Refactored `Program.cs` to use `Genocs.Secrets.AzureKeyVault`, added `SecretSettings` configuration and registration. - Updated `appsettings.json` to replace `vault` with `azureKeyVault` configuration section. - Added `SecretSettings` class in `Genocs.Core.Demo.WebApi.Options`. - Introduced `Extensions` class in `Genocs.Secrets.AzureKeyVault` for Azure Key Vault integration. - Created `Genocs.Secrets.AzureKeyVault.csproj` with dependencies and metadata. - Added `README.md` for `Genocs.Secrets.AzureKeyVault`. - Introduced `AzureKeyVaultSettings` class in `Genocs.Secrets.AzureKeyVault.Options`. --- Directory.Build.props | 2 +- genocs.sln | 6 ++ .../Controllers/HomeController.cs | 15 +++- .../Genocs.Core.Demo.WebApi.csproj | 4 +- .../Options/SecretSettings.cs | 9 ++ src/Genocs.Core.Demo.WebApi/Program.cs | 11 ++- src/Genocs.Core.Demo.WebApi/appsettings.json | 33 +------ .../Extensions.cs | 88 +++++++++++++++++++ .../Genocs.Secrets.AzureKeyVault.csproj | 57 ++++++++++++ .../Options/AzureKeyVaultSettings.cs | 25 ++++++ src/Genocs.Secrets.AzureKeyVault/README.md | 18 ++++ 11 files changed, 232 insertions(+), 36 deletions(-) create mode 100644 src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs create mode 100644 src/Genocs.Secrets.AzureKeyVault/Extensions.cs create mode 100644 src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj create mode 100644 src/Genocs.Secrets.AzureKeyVault/Options/AzureKeyVaultSettings.cs create mode 100644 src/Genocs.Secrets.AzureKeyVault/README.md diff --git a/Directory.Build.props b/Directory.Build.props index d79d1a83..984326b6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/genocs.sln b/genocs.sln index 9d353690..16581cec 100644 --- a/genocs.sln +++ b/genocs.sln @@ -127,6 +127,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application" src\apps\signalr-webapi.dockerfile = src\apps\signalr-webapi.dockerfile EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Genocs.Secrets.AzureKeyVault", "src\Genocs.Secrets.AzureKeyVault\Genocs.Secrets.AzureKeyVault.csproj", "{ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -289,6 +291,10 @@ Global {6CE8740F-8561-481B-AC9F-D1E73C449235}.Debug|Any CPU.Build.0 = Debug|Any CPU {6CE8740F-8561-481B-AC9F-D1E73C449235}.Release|Any CPU.ActiveCfg = Release|Any CPU {6CE8740F-8561-481B-AC9F-D1E73C449235}.Release|Any CPU.Build.0 = Release|Any CPU + {ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECBF1AEE-AE3A-4F81-9943-5675169DEFA7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs index 823bf70f..44726b15 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc; +using Genocs.Core.Demo.WebApi.Options; +using Microsoft.AspNetCore.Mvc; namespace Genocs.Core.Demo.WebApi.Controllers; @@ -6,6 +7,13 @@ namespace Genocs.Core.Demo.WebApi.Controllers; [Route("")] public class HomeController : ControllerBase { + public readonly SecretSettings _secretSettings; + + public HomeController(SecretSettings secretSettings) + { + _secretSettings = secretSettings ?? throw new ArgumentNullException(nameof(secretSettings)); + } + [HttpGet] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] public IActionResult Get() @@ -15,4 +23,9 @@ public IActionResult Get() [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] public IActionResult Ping() => Ok("pong"); + + [HttpGet("secret")] + [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] + public IActionResult GetSecret() + => Ok($"Read: {_secretSettings.Secret}"); } diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 537f6e0a..8289eeb0 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -16,7 +16,6 @@ - @@ -27,19 +26,18 @@ - - + diff --git a/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs b/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs new file mode 100644 index 00000000..62de4357 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs @@ -0,0 +1,9 @@ +namespace Genocs.Core.Demo.WebApi.Options; + +public class SecretSettings +{ + public const string Position = "Secrets"; + + public string? Secret { get; set; } + +} diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index 74ba2986..5a9e4d16 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -1,8 +1,9 @@ using Genocs.Core.Builders; using Genocs.Core.Demo.WebApi.Infrastructure.Extensions; +using Genocs.Core.Demo.WebApi.Options; using Genocs.Logging; using Genocs.Persistence.MongoDb.Extensions; -using Genocs.Secrets.Vault; +using Genocs.Secrets.AzureKeyVault; using Genocs.Tracing; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; @@ -22,7 +23,7 @@ builder.Host .UseLogging() - .UseVault(); + .UseAzureKeyVault(); var services = builder.Services; @@ -43,6 +44,12 @@ services.AddHealthChecks(); +services.Configure(builder.Configuration.GetSection(SecretSettings.Position)); + +var settings = new SecretSettings(); +builder.Configuration.GetSection(SecretSettings.Position).Bind(settings); +services.AddSingleton(settings); + services.Configure(options => { options.Delay = TimeSpan.FromSeconds(2); diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 2af5120a..2147d6a8 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -63,35 +63,10 @@ "connectionString": "<>" } }, - "vault": { - "enabled": true, - "url": "http://localhost:8200", - "authType": "token", - "token": "secret", - "username": "user", - "password": "secret", - "kv": { - "enabled": false, - "engineVersion": 2, - "mountPoint": "kv", - "path": "demo-service/settings" - }, - "pki": { - "enabled": false, - "roleName": "products-service", - "commonName": "demo-service.convey.io" - }, - "lease": { - "mongo": { - "type": "database", - "roleName": "demo-service", - "enabled": false, - "autoRenewal": true, - "templates": { - "connectionString": "mongodb://{{username}}:{{password}}@localhost:27017" - } - } - } + "azureKeyVault": { + "enabled": false, + "name": "<<>>", + "managedIdentityId": "<<>>" }, "httpClient": { "type": "", diff --git a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs new file mode 100644 index 00000000..5d5f3e36 --- /dev/null +++ b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs @@ -0,0 +1,88 @@ +using Azure.Identity; +using Genocs.Core.Builders; +using Genocs.Secrets.AzureKeyVault.Options; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Genocs.Secrets.AzureKeyVault; + +/// +/// The Extensions helper class. +/// +public static class Extensions +{ + /// + /// UseVault. + /// + /// The builder. + /// The section name. + /// The Host builder. + public static IHostBuilder UseAzureKeyVault( + this IHostBuilder builder, + string sectionName = AzureKeyVaultSettings.Position) + => builder.ConfigureAppConfiguration((ctx, cfg) => + { + // TODO Test + var settings = ctx.Configuration.GetOptions(sectionName); + if (!settings.Enabled) + { + return; + } + + cfg.AddAzureKeyVault( + new Uri($"https://{settings.Name}.vault.azure.net/"), + new DefaultAzureCredential(new DefaultAzureCredentialOptions + { + ManagedIdentityClientId = settings.ManagedIdentityId + })); + }); + + /// + /// UseVault. + /// + /// The builder. + /// The section name. + /// The Web Host builder. + public static IWebHostBuilder UseAzureKeyVault( + this IWebHostBuilder builder, + string sectionName = AzureKeyVaultSettings.Position) + => builder.ConfigureAppConfiguration((ctx, cfg) => + { + var settings = new AzureKeyVaultSettings(); + ctx.Configuration.GetSection(sectionName).Bind(settings); + if (!settings.Enabled) + { + return; + } + + cfg.AddAzureKeyVault( + new Uri($"https://{settings.Name}.vault.azure.net/"), + new DefaultAzureCredential(new DefaultAzureCredentialOptions + { + ManagedIdentityClientId = settings.ManagedIdentityId + })); + }); + + public static WebApplicationBuilder UseAzureKeyVault(this WebApplicationBuilder builder) + { + + var settings = new AzureKeyVaultSettings(); + builder.Configuration.GetSection(AzureKeyVaultSettings.Position).Bind(settings); + if (!settings.Enabled) + { + return builder; + } + + builder.Configuration.AddAzureKeyVault( + new Uri($"https://{settings.Name}.vault.azure.net/"), + new DefaultAzureCredential(new DefaultAzureCredentialOptions + { + ManagedIdentityClientId = settings.ManagedIdentityId + })); + + return builder; + } +} \ No newline at end of file diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj new file mode 100644 index 00000000..e5a7a124 --- /dev/null +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -0,0 +1,57 @@ + + + + net8.0;net7.0;net6.0 + Genocs.Secrets.AzureKeyVault + Genocs.Secrets.AzureKeyVault + Genocs.Secrets.AzureKeyVault + The Genocs Secrets AzureKeyVault library + The Genocs Secrets AzureKeyVault library + 10.0 + true + 5.0.0 + 5.0.0 + Nocco Giovanni Emanuele + Genocs + Genocs 2024 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + README.md + Aligned to the ecosystem + True + latest + + + + + True + \ + + + True + \ + + + True + \ + + + + + + + + + + + + + + + + + diff --git a/src/Genocs.Secrets.AzureKeyVault/Options/AzureKeyVaultSettings.cs b/src/Genocs.Secrets.AzureKeyVault/Options/AzureKeyVaultSettings.cs new file mode 100644 index 00000000..a5de48ac --- /dev/null +++ b/src/Genocs.Secrets.AzureKeyVault/Options/AzureKeyVaultSettings.cs @@ -0,0 +1,25 @@ +namespace Genocs.Secrets.AzureKeyVault.Options; + +/// +/// The vault Setting definition. +/// +public class AzureKeyVaultSettings +{ + public const string Position = "AzureKeyVault"; + + /// + /// The flag to enable or disable the Azure Key Vault. + /// + public bool Enabled { get; set; } + + /// + /// The name of the Azure Key Vault. + /// + public string? Name { get; set; } + + /// + /// The managed identity id. + /// + public string? ManagedIdentityId { get; set; } + +} \ No newline at end of file diff --git a/src/Genocs.Secrets.AzureKeyVault/README.md b/src/Genocs.Secrets.AzureKeyVault/README.md new file mode 100644 index 00000000..e45cec0b --- /dev/null +++ b/src/Genocs.Secrets.AzureKeyVault/README.md @@ -0,0 +1,18 @@ +# Genocs Library Azure Key Vault integration + +This package contains a support function to read secret variable from Azure Key Vault. + + +## Description + +This package contains a support function to read secret variable from Azure Key Vault. + + +## Support + +Please check the GitHub repository getting more info. + + +## Release notes + +### [2024-06-12] 5.0.6 From bb92cdbb7688fa5f33c4660729b6b589c41f3e06 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 12 Jun 2024 21:39:08 +0200 Subject: [PATCH 047/104] Update package versions across projects Updated the versions of Swashbuckle.AspNetCore, Microsoft.NET.Test.Sdk, xUnit, and Azure.Monitor.OpenTelemetry.Exporter in various project files. This includes updates to Swashbuckle.AspNetCore and its related packages in `Genocs.Core.Demo.WebApi.csproj` and `Genocs.WebApi.Swagger.csproj` from `6.6.1` to `6.6.2`, updates to `Microsoft.NET.Test.Sdk` across multiple unit test projects from `17.9.0` to `17.10.0`, updates to `xunit` and `xunit.runner.visualstudio` in the same unit test projects from `2.8.0` to `2.8.1`, and an update to `Azure.Monitor.OpenTelemetry.Exporter` in `Genocs.Tracing.csproj` from `1.2.0` to `1.3.0`. These updates likely include bug fixes, new features, and improvements in API documentation, testing frameworks, and telemetry data exporting. --- .../Genocs.Core.Demo.WebApi.csproj | 2 +- src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj | 6 +++--- .../Genocs.Persistence.MongoDB.UnitTests.csproj | 6 +++--- .../Genocs.QueryBuilder.UnitTests.csproj | 6 +++--- .../Genocs.ServiceBusAzure.UnitTests.csproj | 6 +++--- src/Genocs.Tracing/Genocs.Tracing.csproj | 2 +- src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj | 10 +++++----- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 8289eeb0..ad381117 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -31,7 +31,7 @@ - + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index fa630a5c..b9975502 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -7,9 +7,9 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 8c92fbf4..c7880590 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -10,10 +10,10 @@ - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 9930c703..e4ff69ae 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -11,11 +11,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 44384c56..52ee0ab7 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -7,9 +7,9 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index e8196f3c..5932b2b9 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -58,7 +58,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index d292b021..5c9b030e 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -50,11 +50,11 @@ - - - - - + + + + + From b864cc9693111b9d60881a6643e5b16638c15894 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 15 Jun 2024 18:17:21 +0200 Subject: [PATCH 048/104] Refactor and enhance JWT handling and security This commit represents a significant overhaul of the JWT handling and security features within the codebase. Key changes include: - General refactoring for improved readability and maintainability, including updates to comments, variable types, and class names. - Introduction of the `JwtSettings` class, replacing `JwtOptions`, to provide a more flexible configuration setup for JWT handling. - Enhanced null safety with the addition of nullable annotations across various properties. - Creation of the `Genocs.Auth.Options` namespace to centralize authentication-related configurations. - Addition of the `SecurityKeyBuilder` class for generating RSA security keys from XML strings, enhancing security capabilities. - Updates to `JwtHandler` and related classes to work with the new `JwtSettings` class, indicating an overhaul of JWT handling logic. - New features or integrations for authentication, including methods and properties related to OpenID Connect and Firebase authentication. - Code quality improvements through added summaries and better parameter documentation. - Introduction of conditional `ItemGroup` elements in the `.csproj` file to support multiple .NET versions and optimize dependencies. - Configuration and deployment adjustments, including a new `secrets` section in `appsettings.json` and updates in the `README.md` to reflect the library's new focus on security. - Removal of the deprecated `JwtOptions` class and cleanup of outdated comments and code segments. These changes collectively aim to enhance the security features, improve code quality, and ensure compatibility with multiple .NET versions, marking a significant update to the library's authentication and security configurations. --- .../AccessTokenValidatorMiddleware.cs | 21 +++--- src/Genocs.Auth/Builders/JwtOptionsBuilder.cs | 6 +- src/Genocs.Auth/Extensions.cs | 59 +++++++++++++-- src/Genocs.Auth/Handlers/JwtHandler.cs | 7 +- src/Genocs.Auth/IJwtOptionsBuilder.cs | 4 +- .../{JwtOptions.cs => Options/JwtSettings.cs} | 40 +++++----- .../Services/InMemoryAccessTokenService.cs | 8 +- src/Genocs.Core.Demo.WebApi/appsettings.json | 3 + src/Genocs.Security/Genocs.Security.csproj | 13 ++++ src/Genocs.Security/README.md | 63 +++++----------- .../Services/SecurityKeyBuilder.cs | 73 +++++++++++++++++++ 11 files changed, 209 insertions(+), 88 deletions(-) rename src/Genocs.Auth/{JwtOptions.cs => Options/JwtSettings.cs} (50%) create mode 100644 src/Genocs.Security/Services/SecurityKeyBuilder.cs diff --git a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs index 94c54a7b..bf4b93cb 100644 --- a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs +++ b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs @@ -1,11 +1,11 @@ +using Genocs.Auth.Options; using Microsoft.AspNetCore.Http; using System.Net; namespace Genocs.Auth; - /// -/// The access token validator middleware +/// The access token validator middleware. /// public class AccessTokenValidatorMiddleware : IMiddleware { @@ -13,25 +13,26 @@ public class AccessTokenValidatorMiddleware : IMiddleware private readonly IEnumerable _endpoints; /// - /// The AccessTokenValidatorMiddleware constructor + /// The AccessTokenValidatorMiddleware constructor. /// - /// The access token service - /// The options - public AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtOptions options) + /// The access token service. + /// The options. + public AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtSettings options) { _accessTokenService = accessTokenService; _endpoints = options.AllowAnonymousEndpoints ?? Enumerable.Empty(); } /// - /// The InvokeAsync method + /// The InvokeAsync method. /// - /// The http context - /// The request delegate + /// The http context. + /// The request delegate. /// public async Task InvokeAsync(HttpContext context, RequestDelegate next) { - var path = context.Request.Path.HasValue ? context.Request.Path.Value : string.Empty; + string path = context.Request.Path.HasValue ? context.Request.Path.Value : string.Empty; + if (_endpoints.Contains(path)) { await next(context); diff --git a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs index 0ab9ce28..9ef51792 100644 --- a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs +++ b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs @@ -1,8 +1,10 @@ +using Genocs.Auth.Options; + namespace Genocs.Auth.Builders; internal sealed class JwtOptionsBuilder : IJwtOptionsBuilder { - private readonly JwtOptions _options = new(); + private readonly JwtSettings _options = new(); public IJwtOptionsBuilder WithIssuerSigningKey(string issuerSigningKey) { @@ -46,6 +48,6 @@ public IJwtOptionsBuilder WithValidAudience(string validAudience) return this; } - public JwtOptions Build() + public JwtSettings Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index bd55671a..cd62769c 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -5,10 +5,14 @@ using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Tokens; using System.Security.Cryptography.X509Certificates; using System.Text; +using Genocs.Auth.Options; namespace Genocs.Auth; @@ -17,20 +21,24 @@ public static class Extensions private const string SectionName = "jwt"; private const string RegistryName = "auth"; - public static IGenocsBuilder AddJwt(this IGenocsBuilder builder, string sectionName = SectionName, - Action? optionsFactory = null) + public static IGenocsBuilder AddJwt( + this IGenocsBuilder builder, + string sectionName = SectionName, + Action? optionsFactory = null) { if (string.IsNullOrWhiteSpace(sectionName)) { sectionName = SectionName; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); return builder.AddJwt(options, optionsFactory); } - private static IGenocsBuilder AddJwt(this IGenocsBuilder builder, JwtOptions options, - Action? optionsFactory = null) + private static IGenocsBuilder AddJwt( + this IGenocsBuilder builder, + JwtSettings options, + Action? optionsFactory = null) { if (!builder.TryRegister(RegistryName)) { @@ -74,7 +82,7 @@ private static IGenocsBuilder AddJwt(this IGenocsBuilder builder, JwtOptions opt bool hasCertificate = false; if (options.Certificate is not null) { - X509Certificate2 certificate = null; + X509Certificate2? certificate = null; string password = options.Certificate.Password; bool hasPassword = !string.IsNullOrWhiteSpace(password); if (!string.IsNullOrWhiteSpace(options.Certificate.Location)) @@ -162,6 +170,45 @@ private static IGenocsBuilder AddJwt(this IGenocsBuilder builder, JwtOptions opt return builder; } + /// + /// Enable OpenId Connect Authentication. + /// It can be used with Firebase Authentication. + /// + /// The Genocs builder. + /// The configuration name. Default value is 'FirebaseAuthentication'. + /// The Genocs builder you can use for chain. + public static IGenocsBuilder AddOpenIdJwt( + this IGenocsBuilder builder, + string sectionName = "openIdAuth") + { + + + var jwtSettings = new JwtSettings(); + builder.Configuration.GetSection(sectionName).Bind(jwtSettings); + + // Enable Firebase Authentication + string metadataAddress = $"{jwtSettings.Issuer}{jwtSettings.MetadataAddress}"; + var configurationManager = new ConfigurationManager(metadataAddress, new OpenIdConnectConfigurationRetriever()); + + builder.Services + .AddAuthentication(o => + { + o.DefaultAuthenticateScheme = jwtSettings.Challenge; + o.DefaultChallengeScheme = jwtSettings.Challenge; + o.DefaultScheme = jwtSettings.Challenge; + }) + .AddJwtBearer(o => + { + o.IncludeErrorDetails = jwtSettings.IncludeErrorDetails; + o.RefreshOnIssuerKeyNotFound = jwtSettings.RefreshOnIssuerKeyNotFound; + o.MetadataAddress = metadataAddress; + o.ConfigurationManager = configurationManager; + o.Audience = jwtSettings.Audience; + }); + + return builder; + } + public static IApplicationBuilder UseAccessTokenValidator(this IApplicationBuilder app) => app.UseMiddleware(); } diff --git a/src/Genocs.Auth/Handlers/JwtHandler.cs b/src/Genocs.Auth/Handlers/JwtHandler.cs index c06eae7c..f3ce917b 100644 --- a/src/Genocs.Auth/Handlers/JwtHandler.cs +++ b/src/Genocs.Auth/Handlers/JwtHandler.cs @@ -1,3 +1,4 @@ +using Genocs.Auth.Options; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; @@ -19,12 +20,12 @@ internal sealed class JwtHandler : IJwtHandler }; private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler = new(); - private readonly JwtOptions _options; + private readonly JwtSettings _options; private readonly TokenValidationParameters _tokenValidationParameters; private readonly SigningCredentials _signingCredentials; - private readonly string _issuer; + private readonly string? _issuer; - public JwtHandler(JwtOptions options, TokenValidationParameters tokenValidationParameters) + public JwtHandler(JwtSettings options, TokenValidationParameters tokenValidationParameters) { var issuerSigningKey = tokenValidationParameters.IssuerSigningKey; if (issuerSigningKey is null) diff --git a/src/Genocs.Auth/IJwtOptionsBuilder.cs b/src/Genocs.Auth/IJwtOptionsBuilder.cs index 49e358f5..d3aa7cef 100644 --- a/src/Genocs.Auth/IJwtOptionsBuilder.cs +++ b/src/Genocs.Auth/IJwtOptionsBuilder.cs @@ -1,3 +1,5 @@ +using Genocs.Auth.Options; + namespace Genocs.Auth; public interface IJwtOptionsBuilder @@ -8,5 +10,5 @@ public interface IJwtOptionsBuilder IJwtOptionsBuilder WithLifetimeValidation(bool validateLifetime); IJwtOptionsBuilder WithAudienceValidation(bool validateAudience); IJwtOptionsBuilder WithValidAudience(string validAudience); - JwtOptions Build(); + JwtSettings Build(); } \ No newline at end of file diff --git a/src/Genocs.Auth/JwtOptions.cs b/src/Genocs.Auth/Options/JwtSettings.cs similarity index 50% rename from src/Genocs.Auth/JwtOptions.cs rename to src/Genocs.Auth/Options/JwtSettings.cs index b3f2aaf4..7df2684c 100644 --- a/src/Genocs.Auth/JwtOptions.cs +++ b/src/Genocs.Auth/Options/JwtSettings.cs @@ -1,17 +1,17 @@ -namespace Genocs.Auth; +namespace Genocs.Auth.Options; -public class JwtOptions +public class JwtSettings { public bool AuthenticationDisabled { get; set; } - public IEnumerable AllowAnonymousEndpoints { get; set; } - public CertificateOptions Certificate { get; set; } - public string Algorithm { get; set; } - public string Issuer { get; set; } - public string IssuerSigningKey { get; set; } - public string Authority { get; set; } - public string Audience { get; set; } + public IEnumerable? AllowAnonymousEndpoints { get; set; } + public CertificateOptions? Certificate { get; set; } + public string? Algorithm { get; set; } + public string? Issuer { get; set; } + public string? IssuerSigningKey { get; set; } + public string? Authority { get; set; } + public string? Audience { get; set; } public string Challenge { get; set; } = "Bearer"; - public string MetadataAddress { get; set; } + public string MetadataAddress { get; set; } = "/.well-known/openid-configuration"; public bool SaveToken { get; set; } = true; public bool SaveSigninToken { get; set; } public bool RequireAudience { get; set; } = true; @@ -20,10 +20,10 @@ public class JwtOptions public bool RequireSignedTokens { get; set; } = true; public int ExpiryMinutes { get; set; } public TimeSpan? Expiry { get; set; } - public string ValidAudience { get; set; } - public IEnumerable ValidAudiences { get; set; } - public string ValidIssuer { get; set; } - public IEnumerable ValidIssuers { get; set; } + public string? ValidAudience { get; set; } + public IEnumerable? ValidAudiences { get; set; } + public string? ValidIssuer { get; set; } + public IEnumerable? ValidIssuers { get; set; } public bool ValidateActor { get; set; } public bool ValidateAudience { get; set; } = true; public bool ValidateIssuer { get; set; } = true; @@ -32,14 +32,14 @@ public class JwtOptions public bool ValidateIssuerSigningKey { get; set; } public bool RefreshOnIssuerKeyNotFound { get; set; } = true; public bool IncludeErrorDetails { get; set; } = true; - public string AuthenticationType { get; set; } - public string NameClaimType { get; set; } - public string RoleClaimType { get; set; } + public string? AuthenticationType { get; set; } + public string? NameClaimType { get; set; } + public string? RoleClaimType { get; set; } public class CertificateOptions { - public string Location { get; set; } - public string RawData { get; set; } - public string Password { get; set; } + public string? Location { get; set; } + public string? RawData { get; set; } + public string? Password { get; set; } } } \ No newline at end of file diff --git a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs index 5540ba21..8e95a03f 100644 --- a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs +++ b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs @@ -1,3 +1,4 @@ +using Genocs.Auth.Options; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Primitives; @@ -10,9 +11,10 @@ internal sealed class InMemoryAccessTokenService : IAccessTokenService private readonly IHttpContextAccessor _httpContextAccessor; private readonly TimeSpan _expires; - public InMemoryAccessTokenService(IMemoryCache cache, - IHttpContextAccessor httpContextAccessor, - JwtOptions jwtOptions) + public InMemoryAccessTokenService( + IMemoryCache cache, + IHttpContextAccessor httpContextAccessor, + JwtSettings jwtOptions) { _cache = cache; _httpContextAccessor = httpContextAccessor; diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 2147d6a8..858251f9 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -68,6 +68,9 @@ "name": "<<>>", "managedIdentityId": "<<>>" }, + "secrets": { + "Secret": "This is a secret coming from the appsettings.json file" + }, "httpClient": { "type": "", "retries": 2, diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index d9149076..ca02962a 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -49,4 +49,17 @@ + + + + + + + + + + + + + diff --git a/src/Genocs.Security/README.md b/src/Genocs.Security/README.md index 221b7883..7c093329 100644 --- a/src/Genocs.Security/README.md +++ b/src/Genocs.Security/README.md @@ -1,12 +1,27 @@ -# .NET Core Base library +# Genocs Security library -This package contains a set of base functionalities designed by Genocs. -The libraries can be used on both .NET6 and .NET7. +This package contains the functionalities to be used to handle standard security concerns. +The libraries can be used on .NET6, .NET7, .NET8. ## Description -Core NuGet package contains general purpose functionalities to be used on DDD services. +Following an example of how the key should be. +**WARNING: DO NOT USE IT IN PROD!!!** + +``` xml + + svbEQ96xMdgUpnkDiSaULDbM/HVFLHLc46BdyqwEzIhK+Ml2dqWq/RZIh8kLWmYwpB5gqfOya8Wid3GKIpq7Ke8ciV53qW/1ImOZZPxOtwX1mNzvIEagq80QJoMLphtU1ytPWRXvOjBdGUeTzmdV2kpHNax41n4Uv0QpOPIhzME= + AQAB +

+ + + + + +
" +``` + ## Support @@ -15,45 +30,7 @@ Please check the GitHub repository getting more info. ## Release notes -### [2024-01-23] 5.0.6 +### [2024-06-15] 5.0.6 - Refactory Settings -- Updated nuget packages - -### [2023-11-25] 5.0.5 -- Moved to NET8 - -### [yyyy-mm-dd] 5.0.4 -- - -### [yyyy-mm-dd] 5.0.3 -- - -### [yyyy-mm-dd] 5.0.2 -- - -### [yyyy-mm-dd] 5.0.1 -- - -### [2023-11-25] 5.0.0 -- Moved to NET8 - -### [2023-10-13] 5.0.0-preview.5.0 -- Added [editorconfig](https://editorconfig.org/) -- Added StyleCop -- Updated logo -- Updated readme - -### [2023-03-12] 5.0.0-preview.4.0 -- Implemented MongoDB repository interfaces - -### [2023-03-12] 5.0.0 -- New Architecture - -### [2023-03-12] 3.1.0 -- Added Builders -### [2023-03-12] 3.0.0 -- Refactory to implement CQRS pattern -### [2023-03-04] 2.4.1 -- Updated System.Text.Json diff --git a/src/Genocs.Security/Services/SecurityKeyBuilder.cs b/src/Genocs.Security/Services/SecurityKeyBuilder.cs new file mode 100644 index 00000000..51634446 --- /dev/null +++ b/src/Genocs.Security/Services/SecurityKeyBuilder.cs @@ -0,0 +1,73 @@ +using Microsoft.IdentityModel.Tokens; +using System.Security.Cryptography; +using System.Xml; + +namespace Genocs.Security.Services; + +public static class SecurityKeyBuilder +{ + /// + /// Create a new instance of using the provided secret. + /// + /// The secret key as xml string. + /// The created RSA. + + public static SecurityKey CreateRsaSecurityKey(string secret) + { + RSA rsa = RSA.Create(); + rsa = FromCustomXmlString(rsa, secret); + return new RsaSecurityKey(rsa); + } + + /// + /// Helper method to create a RSA instance from a custom XML string. + /// + /// The RSA object instance. + /// The secret key as xml string. + /// The created RSA. + /// In case the secret key is invalid xml. + private static RSA FromCustomXmlString(RSA rsa, string xmlKey) + { + RSAParameters parameters = default(RSAParameters); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(xmlKey); + if (xmlDocument.DocumentElement != null && xmlDocument.DocumentElement!.Name.Equals("RSAKeyValue")) + { + foreach (XmlNode childNode in xmlDocument.DocumentElement!.ChildNodes) + { + switch (childNode.Name) + { + case "Modulus": + parameters.Modulus = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + case "Exponent": + parameters.Exponent = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + case "P": + parameters.P = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + case "Q": + parameters.Q = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + case "DP": + parameters.DP = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + case "DQ": + parameters.DQ = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + case "InverseQ": + parameters.InverseQ = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + case "D": + parameters.D = string.IsNullOrEmpty(childNode.InnerText) ? null : Convert.FromBase64String(childNode.InnerText); + break; + } + } + + rsa.ImportParameters(parameters); + return rsa; + } + + throw new Exception("Invalid XML RSA key."); + } +} \ No newline at end of file From 736964d22cb1715c3c1b0455647077a5797c99ad Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 15 Jun 2024 18:51:34 +0200 Subject: [PATCH 049/104] Refactor and enhance JWT handling and security --- .env | 2 +- .github/workflows/dockerhub-publish.yml | 2 +- .github/workflows/nuget-publish.yml | 2 +- src/Genocs.Auth/Genocs.Auth.csproj | 4 +-- src/Genocs.Auth/README.md | 4 +++ src/Genocs.Common/Genocs.Common.csproj | 2 +- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 4 +-- .../Genocs.Core.Demo.WebApi.csproj | 14 ++++---- .../Genocs.Core.Demo.Worker.csproj | 6 ++-- src/Genocs.Core/Genocs.Core.csproj | 4 +-- .../Genocs.Discovery.Consul.csproj | 6 ++-- .../Genocs.HTTP.RestEase.csproj | 10 +++--- src/Genocs.HTTP/Genocs.HTTP.csproj | 4 +-- .../Genocs.LoadBalancing.Fabio.csproj | 8 ++--- src/Genocs.Logging/Genocs.Logging.csproj | 4 +-- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 6 ++-- .../Genocs.MessageBrokers.Outbox.csproj | 4 +-- .../Genocs.MessageBrokers.RabbitMQ.csproj | 4 +-- .../Genocs.MessageBrokers.csproj | 4 +-- src/Genocs.Metrics/Genocs.Metrics.csproj | 4 +-- .../Genocs.Monitoring.csproj | 8 ++--- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 4 +-- .../Genocs.Persistence.Redis.csproj | 4 +-- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +-- .../Genocs.QueryBuilder.csproj | 2 +- .../Genocs.Secrets.AzureKeyVault.csproj | 4 +-- .../Genocs.Secrets.Vault.csproj | 4 +-- src/Genocs.Security/Genocs.Security.csproj | 4 +-- .../Genocs.ServiceBusAzure.csproj | 4 +-- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 6 ++-- src/Genocs.Tracing/Genocs.Tracing.csproj | 8 ++--- .../Genocs.WebApi.CQRS.csproj | 6 ++-- .../Genocs.WebApi.Security.csproj | 4 +-- .../Genocs.WebApi.Swagger.csproj | 4 +-- src/Genocs.WebApi/Genocs.WebApi.csproj | 4 +-- .../Genocs.APIGateway.csproj | 12 +++---- .../Genocs.Identities.Application.csproj | 20 +++++------ .../Genocs.Orders.WebApi.csproj | 22 ++++++------ .../Genocs.Products.WebApi.csproj | 32 ++++++++--------- .../Genocs.SignalR.WebApi.csproj | 34 +++++++++---------- 42 files changed, 148 insertions(+), 144 deletions(-) diff --git a/.env b/.env index 0a57f1b7..d6d68734 100644 --- a/.env +++ b/.env @@ -7,4 +7,4 @@ PROJECT_EXTERNAL_DNS_NAME_OR_IP=localhost # The docker image version -DOCKER_IMAGE_TAG=5.0.0 +DOCKER_IMAGE_TAG=6.0.0 diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml index 4566a8fc..2b635ced 100644 --- a/.github/workflows/dockerhub-publish.yml +++ b/.github/workflows/dockerhub-publish.yml @@ -13,7 +13,7 @@ on: description: "Image Version" # Default value if no value is explicitly provided - default: "5.0.0" + default: "6.0.0" # Input has to be provided for the workflow to run required: true diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index b1b9bb80..852c23c5 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -13,7 +13,7 @@ on: description: "Packages Version" # Default value if no value is explicitly provided - default: "5.0.0" + default: "6.0.0" # Input has to be provided for the workflow to run required: true diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 301e0e21..163a9497 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -9,7 +9,7 @@ The authorization library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@
- + diff --git a/src/Genocs.Auth/README.md b/src/Genocs.Auth/README.md index bb642339..29459bfd 100644 --- a/src/Genocs.Auth/README.md +++ b/src/Genocs.Auth/README.md @@ -37,6 +37,10 @@ Following are the project settings needed to enable monitoring ## Release notes +### [2024-06-15] 6.0.0 +- Added support for Azure Key Vault +- Unified settings + ### [2024-01-23] 5.0.6 - Refactory Settings - Updated nuget packages diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 0ae4fc34..2ab02e42 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -9,7 +9,7 @@ The common components to build .NET Core projects along with Genocs Library. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 2448a384..d001a674 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 51e0d7f3..f5b7f799 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -12,8 +12,8 @@
- - + + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index ad381117..40ab948e 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -20,13 +20,13 @@ - - - - - - - + + + + + + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 397b8065..71210be0 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 42fbdfc5..7613dec3 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -9,7 +9,7 @@ The core components to build .NET Core projects along with Genocs Library. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 89e6fd98..a488d839 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -9,7 +9,7 @@ The service discovery by Consul library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,8 +48,8 @@ - - + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 41f78a71..d0424313 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -9,7 +9,7 @@ The http support library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -50,10 +50,10 @@ - - - - + + + + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index e1dacf30..8179ec30 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -9,7 +9,7 @@ The http support library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index c2ba5fcd..fcb8230f 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -9,7 +9,7 @@ The load balacer based on Fabio library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -49,9 +49,9 @@ - - - + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 1f67fec2..7e4d7cea 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -9,7 +9,7 @@ The logging library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 63769706..b35fe693 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -9,7 +9,7 @@ The message brokers MongoDB outbox interface library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,8 +47,8 @@ - - + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 07edad63..67133bd3 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -9,7 +9,7 @@ The message brokers outbox interface library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 5d195cdc..66f4cceb 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -9,7 +9,7 @@ The message brokers RabbitMQ outbox interface library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index d40a6c53..08feee1d 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -9,7 +9,7 @@ The message brokers interface library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 57f0f9bb..9916ef03 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -9,7 +9,7 @@ The metrics interface library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index d4a1c0b4..2a945cb1 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -9,7 +9,7 @@ Telemetry and Tracing library. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -49,9 +49,9 @@ - - - + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index c7880590..71219a19 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 021c5b2e..eb912ede 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -9,7 +9,7 @@ The Genocs Library .NET Core to be used with MongoDB as persistence datalayer.. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index cb7c877b..5c0474e4 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -9,7 +9,7 @@ The library containing base repository pattern to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index e4ff69ae..59c8adcc 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 541174a7..e4064be1 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -9,7 +9,7 @@ The persistence agnostic query builder library. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index e5a7a124..0fcc66fa 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -9,7 +9,7 @@ The Genocs Secrets AzureKeyVault library 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index d70d81f6..db18b217 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -9,7 +9,7 @@ The Genocs Secrets Vault library 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index ca02962a..3d20591b 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -9,7 +9,7 @@ The Genocs Security library 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index ff1e0031..9dea0d80 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -9,7 +9,7 @@ The low level library to use Azure Service Bus. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index 420baf36..a2b2c3ff 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -9,7 +9,7 @@ The load balacer based on Fabio library useful to build .NET Core projects. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,8 +47,8 @@ - - + + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 5932b2b9..10143fd3 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -9,7 +9,7 @@ The tracing library to use Azure Service Bus. 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -48,9 +48,9 @@ - - - + + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index a1144df4..c985d721 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -9,7 +9,7 @@ The web api CORS library 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - - + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 06635225..6b36bd67 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -9,7 +9,7 @@ The web api Security library 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 5c9b030e..1bf96a4b 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -9,7 +9,7 @@ The web api Swagger library 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -46,7 +46,7 @@ - + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 7f8c6cec..ededa441 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -9,7 +9,7 @@ The web api library 10.0 true - 5.0.0 + 6.0.0 5.0.0 Nocco Giovanni Emanuele Genocs @@ -47,7 +47,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index f68c444d..530f5ee8 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -19,12 +19,12 @@ - - - - - - + + + + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 2370404a..782eb9a7 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -20,16 +20,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 274707a7..3655f8d5 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -29,17 +29,17 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index c721f991..d567ae87 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -30,22 +30,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 1a810ccc..0c94f416 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -34,23 +34,23 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file From bb5ea5989bdbe0bfa756e3b00b1a15a3e12f3942 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 18 Jun 2024 17:47:04 +0200 Subject: [PATCH 050/104] Refactor auth/config handling and enhance security - Introduced namespaces `Genocs.Auth.Options` and `Genocs.Security.Services` for better organization. - Replaced hardcoded "jwt" with `JwtSettings.Position` for dynamic JWT config. - Renamed `options` to `jwtSettings` in methods for clarity. - Updated token validation to use `jwtSettings`, improving readability. - Enhanced certificate loading using `jwtSettings`. - Added `AddPrivateKeyJwt` method for private key JWT auth support. - Included `Genocs.Security` project reference in `Genocs.Auth.csproj`. - Modified `JwtSettings` and adjusted default section names in configs. - Cleaned up code, standardized method signatures, and updated documentation. - Replaced `MessagingOptions` with `MessagingSettings` and updated usage. - Managed project references and package dependencies for `Genocs.Security`. - Introduced `BaseAggregate` class for common entity properties. - Made minor adjustments for code quality improvements. --- .../azure-pipeline.yml | 0 src/Genocs.Auth/Extensions.cs | 164 ++++++++++++------ src/Genocs.Auth/Genocs.Auth.csproj | 3 + src/Genocs.Auth/Options/JwtSettings.cs | 14 +- src/Genocs.Common/Options/AppSettings.cs | 2 +- .../Aggregates/BaseAggregate.cs | 14 ++ .../Options/SecretSettings.cs | 9 +- src/Genocs.Core.Demo.WebApi/appsettings.json | 23 +-- src/Genocs.Core/CQRS/Commons/IDispatcher.cs | 2 +- .../Services/SecurityKeyBuilder.cs | 1 - .../Middlewares/PublicContractsMiddleware.cs | 4 +- src/Genocs.WebApi/Options/WebApiSettings.cs | 2 +- src/Genocs.WebApi/Parsers/JsonParser.cs | 2 +- .../Framework/CorrelationContextBuilder.cs | 8 +- .../Framework/ICorrelationContextBuilder.cs | 8 +- .../Framework/MessagingMiddleware.cs | 15 +- .../Framework/MessagingOptions.cs | 15 -- .../Options/MessagingSettings.cs | 15 ++ .../api-gateway/Genocs.APIGateway/Startup.cs | 3 +- .../Genocs.SignalR.WebApi.csproj | 1 - 20 files changed, 198 insertions(+), 107 deletions(-) rename azure-pipeline.yml => azure/azure-pipeline.yml (100%) create mode 100644 src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs delete mode 100644 src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingOptions.cs create mode 100644 src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs diff --git a/azure-pipeline.yml b/azure/azure-pipeline.yml similarity index 100% rename from azure-pipeline.yml rename to azure/azure-pipeline.yml diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index cd62769c..4f74c0dc 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -1,34 +1,34 @@ using Genocs.Auth.Handlers; +using Genocs.Auth.Options; using Genocs.Auth.Services; using Genocs.Core.Builders; +using Genocs.Security.Services; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; using System.Security.Cryptography.X509Certificates; using System.Text; -using Genocs.Auth.Options; namespace Genocs.Auth; public static class Extensions { - private const string SectionName = "jwt"; private const string RegistryName = "auth"; public static IGenocsBuilder AddJwt( this IGenocsBuilder builder, - string sectionName = SectionName, + string sectionName = JwtSettings.Position, Action? optionsFactory = null) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = SectionName; + sectionName = JwtSettings.Position; } var options = builder.GetOptions(sectionName); @@ -37,7 +37,7 @@ public static IGenocsBuilder AddJwt( private static IGenocsBuilder AddJwt( this IGenocsBuilder builder, - JwtSettings options, + JwtSettings jwtSettings, Action? optionsFactory = null) { if (!builder.TryRegister(RegistryName)) @@ -50,53 +50,53 @@ private static IGenocsBuilder AddJwt( builder.Services.AddSingleton(); builder.Services.AddTransient(); - if (options.AuthenticationDisabled) + if (!jwtSettings.Enabled) { builder.Services.AddSingleton(); } var tokenValidationParameters = new TokenValidationParameters { - RequireAudience = options.RequireAudience, - ValidIssuer = options.ValidIssuer, - ValidIssuers = options.ValidIssuers, - ValidateActor = options.ValidateActor, - ValidAudience = options.ValidAudience, - ValidAudiences = options.ValidAudiences, - ValidateAudience = options.ValidateAudience, - ValidateIssuer = options.ValidateIssuer, - ValidateLifetime = options.ValidateLifetime, - ValidateTokenReplay = options.ValidateTokenReplay, - ValidateIssuerSigningKey = options.ValidateIssuerSigningKey, - SaveSigninToken = options.SaveSigninToken, - RequireExpirationTime = options.RequireExpirationTime, - RequireSignedTokens = options.RequireSignedTokens, + RequireAudience = jwtSettings.RequireAudience, + ValidIssuer = jwtSettings.ValidIssuer, + ValidIssuers = jwtSettings.ValidIssuers, + ValidateActor = jwtSettings.ValidateActor, + ValidAudience = jwtSettings.ValidAudience, + ValidAudiences = jwtSettings.ValidAudiences, + ValidateAudience = jwtSettings.ValidateAudience, + ValidateIssuer = jwtSettings.ValidateIssuer, + ValidateLifetime = jwtSettings.ValidateLifetime, + ValidateTokenReplay = jwtSettings.ValidateTokenReplay, + ValidateIssuerSigningKey = jwtSettings.ValidateIssuerSigningKey, + SaveSigninToken = jwtSettings.SaveSigninToken, + RequireExpirationTime = jwtSettings.RequireExpirationTime, + RequireSignedTokens = jwtSettings.RequireSignedTokens, ClockSkew = TimeSpan.Zero }; - if (!string.IsNullOrWhiteSpace(options.AuthenticationType)) + if (!string.IsNullOrWhiteSpace(jwtSettings.AuthenticationType)) { - tokenValidationParameters.AuthenticationType = options.AuthenticationType; + tokenValidationParameters.AuthenticationType = jwtSettings.AuthenticationType; } bool hasCertificate = false; - if (options.Certificate is not null) + if (jwtSettings.Certificate is not null) { X509Certificate2? certificate = null; - string password = options.Certificate.Password; + string password = jwtSettings.Certificate.Password; bool hasPassword = !string.IsNullOrWhiteSpace(password); - if (!string.IsNullOrWhiteSpace(options.Certificate.Location)) + if (!string.IsNullOrWhiteSpace(jwtSettings.Certificate.Location)) { certificate = hasPassword - ? new X509Certificate2(options.Certificate.Location, password) - : new X509Certificate2(options.Certificate.Location); + ? new X509Certificate2(jwtSettings.Certificate.Location, password) + : new X509Certificate2(jwtSettings.Certificate.Location); string keyType = certificate.HasPrivateKey ? "with private key" : "with public key only"; - Console.WriteLine($"Loaded X.509 certificate from location: '{options.Certificate.Location}' {keyType}."); + Console.WriteLine($"Loaded X.509 certificate from location: '{jwtSettings.Certificate.Location}' {keyType}."); } - if (!string.IsNullOrWhiteSpace(options.Certificate.RawData)) + if (!string.IsNullOrWhiteSpace(jwtSettings.Certificate.RawData)) { - byte[] rawData = Convert.FromBase64String(options.Certificate.RawData); + byte[] rawData = Convert.FromBase64String(jwtSettings.Certificate.RawData); certificate = hasPassword ? new X509Certificate2(rawData, password) : new X509Certificate2(rawData); @@ -106,9 +106,9 @@ private static IGenocsBuilder AddJwt( if (certificate is not null) { - if (string.IsNullOrWhiteSpace(options.Algorithm)) + if (string.IsNullOrWhiteSpace(jwtSettings.Algorithm)) { - options.Algorithm = SecurityAlgorithms.RsaSha256; + jwtSettings.Algorithm = SecurityAlgorithms.RsaSha256; } hasCertificate = true; @@ -118,53 +118,54 @@ private static IGenocsBuilder AddJwt( } } - if (!string.IsNullOrWhiteSpace(options.IssuerSigningKey) && !hasCertificate) + if (!string.IsNullOrWhiteSpace(jwtSettings.IssuerSigningKey) && !hasCertificate) { - if (string.IsNullOrWhiteSpace(options.Algorithm) || hasCertificate) + if (string.IsNullOrWhiteSpace(jwtSettings.Algorithm) || hasCertificate) { - options.Algorithm = SecurityAlgorithms.HmacSha256; + jwtSettings.Algorithm = SecurityAlgorithms.HmacSha256; } - byte[] rawKey = Encoding.UTF8.GetBytes(options.IssuerSigningKey); + byte[] rawKey = Encoding.UTF8.GetBytes(jwtSettings.IssuerSigningKey); tokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(rawKey); Console.WriteLine("Using symmetric encryption for issuing tokens."); } - if (!string.IsNullOrWhiteSpace(options.NameClaimType)) + if (!string.IsNullOrWhiteSpace(jwtSettings.NameClaimType)) { - tokenValidationParameters.NameClaimType = options.NameClaimType; + tokenValidationParameters.NameClaimType = jwtSettings.NameClaimType; } - if (!string.IsNullOrWhiteSpace(options.RoleClaimType)) + if (!string.IsNullOrWhiteSpace(jwtSettings.RoleClaimType)) { - tokenValidationParameters.RoleClaimType = options.RoleClaimType; + tokenValidationParameters.RoleClaimType = jwtSettings.RoleClaimType; } builder.Services .AddAuthentication(o => { - o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + o.DefaultAuthenticateScheme = jwtSettings.Challenge; + o.DefaultChallengeScheme = jwtSettings.Challenge; + o.DefaultScheme = jwtSettings.Challenge; }) .AddJwtBearer(o => { - o.Authority = options.Authority; - o.Audience = options.Audience; - o.MetadataAddress = options.MetadataAddress; - o.SaveToken = options.SaveToken; - o.RefreshOnIssuerKeyNotFound = options.RefreshOnIssuerKeyNotFound; - o.RequireHttpsMetadata = options.RequireHttpsMetadata; - o.IncludeErrorDetails = options.IncludeErrorDetails; + o.Authority = jwtSettings.Authority; + o.Audience = jwtSettings.Audience; + o.MetadataAddress = jwtSettings.MetadataAddress; + o.SaveToken = jwtSettings.SaveToken; + o.RefreshOnIssuerKeyNotFound = jwtSettings.RefreshOnIssuerKeyNotFound; + o.RequireHttpsMetadata = jwtSettings.RequireHttpsMetadata; + o.IncludeErrorDetails = jwtSettings.IncludeErrorDetails; o.TokenValidationParameters = tokenValidationParameters; - if (!string.IsNullOrWhiteSpace(options.Challenge)) + if (!string.IsNullOrWhiteSpace(jwtSettings.Challenge)) { - o.Challenge = options.Challenge; + o.Challenge = jwtSettings.Challenge; } optionsFactory?.Invoke(o); }); - builder.Services.AddSingleton(options); + builder.Services.AddSingleton(jwtSettings); builder.Services.AddSingleton(tokenValidationParameters); return builder; @@ -175,18 +176,16 @@ private static IGenocsBuilder AddJwt( /// It can be used with Firebase Authentication. /// /// The Genocs builder. - /// The configuration name. Default value is 'FirebaseAuthentication'. + /// The configuration section name. /// The Genocs builder you can use for chain. public static IGenocsBuilder AddOpenIdJwt( this IGenocsBuilder builder, - string sectionName = "openIdAuth") + string sectionName = JwtSettings.Position) { - var jwtSettings = new JwtSettings(); builder.Configuration.GetSection(sectionName).Bind(jwtSettings); - // Enable Firebase Authentication string metadataAddress = $"{jwtSettings.Issuer}{jwtSettings.MetadataAddress}"; var configurationManager = new ConfigurationManager(metadataAddress, new OpenIdConnectConfigurationRetriever()); @@ -209,6 +208,57 @@ public static IGenocsBuilder AddOpenIdJwt( return builder; } + + /// + /// It adds the private key JWT authentication. + /// + /// The Genocs builder. + /// The optional section name. Default name: 'jwt'. + /// The Genocs builder you can use for chaining. + /// Whenever mandatory data like 'IssuerSigningKey' is missing. + public static IGenocsBuilder AddPrivateKeyJwt( + this IGenocsBuilder builder, + string sectionName = JwtSettings.Position) + { + if (string.IsNullOrWhiteSpace(sectionName)) + { + sectionName = JwtSettings.Position; + } + + var jwtSettings = new JwtSettings(); + builder.Configuration.GetSection(sectionName).Bind(jwtSettings); + + if (string.IsNullOrWhiteSpace(jwtSettings.IssuerSigningKey)) + { + throw new InvalidOperationException("Issuer signing key is missing."); + } + + SecurityKey signingKey = SecurityKeyBuilder.CreateRsaSecurityKey(jwtSettings.IssuerSigningKey); + + builder.Services + .AddAuthentication(o => + { + o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(o => + { + o.SaveToken = jwtSettings.SaveToken; + o.RequireHttpsMetadata = jwtSettings.RequireHttpsMetadata; + o.TokenValidationParameters = new TokenValidationParameters() + { + IssuerSigningKey = signingKey, + ValidateAudience = jwtSettings.ValidateAudience, + ValidAudience = jwtSettings.ValidAudience, + ValidateIssuer = jwtSettings.ValidateIssuer, + ValidIssuer = jwtSettings.ValidIssuer, + ValidateLifetime = jwtSettings.ValidateLifetime, + ValidateIssuerSigningKey = jwtSettings.ValidateIssuerSigningKey + }; + }); + + return builder; + } + public static IApplicationBuilder UseAccessTokenValidator(this IApplicationBuilder app) => app.UseMiddleware(); } diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 163a9497..ce0c8e54 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -43,10 +43,13 @@ + + + diff --git a/src/Genocs.Auth/Options/JwtSettings.cs b/src/Genocs.Auth/Options/JwtSettings.cs index 7df2684c..08dfb6de 100644 --- a/src/Genocs.Auth/Options/JwtSettings.cs +++ b/src/Genocs.Auth/Options/JwtSettings.cs @@ -2,7 +2,15 @@ namespace Genocs.Auth.Options; public class JwtSettings { - public bool AuthenticationDisabled { get; set; } + /// + /// Default section name. + /// + public const string Position = "jwt"; + + /// + /// It is used to enable or disable the authentication. + /// + public bool Enabled { get; set; } public IEnumerable? AllowAnonymousEndpoints { get; set; } public CertificateOptions? Certificate { get; set; } public string? Algorithm { get; set; } @@ -10,6 +18,10 @@ public class JwtSettings public string? IssuerSigningKey { get; set; } public string? Authority { get; set; } public string? Audience { get; set; } + + /// + /// This is the Authentication Scheme name. + /// public string Challenge { get; set; } = "Bearer"; public string MetadataAddress { get; set; } = "/.well-known/openid-configuration"; public bool SaveToken { get; set; } = true; diff --git a/src/Genocs.Common/Options/AppSettings.cs b/src/Genocs.Common/Options/AppSettings.cs index 94ac5643..3af8f1ef 100644 --- a/src/Genocs.Common/Options/AppSettings.cs +++ b/src/Genocs.Common/Options/AppSettings.cs @@ -8,7 +8,7 @@ public class AppSettings /// /// Default section name. /// - public const string Position = "App"; + public const string Position = "app"; /// /// Application name. diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs b/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs new file mode 100644 index 00000000..e074b90e --- /dev/null +++ b/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs @@ -0,0 +1,14 @@ +using Genocs.Core.Domain.Entities; +using Genocs.Core.Domain.Entities.Auditing; +using Genocs.Persistence.MongoDb.Repositories.Clean; +using MongoDB.Bson; + +namespace Genocs.Core.Demo.Domain.Aggregates; + +/// +/// Base aggregate class used for all entities. +/// +public class BaseAggregate : AggregateRoot, IMongoDbEntity, IHasCreationTime +{ + public DateTime CreationTime { get; set; } = DateTime.UtcNow; +} \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs b/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs index 62de4357..08d05a8a 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs @@ -2,8 +2,15 @@ public class SecretSettings { - public const string Position = "Secrets"; + /// + /// Default section name. + /// + public const string Position = "secrets"; + + /// + /// This is an example of a secret. That should be stored in a secure way. + /// public string? Secret { get; set; } } diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 858251f9..750cbaac 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -1,18 +1,11 @@ { - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Information", - "Microsoft": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "ConnectionStrings": { - "ApplicationInsights": "" - }, - "AppSettings": { - "ServiceName": "Demo-WebApi" + "app": { + "name": "Demo WebApi", + "service": "Demo WebApi", + "instance": "1", + "version": "v1.0", + "displayBanner": true, + "displayVersion": true }, "RabbitMQ": { "HostName": "localhost", @@ -69,7 +62,7 @@ "managedIdentityId": "<<>>" }, "secrets": { - "Secret": "This is a secret coming from the appsettings.json file" + "Secret": "This is a secret coming from the appsettings.json file" }, "httpClient": { "type": "", diff --git a/src/Genocs.Core/CQRS/Commons/IDispatcher.cs b/src/Genocs.Core/CQRS/Commons/IDispatcher.cs index cca50975..4df4070f 100644 --- a/src/Genocs.Core/CQRS/Commons/IDispatcher.cs +++ b/src/Genocs.Core/CQRS/Commons/IDispatcher.cs @@ -20,7 +20,7 @@ Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand; /// - /// Generic event publisher + /// Generic event publisher. /// /// /// diff --git a/src/Genocs.Security/Services/SecurityKeyBuilder.cs b/src/Genocs.Security/Services/SecurityKeyBuilder.cs index 51634446..70036a21 100644 --- a/src/Genocs.Security/Services/SecurityKeyBuilder.cs +++ b/src/Genocs.Security/Services/SecurityKeyBuilder.cs @@ -11,7 +11,6 @@ public static class SecurityKeyBuilder /// /// The secret key as xml string. /// The created RSA. - public static SecurityKey CreateRsaSecurityKey(string secret) { RSA rsa = RSA.Create(); diff --git a/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs b/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs index ace00b60..555198a0 100644 --- a/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs +++ b/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs @@ -86,8 +86,8 @@ private void Load(Type attributeType) foreach (var @event in contracts.Where(t => typeof(IEvent).IsAssignableFrom(t) && t != typeof(RejectedEvent))) { - var instance = @event.GetDefaultInstance(); - var name = instance.GetType().Name; + object? instance = @event.GetDefaultInstance(); + string? name = instance?.GetType().Name; if (Contracts.Events.ContainsKey(name)) { diff --git a/src/Genocs.WebApi/Options/WebApiSettings.cs b/src/Genocs.WebApi/Options/WebApiSettings.cs index 666d7ec3..f7429c94 100644 --- a/src/Genocs.WebApi/Options/WebApiSettings.cs +++ b/src/Genocs.WebApi/Options/WebApiSettings.cs @@ -1,7 +1,7 @@ namespace Genocs.WebApi.Options; /// -/// The WebApiSettings definiiton +/// The WebApiSettings definiiton. /// public class WebApiSettings { diff --git a/src/Genocs.WebApi/Parsers/JsonParser.cs b/src/Genocs.WebApi/Parsers/JsonParser.cs index c4b84e5f..7a2dec07 100644 --- a/src/Genocs.WebApi/Parsers/JsonParser.cs +++ b/src/Genocs.WebApi/Parsers/JsonParser.cs @@ -78,7 +78,7 @@ private void VisitValue(JsonElement value) case JsonValueKind.True: case JsonValueKind.False: case JsonValueKind.Null: - var key = _stack.Peek(); + string key = _stack.Peek(); if (_data.ContainsKey(key)) { diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs index 0a89e5e3..c8299cf4 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs @@ -4,8 +4,12 @@ namespace Genocs.APIGateway.Framework; internal sealed class CorrelationContextBuilder : ICorrelationContextBuilder { - public CorrelationContext Build(HttpContext context, string correlationId, string spanContext, - string name = null, string resourceId = null) + public CorrelationContext Build( + HttpContext context, + string correlationId, + string spanContext, + string name = null, + string resourceId = null) => new CorrelationContext { CorrelationId = correlationId, diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/ICorrelationContextBuilder.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/ICorrelationContextBuilder.cs index c64456f7..9618311f 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/ICorrelationContextBuilder.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/ICorrelationContextBuilder.cs @@ -2,6 +2,10 @@ namespace Genocs.APIGateway.Framework; internal interface ICorrelationContextBuilder { - CorrelationContext Build(HttpContext context, string correlationId, string spanContext, string? name = null, - string? resourceId = null); + CorrelationContext Build( + HttpContext context, + string correlationId, + string spanContext, + string? name = null, + string? resourceId = null); } \ No newline at end of file diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs index bb224d67..5575cb06 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs @@ -1,3 +1,4 @@ +using Genocs.APIGateway.Options; using Genocs.MessageBrokers.RabbitMQ; using Genocs.MessageBrokers.RabbitMQ.Conventions; using Microsoft.Extensions.Options; @@ -15,11 +16,15 @@ internal class MessagingMiddleware : IMiddleware private readonly ITracer _tracer; private readonly ICorrelationContextBuilder _correlationContextBuilder; private readonly CorrelationIdFactory _correlationIdFactory; - private readonly IDictionary> _endpoints; + private readonly IDictionary> _endpoints; - public MessagingMiddleware(IRabbitMQClient rabbitMQClient, RouteMatcher routeMatcher, ITracer tracer, - ICorrelationContextBuilder correlationContextBuilder, CorrelationIdFactory correlationIdFactory, - IOptions messagingOptions) + public MessagingMiddleware( + IRabbitMQClient rabbitMQClient, + RouteMatcher routeMatcher, + ITracer tracer, + ICorrelationContextBuilder correlationContextBuilder, + CorrelationIdFactory correlationIdFactory, + IOptions messagingOptions) { if (messagingOptions is null) { @@ -34,7 +39,7 @@ public MessagingMiddleware(IRabbitMQClient rabbitMQClient, RouteMatcher routeMat _endpoints = messagingOptions.Value.Endpoints?.Any() is true ? messagingOptions.Value.Endpoints.GroupBy(e => e.Method.ToUpperInvariant()) .ToDictionary(e => e.Key, e => e.ToList()) - : new Dictionary>(); + : new Dictionary>(); } public async Task InvokeAsync(HttpContext context, RequestDelegate next) diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingOptions.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingOptions.cs deleted file mode 100644 index 9f30b83e..00000000 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Genocs.APIGateway.Framework; - -internal class MessagingOptions -{ - public bool Enabled { get; set; } - public IEnumerable? Endpoints { get; set; } - - internal class EndpointOptions - { - public string Method { get; set; } - public string Path { get; set; } - public string Exchange { get; set; } - public string RoutingKey { get; set; } - } -} \ No newline at end of file diff --git a/src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs b/src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs new file mode 100644 index 00000000..113498cc --- /dev/null +++ b/src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs @@ -0,0 +1,15 @@ +namespace Genocs.APIGateway.Options; + +internal class MessagingSettings +{ + public bool Enabled { get; set; } + public IEnumerable? Endpoints { get; set; } + + internal class EndpointSettings + { + public string? Method { get; set; } + public string? Path { get; set; } + public string? Exchange { get; set; } + public string? RoutingKey { get; set; } + } +} \ No newline at end of file diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index 11a962b5..a2dae299 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -1,4 +1,5 @@ using Genocs.APIGateway.Framework; +using Genocs.APIGateway.Options; using Genocs.Auth; using Genocs.Common.Options; using Genocs.Core.Builders; @@ -31,7 +32,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.Configure(Configuration.GetSection("messaging")); + services.Configure(Configuration.GetSection("messaging")); services.AddReverseProxy() .LoadFromConfig(Configuration.GetSection("ReverseProxy")); services.AddSingleton(); diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 0c94f416..8b977205 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -52,5 +52,4 @@ - \ No newline at end of file From 3a28fd1bf3f42c3de94cdd58ae002eb91b14fe2c Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 19 Jun 2024 18:18:40 +0200 Subject: [PATCH 051/104] Added auth features and AuthorizedController - Added `Genocs.Auth` project reference and package to `Genocs.Core.Demo.WebApi.csproj` for authentication support. - Included `Genocs.Auth` namespace in `Program.cs` for direct usage of its classes and members. - Enhanced service registration in `Program.cs` with `.AddPrivateKeyJwt()` for JWT authentication setup. - Created `AuthorizedController` with `[ApiController]`, `[Route("[controller]")]`, and `[Authorize]` attributes for secured API endpoints. - Implemented asynchronous action `PostSubmitDemoCommand` in `AuthorizedController`, utilizing `System.Net.Mime.MediaTypeNames.Application.Json`. --- .../Controllers/AuthorizedController.cs | 26 +++++++++++++++++++ .../Genocs.Core.Demo.WebApi.csproj | 2 ++ src/Genocs.Core.Demo.WebApi/Program.cs | 2 ++ 3 files changed, 30 insertions(+) create mode 100644 src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs new file mode 100644 index 00000000..0f922b23 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Net.Mime; + +namespace Genocs.Core.Demo.WebApi.Controllers; + +[ApiController] +[Route("[controller]")] +[Authorize] +public class AuthorizedController : ControllerBase +{ + private readonly ILogger _logger; + + public AuthorizedController(ILogger logger) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + [HttpGet("GetAuthorized")] + [Consumes(MediaTypeNames.Application.Json)] + [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] + public async Task PostSubmitDemoCommand() + { + return await Task.Run(() => Ok("Done")); + } +} diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 40ab948e..6a363384 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -12,6 +12,7 @@ + @@ -22,6 +23,7 @@ + diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index 5a9e4d16..a9436578 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -1,3 +1,4 @@ +using Genocs.Auth; using Genocs.Core.Builders; using Genocs.Core.Demo.WebApi.Infrastructure.Extensions; using Genocs.Core.Demo.WebApi.Options; @@ -29,6 +30,7 @@ services .AddGenocs(builder.Configuration) + .AddPrivateKeyJwt() .AddOpenTelemetry() .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()) From 7bae2b7496200b36a9f0f0c4f0dadf60b74c3421 Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Sat, 22 Jun 2024 09:14:39 +0200 Subject: [PATCH 052/104] Sincronize naming conventions --- .../AccessTokenValidatorMiddleware.cs | 4 +- src/Genocs.Auth/Builders/JwtOptionsBuilder.cs | 6 +- .../JwtOptions.cs} | 4 +- src/Genocs.Auth/Extensions.cs | 20 ++--- src/Genocs.Auth/Genocs.Auth.csproj | 4 +- src/Genocs.Auth/Handlers/JwtHandler.cs | 6 +- src/Genocs.Auth/IJwtOptionsBuilder.cs | 4 +- src/Genocs.Auth/README_NUGET.md | 85 +++++++++++++++++++ .../Services/InMemoryAccessTokenService.cs | 6 +- .../AppOptions.cs} | 4 +- src/Genocs.Common/Genocs.Common.csproj | 4 +- src/Genocs.Common/README_NUGET.md | 59 +++++++++++++ .../Services/ExternalServiceClient.cs | 4 +- src/Genocs.Core.Demo.WebApi/Program.cs | 2 +- src/Genocs.Core/Builders/Extensions.cs | 12 +-- src/Genocs.Core/Genocs.Core.csproj | 4 +- src/Genocs.Core/README_NUGET.md | 63 ++++++++++++++ .../Builders/ConsulOptionsBuilder.cs | 6 +- .../ConsulOptions.cs} | 9 +- .../IConsulOptionsBuilder.cs | 4 +- src/Genocs.Discovery.Consul/Extensions.cs | 18 ++-- .../Http/ConsulHttpClient.cs | 4 +- .../ConsulServiceDiscoveryMessageHandler.cs | 27 +++--- ...eBuilders.cs => RestEaseOptionsBuilder.cs} | 18 ++-- .../Configurations/IRestEaseOptionsBuilder.cs | 8 ++ .../RestEaseOptions.cs} | 4 +- src/Genocs.HTTP.RestEase/Extensions.cs | 24 +++--- .../IRestEaseServiceBuilder.cs | 4 +- .../IRestEaseSettingsBuilder.cs | 10 --- .../HttpClientOptions.cs} | 16 ++-- src/Genocs.HTTP/Extensions.cs | 4 +- src/Genocs.HTTP/GenocsHttpClient.cs | 6 +- src/Genocs.HTTP/GenocsHttpLoggingFilter.cs | 6 +- .../GenocsLoggingScopeHttpMessageHandler.cs | 4 +- .../Builders/FabioOptionsBuilder.cs | 6 +- .../FabioOptions.cs} | 6 +- .../IFabioOptionsBuilder.cs | 6 +- src/Genocs.LoadBalancing.Fabio/Extensions.cs | 28 +++--- .../Http/FabioHttpClient.cs | 4 +- .../MessageHandlers/FabioMessageHandler.cs | 6 +- .../AzureOptions.cs} | 4 +- .../ConsoleOptions.cs} | 4 +- .../ElkOptions.cs} | 4 +- .../LocalFileOptions.cs} | 4 +- .../LoggerOptions.cs} | 19 ++--- .../LokiOptions.cs} | 4 +- .../MongoOptions.cs} | 4 +- .../SeqOptions.cs} | 4 +- src/Genocs.Logging/Extensions.cs | 48 +++++------ .../Builders/MetricsOptionsBuilder.cs | 20 ++--- .../Configurations/IMetricsSettingsBuilder.cs | 14 +++ .../MetricsSettings.cs | 2 +- src/Genocs.Metrics/AppMetrics/Extensions.cs | 42 ++++----- .../AppMetrics/IMetricsOptionsBuilder.cs | 16 ---- .../EncryptionUnitTest.cs | 1 - .../Builders/MongoDbOptionsBuilder.cs | 7 +- .../IMongoDbOptionsBuilder.cs | 6 +- .../MongoDbEncryptionOptions.cs | 69 +++++++++++++++ .../MongoDbOptions.cs} | 6 +- .../Encryptions/AzureInitializer.cs | 8 +- .../Extensions/MongoDbExtensions.cs | 30 +++---- .../Initializers/MongoDbInitializer.cs | 4 +- .../MongoDatabaseProvider.cs | 17 ++-- .../Options/MongoDbEncryptionSettings.cs | 70 --------------- src/Genocs.Tracing/Extensions.cs | 8 +- .../Builders/DispatcherEndpointsBuilder.cs | 24 ++++-- .../CertificateMiddleware.cs | 11 +-- .../SecurityOptions.cs} | 12 +-- src/Genocs.WebApi.Security/Extensions.cs | 5 +- .../Builders/SwaggerOptionsBuilder.cs | 4 +- .../ISwaggerOptionsBuilder.cs | 2 +- .../SwaggerOptions.cs | 2 +- src/Genocs.WebApi.Swagger/Docs/Extensions.cs | 3 +- src/Genocs.WebApi.Swagger/Extensions.cs | 1 + .../api-gateway/Genocs.APIGateway/Startup.cs | 4 +- .../CorrelationIdFactory.cs | 4 +- .../Extensions.cs | 4 +- .../Services/ProductServiceClient.cs | 18 ++-- testEnvironments.json | 17 ++++ 79 files changed, 640 insertions(+), 405 deletions(-) rename src/Genocs.Auth/{Options/JwtSettings.cs => Configurations/JwtOptions.cs} (97%) create mode 100644 src/Genocs.Auth/README_NUGET.md rename src/Genocs.Common/{Options/AppSettings.cs => Configurations/AppOptions.cs} (93%) create mode 100644 src/Genocs.Common/README_NUGET.md create mode 100644 src/Genocs.Core/README_NUGET.md rename src/Genocs.Discovery.Consul/{Options/ConsulSettings.cs => Configurations/ConsulOptions.cs} (79%) rename src/Genocs.Discovery.Consul/{Options => Configurations}/IConsulOptionsBuilder.cs (88%) rename src/Genocs.HTTP.RestEase/Builders/{RestEaseBuilders.cs => RestEaseOptionsBuilder.cs} (62%) create mode 100644 src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs rename src/Genocs.HTTP.RestEase/{Options/RestEaseSettings.cs => Configurations/RestEaseOptions.cs} (80%) delete mode 100644 src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs rename src/Genocs.HTTP/{Options/HttpClientSettings.cs => Configurations/HttpClientOptions.cs} (63%) rename src/Genocs.LoadBalancing.Fabio/{Options/FabioSettings.cs => Configurations/FabioOptions.cs} (83%) rename src/Genocs.LoadBalancing.Fabio/{ => Configurations}/IFabioOptionsBuilder.cs (90%) rename src/Genocs.Logging/{Options/AzureSettings.cs => Configurations/AzureOptions.cs} (85%) rename src/Genocs.Logging/{Options/ConsoleSettings.cs => Configurations/ConsoleOptions.cs} (75%) rename src/Genocs.Logging/{Options/ElkSettings.cs => Configurations/ElkOptions.cs} (90%) rename src/Genocs.Logging/{Options/LocalFileSettings.cs => Configurations/LocalFileOptions.cs} (87%) rename src/Genocs.Logging/{Options/LoggerSettings.cs => Configurations/LoggerOptions.cs} (67%) rename src/Genocs.Logging/{Options/LokiSettings.cs => Configurations/LokiOptions.cs} (96%) rename src/Genocs.Logging/{Options/MongoSettings.cs => Configurations/MongoOptions.cs} (76%) rename src/Genocs.Logging/{Options/SeqSettings.cs => Configurations/SeqOptions.cs} (64%) create mode 100644 src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs rename src/Genocs.Metrics/AppMetrics/{Options => Configurations}/MetricsSettings.cs (96%) delete mode 100644 src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs rename src/Genocs.Persistence.MongoDb/{Repositories => Configurations}/IMongoDbOptionsBuilder.cs (87%) create mode 100644 src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs rename src/Genocs.Persistence.MongoDb/{Options/MongoDbSettings.cs => Configurations/MongoDbOptions.cs} (91%) delete mode 100644 src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs rename src/Genocs.WebApi.Security/{Options/SecuritySettings.cs => Configurations/SecurityOptions.cs} (72%) rename src/Genocs.WebApi.Swagger/{Docs => }/Builders/SwaggerOptionsBuilder.cs (93%) rename src/Genocs.WebApi.Swagger/{Docs => Configurations}/ISwaggerOptionsBuilder.cs (91%) rename src/Genocs.WebApi.Swagger/{Docs => Configurations}/SwaggerOptions.cs (88%) create mode 100644 testEnvironments.json diff --git a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs index bf4b93cb..b0de9341 100644 --- a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs +++ b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; using Microsoft.AspNetCore.Http; using System.Net; @@ -17,7 +17,7 @@ public class AccessTokenValidatorMiddleware : IMiddleware /// /// The access token service. /// The options. - public AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtSettings options) + public AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtOptions options) { _accessTokenService = accessTokenService; _endpoints = options.AllowAnonymousEndpoints ?? Enumerable.Empty(); diff --git a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs index 9ef51792..c81ab262 100644 --- a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs +++ b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs @@ -1,10 +1,10 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; namespace Genocs.Auth.Builders; internal sealed class JwtOptionsBuilder : IJwtOptionsBuilder { - private readonly JwtSettings _options = new(); + private readonly JwtOptions _options = new(); public IJwtOptionsBuilder WithIssuerSigningKey(string issuerSigningKey) { @@ -48,6 +48,6 @@ public IJwtOptionsBuilder WithValidAudience(string validAudience) return this; } - public JwtSettings Build() + public JwtOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Auth/Options/JwtSettings.cs b/src/Genocs.Auth/Configurations/JwtOptions.cs similarity index 97% rename from src/Genocs.Auth/Options/JwtSettings.cs rename to src/Genocs.Auth/Configurations/JwtOptions.cs index 08dfb6de..cc181c18 100644 --- a/src/Genocs.Auth/Options/JwtSettings.cs +++ b/src/Genocs.Auth/Configurations/JwtOptions.cs @@ -1,6 +1,6 @@ -namespace Genocs.Auth.Options; +namespace Genocs.Auth.Configurations; -public class JwtSettings +public class JwtOptions { /// /// Default section name. diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index 4f74c0dc..f0077ec1 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -1,5 +1,5 @@ +using Genocs.Auth.Configurations; using Genocs.Auth.Handlers; -using Genocs.Auth.Options; using Genocs.Auth.Services; using Genocs.Core.Builders; using Genocs.Security.Services; @@ -23,21 +23,21 @@ public static class Extensions public static IGenocsBuilder AddJwt( this IGenocsBuilder builder, - string sectionName = JwtSettings.Position, + string sectionName = JwtOptions.Position, Action? optionsFactory = null) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = JwtSettings.Position; + sectionName = JwtOptions.Position; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); return builder.AddJwt(options, optionsFactory); } private static IGenocsBuilder AddJwt( this IGenocsBuilder builder, - JwtSettings jwtSettings, + JwtOptions jwtSettings, Action? optionsFactory = null) { if (!builder.TryRegister(RegistryName)) @@ -180,10 +180,10 @@ private static IGenocsBuilder AddJwt( /// The Genocs builder you can use for chain. public static IGenocsBuilder AddOpenIdJwt( this IGenocsBuilder builder, - string sectionName = JwtSettings.Position) + string sectionName = JwtOptions.Position) { - var jwtSettings = new JwtSettings(); + var jwtSettings = new JwtOptions(); builder.Configuration.GetSection(sectionName).Bind(jwtSettings); string metadataAddress = $"{jwtSettings.Issuer}{jwtSettings.MetadataAddress}"; @@ -218,14 +218,14 @@ public static IGenocsBuilder AddOpenIdJwt( /// Whenever mandatory data like 'IssuerSigningKey' is missing. public static IGenocsBuilder AddPrivateKeyJwt( this IGenocsBuilder builder, - string sectionName = JwtSettings.Position) + string sectionName = JwtOptions.Position) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = JwtSettings.Position; + sectionName = JwtOptions.Position; } - var jwtSettings = new JwtSettings(); + var jwtSettings = new JwtOptions(); builder.Configuration.GetSection(sectionName).Bind(jwtSettings); if (string.IsNullOrWhiteSpace(jwtSettings.IssuerSigningKey)) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index ce0c8e54..d90636d6 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Auth/Handlers/JwtHandler.cs b/src/Genocs.Auth/Handlers/JwtHandler.cs index f3ce917b..36e197e0 100644 --- a/src/Genocs.Auth/Handlers/JwtHandler.cs +++ b/src/Genocs.Auth/Handlers/JwtHandler.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; @@ -20,12 +20,12 @@ internal sealed class JwtHandler : IJwtHandler }; private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler = new(); - private readonly JwtSettings _options; + private readonly JwtOptions _options; private readonly TokenValidationParameters _tokenValidationParameters; private readonly SigningCredentials _signingCredentials; private readonly string? _issuer; - public JwtHandler(JwtSettings options, TokenValidationParameters tokenValidationParameters) + public JwtHandler(JwtOptions options, TokenValidationParameters tokenValidationParameters) { var issuerSigningKey = tokenValidationParameters.IssuerSigningKey; if (issuerSigningKey is null) diff --git a/src/Genocs.Auth/IJwtOptionsBuilder.cs b/src/Genocs.Auth/IJwtOptionsBuilder.cs index d3aa7cef..2409fe18 100644 --- a/src/Genocs.Auth/IJwtOptionsBuilder.cs +++ b/src/Genocs.Auth/IJwtOptionsBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; namespace Genocs.Auth; @@ -10,5 +10,5 @@ public interface IJwtOptionsBuilder IJwtOptionsBuilder WithLifetimeValidation(bool validateLifetime); IJwtOptionsBuilder WithAudienceValidation(bool validateAudience); IJwtOptionsBuilder WithValidAudience(string validAudience); - JwtSettings Build(); + JwtOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.Auth/README_NUGET.md b/src/Genocs.Auth/README_NUGET.md new file mode 100644 index 00000000..29459bfd --- /dev/null +++ b/src/Genocs.Auth/README_NUGET.md @@ -0,0 +1,85 @@ +# .NET Core Auth client library + +This package contains a set of functionalities to handling authorization logic as JWT. +First of all I have to say thanks to devmentors. + +The libraries are built using .NET7. + + +## Description + +This package contains a set of functionalities to handling authorization logic as JWT. + + +## Support + +Please check the GitHub repository getting more info. + + +### DataProvider Settings +Following are the project settings needed to enable monitoring + +``` json + "jwt": { + "certificate": { + "location": "certs/localhost.pfx", + "password": "test", + "rawData": "" + }, + "issuer": "genocs-identity-service", + "validIssuer": "genocs-identity-service", + "validateAudience": false, + "validateIssuer": true, + "validateLifetime": true, + "expiry": "01:00:00" + } +``` + +## Release notes + +### [2024-06-15] 6.0.0 +- Added support for Azure Key Vault +- Unified settings + +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + +### [2023-11-25] 5.0.0 +- Moved to NET8 + +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 +- Implemented MongoDB repository interfaces + +### [2023-03-24] 5.0.0 +- New Architecture + +### [2023-03-12] 3.1.0 +- Added Builders + +### [2023-03-12] 3.0.0 +- Refactory to implement CQRS pattern + +### [2023-03-04] 2.4.1 +- Updated System.Text.Json \ No newline at end of file diff --git a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs index 8e95a03f..f1134825 100644 --- a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs +++ b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Primitives; @@ -14,11 +14,11 @@ internal sealed class InMemoryAccessTokenService : IAccessTokenService public InMemoryAccessTokenService( IMemoryCache cache, IHttpContextAccessor httpContextAccessor, - JwtSettings jwtOptions) + JwtOptions jwtSettings) { _cache = cache; _httpContextAccessor = httpContextAccessor; - _expires = jwtOptions.Expiry ?? TimeSpan.FromMinutes(jwtOptions.ExpiryMinutes); + _expires = jwtSettings.Expiry ?? TimeSpan.FromMinutes(jwtSettings.ExpiryMinutes); } public Task IsCurrentActiveToken() diff --git a/src/Genocs.Common/Options/AppSettings.cs b/src/Genocs.Common/Configurations/AppOptions.cs similarity index 93% rename from src/Genocs.Common/Options/AppSettings.cs rename to src/Genocs.Common/Configurations/AppOptions.cs index 3af8f1ef..a5596f68 100644 --- a/src/Genocs.Common/Options/AppSettings.cs +++ b/src/Genocs.Common/Configurations/AppOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.Common.Options; +namespace Genocs.Common.Configurations; /// /// The application settings. /// -public class AppSettings +public class AppOptions { /// /// Default section name. diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 2ab02e42..b18067f9 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Common/README_NUGET.md b/src/Genocs.Common/README_NUGET.md new file mode 100644 index 00000000..db3b92d4 --- /dev/null +++ b/src/Genocs.Common/README_NUGET.md @@ -0,0 +1,59 @@ +# .NET Core Common library + +This package contains a set of base functionalities designed by Genocs. +The libraries are built using .NET standard 2.1. + + +## Description + +Core Common NuGet package contains general types, interfaces and classes to be used on DDD services. + +## Support + +Please check the GitHub repository getting more info. + + +## Release notes + +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + +### [2023-11-25] 5.0.0 +- Moved to NET8 + +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 +- Implemented MongoDB repository interfaces + +### [2023-03-24] 5.0.0 +- New Architecture + +### [2023-03-12] 3.1.0 +- Added Builders + +### [2023-03-12] 3.0.0 +- Refactory to implement CQRS pattern + +### [2023-03-04] 2.4.1 +- Updated System.Text.Json \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs index 459ebd9c..1a9beaa0 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs @@ -1,6 +1,6 @@ using Genocs.Core.Demo.WebApi.Options; using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.Security; using Newtonsoft.Json; @@ -26,7 +26,7 @@ public class ExternalServiceClient : IExternalServiceClient public ExternalServiceClient( IHttpClient client, IHasher hasher, - HttpClientSettings httpClientSettings, + HttpClientOptions httpClientSettings, ExternalServiceSettings externalServiceSettings) { _client = client ?? throw new ArgumentNullException(nameof(client)); diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index a9436578..648f8938 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -6,6 +6,7 @@ using Genocs.Persistence.MongoDb.Extensions; using Genocs.Secrets.AzureKeyVault; using Genocs.Tracing; +using Genocs.WebApi.Security; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; using Serilog.Events; @@ -30,7 +31,6 @@ services .AddGenocs(builder.Configuration) - .AddPrivateKeyJwt() .AddOpenTelemetry() .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()) diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs index 6cd7ed22..8436b812 100644 --- a/src/Genocs.Core/Builders/Extensions.cs +++ b/src/Genocs.Core/Builders/Extensions.cs @@ -1,4 +1,4 @@ -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Common.Types; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; @@ -20,18 +20,18 @@ public static class Extensions public static IGenocsBuilder AddGenocs(this IServiceCollection services, IConfiguration? configuration = null) { var builder = GenocsBuilder.Create(services, configuration); - var options = builder.GetOptions(AppSettings.Position); - services.AddSingleton(options); + var settings = builder.GetOptions(AppOptions.Position); + services.AddSingleton(settings); builder.Services.AddMemoryCache(); services.AddSingleton(); - if (!options.DisplayBanner || string.IsNullOrWhiteSpace(options.Name)) + if (!settings.DisplayBanner || string.IsNullOrWhiteSpace(settings.Name)) { return builder; } - string version = options.DisplayVersion ? $" {options.Version}" : string.Empty; - Console.WriteLine(Figgle.FiggleFonts.Doom.Render(options.Name + version)); + string version = settings.DisplayVersion ? $" {settings.Version}" : string.Empty; + Console.WriteLine(Figgle.FiggleFonts.Doom.Render(settings.Name + version)); ConsoleColor current = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("Runtime Version: {0}", Environment.Version.ToString()); diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 7613dec3..6e259383 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Updated to NET8 True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Core/README_NUGET.md b/src/Genocs.Core/README_NUGET.md new file mode 100644 index 00000000..7aebc35c --- /dev/null +++ b/src/Genocs.Core/README_NUGET.md @@ -0,0 +1,63 @@ +# .NET Core library + +This package contains a set of base functionalities designed by Genocs. +The library is built to be used on .NET standard 2.1 and NET6, NET7 NET8. + +## Description + +Core NuGet package contains general purpose functionalities to be used on DDD services. + + +## Support + +Please check the GitHub repository getting more info. + + +## Release notes + +### [2024-06-22] 6.0.0-preview.1.0 +- Upgrade toward Version 6.0.0 +- + +### [2024-01-23] 5.0.6 +- Refactory Settings +- Updated nuget packages + +### [2023-11-25] 5.0.5 +- Moved to NET8 + +### [yyyy-mm-dd] 5.0.4 +- + +### [yyyy-mm-dd] 5.0.3 +- + +### [yyyy-mm-dd] 5.0.2 +- + +### [yyyy-mm-dd] 5.0.1 +- + +### [2023-11-25] 5.0.0 +- Moved to NET8 + +### [2023-10-13] 5.0.0-preview.5.0 +- Added [editorconfig](https://editorconfig.org/) +- Added StyleCop +- Updated logo +- Updated readme + +### [2023-03-12] 5.0.0-preview.4.0 +- Implemented MongoDB repository interfaces + +### [2023-03-12] 5.0.0 +- New Architecture + +### [2023-03-12] 3.1.0 +- Added Builders + +### [2023-03-12] 3.0.0 +- Refactory to implement CQRS pattern + +### [2023-03-04] 2.4.1 +- Updated System.Text.Json diff --git a/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs b/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs index 8c7e3685..f5b29178 100644 --- a/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs +++ b/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs @@ -1,10 +1,10 @@ -using Genocs.Discovery.Consul.Options; +using Genocs.Discovery.Consul.Configurations; namespace Genocs.Discovery.Consul.Builders; internal sealed class ConsulOptionsBuilder : IConsulOptionsBuilder { - private readonly ConsulSettings _options = new(); + private readonly ConsulOptions _options = new(); public IConsulOptionsBuilder Enable(bool enabled) { @@ -60,5 +60,5 @@ public IConsulOptionsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLoca return this; } - public ConsulSettings Build() => _options; + public ConsulOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs similarity index 79% rename from src/Genocs.Discovery.Consul/Options/ConsulSettings.cs rename to src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs index d16f9642..fec77e24 100644 --- a/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs +++ b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs @@ -1,7 +1,12 @@ -namespace Genocs.Discovery.Consul.Options; +namespace Genocs.Discovery.Consul.Configurations; -public class ConsulSettings +public class ConsulOptions { + /// + /// Default section name. + /// + public const string Position = "consul"; + public bool Enabled { get; set; } public string? Url { get; set; } public string? Service { get; set; } diff --git a/src/Genocs.Discovery.Consul/Options/IConsulOptionsBuilder.cs b/src/Genocs.Discovery.Consul/Configurations/IConsulOptionsBuilder.cs similarity index 88% rename from src/Genocs.Discovery.Consul/Options/IConsulOptionsBuilder.cs rename to src/Genocs.Discovery.Consul/Configurations/IConsulOptionsBuilder.cs index c4d8d850..63b5aeda 100644 --- a/src/Genocs.Discovery.Consul/Options/IConsulOptionsBuilder.cs +++ b/src/Genocs.Discovery.Consul/Configurations/IConsulOptionsBuilder.cs @@ -1,4 +1,4 @@ -namespace Genocs.Discovery.Consul.Options; +namespace Genocs.Discovery.Consul.Configurations; public interface IConsulOptionsBuilder { @@ -11,5 +11,5 @@ public interface IConsulOptionsBuilder IConsulOptionsBuilder WithPingInterval(string pingInterval); IConsulOptionsBuilder WithRemoteAfterInterval(string remoteAfterInterval); IConsulOptionsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace); - ConsulSettings Build(); + ConsulOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/Extensions.cs b/src/Genocs.Discovery.Consul/Extensions.cs index ecebcb98..a8a8c511 100644 --- a/src/Genocs.Discovery.Consul/Extensions.cs +++ b/src/Genocs.Discovery.Consul/Extensions.cs @@ -1,12 +1,12 @@ using Genocs.Core.Builders; using Genocs.Discovery.Consul.Builders; +using Genocs.Discovery.Consul.Configurations; using Genocs.Discovery.Consul.Http; using Genocs.Discovery.Consul.MessageHandlers; using Genocs.Discovery.Consul.Models; -using Genocs.Discovery.Consul.Options; using Genocs.Discovery.Consul.Services; using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.DependencyInjection; namespace Genocs.Discovery.Consul; @@ -27,15 +27,15 @@ public static IGenocsBuilder AddConsul( sectionName = SectionName; } - var consulOptions = builder.GetOptions(sectionName); - var httpClientOptions = builder.GetOptions(httpClientSectionName); + var consulOptions = builder.GetOptions(sectionName); + var httpClientOptions = builder.GetOptions(httpClientSectionName); return builder.AddConsul(consulOptions, httpClientOptions); } public static IGenocsBuilder AddConsul( this IGenocsBuilder builder, Func buildOptions, - HttpClientSettings httpClientOptions) + HttpClientOptions httpClientOptions) { var options = buildOptions(new ConsulOptionsBuilder()).Build(); return builder.AddConsul(options, httpClientOptions); @@ -43,8 +43,8 @@ public static IGenocsBuilder AddConsul( public static IGenocsBuilder AddConsul( this IGenocsBuilder builder, - ConsulSettings options, - HttpClientSettings httpClientOptions) + ConsulOptions options, + HttpClientOptions httpClientOptions) { builder.Services.AddSingleton(options); if (!options.Enabled || !builder.TryRegister(RegistryName)) @@ -78,9 +78,9 @@ public static void AddConsulHttpClient(this IGenocsBuilder builder, string clien => builder.Services.AddHttpClient(clientName) .AddHttpMessageHandler(c => new ConsulServiceDiscoveryMessageHandler( c.GetRequiredService(), - c.GetRequiredService(), serviceName, true)); + c.GetRequiredService(), serviceName, true)); - private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulSettings options) + private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulOptions options) { bool enabled = options.Enabled; string? consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); diff --git a/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs b/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs index 5b8691fe..10c6e7b7 100644 --- a/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs +++ b/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs @@ -1,11 +1,11 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; namespace Genocs.Discovery.Consul.Http; internal sealed class ConsulHttpClient : GenocsHttpClient, IConsulHttpClient { - public ConsulHttpClient(HttpClient client, HttpClientSettings options, IHttpClientSerializer serializer, + public ConsulHttpClient(HttpClient client, HttpClientOptions options, IHttpClientSerializer serializer, ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) : base(client, options, serializer, correlationContextFactory, correlationIdFactory) { diff --git a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs index 162f57a7..a13a67a5 100644 --- a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs +++ b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs @@ -1,29 +1,34 @@ -using Genocs.Discovery.Consul.Options; +using Genocs.Discovery.Consul.Configurations; namespace Genocs.Discovery.Consul.MessageHandlers; internal sealed class ConsulServiceDiscoveryMessageHandler : DelegatingHandler { private readonly IConsulServicesRegistry _servicesRegistry; - private readonly ConsulSettings _options; + private readonly ConsulOptions _settings; private readonly string? _serviceName; private readonly bool? _overrideRequestUri; public ConsulServiceDiscoveryMessageHandler( IConsulServicesRegistry servicesRegistry, - ConsulSettings options, + ConsulOptions settings, string? serviceName = null, bool? overrideRequestUri = null) { - if (string.IsNullOrWhiteSpace(options.Url)) - { - throw new InvalidOperationException("Consul URL was not provided."); - } - _servicesRegistry = servicesRegistry; - _options = options; + _settings = settings; _serviceName = serviceName; _overrideRequestUri = overrideRequestUri; + + if (!settings.Enabled) + { + return; + } + + if (string.IsNullOrWhiteSpace(settings.Url)) + { + throw new InvalidOperationException("Consul URL was not provided."); + } } protected override async Task SendAsync( @@ -50,7 +55,7 @@ private async Task SendAsync( Uri uri, CancellationToken cancellationToken) { - if (!_options.Enabled) + if (!_settings.Enabled) { return await base.SendAsync(request, cancellationToken); } @@ -68,7 +73,7 @@ private async Task GetRequestUriAsync( var service = await _servicesRegistry.GetAsync(serviceName) ?? throw new ConsulServiceNotFoundException($"Consul service: '{serviceName}' was not found.", serviceName); - if (!_options.SkipLocalhostDockerDnsReplace) + if (!_settings.SkipLocalhostDockerDnsReplace) { service.Address = service.Address.Replace("docker.for.mac.localhost", "localhost") .Replace("docker.for.win.localhost", "localhost") diff --git a/src/Genocs.HTTP.RestEase/Builders/RestEaseBuilders.cs b/src/Genocs.HTTP.RestEase/Builders/RestEaseOptionsBuilder.cs similarity index 62% rename from src/Genocs.HTTP.RestEase/Builders/RestEaseBuilders.cs rename to src/Genocs.HTTP.RestEase/Builders/RestEaseOptionsBuilder.cs index da1d0b69..55bb2367 100644 --- a/src/Genocs.HTTP.RestEase/Builders/RestEaseBuilders.cs +++ b/src/Genocs.HTTP.RestEase/Builders/RestEaseOptionsBuilder.cs @@ -1,26 +1,26 @@ -using Genocs.HTTP.RestEase.Options; +using Genocs.HTTP.RestEase.Configurations; namespace Genocs.HTTP.RestEase.Builders; -internal sealed class RestEaseSettingsBuilder : IRestEaseSettingsBuilder +internal sealed class RestEaseOptionsBuilder : IRestEaseOptionsBuilder { - private readonly RestEaseSettings _options = new(); - private readonly List _services = new(); + private readonly RestEaseOptions _options = new(); + private readonly List _services = new(); - public IRestEaseSettingsBuilder WithLoadBalancer(string loadBalancer) + public IRestEaseOptionsBuilder WithLoadBalancer(string loadBalancer) { _options.LoadBalancer = loadBalancer; return this; } - public IRestEaseSettingsBuilder WithService(Func buildService) + public IRestEaseOptionsBuilder WithService(Func buildService) { var service = buildService(new RestEaseServiceBuilder()).Build(); _services.Add(service); return this; } - public RestEaseSettings Build() + public RestEaseOptions Build() { _options.Services = _services; return _options; @@ -28,7 +28,7 @@ public RestEaseSettings Build() private class RestEaseServiceBuilder : IRestEaseServiceBuilder { - private readonly RestEaseSettings.Service _service = new(); + private readonly RestEaseOptions.Service _service = new(); public IRestEaseServiceBuilder WithName(string name) { @@ -54,6 +54,6 @@ public IRestEaseServiceBuilder WithPort(int port) return this; } - public RestEaseSettings.Service Build() => _service; + public RestEaseOptions.Service Build() => _service; } } \ No newline at end of file diff --git a/src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs b/src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs new file mode 100644 index 00000000..f013109a --- /dev/null +++ b/src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs @@ -0,0 +1,8 @@ +namespace Genocs.HTTP.RestEase.Configurations; + +public interface IRestEaseOptionsBuilder +{ + IRestEaseOptionsBuilder WithLoadBalancer(string loadBalancer); + IRestEaseOptionsBuilder WithService(Func buildService); + RestEaseOptions Build(); +} \ No newline at end of file diff --git a/src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs b/src/Genocs.HTTP.RestEase/Configurations/RestEaseOptions.cs similarity index 80% rename from src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs rename to src/Genocs.HTTP.RestEase/Configurations/RestEaseOptions.cs index f5b4c1f3..87f927bc 100644 --- a/src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs +++ b/src/Genocs.HTTP.RestEase/Configurations/RestEaseOptions.cs @@ -1,6 +1,6 @@ -namespace Genocs.HTTP.RestEase.Options; +namespace Genocs.HTTP.RestEase.Configurations; -public class RestEaseSettings +public class RestEaseOptions { public string? LoadBalancer { get; set; } public IEnumerable? Services { get; set; } diff --git a/src/Genocs.HTTP.RestEase/Extensions.cs b/src/Genocs.HTTP.RestEase/Extensions.cs index 70020773..307bf90e 100644 --- a/src/Genocs.HTTP.RestEase/Extensions.cs +++ b/src/Genocs.HTTP.RestEase/Extensions.cs @@ -1,12 +1,12 @@ using Genocs.Core.Builders; using Genocs.Discovery.Consul; -using Genocs.Discovery.Consul.Options; -using Genocs.HTTP.Options; +using Genocs.Discovery.Consul.Configurations; +using Genocs.HTTP.Configurations; using Genocs.HTTP.RestEase.Builders; -using Genocs.HTTP.RestEase.Options; +using Genocs.HTTP.RestEase.Configurations; using Genocs.HTTP.RestEase.Serializers; using Genocs.LoadBalancing.Fabio; -using Genocs.LoadBalancing.Fabio.Options; +using Genocs.LoadBalancing.Fabio.Configurations; using Microsoft.Extensions.DependencyInjection; using RestEase; @@ -27,26 +27,26 @@ public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, st sectionName = SectionName; } - var restEaseOptions = builder.GetOptions(sectionName); + var restEaseOptions = builder.GetOptions(sectionName); return builder.AddServiceClient(serviceName, restEaseOptions, b => b.AddFabio(fabioSectionName, consulSectionName, httpClientSectionName)); } public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, - Func buildOptions, + Func buildOptions, Func buildConsulOptions, Func buildFabioOptions, - HttpClientSettings httpClientOptions) + HttpClientOptions httpClientOptions) where T : class { - var options = buildOptions(new RestEaseSettingsBuilder()).Build(); + var options = buildOptions(new RestEaseOptionsBuilder()).Build(); return builder.AddServiceClient(serviceName, options, b => b.AddFabio(buildFabioOptions, buildConsulOptions, httpClientOptions)); } public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, - RestEaseSettings options, ConsulSettings consulOptions, FabioSettings fabioOptions, - HttpClientSettings httpClientOptions) + RestEaseOptions options, ConsulOptions consulOptions, FabioOptions fabioOptions, + HttpClientOptions httpClientOptions) where T : class => builder.AddServiceClient(serviceName, options, b => b.AddFabio(fabioOptions, consulOptions, httpClientOptions)); @@ -54,7 +54,7 @@ public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, st private static IGenocsBuilder AddServiceClient( this IGenocsBuilder builder, string serviceName, - RestEaseSettings options, + RestEaseOptions options, Action registerFabio) where T : class { @@ -89,7 +89,7 @@ private static void ConfigureDefaultClient( IServiceCollection services, string clientName, string serviceName, - RestEaseSettings options) + RestEaseOptions options) { services.AddHttpClient(clientName, client => { diff --git a/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs b/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs index 680728ac..bcbdae00 100644 --- a/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs +++ b/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.RestEase.Options; +using Genocs.HTTP.RestEase.Configurations; namespace Genocs.HTTP.RestEase; @@ -8,5 +8,5 @@ public interface IRestEaseServiceBuilder IRestEaseServiceBuilder WithScheme(string scheme); IRestEaseServiceBuilder WithHost(string host); IRestEaseServiceBuilder WithPort(int port); - RestEaseSettings.Service Build(); + RestEaseOptions.Service Build(); } \ No newline at end of file diff --git a/src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs b/src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs deleted file mode 100644 index 15353665..00000000 --- a/src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Genocs.HTTP.RestEase.Options; - -namespace Genocs.HTTP.RestEase; - -public interface IRestEaseSettingsBuilder -{ - IRestEaseSettingsBuilder WithLoadBalancer(string loadBalancer); - IRestEaseSettingsBuilder WithService(Func buildService); - RestEaseSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.HTTP/Options/HttpClientSettings.cs b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs similarity index 63% rename from src/Genocs.HTTP/Options/HttpClientSettings.cs rename to src/Genocs.HTTP/Configurations/HttpClientOptions.cs index 42fde541..213dbb69 100644 --- a/src/Genocs.HTTP/Options/HttpClientSettings.cs +++ b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.HTTP.Options; +namespace Genocs.HTTP.Configurations; /// -/// The HttpClient Settings class. +/// The HttpClient settings. /// -public class HttpClientSettings +public class HttpClientOptions { /// /// It defines if set consul as service discovery or Fabio as load balancer. @@ -20,15 +20,15 @@ public class HttpClientSettings /// It defines the list of services to be registered. /// public IDictionary? Services { get; set; } - public RequestMaskingSettings RequestMasking { get; set; } + public RequestMaskingSettings? RequestMasking { get; set; } public bool RemoveCharsetFromContentType { get; set; } - public string CorrelationContextHeader { get; set; } - public string CorrelationIdHeader { get; set; } + public string? CorrelationContextHeader { get; set; } + public string? CorrelationIdHeader { get; set; } public class RequestMaskingSettings { public bool Enabled { get; set; } - public IEnumerable UrlParts { get; set; } - public string MaskTemplate { get; set; } + public IEnumerable? UrlParts { get; set; } + public string? MaskTemplate { get; set; } } } \ No newline at end of file diff --git a/src/Genocs.HTTP/Extensions.cs b/src/Genocs.HTTP/Extensions.cs index 13238b93..908bb7d1 100644 --- a/src/Genocs.HTTP/Extensions.cs +++ b/src/Genocs.HTTP/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Core.Builders; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Http; @@ -38,7 +38,7 @@ public static IGenocsBuilder AddHttpClient( throw new ArgumentException("HTTP client name cannot be empty.", nameof(clientName)); } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); if (maskedRequestUrlParts is not null && options.RequestMasking is not null) { options.RequestMasking.UrlParts = maskedRequestUrlParts; diff --git a/src/Genocs.HTTP/GenocsHttpClient.cs b/src/Genocs.HTTP/GenocsHttpClient.cs index c407de2a..84f89ed7 100644 --- a/src/Genocs.HTTP/GenocsHttpClient.cs +++ b/src/Genocs.HTTP/GenocsHttpClient.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Polly; using System.Net.Http.Headers; using System.Text; @@ -12,12 +12,12 @@ public class GenocsHttpClient : IHttpClient { private const string JsonContentType = "application/json"; private readonly HttpClient _client; - private readonly HttpClientSettings _options; + private readonly HttpClientOptions _options; private readonly IHttpClientSerializer _serializer; public GenocsHttpClient( HttpClient client, - HttpClientSettings options, + HttpClientOptions options, IHttpClientSerializer serializer, ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) diff --git a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs index 7d30997a..8ba7d583 100644 --- a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs +++ b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.Http; using Microsoft.Extensions.Logging; @@ -8,9 +8,9 @@ namespace Genocs.HTTP; internal sealed class GenocsHttpLoggingFilter : IHttpMessageHandlerBuilderFilter { private readonly ILoggerFactory _loggerFactory; - private readonly HttpClientSettings _options; + private readonly HttpClientOptions _options; - public GenocsHttpLoggingFilter(ILoggerFactory loggerFactory, HttpClientSettings options) + public GenocsHttpLoggingFilter(ILoggerFactory loggerFactory, HttpClientOptions options) { _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _options = options; diff --git a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs index 529f245f..ef9bdfbb 100644 --- a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs +++ b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.Logging; using System.Net; @@ -10,7 +10,7 @@ internal sealed class GenocsLoggingScopeHttpMessageHandler : DelegatingHandler private readonly HashSet _maskedRequestUrlParts; private readonly string _maskTemplate; - public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientSettings options) + public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientOptions options) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _ = options ?? throw new ArgumentNullException(nameof(options)); diff --git a/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs index ec923b1d..96e11ed9 100644 --- a/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs +++ b/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.LoadBalancing.Fabio.Options; +using Genocs.LoadBalancing.Fabio.Configurations; namespace Genocs.LoadBalancing.Fabio.Builders; @@ -7,7 +7,7 @@ namespace Genocs.LoadBalancing.Fabio.Builders; /// public class FabioOptionsBuilder : IFabioOptionsBuilder { - private readonly FabioSettings _options = new(); + private readonly FabioOptions _options = new(); /// /// Enable or disable the Fabio load balancer @@ -46,5 +46,5 @@ public IFabioOptionsBuilder WithService(string service) /// Build the Fabio options /// /// The Fabio options - public FabioSettings Build() => _options; + public FabioOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs similarity index 83% rename from src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs rename to src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs index f7e6d9ab..28803892 100644 --- a/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs +++ b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.LoadBalancing.Fabio.Options; +namespace Genocs.LoadBalancing.Fabio.Configurations; /// /// The Fabio settings. /// -public class FabioSettings +public class FabioOptions { /// /// The default Fabio section name. @@ -11,7 +11,7 @@ public class FabioSettings public const string Position = "fabio"; /// - /// Gets or sets a value indicating whether this is enabled. + /// Gets or sets a value indicating whether this is enabled. /// public bool Enabled { get; set; } diff --git a/src/Genocs.LoadBalancing.Fabio/IFabioOptionsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioOptionsBuilder.cs similarity index 90% rename from src/Genocs.LoadBalancing.Fabio/IFabioOptionsBuilder.cs rename to src/Genocs.LoadBalancing.Fabio/Configurations/IFabioOptionsBuilder.cs index 478c1cb3..a0e41b20 100644 --- a/src/Genocs.LoadBalancing.Fabio/IFabioOptionsBuilder.cs +++ b/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioOptionsBuilder.cs @@ -1,6 +1,4 @@ -using Genocs.LoadBalancing.Fabio.Options; - -namespace Genocs.LoadBalancing.Fabio; +namespace Genocs.LoadBalancing.Fabio.Configurations; /// /// The Fabio options builder interface definition @@ -32,5 +30,5 @@ public interface IFabioOptionsBuilder /// Build the Fabio options /// /// The Fabio options - FabioSettings Build(); + FabioOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Extensions.cs b/src/Genocs.LoadBalancing.Fabio/Extensions.cs index e0e507f9..8a1b9853 100644 --- a/src/Genocs.LoadBalancing.Fabio/Extensions.cs +++ b/src/Genocs.LoadBalancing.Fabio/Extensions.cs @@ -1,13 +1,13 @@ using Genocs.Core.Builders; using Genocs.Discovery.Consul; +using Genocs.Discovery.Consul.Configurations; using Genocs.Discovery.Consul.Models; -using Genocs.Discovery.Consul.Options; using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.LoadBalancing.Fabio.Builders; +using Genocs.LoadBalancing.Fabio.Configurations; using Genocs.LoadBalancing.Fabio.Http; using Genocs.LoadBalancing.Fabio.MessageHandlers; -using Genocs.LoadBalancing.Fabio.Options; using Microsoft.Extensions.DependencyInjection; namespace Genocs.LoadBalancing.Fabio; @@ -16,17 +16,17 @@ public static class Extensions { private const string RegistryName = "loadBalancing.fabio"; - public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, string sectionName = FabioSettings.Position, + public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, string sectionName = FabioOptions.Position, string consulSectionName = "consul", string httpClientSectionName = "httpClient") { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = FabioSettings.Position; + sectionName = FabioOptions.Position; } - var fabioOptions = builder.GetOptions(sectionName); - var consulOptions = builder.GetOptions(consulSectionName); - var httpClientOptions = builder.GetOptions(httpClientSectionName); + var fabioOptions = builder.GetOptions(sectionName); + var consulOptions = builder.GetOptions(consulSectionName); + var httpClientOptions = builder.GetOptions(httpClientSectionName); return builder.AddFabio(fabioOptions, httpClientOptions, b => b.AddConsul(consulOptions, httpClientOptions)); } @@ -34,19 +34,19 @@ public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, string sectio public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, Func buildOptions, Func buildConsulOptions, - HttpClientSettings httpClientOptions) + HttpClientOptions httpClientOptions) { var fabioOptions = buildOptions(new FabioOptionsBuilder()).Build(); return builder.AddFabio(fabioOptions, httpClientOptions, b => b.AddConsul(buildConsulOptions, httpClientOptions)); } - public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioSettings fabioOptions, - ConsulSettings consulOptions, HttpClientSettings httpClientOptions) + public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioOptions fabioOptions, + ConsulOptions consulOptions, HttpClientOptions httpClientOptions) => builder.AddFabio(fabioOptions, httpClientOptions, b => b.AddConsul(consulOptions, httpClientOptions)); - private static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioSettings fabioOptions, - HttpClientSettings httpClientOptions, Action registerConsul) + private static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioOptions fabioOptions, + HttpClientOptions httpClientOptions, Action registerConsul) { registerConsul(builder); builder.Services.AddSingleton(fabioOptions); @@ -87,7 +87,7 @@ private static IGenocsBuilder AddFabio(this IGenocsBuilder builder, FabioSetting public static void AddFabioHttpClient(this IGenocsBuilder builder, string clientName, string serviceName) => builder.Services.AddHttpClient(clientName) - .AddHttpMessageHandler(c => new FabioMessageHandler(c.GetRequiredService(), serviceName)); + .AddHttpMessageHandler(c => new FabioMessageHandler(c.GetRequiredService(), serviceName)); private static void UpdateConsulRegistration(this IServiceCollection services, ServiceRegistration registration) diff --git a/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs b/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs index cb622682..1da11604 100644 --- a/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs +++ b/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs @@ -1,11 +1,11 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; namespace Genocs.LoadBalancing.Fabio.Http; internal sealed class FabioHttpClient : GenocsHttpClient, IFabioHttpClient { - public FabioHttpClient(HttpClient client, HttpClientSettings options, IHttpClientSerializer serializer, + public FabioHttpClient(HttpClient client, HttpClientOptions options, IHttpClientSerializer serializer, ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) : base(client, options, serializer, correlationContextFactory, correlationIdFactory) { diff --git a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs index 416fb18a..f8afb667 100644 --- a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs +++ b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs @@ -1,13 +1,13 @@ -using Genocs.LoadBalancing.Fabio.Options; +using Genocs.LoadBalancing.Fabio.Configurations; namespace Genocs.LoadBalancing.Fabio.MessageHandlers; internal sealed class FabioMessageHandler : DelegatingHandler { - private readonly FabioSettings _options; + private readonly FabioOptions _options; private readonly string _servicePath; - public FabioMessageHandler(FabioSettings options, string? serviceName = null) + public FabioMessageHandler(FabioOptions options, string? serviceName = null) { if (string.IsNullOrWhiteSpace(options.Url)) { diff --git a/src/Genocs.Logging/Options/AzureSettings.cs b/src/Genocs.Logging/Configurations/AzureOptions.cs similarity index 85% rename from src/Genocs.Logging/Options/AzureSettings.cs rename to src/Genocs.Logging/Configurations/AzureOptions.cs index 387881f8..dc2f326a 100644 --- a/src/Genocs.Logging/Options/AzureSettings.cs +++ b/src/Genocs.Logging/Configurations/AzureOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Azure application insights logging settings. /// -public class AzureSettings +public class AzureOptions { /// /// It define whether the Azure application insights logger and tracing are enabled or not. diff --git a/src/Genocs.Logging/Options/ConsoleSettings.cs b/src/Genocs.Logging/Configurations/ConsoleOptions.cs similarity index 75% rename from src/Genocs.Logging/Options/ConsoleSettings.cs rename to src/Genocs.Logging/Configurations/ConsoleOptions.cs index a647aa26..4289e516 100644 --- a/src/Genocs.Logging/Options/ConsoleSettings.cs +++ b/src/Genocs.Logging/Configurations/ConsoleOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Console Settings. /// -public class ConsoleSettings +public class ConsoleOptions { /// /// It define whether the console logger and tracing are enabled or not. diff --git a/src/Genocs.Logging/Options/ElkSettings.cs b/src/Genocs.Logging/Configurations/ElkOptions.cs similarity index 90% rename from src/Genocs.Logging/Options/ElkSettings.cs rename to src/Genocs.Logging/Configurations/ElkOptions.cs index b67d082d..b090e0ed 100644 --- a/src/Genocs.Logging/Options/ElkSettings.cs +++ b/src/Genocs.Logging/Configurations/ElkOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Elasticsearch Settings. /// -public class ElkSettings +public class ElkOptions { /// /// It define whether the Elasticsearch logger and tracing are enabled or not. diff --git a/src/Genocs.Logging/Options/LocalFileSettings.cs b/src/Genocs.Logging/Configurations/LocalFileOptions.cs similarity index 87% rename from src/Genocs.Logging/Options/LocalFileSettings.cs rename to src/Genocs.Logging/Configurations/LocalFileOptions.cs index bc5d0993..5b956ae1 100644 --- a/src/Genocs.Logging/Options/LocalFileSettings.cs +++ b/src/Genocs.Logging/Configurations/LocalFileOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// File settings for local file logging. /// -public class LocalFileSettings +public class LocalFileOptions { /// /// If enabled, local file logging is enabled. diff --git a/src/Genocs.Logging/Options/LoggerSettings.cs b/src/Genocs.Logging/Configurations/LoggerOptions.cs similarity index 67% rename from src/Genocs.Logging/Options/LoggerSettings.cs rename to src/Genocs.Logging/Configurations/LoggerOptions.cs index a604ae66..087f9da8 100644 --- a/src/Genocs.Logging/Options/LoggerSettings.cs +++ b/src/Genocs.Logging/Configurations/LoggerOptions.cs @@ -1,10 +1,9 @@ -namespace Genocs.Logging.Options; - +namespace Genocs.Logging.Configurations; /// /// Logger Settings. /// -public class LoggerSettings +public class LoggerOptions { /// /// Default section name. @@ -16,25 +15,25 @@ public class LoggerSettings /// /// The Console Logging and tracing Settings. /// - public ConsoleSettings? Console { get; set; } - public LocalFileSettings? File { get; set; } - public ElkSettings? Elk { get; set; } - public SeqSettings? Seq { get; set; } + public ConsoleOptions? Console { get; set; } + public LocalFileOptions? File { get; set; } + public ElkOptions? Elk { get; set; } + public SeqOptions? Seq { get; set; } /// /// Loki logging settings. /// - public LokiSettings? Loki { get; set; } + public LokiOptions? Loki { get; set; } /// /// Azure application insights logging settings. /// - public AzureSettings? Azure { get; set; } + public AzureOptions? Azure { get; set; } /// /// MongoDb logging settings. /// - public MongoSettings? Mongo { get; set; } + public MongoOptions? Mongo { get; set; } public IDictionary? MinimumLevelOverrides { get; set; } public IEnumerable? ExcludePaths { get; set; } diff --git a/src/Genocs.Logging/Options/LokiSettings.cs b/src/Genocs.Logging/Configurations/LokiOptions.cs similarity index 96% rename from src/Genocs.Logging/Options/LokiSettings.cs rename to src/Genocs.Logging/Configurations/LokiOptions.cs index 9c19d209..0910a170 100644 --- a/src/Genocs.Logging/Options/LokiSettings.cs +++ b/src/Genocs.Logging/Configurations/LokiOptions.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Relevant options for the Serilog Loki sink. @@ -24,7 +24,7 @@ /// CreateLevelLabel /// /// -public class LokiSettings +public class LokiOptions { /// /// Whether or not to enable Loki Logging. diff --git a/src/Genocs.Logging/Options/MongoSettings.cs b/src/Genocs.Logging/Configurations/MongoOptions.cs similarity index 76% rename from src/Genocs.Logging/Options/MongoSettings.cs rename to src/Genocs.Logging/Configurations/MongoOptions.cs index a8e2e47b..c2750e18 100644 --- a/src/Genocs.Logging/Options/MongoSettings.cs +++ b/src/Genocs.Logging/Configurations/MongoOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// MongoDb logging settings. /// -public class MongoSettings +public class MongoOptions { /// /// It define whether the MongoDb logger and tracing are enabled or not. diff --git a/src/Genocs.Logging/Options/SeqSettings.cs b/src/Genocs.Logging/Configurations/SeqOptions.cs similarity index 64% rename from src/Genocs.Logging/Options/SeqSettings.cs rename to src/Genocs.Logging/Configurations/SeqOptions.cs index 26432556..7fc4a973 100644 --- a/src/Genocs.Logging/Options/SeqSettings.cs +++ b/src/Genocs.Logging/Configurations/SeqOptions.cs @@ -1,6 +1,6 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; -public class SeqSettings +public class SeqOptions { public bool Enabled { get; set; } public string? Url { get; set; } diff --git a/src/Genocs.Logging/Extensions.cs b/src/Genocs.Logging/Extensions.cs index 76fe5817..0f9b7fd6 100644 --- a/src/Genocs.Logging/Extensions.cs +++ b/src/Genocs.Logging/Extensions.cs @@ -1,6 +1,6 @@ -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; -using Genocs.Logging.Options; +using Genocs.Logging.Configurations; using Microsoft.ApplicationInsights.Extensibility; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; @@ -31,16 +31,16 @@ public static IHostBuilder UseLogging( { if (string.IsNullOrWhiteSpace(loggerSectionName)) { - loggerSectionName = LoggerSettings.Position; + loggerSectionName = LoggerOptions.Position; } if (string.IsNullOrWhiteSpace(appSectionName)) { - appSectionName = AppSettings.Position; + appSectionName = AppOptions.Position; } - var loggerOptions = context.Configuration.GetOptions(loggerSectionName); - var appOptions = context.Configuration.GetOptions(appSectionName); + var loggerOptions = context.Configuration.GetOptions(loggerSectionName); + var appOptions = context.Configuration.GetOptions(appSectionName); MapOptions(loggerOptions, appOptions, loggerConfiguration, context.HostingEnvironment.EnvironmentName); configure?.Invoke(context, loggerConfiguration); @@ -52,48 +52,48 @@ public static IEndpointConventionBuilder MapLogLevelHandler( => builder.MapPost(endpointRoute, LevelSwitch); private static void MapOptions( - LoggerSettings loggerOptions, - AppSettings appOptions, + LoggerOptions loggerSettings, + AppOptions appSettings, LoggerConfiguration loggerConfiguration, string environmentName) { - LoggingLevelSwitch.MinimumLevel = GetLogEventLevel(loggerOptions.Level); + LoggingLevelSwitch.MinimumLevel = GetLogEventLevel(loggerSettings.Level); loggerConfiguration.Enrich.FromLogContext() .MinimumLevel.ControlledBy(LoggingLevelSwitch) .Enrich.WithProperty("Environment", environmentName) - .Enrich.WithProperty("Application", appOptions.Service) - .Enrich.WithProperty("Instance", appOptions.Instance) - .Enrich.WithProperty("Version", appOptions.Version); + .Enrich.WithProperty("Application", appSettings.Service) + .Enrich.WithProperty("Instance", appSettings.Instance) + .Enrich.WithProperty("Version", appSettings.Version); - foreach (var (key, value) in loggerOptions.Tags ?? new Dictionary()) + foreach (var (key, value) in loggerSettings.Tags ?? new Dictionary()) { loggerConfiguration.Enrich.WithProperty(key, value); } - foreach (var (key, value) in loggerOptions.MinimumLevelOverrides ?? new Dictionary()) + foreach (var (key, value) in loggerSettings.MinimumLevelOverrides ?? new Dictionary()) { var logLevel = GetLogEventLevel(value); loggerConfiguration.MinimumLevel.Override(key, logLevel); } - loggerOptions.ExcludePaths?.ToList().ForEach(p => loggerConfiguration.Filter + loggerSettings.ExcludePaths?.ToList().ForEach(p => loggerConfiguration.Filter .ByExcluding(Matching.WithProperty("RequestPath", n => n.EndsWith(p)))); - loggerOptions.ExcludeProperties?.ToList().ForEach(p => loggerConfiguration.Filter + loggerSettings.ExcludeProperties?.ToList().ForEach(p => loggerConfiguration.Filter .ByExcluding(Matching.WithProperty(p))); - Configure(loggerConfiguration, loggerOptions); + Configure(loggerConfiguration, loggerSettings); } - private static void Configure(LoggerConfiguration loggerConfiguration, LoggerSettings options) + private static void Configure(LoggerConfiguration loggerConfiguration, LoggerOptions options) { - var consoleOptions = options.Console ?? new ConsoleSettings(); - var fileOptions = options.File ?? new LocalFileSettings(); - var elkOptions = options.Elk ?? new ElkSettings(); - var seqOptions = options.Seq ?? new SeqSettings(); - var lokiOptions = options.Loki ?? new LokiSettings(); - var azureOptions = options.Azure ?? new AzureSettings(); + var consoleOptions = options.Console ?? new ConsoleOptions(); + var fileOptions = options.File ?? new LocalFileOptions(); + var elkOptions = options.Elk ?? new ElkOptions(); + var seqOptions = options.Seq ?? new SeqOptions(); + var lokiOptions = options.Loki ?? new LokiOptions(); + var azureOptions = options.Azure ?? new AzureOptions(); // console if (consoleOptions.Enabled) diff --git a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs index ffd23f2e..3c0bb4b0 100644 --- a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs +++ b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs @@ -1,54 +1,54 @@ -using Genocs.Metrics.AppMetrics.Options; +using Genocs.Metrics.AppMetrics.Configurations; namespace Genocs.Metrics.AppMetrics.Builders; -internal sealed class MetricsOptionsBuilder : IMetricsOptionsBuilder +internal sealed class MetricsOptionsBuilder : IMetricsSettingsBuilder { private readonly MetricsSettings _options = new(); - public IMetricsOptionsBuilder Enable(bool enabled) + public IMetricsSettingsBuilder Enable(bool enabled) { _options.Enabled = enabled; return this; } - public IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled) + public IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled) { _options.InfluxEnabled = influxEnabled; return this; } - public IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled) + public IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled) { _options.PrometheusEnabled = prometheusEnabled; return this; } - public IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter) + public IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter) { _options.PrometheusFormatter = prometheusFormatter; return this; } - public IMetricsOptionsBuilder WithInfluxUrl(string influxUrl) + public IMetricsSettingsBuilder WithInfluxUrl(string influxUrl) { _options.InfluxUrl = influxUrl; return this; } - public IMetricsOptionsBuilder WithDatabase(string database) + public IMetricsSettingsBuilder WithDatabase(string database) { _options.Database = database; return this; } - public IMetricsOptionsBuilder WithInterval(int interval) + public IMetricsSettingsBuilder WithInterval(int interval) { _options.Interval = interval; return this; } - public IMetricsOptionsBuilder WithTags(IDictionary tags) + public IMetricsSettingsBuilder WithTags(IDictionary tags) { _options.Tags = tags; return this; diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs new file mode 100644 index 00000000..e9964080 --- /dev/null +++ b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs @@ -0,0 +1,14 @@ +namespace Genocs.Metrics.AppMetrics.Configurations; + +public interface IMetricsSettingsBuilder +{ + IMetricsSettingsBuilder Enable(bool enabled); + IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled); + IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled); + IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter); + IMetricsSettingsBuilder WithInfluxUrl(string influxUrl); + IMetricsSettingsBuilder WithDatabase(string database); + IMetricsSettingsBuilder WithInterval(int interval); + IMetricsSettingsBuilder WithTags(IDictionary tags); + MetricsSettings Build(); +} \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs similarity index 96% rename from src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs rename to src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs index 19f0144c..1a3f226f 100644 --- a/src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs +++ b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Metrics.AppMetrics.Options; +namespace Genocs.Metrics.AppMetrics.Configurations; /// /// The MetricsSettings class. diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index 4829b458..54f939f6 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -4,11 +4,11 @@ using App.Metrics.AspNetCore.Health.Endpoints; using App.Metrics.AspNetCore.Tracking; using App.Metrics.Formatters.Prometheus; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; using Genocs.Metrics.AppMetrics; using Genocs.Metrics.AppMetrics.Builders; -using Genocs.Metrics.AppMetrics.Options; +using Genocs.Metrics.AppMetrics.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -37,11 +37,11 @@ public static IGenocsBuilder AddMetrics( if (string.IsNullOrWhiteSpace(appSectionName)) { - appSectionName = AppSettings.Position; + appSectionName = AppOptions.Position; } var metricsOptions = builder.GetOptions(metricsSectionName); - var appOptions = builder.GetOptions(appSectionName); + var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); } @@ -49,7 +49,7 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - Func buildOptions, + Func buildOptions, string appSectionName = AppSectionName) { if (string.IsNullOrWhiteSpace(appSectionName)) @@ -58,7 +58,7 @@ public static IGenocsBuilder AddMetrics( } var metricsOptions = buildOptions(new MetricsOptionsBuilder()).Build(); - var appOptions = builder.GetOptions(appSectionName); + var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); } @@ -66,11 +66,11 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's and IIS ServerOptions AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - MetricsSettings metricsOptions, - AppSettings appOptions) + MetricsSettings metricsSettings, + AppOptions appSettings) { - builder.Services.AddSingleton(metricsOptions); - if (!builder.TryRegister(RegistryName) || !metricsOptions.Enabled || _initialized) + builder.Services.AddSingleton(metricsSettings); + if (!builder.TryRegister(RegistryName) || !metricsSettings.Enabled || _initialized) { return builder; } @@ -79,7 +79,7 @@ public static IGenocsBuilder AddMetrics( var metricsBuilder = new MetricsBuilder().Configuration.Configure(cfg => { - var tags = metricsOptions.Tags; + var tags = metricsSettings.Tags; if (tags is null) { return; @@ -88,17 +88,17 @@ public static IGenocsBuilder AddMetrics( tags.TryGetValue("app", out string? app); tags.TryGetValue("env", out string? env); tags.TryGetValue("server", out string? server); - cfg.AddAppTag(string.IsNullOrWhiteSpace(app) ? appOptions.Service : app); + cfg.AddAppTag(string.IsNullOrWhiteSpace(app) ? appSettings.Service : app); cfg.AddEnvTag(string.IsNullOrWhiteSpace(env) ? null : env); cfg.AddServerTag(string.IsNullOrWhiteSpace(server) ? null : server); - if (!string.IsNullOrWhiteSpace(appOptions.Instance)) + if (!string.IsNullOrWhiteSpace(appSettings.Instance)) { - cfg.GlobalTags.Add("instance", appOptions.Instance); + cfg.GlobalTags.Add("instance", appSettings.Instance); } - if (!string.IsNullOrWhiteSpace(appOptions.Version)) + if (!string.IsNullOrWhiteSpace(appSettings.Version)) { - cfg.GlobalTags.Add("version", appOptions.Version); + cfg.GlobalTags.Add("version", appSettings.Version); } foreach (var tag in tags) @@ -115,19 +115,19 @@ public static IGenocsBuilder AddMetrics( } }); - if (metricsOptions.InfluxEnabled) + if (metricsSettings.InfluxEnabled) { metricsBuilder.Report.ToInfluxDb(o => { - o.InfluxDb.Database = metricsOptions.Database; - o.InfluxDb.BaseUri = new Uri(metricsOptions.InfluxUrl!); + o.InfluxDb.Database = metricsSettings.Database; + o.InfluxDb.BaseUri = new Uri(metricsSettings.InfluxUrl!); o.InfluxDb.CreateDataBaseIfNotExists = true; - o.FlushInterval = TimeSpan.FromSeconds(metricsOptions.Interval); + o.FlushInterval = TimeSpan.FromSeconds(metricsSettings.Interval); }); } var metrics = metricsBuilder.Build(); - var metricsWebHostOptions = GetMetricsWebHostOptions(metricsOptions); + var metricsWebHostOptions = GetMetricsWebHostOptions(metricsSettings); using var serviceProvider = builder.Services.BuildServiceProvider(); var configuration = builder.Configuration ?? serviceProvider.GetRequiredService(); diff --git a/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs deleted file mode 100644 index dff0200c..00000000 --- a/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Genocs.Metrics.AppMetrics.Options; - -namespace Genocs.Metrics.AppMetrics; - -public interface IMetricsOptionsBuilder -{ - IMetricsOptionsBuilder Enable(bool enabled); - IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled); - IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled); - IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter); - IMetricsOptionsBuilder WithInfluxUrl(string influxUrl); - IMetricsOptionsBuilder WithDatabase(string database); - IMetricsOptionsBuilder WithInterval(int interval); - IMetricsOptionsBuilder WithTags(IDictionary tags); - MetricsSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs b/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs index c799988e..67fe7ec6 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs +++ b/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs @@ -1,5 +1,4 @@ using Genocs.Persistence.MongoDb.Encryptions; -using Genocs.Persistence.MongoDb.Options; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using Moq; diff --git a/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs b/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs index 99e3a861..512a9838 100644 --- a/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs +++ b/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs @@ -1,11 +1,10 @@ -using Genocs.Persistence.MongoDb.Options; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Configurations; namespace Genocs.Persistence.MongoDb.Builders; internal sealed class MongoDbOptionsBuilder : IMongoDbOptionsBuilder { - private readonly MongoDbSettings _options = new(); + private readonly MongoDbOptions _options = new(); public IMongoDbOptionsBuilder WithConnectionString(string connectionString) { @@ -25,6 +24,6 @@ public IMongoDbOptionsBuilder WithSeed(bool seed) return this; } - public MongoDbSettings Build() + public MongoDbOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs b/src/Genocs.Persistence.MongoDb/Configurations/IMongoDbOptionsBuilder.cs similarity index 87% rename from src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs rename to src/Genocs.Persistence.MongoDb/Configurations/IMongoDbOptionsBuilder.cs index 36e91713..714aa05a 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs +++ b/src/Genocs.Persistence.MongoDb/Configurations/IMongoDbOptionsBuilder.cs @@ -1,6 +1,4 @@ -using Genocs.Persistence.MongoDb.Options; - -namespace Genocs.Persistence.MongoDb.Repositories; +namespace Genocs.Persistence.MongoDb.Configurations; /// /// The MongoDB Options Builder. @@ -32,5 +30,5 @@ public interface IMongoDbOptionsBuilder /// Get the settings. /// /// MongoDbSettings instance. - MongoDbSettings Build(); + MongoDbOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs new file mode 100644 index 00000000..70db85df --- /dev/null +++ b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs @@ -0,0 +1,69 @@ +namespace Genocs.Persistence.MongoDb.Configurations; + +/// +/// MongoDb encryption database Settings. +/// +public class MongoDbEncryptionOptions +{ + + /// + /// Default Section name. + /// + public const string Position = "MongoDbEncryption"; + + /// + /// The Database connection string. + /// + public string ConnectionString { get; set; } = default!; + + /// + /// The shared library used to encrypt. + /// + public string LibPath { get; set; } = default!; + + /// + /// Azure Tenant Id. + /// + public string TenantId { get; set; } = default!; + + /// + /// Azure Client Id. + /// + public string ClientId { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string ClientSecret { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string KeyName { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string KeyVersion { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string KeyVaultEndpoint { get; set; } = default!; + + /// + /// Check if the MongoDbSettings object contains valid data. + /// + /// MongoDbSettings object. + /// return true if valid otherwise false. + public static bool IsValid(MongoDbEncryptionOptions settings) + { + if (settings is null) return false; + + if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; + if (string.IsNullOrWhiteSpace(settings.LibPath)) return false; + + return true; + + } +} diff --git a/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbOptions.cs similarity index 91% rename from src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs rename to src/Genocs.Persistence.MongoDb/Configurations/MongoDbOptions.cs index 6dc46179..67c2d753 100644 --- a/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs +++ b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbOptions.cs @@ -1,11 +1,11 @@ using System.ComponentModel; -namespace Genocs.Persistence.MongoDb.Options; +namespace Genocs.Persistence.MongoDb.Configurations; /// /// MongoDb database Settings. /// -public class MongoDbSettings +public class MongoDbOptions { /// /// Default Section name. @@ -43,7 +43,7 @@ public class MongoDbSettings /// /// MongoDbSettings object. /// return true if valid otherwise false. - public static bool IsValid(MongoDbSettings settings) + public static bool IsValid(MongoDbOptions settings) { if (settings is null) return false; diff --git a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs index ed2200f7..911344a6 100644 --- a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs @@ -1,4 +1,4 @@ -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; @@ -15,11 +15,11 @@ public class AzureInitializer /// Setup the client /// /// - public AutoEncryptionOptions EncryptionOptions(IOptions options) + public AutoEncryptionOptions EncryptionOptions(IOptions options) { // Ge settings - MongoDbEncryptionSettings settings = options.Value; - MongoDbEncryptionSettings.IsValid(settings); + MongoDbEncryptionOptions settings = options.Value; + MongoDbEncryptionOptions.IsValid(settings); // start-kmsproviders var kmsProviders = new Dictionary>(); diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs index d418b605..06d4b5a4 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs @@ -1,9 +1,9 @@ using Genocs.Common.Types; using Genocs.Core.Builders; using Genocs.Persistence.MongoDb.Builders; +using Genocs.Persistence.MongoDb.Configurations; using Genocs.Persistence.MongoDb.Factories; using Genocs.Persistence.MongoDb.Initializers; -using Genocs.Persistence.MongoDb.Options; using Genocs.Persistence.MongoDb.Repositories; using Genocs.Persistence.MongoDb.Repositories.Clean; using Genocs.Persistence.MongoDb.Repositories.Mentor; @@ -34,16 +34,16 @@ public static class MongoDbExtensions /// The Genocs builder. public static IGenocsBuilder AddMongo( this IGenocsBuilder builder, - string sectionName = MongoDbSettings.Position, + string sectionName = MongoDbOptions.Position, Type? seederType = null, bool registerConventions = true) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = MongoDbSettings.Position; + sectionName = MongoDbOptions.Position; } - var mongoOptions = builder.GetOptions(sectionName); + var mongoOptions = builder.GetOptions(sectionName); return builder.AddMongo(mongoOptions, seederType, registerConventions); } @@ -70,32 +70,32 @@ public static IGenocsBuilder AddMongo( /// Setup MongoDb support. /// /// The Genocs builder. - /// The settings. + /// The settings. /// /// /// The Genocs builder. public static IGenocsBuilder AddMongo( this IGenocsBuilder builder, - MongoDbSettings mongoOptions, + MongoDbOptions options, Type? seederType = null, bool registerConventions = true) { - if (!builder.TryRegister(MongoDbSettings.Position)) + if (!builder.TryRegister(MongoDbOptions.Position)) { return builder; } - if (mongoOptions.SetRandomDatabaseSuffix) + if (options.SetRandomDatabaseSuffix) { string suffix = $"{Guid.NewGuid():N}"; Console.WriteLine($"Setting a random MongoDB database suffix: '{suffix}'."); - mongoOptions.Database = $"{mongoOptions.Database}_{suffix}"; + options.Database = $"{options.Database}_{suffix}"; } - builder.Services.AddSingleton(mongoOptions); + builder.Services.AddSingleton(options); builder.Services.AddSingleton(sp => { - var options = sp.GetRequiredService(); + var options = sp.GetRequiredService(); MongoClientSettings clientSettings = MongoClientSettings.FromConnectionString(options.ConnectionString); @@ -109,7 +109,7 @@ public static IGenocsBuilder AddMongo( builder.Services.AddTransient(sp => { - var options = sp.GetRequiredService(); + var options = sp.GetRequiredService(); var client = sp.GetRequiredService(); return client.GetDatabase(options.Database); }); @@ -168,13 +168,13 @@ public static IGenocsBuilder AddMongoRepository( /// The Genocs builder. public static IGenocsBuilder AddMongoFast( this IGenocsBuilder builder, - string sectionName = MongoDbSettings.Position, + string sectionName = MongoDbOptions.Position, bool registerConventions = true) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = MongoDbSettings.Position; + sectionName = MongoDbOptions.Position; } var section = builder.Configuration.GetSection(sectionName); @@ -184,7 +184,7 @@ public static IGenocsBuilder AddMongoFast( return builder; } - builder.Services.Configure(section); + builder.Services.Configure(section); builder.Services.AddSingleton(); builder.Services.AddScoped(typeof(IMongoDbRepository<>), typeof(MongoDbRepository<>)); diff --git a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs index 11b4c6ad..dd60928e 100644 --- a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs @@ -1,4 +1,4 @@ -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; using Genocs.Persistence.MongoDb.Repositories; using MongoDB.Driver; @@ -11,7 +11,7 @@ internal sealed class MongoDbInitializer : IMongoDbInitializer private readonly IMongoDatabase _database; private readonly IMongoDbSeeder _seeder; - public MongoDbInitializer(IMongoDatabase database, IMongoDbSeeder seeder, MongoDbSettings options) + public MongoDbInitializer(IMongoDatabase database, IMongoDbSeeder seeder, MongoDbOptions options) { _database = database; _seeder = seeder; diff --git a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs index 412c8475..24485ab7 100644 --- a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs +++ b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs @@ -1,5 +1,4 @@ -using Genocs.Persistence.MongoDb.Encryptions; -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; using Microsoft.Extensions.Options; using MongoDB.Driver; using MongoDB.Driver.Core.Extensions.DiagnosticSources; @@ -8,35 +7,35 @@ namespace Genocs.Persistence.MongoDb; /// -/// The MongoDatabaseProvider +/// The MongoDatabaseProvider. /// public class MongoDatabaseProvider : IMongoDatabaseProvider { /// - /// Reference to MongoClient + /// Reference to MongoClient. /// public IMongoClient MongoClient { get; private set; } /// - /// Reference to Database + /// Reference to Database. /// public IMongoDatabase Database { get; private set; } /// - /// Default Constructor + /// Default Constructor. /// /// /// /// - public MongoDatabaseProvider(IOptions options, IOptions encrypOptions) + public MongoDatabaseProvider(IOptions options, IOptions encrypOptions) { if (options == null) throw new NullReferenceException(nameof(options)); - MongoDbSettings dBSettings = options.Value; + MongoDbOptions dBSettings = options.Value; if (dBSettings == null) throw new NullReferenceException(nameof(dBSettings)); - if (!MongoDbSettings.IsValid(dBSettings)) throw new InvalidOperationException($"{nameof(dBSettings)} is invalid"); + if (!MongoDbOptions.IsValid(dBSettings)) throw new InvalidOperationException($"{nameof(dBSettings)} is invalid"); MongoClientSettings clientSettings = MongoClientSettings.FromConnectionString(dBSettings.ConnectionString); diff --git a/src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs b/src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs deleted file mode 100644 index 35e03b2c..00000000 --- a/src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace Genocs.Persistence.MongoDb.Options -{ - /// - /// MongoDb encryption database Settings - /// - public class MongoDbEncryptionSettings - { - - /// - /// Default Section name - /// - public const string Position = "MongoDbEncryption"; - - /// - /// The Database connection string - /// - public string ConnectionString { get; set; } = default!; - - /// - /// The shared library used to encrypt - /// - public string LibPath { get; set; } = default!; - - /// - /// Azure Tenant Id - /// - public string TenantId { get; set; } = default!; - - /// - /// Azure Client Id - /// - public string ClientId { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string ClientSecret { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyName { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyVersion { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyVaultEndpoint { get; set; } = default!; - - /// - /// Check if the MongoDbSettings object contains valid data - /// - /// MongoDbSettings object - /// return true if valid otherwise false - public static bool IsValid(MongoDbEncryptionSettings settings) - { - if (settings is null) return false; - - if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; - if (string.IsNullOrWhiteSpace(settings.LibPath)) return false; - - return true; - - } - } -} diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index beb99dfb..b47ad831 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -1,7 +1,7 @@ using Azure.Monitor.OpenTelemetry.Exporter; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; -using Genocs.Logging.Options; +using Genocs.Logging.Configurations; using Genocs.Tracing.Jaeger.Options; using Jaeger.Samplers; using Jaeger.Senders.Thrift; @@ -28,7 +28,7 @@ public static class Extensions public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) { - var appOptions = builder.GetOptions(AppSettings.Position); + var appOptions = builder.GetOptions(AppOptions.Position); // No OpenTelemetryTracing in case of missing ServiceName if (string.IsNullOrWhiteSpace(appOptions.Service)) @@ -47,7 +47,7 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) .AddEnvironmentVariableDetector()) .AddSource("*"); - var loggerOptions = builder.GetOptions(LoggerSettings.Position); + var loggerOptions = builder.GetOptions(LoggerOptions.Position); // No OpenTelemetryTracing in case of missing LoggerSettings if (loggerOptions != null) diff --git a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs index 52a4864a..24036299 100644 --- a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs +++ b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs @@ -15,20 +15,28 @@ public DispatcherEndpointsBuilder(IEndpointsBuilder builder) _builder = builder; } - public IDispatcherEndpointsBuilder Get(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) + public IDispatcherEndpointsBuilder Get( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) { _builder.Get(path, context, endpoint, auth, roles, policies); return this; } - public IDispatcherEndpointsBuilder Get(string path, - Func? beforeDispatch = null, - Func? afterDispatch = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) where TQuery : class, IQuery + public IDispatcherEndpointsBuilder Get( + string path, + Func? beforeDispatch = null, + Func? afterDispatch = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) + where TQuery : class, IQuery { _builder.Get(path, async (query, ctx) => { diff --git a/src/Genocs.WebApi.Security/CertificateMiddleware.cs b/src/Genocs.WebApi.Security/CertificateMiddleware.cs index ea5e18d8..e976c994 100644 --- a/src/Genocs.WebApi.Security/CertificateMiddleware.cs +++ b/src/Genocs.WebApi.Security/CertificateMiddleware.cs @@ -1,3 +1,4 @@ +using Genocs.WebApi.Security.Configurations; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System.Security.Cryptography.X509Certificates; @@ -8,16 +9,16 @@ internal sealed class CertificateMiddleware : IMiddleware { private readonly ICertificatePermissionValidator _certificatePermissionValidator; private readonly ILogger _logger; - private readonly SecuritySettings.CertificateSettings _options; + private readonly SecurityOptions.CertificateOptions _options; private readonly HashSet _allowedHosts; - private readonly IDictionary _acl; + private readonly IDictionary _acl; private readonly IDictionary _subjects = new Dictionary(); private readonly bool _validateAcl; private readonly bool _skipRevocationCheck; public CertificateMiddleware( ICertificatePermissionValidator certificatePermissionValidator, - SecuritySettings options, + SecurityOptions options, ILogger logger) { _certificatePermissionValidator = certificatePermissionValidator; @@ -32,7 +33,7 @@ public CertificateMiddleware( return; } - _acl = new Dictionary(); + _acl = new Dictionary(); foreach (var (key, acl) in _options.Acl) { if (!string.IsNullOrWhiteSpace(acl.ValidIssuer) && !acl.ValidIssuer.StartsWith("CN=")) @@ -77,7 +78,7 @@ public Task InvokeAsync(HttpContext context, RequestDelegate next) return next(context); } - SecuritySettings.CertificateSettings.AclSettings acl; + SecurityOptions.CertificateOptions.AclOptions acl; if (_subjects.TryGetValue(certificate.Subject, out string? subject)) { if (!_acl.TryGetValue(subject, out var existingAcl)) diff --git a/src/Genocs.WebApi.Security/Options/SecuritySettings.cs b/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs similarity index 72% rename from src/Genocs.WebApi.Security/Options/SecuritySettings.cs rename to src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs index 08fb937a..dc4c04ee 100644 --- a/src/Genocs.WebApi.Security/Options/SecuritySettings.cs +++ b/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs @@ -1,22 +1,22 @@ -namespace Genocs.WebApi.Security; +namespace Genocs.WebApi.Security.Configurations; -public class SecuritySettings +public class SecurityOptions { - public CertificateSettings? Certificate { get; set; } + public CertificateOptions? Certificate { get; set; } - public class CertificateSettings + public class CertificateOptions { public bool Enabled { get; set; } public string? Header { get; set; } public bool AllowSubdomains { get; set; } public IEnumerable? AllowedDomains { get; set; } public IEnumerable? AllowedHosts { get; set; } - public IDictionary? Acl { get; set; } + public IDictionary? Acl { get; set; } public bool SkipRevocationCheck { get; set; } public string GetHeaderName() => string.IsNullOrWhiteSpace(Header) ? "Certificate" : Header; - public class AclSettings + public class AclOptions { public string? ValidIssuer { get; set; } public string? ValidThumbprint { get; set; } diff --git a/src/Genocs.WebApi.Security/Extensions.cs b/src/Genocs.WebApi.Security/Extensions.cs index a615b8c6..d81de65b 100644 --- a/src/Genocs.WebApi.Security/Extensions.cs +++ b/src/Genocs.WebApi.Security/Extensions.cs @@ -1,4 +1,5 @@ using Genocs.Core.Builders; +using Genocs.WebApi.Security.Configurations; using Microsoft.AspNetCore.Authentication.Certificate; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; @@ -16,7 +17,7 @@ public static IGenocsBuilder AddCertificateAuthentication( string sectionName = SectionName, Type? permissionValidatorType = null) { - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); if (!builder.TryRegister(RegistryName)) { @@ -56,7 +57,7 @@ public static IGenocsBuilder AddCertificateAuthentication( public static IApplicationBuilder UseCertificateAuthentication(this IApplicationBuilder app) { - var options = app.ApplicationServices.GetRequiredService(); + var options = app.ApplicationServices.GetRequiredService(); if (options.Certificate is null || !options.Certificate.Enabled) { return app; diff --git a/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs similarity index 93% rename from src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs rename to src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs index 90e21984..81c7e66c 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs @@ -1,4 +1,6 @@ -namespace Genocs.WebApi.Swagger.Docs.Builders; +using Genocs.WebApi.Swagger.Configurations; + +namespace Genocs.WebApi.Swagger.Builders; internal sealed class SwaggerOptionsBuilder : ISwaggerOptionsBuilder { diff --git a/src/Genocs.WebApi.Swagger/Docs/ISwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Configurations/ISwaggerOptionsBuilder.cs similarity index 91% rename from src/Genocs.WebApi.Swagger/Docs/ISwaggerOptionsBuilder.cs rename to src/Genocs.WebApi.Swagger/Configurations/ISwaggerOptionsBuilder.cs index 1527d2a4..e030d897 100644 --- a/src/Genocs.WebApi.Swagger/Docs/ISwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Configurations/ISwaggerOptionsBuilder.cs @@ -1,4 +1,4 @@ -namespace Genocs.WebApi.Swagger.Docs; +namespace Genocs.WebApi.Swagger.Configurations; public interface ISwaggerOptionsBuilder { diff --git a/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs b/src/Genocs.WebApi.Swagger/Configurations/SwaggerOptions.cs similarity index 88% rename from src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs rename to src/Genocs.WebApi.Swagger/Configurations/SwaggerOptions.cs index 30e30d6c..1c46822c 100644 --- a/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs +++ b/src/Genocs.WebApi.Swagger/Configurations/SwaggerOptions.cs @@ -1,4 +1,4 @@ -namespace Genocs.WebApi.Swagger.Docs; +namespace Genocs.WebApi.Swagger.Configurations; public class SwaggerOptions { diff --git a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs index b752a211..84f0d6b2 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs @@ -1,5 +1,6 @@ using Genocs.Core.Builders; -using Genocs.WebApi.Swagger.Docs.Builders; +using Genocs.WebApi.Swagger.Builders; +using Genocs.WebApi.Swagger.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; diff --git a/src/Genocs.WebApi.Swagger/Extensions.cs b/src/Genocs.WebApi.Swagger/Extensions.cs index 585d9ceb..af8d231c 100644 --- a/src/Genocs.WebApi.Swagger/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Extensions.cs @@ -1,4 +1,5 @@ using Genocs.Core.Builders; +using Genocs.WebApi.Swagger.Configurations; using Genocs.WebApi.Swagger.Docs; using Genocs.WebApi.Swagger.Filters; using Microsoft.Extensions.DependencyInjection; diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index a2dae299..2653d378 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -1,7 +1,7 @@ using Genocs.APIGateway.Framework; using Genocs.APIGateway.Options; using Genocs.Auth; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; using Genocs.MessageBrokers.RabbitMQ; using Genocs.Metrics.Prometheus; @@ -90,7 +90,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { endpoints.MapGet("/", async context => { - await context.Response.WriteAsync(context.RequestServices.GetService()?.Name ?? "Service"); + await context.Response.WriteAsync(context.RequestServices.GetService()?.Name ?? "Service"); }); endpoints.MapReverseProxy(); diff --git a/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs b/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs index b9231895..198edd60 100644 --- a/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs +++ b/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs @@ -1,5 +1,5 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.MessageBrokers; using Microsoft.AspNetCore.Http; @@ -14,7 +14,7 @@ internal class CorrelationIdFactory : ICorrelationIdFactory private readonly string _header; public CorrelationIdFactory(IMessagePropertiesAccessor messagePropertiesAccessor, - IHttpContextAccessor httpContextAccessor, HttpClientSettings httpClientOptions) + IHttpContextAccessor httpContextAccessor, HttpClientOptions httpClientOptions) { _messagePropertiesAccessor = messagePropertiesAccessor; _httpContextAccessor = httpContextAccessor; diff --git a/src/apps/identity/Genocs.Identities.Application/Extensions.cs b/src/apps/identity/Genocs.Identities.Application/Extensions.cs index 593c58a1..0d19358d 100644 --- a/src/apps/identity/Genocs.Identities.Application/Extensions.cs +++ b/src/apps/identity/Genocs.Identities.Application/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Auth; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; using Genocs.Core.CQRS.Commands; using Genocs.Core.CQRS.Events; @@ -106,7 +106,7 @@ public static IApplicationBuilder UseCore(this IApplicationBuilder app) } public static async Task GetAppName(this HttpContext httpContext) - => await httpContext.Response.WriteAsync(httpContext.RequestServices?.GetService()?.Name ?? string.Empty); + => await httpContext.Response.WriteAsync(httpContext.RequestServices?.GetService()?.Name ?? string.Empty); internal static CorrelationContext GetCorrelationContext(this IHttpContextAccessor accessor) => accessor.HttpContext?.Request.Headers.TryGetValue("Correlation-Context", out var json) is true diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs index 1577cb9b..802e1de3 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs @@ -1,9 +1,9 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.Orders.WebApi.DTO; using Genocs.Secrets.Vault; using Genocs.Secrets.Vault.Options; -using Genocs.WebApi.Security; +using Genocs.WebApi.Security.Configurations; namespace Genocs.Orders.WebApi.Services; @@ -22,13 +22,13 @@ public class ProductServiceClient : IProductServiceClient /// The certification service. /// /// - /// + /// public ProductServiceClient( IHttpClient client, ICertificatesService certificatesService, - HttpClientSettings httpClientOptions, + HttpClientOptions httpClientOptions, VaultSettings vaultOptions, - SecuritySettings securitySettings) + SecurityOptions securityOptions) { _client = client ?? throw new ArgumentNullException(nameof(client)); @@ -43,9 +43,9 @@ public ProductServiceClient( throw new ArgumentNullException(nameof(vaultOptions)); } - if (securitySettings is null) + if (securityOptions is null) { - throw new ArgumentNullException(nameof(securitySettings)); + throw new ArgumentNullException(nameof(securityOptions)); } string? url = httpClientOptions?.Services?["products"]; @@ -58,7 +58,7 @@ public ProductServiceClient( _url = url; if (!vaultOptions.Enabled || vaultOptions.Pki?.Enabled != true || - securitySettings.Certificate?.Enabled != true) + securityOptions.Certificate?.Enabled != true) { return; } @@ -69,7 +69,7 @@ public ProductServiceClient( return; } - string header = securitySettings.Certificate.GetHeaderName(); + string header = securityOptions.Certificate.GetHeaderName(); string certificateData = certificate.GetRawCertDataString(); _client.SetHeaders(h => h.Add(header, certificateData)); } diff --git a/testEnvironments.json b/testEnvironments.json new file mode 100644 index 00000000..a110b57d --- /dev/null +++ b/testEnvironments.json @@ -0,0 +1,17 @@ +{ + "version": "1", + "environments": [ + // See https://aka.ms/remotetesting for more details + // about how to configure remote environments. + //{ + // "name": "WSL Ubuntu", + // "type": "wsl", + // "wslDistribution": "Ubuntu" + //}, + //{ + // "name": "Docker dotnet/sdk", + // "type": "docker", + // "dockerImage": "mcr.microsoft.com/dotnet/sdk" + //} + ] +} \ No newline at end of file From 34b35b2c4979c95b957f144cf7e680d16fca450d Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Sat, 22 Jun 2024 09:52:08 +0200 Subject: [PATCH 053/104] Cleanup data after uniform naming conventions --- src/Genocs.Auth/Extensions.cs | 138 +++++++++--------- .../ExternalServiceOptions.cs} | 2 +- .../RabbitMQOptions.cs} | 2 +- .../SecretOptions.cs} | 2 +- .../Controllers/HomeController.cs | 4 +- .../Extensions/BuilderExtensions.cs | 3 +- .../Extensions/ServiceCollectionExtensions.cs | 14 +- .../Services/ExternalServiceClient.cs | 4 +- src/Genocs.Core.Demo.WebApi/Program.cs | 5 +- .../Configurations/ConsulOptions.cs | 4 +- .../ConsulServiceDiscoveryMessageHandler.cs | 14 +- .../Configurations/HttpClientOptions.cs | 4 +- src/Genocs.Logging/Extensions.cs | 24 +-- .../Internals/MongoMessageOutbox.cs | 4 +- .../Internals/MongoOutboxInitializer.cs | 6 +- .../OutboxOptions.cs} | 4 +- .../MessageOutboxConfigurator.cs | 6 +- .../Extensions.cs | 4 +- .../IMessageOutboxConfigurator.cs | 4 +- .../Outbox/InMemoryMessageOutbox.cs | 4 +- .../Processors/OutboxProcessor.cs | 6 +- .../Builders/MetricsOptionsBuilder.cs | 22 +-- .../Configurations/IMetricsOptionsBuilder.cs | 14 ++ .../Configurations/IMetricsSettingsBuilder.cs | 14 -- .../{MetricsSettings.cs => MetricsOptions.cs} | 2 +- src/Genocs.Metrics/AppMetrics/Extensions.cs | 12 +- .../Extensions.cs | 9 +- .../VaultOptions.cs} | 16 +- src/Genocs.Secrets.Vault/Extensions.cs | 40 +++-- .../Internals/CertificatesIssuer.cs | 6 +- .../Internals/KeyValueSecrets.cs | 6 +- .../Internals/VaultHostedService.cs | 6 +- .../MessagingOptions.cs} | 8 +- .../Framework/MessagingMiddleware.cs | 8 +- .../api-gateway/Genocs.APIGateway/Startup.cs | 4 +- .../OutboxCommandHandlerDecorator.cs | 4 +- .../Decorators/OutboxEventHandlerDecorator.cs | 4 +- .../Services/ProductServiceClient.cs | 4 +- .../SignalROptions.cs} | 4 +- .../Framework/Extensions.cs | 6 +- 40 files changed, 220 insertions(+), 227 deletions(-) rename src/Genocs.Core.Demo.WebApi/{Options/ExternalServiceSettings.cs => Configurations/ExternalServiceOptions.cs} (87%) rename src/Genocs.Core.Demo.WebApi/{Options/RabbitMQSettings.cs => Configurations/RabbitMQOptions.cs} (92%) rename src/Genocs.Core.Demo.WebApi/{Options/SecretSettings.cs => Configurations/SecretOptions.cs} (92%) rename src/Genocs.MessageBrokers.Outbox/{Options/OutboxSettings.cs => Configurations/OutboxOptions.cs} (79%) create mode 100644 src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs delete mode 100644 src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs rename src/Genocs.Metrics/AppMetrics/Configurations/{MetricsSettings.cs => MetricsOptions.cs} (97%) rename src/Genocs.Secrets.Vault/{Options/VaultSettings.cs => Configurations/VaultOptions.cs} (84%) rename src/apps/api-gateway/Genocs.APIGateway/{Options/MessagingSettings.cs => Configurations/MessagingOptions.cs} (57%) rename src/apps/signalr/Genocs.SignalR.WebApi/{Options/SignalRSettings.cs => Configurations/SignalROptions.cs} (66%) diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index f0077ec1..da3cf466 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -37,7 +37,7 @@ public static IGenocsBuilder AddJwt( private static IGenocsBuilder AddJwt( this IGenocsBuilder builder, - JwtOptions jwtSettings, + JwtOptions options, Action? optionsFactory = null) { if (!builder.TryRegister(RegistryName)) @@ -50,53 +50,53 @@ private static IGenocsBuilder AddJwt( builder.Services.AddSingleton(); builder.Services.AddTransient(); - if (!jwtSettings.Enabled) + if (!options.Enabled) { builder.Services.AddSingleton(); } var tokenValidationParameters = new TokenValidationParameters { - RequireAudience = jwtSettings.RequireAudience, - ValidIssuer = jwtSettings.ValidIssuer, - ValidIssuers = jwtSettings.ValidIssuers, - ValidateActor = jwtSettings.ValidateActor, - ValidAudience = jwtSettings.ValidAudience, - ValidAudiences = jwtSettings.ValidAudiences, - ValidateAudience = jwtSettings.ValidateAudience, - ValidateIssuer = jwtSettings.ValidateIssuer, - ValidateLifetime = jwtSettings.ValidateLifetime, - ValidateTokenReplay = jwtSettings.ValidateTokenReplay, - ValidateIssuerSigningKey = jwtSettings.ValidateIssuerSigningKey, - SaveSigninToken = jwtSettings.SaveSigninToken, - RequireExpirationTime = jwtSettings.RequireExpirationTime, - RequireSignedTokens = jwtSettings.RequireSignedTokens, + RequireAudience = options.RequireAudience, + ValidIssuer = options.ValidIssuer, + ValidIssuers = options.ValidIssuers, + ValidateActor = options.ValidateActor, + ValidAudience = options.ValidAudience, + ValidAudiences = options.ValidAudiences, + ValidateAudience = options.ValidateAudience, + ValidateIssuer = options.ValidateIssuer, + ValidateLifetime = options.ValidateLifetime, + ValidateTokenReplay = options.ValidateTokenReplay, + ValidateIssuerSigningKey = options.ValidateIssuerSigningKey, + SaveSigninToken = options.SaveSigninToken, + RequireExpirationTime = options.RequireExpirationTime, + RequireSignedTokens = options.RequireSignedTokens, ClockSkew = TimeSpan.Zero }; - if (!string.IsNullOrWhiteSpace(jwtSettings.AuthenticationType)) + if (!string.IsNullOrWhiteSpace(options.AuthenticationType)) { - tokenValidationParameters.AuthenticationType = jwtSettings.AuthenticationType; + tokenValidationParameters.AuthenticationType = options.AuthenticationType; } bool hasCertificate = false; - if (jwtSettings.Certificate is not null) + if (options.Certificate is not null) { X509Certificate2? certificate = null; - string password = jwtSettings.Certificate.Password; + string password = options.Certificate.Password; bool hasPassword = !string.IsNullOrWhiteSpace(password); - if (!string.IsNullOrWhiteSpace(jwtSettings.Certificate.Location)) + if (!string.IsNullOrWhiteSpace(options.Certificate.Location)) { certificate = hasPassword - ? new X509Certificate2(jwtSettings.Certificate.Location, password) - : new X509Certificate2(jwtSettings.Certificate.Location); + ? new X509Certificate2(options.Certificate.Location, password) + : new X509Certificate2(options.Certificate.Location); string keyType = certificate.HasPrivateKey ? "with private key" : "with public key only"; - Console.WriteLine($"Loaded X.509 certificate from location: '{jwtSettings.Certificate.Location}' {keyType}."); + Console.WriteLine($"Loaded X.509 certificate from location: '{options.Certificate.Location}' {keyType}."); } - if (!string.IsNullOrWhiteSpace(jwtSettings.Certificate.RawData)) + if (!string.IsNullOrWhiteSpace(options.Certificate.RawData)) { - byte[] rawData = Convert.FromBase64String(jwtSettings.Certificate.RawData); + byte[] rawData = Convert.FromBase64String(options.Certificate.RawData); certificate = hasPassword ? new X509Certificate2(rawData, password) : new X509Certificate2(rawData); @@ -106,9 +106,9 @@ private static IGenocsBuilder AddJwt( if (certificate is not null) { - if (string.IsNullOrWhiteSpace(jwtSettings.Algorithm)) + if (string.IsNullOrWhiteSpace(options.Algorithm)) { - jwtSettings.Algorithm = SecurityAlgorithms.RsaSha256; + options.Algorithm = SecurityAlgorithms.RsaSha256; } hasCertificate = true; @@ -118,54 +118,54 @@ private static IGenocsBuilder AddJwt( } } - if (!string.IsNullOrWhiteSpace(jwtSettings.IssuerSigningKey) && !hasCertificate) + if (!string.IsNullOrWhiteSpace(options.IssuerSigningKey) && !hasCertificate) { - if (string.IsNullOrWhiteSpace(jwtSettings.Algorithm) || hasCertificate) + if (string.IsNullOrWhiteSpace(options.Algorithm) || hasCertificate) { - jwtSettings.Algorithm = SecurityAlgorithms.HmacSha256; + options.Algorithm = SecurityAlgorithms.HmacSha256; } - byte[] rawKey = Encoding.UTF8.GetBytes(jwtSettings.IssuerSigningKey); + byte[] rawKey = Encoding.UTF8.GetBytes(options.IssuerSigningKey); tokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(rawKey); Console.WriteLine("Using symmetric encryption for issuing tokens."); } - if (!string.IsNullOrWhiteSpace(jwtSettings.NameClaimType)) + if (!string.IsNullOrWhiteSpace(options.NameClaimType)) { - tokenValidationParameters.NameClaimType = jwtSettings.NameClaimType; + tokenValidationParameters.NameClaimType = options.NameClaimType; } - if (!string.IsNullOrWhiteSpace(jwtSettings.RoleClaimType)) + if (!string.IsNullOrWhiteSpace(options.RoleClaimType)) { - tokenValidationParameters.RoleClaimType = jwtSettings.RoleClaimType; + tokenValidationParameters.RoleClaimType = options.RoleClaimType; } builder.Services .AddAuthentication(o => { - o.DefaultAuthenticateScheme = jwtSettings.Challenge; - o.DefaultChallengeScheme = jwtSettings.Challenge; - o.DefaultScheme = jwtSettings.Challenge; + o.DefaultAuthenticateScheme = options.Challenge; + o.DefaultChallengeScheme = options.Challenge; + o.DefaultScheme = options.Challenge; }) .AddJwtBearer(o => { - o.Authority = jwtSettings.Authority; - o.Audience = jwtSettings.Audience; - o.MetadataAddress = jwtSettings.MetadataAddress; - o.SaveToken = jwtSettings.SaveToken; - o.RefreshOnIssuerKeyNotFound = jwtSettings.RefreshOnIssuerKeyNotFound; - o.RequireHttpsMetadata = jwtSettings.RequireHttpsMetadata; - o.IncludeErrorDetails = jwtSettings.IncludeErrorDetails; + o.Authority = options.Authority; + o.Audience = options.Audience; + o.MetadataAddress = options.MetadataAddress; + o.SaveToken = options.SaveToken; + o.RefreshOnIssuerKeyNotFound = options.RefreshOnIssuerKeyNotFound; + o.RequireHttpsMetadata = options.RequireHttpsMetadata; + o.IncludeErrorDetails = options.IncludeErrorDetails; o.TokenValidationParameters = tokenValidationParameters; - if (!string.IsNullOrWhiteSpace(jwtSettings.Challenge)) + if (!string.IsNullOrWhiteSpace(options.Challenge)) { - o.Challenge = jwtSettings.Challenge; + o.Challenge = options.Challenge; } optionsFactory?.Invoke(o); }); - builder.Services.AddSingleton(jwtSettings); + builder.Services.AddSingleton(options); builder.Services.AddSingleton(tokenValidationParameters); return builder; @@ -183,26 +183,25 @@ public static IGenocsBuilder AddOpenIdJwt( string sectionName = JwtOptions.Position) { - var jwtSettings = new JwtOptions(); - builder.Configuration.GetSection(sectionName).Bind(jwtSettings); + JwtOptions options = builder.Configuration.GetOptions(sectionName); - string metadataAddress = $"{jwtSettings.Issuer}{jwtSettings.MetadataAddress}"; + string metadataAddress = $"{options.Issuer}{options.MetadataAddress}"; var configurationManager = new ConfigurationManager(metadataAddress, new OpenIdConnectConfigurationRetriever()); builder.Services .AddAuthentication(o => { - o.DefaultAuthenticateScheme = jwtSettings.Challenge; - o.DefaultChallengeScheme = jwtSettings.Challenge; - o.DefaultScheme = jwtSettings.Challenge; + o.DefaultAuthenticateScheme = options.Challenge; + o.DefaultChallengeScheme = options.Challenge; + o.DefaultScheme = options.Challenge; }) .AddJwtBearer(o => { - o.IncludeErrorDetails = jwtSettings.IncludeErrorDetails; - o.RefreshOnIssuerKeyNotFound = jwtSettings.RefreshOnIssuerKeyNotFound; + o.IncludeErrorDetails = options.IncludeErrorDetails; + o.RefreshOnIssuerKeyNotFound = options.RefreshOnIssuerKeyNotFound; o.MetadataAddress = metadataAddress; o.ConfigurationManager = configurationManager; - o.Audience = jwtSettings.Audience; + o.Audience = options.Audience; }); return builder; @@ -225,15 +224,14 @@ public static IGenocsBuilder AddPrivateKeyJwt( sectionName = JwtOptions.Position; } - var jwtSettings = new JwtOptions(); - builder.Configuration.GetSection(sectionName).Bind(jwtSettings); + JwtOptions options = builder.Configuration.GetOptions(sectionName); - if (string.IsNullOrWhiteSpace(jwtSettings.IssuerSigningKey)) + if (string.IsNullOrWhiteSpace(options.IssuerSigningKey)) { throw new InvalidOperationException("Issuer signing key is missing."); } - SecurityKey signingKey = SecurityKeyBuilder.CreateRsaSecurityKey(jwtSettings.IssuerSigningKey); + SecurityKey signingKey = SecurityKeyBuilder.CreateRsaSecurityKey(options.IssuerSigningKey); builder.Services .AddAuthentication(o => @@ -242,17 +240,17 @@ public static IGenocsBuilder AddPrivateKeyJwt( }) .AddJwtBearer(o => { - o.SaveToken = jwtSettings.SaveToken; - o.RequireHttpsMetadata = jwtSettings.RequireHttpsMetadata; + o.SaveToken = options.SaveToken; + o.RequireHttpsMetadata = options.RequireHttpsMetadata; o.TokenValidationParameters = new TokenValidationParameters() { IssuerSigningKey = signingKey, - ValidateAudience = jwtSettings.ValidateAudience, - ValidAudience = jwtSettings.ValidAudience, - ValidateIssuer = jwtSettings.ValidateIssuer, - ValidIssuer = jwtSettings.ValidIssuer, - ValidateLifetime = jwtSettings.ValidateLifetime, - ValidateIssuerSigningKey = jwtSettings.ValidateIssuerSigningKey + ValidateAudience = options.ValidateAudience, + ValidAudience = options.ValidAudience, + ValidateIssuer = options.ValidateIssuer, + ValidIssuer = options.ValidIssuer, + ValidateLifetime = options.ValidateLifetime, + ValidateIssuerSigningKey = options.ValidateIssuerSigningKey }; }); diff --git a/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs b/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs similarity index 87% rename from src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs rename to src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs index 4a73893e..57e3d955 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.Core.Demo.WebApi.Options; -public class ExternalServiceSettings +public class ExternalServiceOptions { public const string Position = "ExternalService"; diff --git a/src/Genocs.Core.Demo.WebApi/Options/RabbitMQSettings.cs b/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs similarity index 92% rename from src/Genocs.Core.Demo.WebApi/Options/RabbitMQSettings.cs rename to src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs index 0afe6136..92bc8656 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/RabbitMQSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.Core.Demo.WebApi.Options; -public class RabbitMQSettings +public class RabbitMQOptions { public const string Position = "RabbitMQ"; diff --git a/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs b/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs similarity index 92% rename from src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs rename to src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs index 08d05a8a..51ef9d67 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.Core.Demo.WebApi.Options; -public class SecretSettings +public class SecretOptions { /// /// Default section name. diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs index 44726b15..9aaea49b 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs @@ -7,9 +7,9 @@ namespace Genocs.Core.Demo.WebApi.Controllers; [Route("")] public class HomeController : ControllerBase { - public readonly SecretSettings _secretSettings; + public readonly SecretOptions _secretSettings; - public HomeController(SecretSettings secretSettings) + public HomeController(SecretOptions secretSettings) { _secretSettings = secretSettings ?? throw new ArgumentNullException(nameof(secretSettings)); } diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs index 0cdf5260..b73a2daf 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs @@ -26,8 +26,7 @@ public static IGenocsBuilder AddApplicationServices(this IGenocsBuilder builder) builder.AddHttpClient(); // Add the External Service settings - var settings = new ExternalServiceSettings(); - builder.Configuration.GetSection(ExternalServiceSettings.Position).Bind(settings); + ExternalServiceOptions settings = builder.Configuration.GetOptions(ExternalServiceOptions.Position); builder.Services.AddSingleton(settings); // Add the External Service http Client diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs index ef682b8b..3d7ed6ad 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using Genocs.Core.Demo.WebApi.Options; +using Genocs.Core.Builders; +using Genocs.Core.Demo.WebApi.Options; using Genocs.ServiceBusAzure.Options; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; @@ -50,10 +51,9 @@ public static IServiceCollection AddAzureServiceBusQueue(this IServiceCollection public static IServiceCollection AddCustomMassTransit(this IServiceCollection services, IConfiguration configuration) { - var rabbitMQSettings = new RabbitMQSettings(); - configuration.GetSection(RabbitMQSettings.Position).Bind(rabbitMQSettings); + RabbitMQOptions options = configuration.GetOptions(RabbitMQOptions.Position); - services.AddSingleton(rabbitMQSettings); + services.AddSingleton(options); services.AddMassTransit(x => { @@ -63,11 +63,11 @@ public static IServiceCollection AddCustomMassTransit(this IServiceCollection se { cfg.ConfigureEndpoints(context); //cfg.UseHealthCheck(context); - cfg.Host(rabbitMQSettings.HostName, rabbitMQSettings.VirtualHost, + cfg.Host(options.HostName, options.VirtualHost, h => { - h.Username(rabbitMQSettings.UserName); - h.Password(rabbitMQSettings.Password); + h.Username(options.UserName); + h.Password(options.Password); } ); }); diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs index 1a9beaa0..f789d41a 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs @@ -14,7 +14,7 @@ public class ExternalServiceClient : IExternalServiceClient private readonly IHttpClient _client; private readonly string _url; private readonly IHasher _hasher; - private readonly ExternalServiceSettings _externalServiceSettings; + private readonly ExternalServiceOptions _externalServiceSettings; /// /// The standard constructor. @@ -27,7 +27,7 @@ public ExternalServiceClient( IHttpClient client, IHasher hasher, HttpClientOptions httpClientSettings, - ExternalServiceSettings externalServiceSettings) + ExternalServiceOptions externalServiceSettings) { _client = client ?? throw new ArgumentNullException(nameof(client)); _hasher = hasher ?? throw new ArgumentNullException(nameof(hasher)); diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index 648f8938..6a0b01a7 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -46,10 +46,9 @@ services.AddHealthChecks(); -services.Configure(builder.Configuration.GetSection(SecretSettings.Position)); +services.Configure(builder.Configuration.GetSection(SecretOptions.Position)); -var settings = new SecretSettings(); -builder.Configuration.GetSection(SecretSettings.Position).Bind(settings); +SecretOptions settings = builder.Configuration.GetOptions(SecretOptions.Position); services.AddSingleton(settings); services.Configure(options => diff --git a/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs index fec77e24..3f1f6cc9 100644 --- a/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs +++ b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs @@ -20,9 +20,9 @@ public class ConsulOptions public IDictionary? Meta { get; set; } public bool EnableTagOverride { get; set; } public bool SkipLocalhostDockerDnsReplace { get; set; } - public ConnectSettings? Connect { get; set; } + public ConnectOptions? Connect { get; set; } - public class ConnectSettings + public class ConnectOptions { public bool Enabled { get; set; } } diff --git a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs index a13a67a5..481db53f 100644 --- a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs +++ b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs @@ -5,27 +5,27 @@ namespace Genocs.Discovery.Consul.MessageHandlers; internal sealed class ConsulServiceDiscoveryMessageHandler : DelegatingHandler { private readonly IConsulServicesRegistry _servicesRegistry; - private readonly ConsulOptions _settings; + private readonly ConsulOptions _options; private readonly string? _serviceName; private readonly bool? _overrideRequestUri; public ConsulServiceDiscoveryMessageHandler( IConsulServicesRegistry servicesRegistry, - ConsulOptions settings, + ConsulOptions options, string? serviceName = null, bool? overrideRequestUri = null) { _servicesRegistry = servicesRegistry; - _settings = settings; + _options = options; _serviceName = serviceName; _overrideRequestUri = overrideRequestUri; - if (!settings.Enabled) + if (!options.Enabled) { return; } - if (string.IsNullOrWhiteSpace(settings.Url)) + if (string.IsNullOrWhiteSpace(options.Url)) { throw new InvalidOperationException("Consul URL was not provided."); } @@ -55,7 +55,7 @@ private async Task SendAsync( Uri uri, CancellationToken cancellationToken) { - if (!_settings.Enabled) + if (!_options.Enabled) { return await base.SendAsync(request, cancellationToken); } @@ -73,7 +73,7 @@ private async Task GetRequestUriAsync( var service = await _servicesRegistry.GetAsync(serviceName) ?? throw new ConsulServiceNotFoundException($"Consul service: '{serviceName}' was not found.", serviceName); - if (!_settings.SkipLocalhostDockerDnsReplace) + if (!_options.SkipLocalhostDockerDnsReplace) { service.Address = service.Address.Replace("docker.for.mac.localhost", "localhost") .Replace("docker.for.win.localhost", "localhost") diff --git a/src/Genocs.HTTP/Configurations/HttpClientOptions.cs b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs index 213dbb69..04a267f7 100644 --- a/src/Genocs.HTTP/Configurations/HttpClientOptions.cs +++ b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs @@ -20,12 +20,12 @@ public class HttpClientOptions /// It defines the list of services to be registered. /// public IDictionary? Services { get; set; } - public RequestMaskingSettings? RequestMasking { get; set; } + public RequestMaskingOptions? RequestMasking { get; set; } public bool RemoveCharsetFromContentType { get; set; } public string? CorrelationContextHeader { get; set; } public string? CorrelationIdHeader { get; set; } - public class RequestMaskingSettings + public class RequestMaskingOptions { public bool Enabled { get; set; } public IEnumerable? UrlParts { get; set; } diff --git a/src/Genocs.Logging/Extensions.cs b/src/Genocs.Logging/Extensions.cs index 0f9b7fd6..5ba6181a 100644 --- a/src/Genocs.Logging/Extensions.cs +++ b/src/Genocs.Logging/Extensions.cs @@ -52,38 +52,38 @@ public static IEndpointConventionBuilder MapLogLevelHandler( => builder.MapPost(endpointRoute, LevelSwitch); private static void MapOptions( - LoggerOptions loggerSettings, - AppOptions appSettings, + LoggerOptions loggerOptions, + AppOptions appOptions, LoggerConfiguration loggerConfiguration, string environmentName) { - LoggingLevelSwitch.MinimumLevel = GetLogEventLevel(loggerSettings.Level); + LoggingLevelSwitch.MinimumLevel = GetLogEventLevel(loggerOptions.Level); loggerConfiguration.Enrich.FromLogContext() .MinimumLevel.ControlledBy(LoggingLevelSwitch) .Enrich.WithProperty("Environment", environmentName) - .Enrich.WithProperty("Application", appSettings.Service) - .Enrich.WithProperty("Instance", appSettings.Instance) - .Enrich.WithProperty("Version", appSettings.Version); + .Enrich.WithProperty("Application", appOptions.Service) + .Enrich.WithProperty("Instance", appOptions.Instance) + .Enrich.WithProperty("Version", appOptions.Version); - foreach (var (key, value) in loggerSettings.Tags ?? new Dictionary()) + foreach (var (key, value) in loggerOptions.Tags ?? new Dictionary()) { loggerConfiguration.Enrich.WithProperty(key, value); } - foreach (var (key, value) in loggerSettings.MinimumLevelOverrides ?? new Dictionary()) + foreach (var (key, value) in loggerOptions.MinimumLevelOverrides ?? new Dictionary()) { var logLevel = GetLogEventLevel(value); loggerConfiguration.MinimumLevel.Override(key, logLevel); } - loggerSettings.ExcludePaths?.ToList().ForEach(p => loggerConfiguration.Filter + loggerOptions.ExcludePaths?.ToList().ForEach(p => loggerConfiguration.Filter .ByExcluding(Matching.WithProperty("RequestPath", n => n.EndsWith(p)))); - loggerSettings.ExcludeProperties?.ToList().ForEach(p => loggerConfiguration.Filter + loggerOptions.ExcludeProperties?.ToList().ForEach(p => loggerConfiguration.Filter .ByExcluding(Matching.WithProperty(p))); - Configure(loggerConfiguration, loggerSettings); + Configure(loggerConfiguration, loggerOptions); } private static void Configure(LoggerConfiguration loggerConfiguration, LoggerOptions options) @@ -203,7 +203,7 @@ private static async Task LevelSwitch(HttpContext context) return; } - var level = context.Request.Query["level"].ToString(); + string level = context.Request.Query["level"].ToString(); if (string.IsNullOrEmpty(level)) { diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs index 291ef5f6..2c5212bd 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs @@ -1,5 +1,5 @@ +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Messages; -using Genocs.MessageBrokers.Outbox.Options; using Genocs.Persistence.MongoDb.Repositories; using Genocs.Persistence.MongoDb.Repositories.Mentor; using Microsoft.Extensions.Logging; @@ -31,7 +31,7 @@ internal sealed class MongoMessageOutbox : IMessageOutbox, IMessageOutboxAccesso public MongoMessageOutbox(IMongoSessionFactory sessionFactory, IMongoRepository inboxRepository, IMongoRepository outboxRepository, - OutboxSettings options, ILogger logger) + OutboxOptions options, ILogger logger) { _sessionFactory = sessionFactory; _inboxRepository = inboxRepository; diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs index 05d67b59..2fd0ea9d 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs @@ -1,6 +1,6 @@ using Genocs.Common.Types; +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Messages; -using Genocs.MessageBrokers.Outbox.Options; using MongoDB.Driver; namespace Genocs.MessageBrokers.Outbox.MongoDB.Internals; @@ -8,9 +8,9 @@ namespace Genocs.MessageBrokers.Outbox.MongoDB.Internals; internal sealed class MongoOutboxInitializer : IInitializer { private readonly IMongoDatabase _database; - private readonly OutboxSettings _options; + private readonly OutboxOptions _options; - public MongoOutboxInitializer(IMongoDatabase database, OutboxSettings options) + public MongoOutboxInitializer(IMongoDatabase database, OutboxOptions options) { _database = database; _options = options; diff --git a/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs b/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxOptions.cs similarity index 79% rename from src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs rename to src/Genocs.MessageBrokers.Outbox/Configurations/OutboxOptions.cs index f26273a7..da6aaec7 100644 --- a/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs +++ b/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxOptions.cs @@ -1,6 +1,6 @@ -namespace Genocs.MessageBrokers.Outbox.Options; +namespace Genocs.MessageBrokers.Outbox.Configurations; -public class OutboxSettings +public class OutboxOptions { public bool Enabled { get; set; } public int Expiry { get; set; } diff --git a/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs b/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs index 18aeb4dc..c5db113f 100644 --- a/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs +++ b/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs @@ -1,14 +1,14 @@ using Genocs.Core.Builders; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.MessageBrokers.Outbox.Configurators; internal sealed class MessageOutboxConfigurator : IMessageOutboxConfigurator { public IGenocsBuilder Builder { get; } - public OutboxSettings Options { get; } + public OutboxOptions Options { get; } - public MessageOutboxConfigurator(IGenocsBuilder builder, OutboxSettings options) + public MessageOutboxConfigurator(IGenocsBuilder builder, OutboxOptions options) { Builder = builder; Options = options; diff --git a/src/Genocs.MessageBrokers.Outbox/Extensions.cs b/src/Genocs.MessageBrokers.Outbox/Extensions.cs index ce2d06c4..2a966f11 100644 --- a/src/Genocs.MessageBrokers.Outbox/Extensions.cs +++ b/src/Genocs.MessageBrokers.Outbox/Extensions.cs @@ -1,6 +1,6 @@ using Genocs.Core.Builders; +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Configurators; -using Genocs.MessageBrokers.Outbox.Options; using Genocs.MessageBrokers.Outbox.Outbox; using Genocs.MessageBrokers.Outbox.Processors; using Microsoft.Extensions.DependencyInjection; @@ -27,7 +27,7 @@ public static IGenocsBuilder AddMessageOutbox( return builder; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); var configurator = new MessageOutboxConfigurator(builder, options); diff --git a/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs b/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs index dfd18932..ddf94a6f 100644 --- a/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs +++ b/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs @@ -1,10 +1,10 @@ using Genocs.Core.Builders; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.MessageBrokers.Outbox; public interface IMessageOutboxConfigurator { IGenocsBuilder Builder { get; } - OutboxSettings Options { get; } + OutboxOptions Options { get; } } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs index 316b435f..82624406 100644 --- a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs @@ -1,5 +1,5 @@ +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Messages; -using Genocs.MessageBrokers.Outbox.Options; using Microsoft.Extensions.Logging; using System.Collections.Concurrent; @@ -14,7 +14,7 @@ internal sealed class InMemoryMessageOutbox : IMessageOutbox, IMessageOutboxAcce private readonly ILogger _logger; private readonly int _expiry; - public InMemoryMessageOutbox(OutboxSettings options, ILogger logger) + public InMemoryMessageOutbox(OutboxOptions options, ILogger logger) { _logger = logger; _expiry = options.Expiry; diff --git a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs index 67f5b005..a9799d06 100644 --- a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs +++ b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs @@ -1,4 +1,4 @@ -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -10,13 +10,13 @@ internal sealed class OutboxProcessor : IHostedService { private readonly IServiceProvider _serviceProvider; private readonly IBusPublisher _publisher; - private readonly OutboxSettings _options; + private readonly OutboxOptions _options; private readonly ILogger _logger; private readonly TimeSpan _interval; private readonly OutboxType _type; private Timer _timer; - public OutboxProcessor(IServiceProvider serviceProvider, IBusPublisher publisher, OutboxSettings options, + public OutboxProcessor(IServiceProvider serviceProvider, IBusPublisher publisher, OutboxOptions options, ILogger logger) { if (options.Enabled && options.IntervalMilliseconds <= 0) diff --git a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs index 3c0bb4b0..b789eee7 100644 --- a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs +++ b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs @@ -2,58 +2,58 @@ namespace Genocs.Metrics.AppMetrics.Builders; -internal sealed class MetricsOptionsBuilder : IMetricsSettingsBuilder +internal sealed class MetricsOptionsBuilder : IMetricsOptionsBuilder { - private readonly MetricsSettings _options = new(); + private readonly MetricsOptions _options = new(); - public IMetricsSettingsBuilder Enable(bool enabled) + public IMetricsOptionsBuilder Enable(bool enabled) { _options.Enabled = enabled; return this; } - public IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled) + public IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled) { _options.InfluxEnabled = influxEnabled; return this; } - public IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled) + public IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled) { _options.PrometheusEnabled = prometheusEnabled; return this; } - public IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter) + public IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter) { _options.PrometheusFormatter = prometheusFormatter; return this; } - public IMetricsSettingsBuilder WithInfluxUrl(string influxUrl) + public IMetricsOptionsBuilder WithInfluxUrl(string influxUrl) { _options.InfluxUrl = influxUrl; return this; } - public IMetricsSettingsBuilder WithDatabase(string database) + public IMetricsOptionsBuilder WithDatabase(string database) { _options.Database = database; return this; } - public IMetricsSettingsBuilder WithInterval(int interval) + public IMetricsOptionsBuilder WithInterval(int interval) { _options.Interval = interval; return this; } - public IMetricsSettingsBuilder WithTags(IDictionary tags) + public IMetricsOptionsBuilder WithTags(IDictionary tags) { _options.Tags = tags; return this; } - public MetricsSettings Build() + public MetricsOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs new file mode 100644 index 00000000..750b1d4b --- /dev/null +++ b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs @@ -0,0 +1,14 @@ +namespace Genocs.Metrics.AppMetrics.Configurations; + +public interface IMetricsOptionsBuilder +{ + IMetricsOptionsBuilder Enable(bool enabled); + IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled); + IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled); + IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter); + IMetricsOptionsBuilder WithInfluxUrl(string influxUrl); + IMetricsOptionsBuilder WithDatabase(string database); + IMetricsOptionsBuilder WithInterval(int interval); + IMetricsOptionsBuilder WithTags(IDictionary tags); + MetricsOptions Build(); +} \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs deleted file mode 100644 index e9964080..00000000 --- a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Genocs.Metrics.AppMetrics.Configurations; - -public interface IMetricsSettingsBuilder -{ - IMetricsSettingsBuilder Enable(bool enabled); - IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled); - IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled); - IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter); - IMetricsSettingsBuilder WithInfluxUrl(string influxUrl); - IMetricsSettingsBuilder WithDatabase(string database); - IMetricsSettingsBuilder WithInterval(int interval); - IMetricsSettingsBuilder WithTags(IDictionary tags); - MetricsSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsOptions.cs similarity index 97% rename from src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs rename to src/Genocs.Metrics/AppMetrics/Configurations/MetricsOptions.cs index 1a3f226f..14cf9e07 100644 --- a/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs +++ b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsOptions.cs @@ -3,7 +3,7 @@ namespace Genocs.Metrics.AppMetrics.Configurations; /// /// The MetricsSettings class. /// -public class MetricsSettings +public class MetricsOptions { /// /// Default section name. diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index 54f939f6..94e769c3 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -40,7 +40,7 @@ public static IGenocsBuilder AddMetrics( appSectionName = AppOptions.Position; } - var metricsOptions = builder.GetOptions(metricsSectionName); + var metricsOptions = builder.GetOptions(metricsSectionName); var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); @@ -49,7 +49,7 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - Func buildOptions, + Func buildOptions, string appSectionName = AppSectionName) { if (string.IsNullOrWhiteSpace(appSectionName)) @@ -66,7 +66,7 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's and IIS ServerOptions AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - MetricsSettings metricsSettings, + Configurations.MetricsOptions metricsSettings, AppOptions appSettings) { builder.Services.AddSingleton(metricsSettings); @@ -148,10 +148,10 @@ public static IGenocsBuilder AddMetrics( public static IApplicationBuilder UseMetrics(this IApplicationBuilder app) { - MetricsOptions options; + App.Metrics.MetricsOptions options; using (var scope = app.ApplicationServices.CreateScope()) { - options = scope.ServiceProvider.GetRequiredService(); + options = scope.ServiceProvider.GetRequiredService(); } return !options.Enabled @@ -161,7 +161,7 @@ public static IApplicationBuilder UseMetrics(this IApplicationBuilder app) .UseMetricsAllMiddleware(); } - private static MetricsWebHostOptions GetMetricsWebHostOptions(MetricsSettings metricsOptions) + private static MetricsWebHostOptions GetMetricsWebHostOptions(Configurations.MetricsOptions metricsOptions) { var options = new MetricsWebHostOptions(); diff --git a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs index 5d5f3e36..e1bf0465 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs @@ -15,7 +15,8 @@ namespace Genocs.Secrets.AzureKeyVault; public static class Extensions { /// - /// UseVault. + /// This method is used to add the Azure Key Vault to the Host builder. + /// You can use the Azure Key Vault to store and manage application secrets. /// /// The builder. /// The section name. @@ -51,8 +52,7 @@ public static IWebHostBuilder UseAzureKeyVault( string sectionName = AzureKeyVaultSettings.Position) => builder.ConfigureAppConfiguration((ctx, cfg) => { - var settings = new AzureKeyVaultSettings(); - ctx.Configuration.GetSection(sectionName).Bind(settings); + AzureKeyVaultSettings settings = ctx.Configuration.GetOptions(sectionName); if (!settings.Enabled) { return; @@ -69,8 +69,7 @@ public static IWebHostBuilder UseAzureKeyVault( public static WebApplicationBuilder UseAzureKeyVault(this WebApplicationBuilder builder) { - var settings = new AzureKeyVaultSettings(); - builder.Configuration.GetSection(AzureKeyVaultSettings.Position).Bind(settings); + AzureKeyVaultSettings settings = builder.Configuration.GetOptions(AzureKeyVaultSettings.Position); if (!settings.Enabled) { return builder; diff --git a/src/Genocs.Secrets.Vault/Options/VaultSettings.cs b/src/Genocs.Secrets.Vault/Configurations/VaultOptions.cs similarity index 84% rename from src/Genocs.Secrets.Vault/Options/VaultSettings.cs rename to src/Genocs.Secrets.Vault/Configurations/VaultOptions.cs index 9d0bf271..f2775730 100644 --- a/src/Genocs.Secrets.Vault/Options/VaultSettings.cs +++ b/src/Genocs.Secrets.Vault/Configurations/VaultOptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.Secrets.Vault.Options; +namespace Genocs.Secrets.Vault.Configurations; /// /// The vault Setting definition. /// -public class VaultSettings +public class VaultOptions { public bool Enabled { get; set; } public string? Url { get; set; } @@ -14,11 +14,11 @@ public class VaultSettings public string? Password { get; set; } public bool RevokeLeaseOnShutdown { get; set; } public int RenewalsInterval { get; set; } - public KeyValueSettings Kv { get; set; } - public PkiSettings Pki { get; set; } - public IDictionary Lease { get; set; } + public KeyValueOptions Kv { get; set; } + public PkiOptions Pki { get; set; } + public IDictionary Lease { get; set; } - public class KeyValueSettings + public class KeyValueOptions { public bool Enabled { get; set; } public int EngineVersion { get; set; } = 2; @@ -27,7 +27,7 @@ public class KeyValueSettings public int? Version { get; set; } } - public class LeaseSettings + public class LeaseOptions { public bool Enabled { get; set; } public string? Type { get; set; } @@ -37,7 +37,7 @@ public class LeaseSettings public IDictionary Templates { get; set; } } - public class PkiSettings + public class PkiOptions { public bool Enabled { get; set; } public string RoleName { get; set; } diff --git a/src/Genocs.Secrets.Vault/Extensions.cs b/src/Genocs.Secrets.Vault/Extensions.cs index 914de108..166aa19e 100644 --- a/src/Genocs.Secrets.Vault/Extensions.cs +++ b/src/Genocs.Secrets.Vault/Extensions.cs @@ -1,6 +1,6 @@ using Genocs.Core.Builders; +using Genocs.Secrets.Vault.Configurations; using Genocs.Secrets.Vault.Internals; -using Genocs.Secrets.Vault.Options; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Memory; @@ -39,7 +39,7 @@ public static IHostBuilder UseVault( .ConfigureAppConfiguration((ctx, cfg) => { // TODO Test - VaultSettings options = ctx.Configuration.GetOptions(sectionName); + VaultOptions options = ctx.Configuration.GetOptions(sectionName); if (!options.Enabled) { return; @@ -49,7 +49,7 @@ public static IHostBuilder UseVault( }); /// - /// UseVault + /// UseVault. /// /// /// @@ -63,8 +63,7 @@ public static IWebHostBuilder UseVault( .ConfigureAppConfiguration((ctx, cfg) => { // TODO Test - var options = new VaultSettings(); - ctx.Configuration.GetSection(sectionName).Bind(options); + VaultOptions options = ctx.Configuration.GetOptions(sectionName); if (!options.Enabled) { return; @@ -86,8 +85,7 @@ private static IServiceCollection AddVault(this IServiceCollection services, str configuration = serviceProvider.GetRequiredService(); } - var options = new VaultSettings(); - configuration.GetSection(sectionName).Bind(options); + VaultOptions options = configuration.GetOptions(sectionName); if (!options.Enabled) { return services; @@ -114,13 +112,13 @@ private static IServiceCollection AddVault(this IServiceCollection services, str return services; } - private static void VerifyOptions(VaultSettings options) + private static void VerifyOptions(VaultOptions options) { if (options.Kv is null) { if (!string.IsNullOrWhiteSpace(options.Key)) { - options.Kv = new VaultSettings.KeyValueSettings + options.Kv = new VaultOptions.KeyValueOptions { Enabled = options.Enabled, Path = options.Key @@ -143,7 +141,7 @@ private static void VerifyOptions(VaultSettings options) private static async Task AddVaultAsync( this IConfigurationBuilder builder, - VaultSettings options, + VaultOptions options, string? keyValuePath) { VerifyOptions(options); @@ -194,7 +192,7 @@ private static async Task AddVaultAsync( private static Task InitLeaseAsync( string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) => options.Type.ToLowerInvariant() switch { @@ -209,7 +207,7 @@ private static Task InitLeaseAsync( private static async Task SetActiveDirectorySecretsAsync( string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.ActiveDirectory; @@ -225,7 +223,7 @@ private static async Task SetActiveDirectorySecretsAsync( } private static async Task SetAzureSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Azure; @@ -240,7 +238,7 @@ private static async Task SetAzureSecretsAsync(string key, IVaultClient client, } private static async Task SetConsulSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Consul; @@ -254,7 +252,7 @@ private static async Task SetConsulSecretsAsync(string key, IVaultClient client, } private static async Task SetDatabaseSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Database; @@ -268,7 +266,7 @@ private static async Task SetDatabaseSecretsAsync(string key, IVaultClient clien }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static async Task SetPkiSecretsAsync(IVaultClient client, VaultSettings options) + private static async Task SetPkiSecretsAsync(IVaultClient client, VaultOptions options) { var issuer = new CertificatesIssuer(client, options); var certificate = await issuer.IssueAsync(); @@ -276,7 +274,7 @@ private static async Task SetPkiSecretsAsync(IVaultClient client, VaultSettings } private static async Task SetRabbitMqSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.RabbitMQ; @@ -290,7 +288,7 @@ private static async Task SetRabbitMqSecretsAsync(string key, IVaultClient clien }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static void SetSecrets(string key, VaultSettings.LeaseSettings options, + private static void SetSecrets(string key, VaultOptions.LeaseOptions options, IDictionary configuration, string name, Func<(object, Dictionary, string, int, bool)> lease) { @@ -301,7 +299,7 @@ private static void SetSecrets(string key, VaultSettings.LeaseSettings options, LeaseService.Set(key, leaseData); } - private static (IVaultClient client, VaultClientSettings settings) GetClientAndSettings(VaultSettings options) + private static (IVaultClient client, VaultClientSettings settings) GetClientAndSettings(VaultOptions options) { var settings = new VaultClientSettings(options.Url, GetAuthMethod(options)); var client = new VaultClient(settings); @@ -309,7 +307,7 @@ private static (IVaultClient client, VaultClientSettings settings) GetClientAndS return (client, settings); } - private static void SetTemplates(string key, VaultSettings.LeaseSettings lease, + private static void SetTemplates(string key, VaultOptions.LeaseOptions lease, IDictionary configuration, IDictionary values) { if (lease.Templates is null || !lease.Templates.Any()) @@ -331,7 +329,7 @@ private static void SetTemplates(string key, VaultSettings.LeaseSettings lease, } } - private static IAuthMethodInfo GetAuthMethod(VaultSettings options) + private static IAuthMethodInfo GetAuthMethod(VaultOptions options) => options.AuthType?.ToLowerInvariant() switch { "token" => new TokenAuthMethodInfo(options.Token), diff --git a/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs b/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs index ef83211d..24235366 100644 --- a/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs +++ b/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs @@ -1,7 +1,7 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; -using Genocs.Secrets.Vault.Options; +using Genocs.Secrets.Vault.Configurations; using VaultSharp; using VaultSharp.V1.SecretsEngines; using VaultSharp.V1.SecretsEngines.PKI; @@ -11,12 +11,12 @@ namespace Genocs.Secrets.Vault.Internals; internal sealed class CertificatesIssuer : ICertificatesIssuer { private readonly IVaultClient _client; - private readonly VaultSettings.PkiSettings _options; + private readonly VaultOptions.PkiOptions _options; private readonly CertificateFormat _certificateFormat; private readonly PrivateKeyFormat _privateKeyFormat; private readonly string _mountPoint; - public CertificatesIssuer(IVaultClient client, VaultSettings options) + public CertificatesIssuer(IVaultClient client, VaultOptions options) { _client = client; _options = options.Pki; diff --git a/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs b/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs index a6d268f1..e65c9c12 100644 --- a/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs +++ b/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs @@ -1,5 +1,5 @@ using System.Text.Json; -using Genocs.Secrets.Vault.Options; +using Genocs.Secrets.Vault.Configurations; using VaultSharp; namespace Genocs.Secrets.Vault.Internals; @@ -7,9 +7,9 @@ namespace Genocs.Secrets.Vault.Internals; internal sealed class KeyValueSecrets : IKeyValueSecrets { private readonly IVaultClient _client; - private readonly VaultSettings _options; + private readonly VaultOptions _options; - public KeyValueSecrets(IVaultClient client, VaultSettings options) + public KeyValueSecrets(IVaultClient client, VaultOptions options) { _client = client; _options = options; diff --git a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs index 94023818..25857843 100644 --- a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs +++ b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs @@ -1,4 +1,4 @@ -using Genocs.Secrets.Vault.Options; +using Genocs.Secrets.Vault.Configurations; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using VaultSharp; @@ -11,7 +11,7 @@ internal sealed class VaultHostedService : BackgroundService private readonly ILeaseService _leaseService; private readonly ICertificatesIssuer _certificatesIssuer; private readonly ICertificatesService _certificatesService; - private readonly VaultSettings _options; + private readonly VaultOptions _options; private readonly ILogger _logger; private readonly int _interval; @@ -20,7 +20,7 @@ public VaultHostedService( ILeaseService leaseService, ICertificatesIssuer certificatesIssuer, ICertificatesService certificatesService, - VaultSettings options, + VaultOptions options, ILogger logger) { _client = client; diff --git a/src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs b/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs similarity index 57% rename from src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs rename to src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs index 113498cc..f2614b7e 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs @@ -1,11 +1,11 @@ -namespace Genocs.APIGateway.Options; +namespace Genocs.APIGateway.Configurations; -internal class MessagingSettings +internal class MessagingOptions { public bool Enabled { get; set; } - public IEnumerable? Endpoints { get; set; } + public IEnumerable? Endpoints { get; set; } - internal class EndpointSettings + internal class EndpointOptions { public string? Method { get; set; } public string? Path { get; set; } diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs index 5575cb06..d9665a2b 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs @@ -1,4 +1,4 @@ -using Genocs.APIGateway.Options; +using Genocs.APIGateway.Configurations; using Genocs.MessageBrokers.RabbitMQ; using Genocs.MessageBrokers.RabbitMQ.Conventions; using Microsoft.Extensions.Options; @@ -16,7 +16,7 @@ internal class MessagingMiddleware : IMiddleware private readonly ITracer _tracer; private readonly ICorrelationContextBuilder _correlationContextBuilder; private readonly CorrelationIdFactory _correlationIdFactory; - private readonly IDictionary> _endpoints; + private readonly IDictionary> _endpoints; public MessagingMiddleware( IRabbitMQClient rabbitMQClient, @@ -24,7 +24,7 @@ public MessagingMiddleware( ITracer tracer, ICorrelationContextBuilder correlationContextBuilder, CorrelationIdFactory correlationIdFactory, - IOptions messagingOptions) + IOptions messagingOptions) { if (messagingOptions is null) { @@ -39,7 +39,7 @@ public MessagingMiddleware( _endpoints = messagingOptions.Value.Endpoints?.Any() is true ? messagingOptions.Value.Endpoints.GroupBy(e => e.Method.ToUpperInvariant()) .ToDictionary(e => e.Key, e => e.ToList()) - : new Dictionary>(); + : new Dictionary>(); } public async Task InvokeAsync(HttpContext context, RequestDelegate next) diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index 2653d378..1e7addfb 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -1,5 +1,5 @@ +using Genocs.APIGateway.Configurations; using Genocs.APIGateway.Framework; -using Genocs.APIGateway.Options; using Genocs.Auth; using Genocs.Common.Configurations; using Genocs.Core.Builders; @@ -32,7 +32,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.Configure(Configuration.GetSection("messaging")); + services.Configure(Configuration.GetSection("messaging")); services.AddReverseProxy() .LoadFromConfig(Configuration.GetSection("ReverseProxy")); services.AddSingleton(); diff --git a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs index 27216af2..5401d00c 100644 --- a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs +++ b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs @@ -2,7 +2,7 @@ using Genocs.Core.CQRS.Commands; using Genocs.MessageBrokers; using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.Identities.Application.Decorators; @@ -16,7 +16,7 @@ internal sealed class OutboxCommandHandlerDecorator : ICommandHandler< private readonly bool _enabled; public OutboxCommandHandlerDecorator(ICommandHandler handler, IMessageOutbox outbox, - OutboxSettings outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) + OutboxOptions outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) { _handler = handler; _outbox = outbox; diff --git a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs index 1c3ef1dd..0bad3e59 100644 --- a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs +++ b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs @@ -2,7 +2,7 @@ using Genocs.Core.CQRS.Events; using Genocs.MessageBrokers; using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.Identities.Application.Decorators; @@ -16,7 +16,7 @@ internal sealed class OutboxEventHandlerDecorator : IEventHandler handler, IMessageOutbox outbox, - OutboxSettings outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) + OutboxOptions outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) { _handler = handler; _outbox = outbox; diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs index 802e1de3..4530716a 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs @@ -2,7 +2,7 @@ using Genocs.HTTP.Configurations; using Genocs.Orders.WebApi.DTO; using Genocs.Secrets.Vault; -using Genocs.Secrets.Vault.Options; +using Genocs.Secrets.Vault.Configurations; using Genocs.WebApi.Security.Configurations; namespace Genocs.Orders.WebApi.Services; @@ -27,7 +27,7 @@ public ProductServiceClient( IHttpClient client, ICertificatesService certificatesService, HttpClientOptions httpClientOptions, - VaultSettings vaultOptions, + VaultOptions vaultOptions, SecurityOptions securityOptions) { _client = client ?? throw new ArgumentNullException(nameof(client)); diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs similarity index 66% rename from src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs rename to src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs index 1b1572fa..6dc84226 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.SignalR.WebApi.Options; +namespace Genocs.SignalR.WebApi.Configurations; /// /// The signalR Settings definition. /// -public class SignalRSettings +public class SignalROptions { public string? Backplane { get; set; } public string? Hub { get; set; } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs index 4339e3f3..4a8d6756 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Core.Builders; -using Genocs.SignalR.WebApi.Options; +using Genocs.SignalR.WebApi.Configurations; namespace Genocs.SignalR.WebApi.Framework; @@ -10,7 +10,7 @@ public static string ToUserGroup(this Guid userId) public static IGenocsBuilder AddSignalR(this IGenocsBuilder builder) { - var options = builder.Configuration.GetOptions("signalr"); + var options = builder.Configuration.GetOptions("signalr"); if (options is not null) { @@ -22,7 +22,7 @@ public static IGenocsBuilder AddSignalR(this IGenocsBuilder builder) public static IGenocsBuilder UseSignalR(this IGenocsBuilder builder) { - var options = builder.GetOptions("signalr"); + var options = builder.GetOptions("signalr"); if (options is not null) { From 3b27e463fa91d72fe87473c7d6918114896433cd Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Thu, 4 Jul 2024 12:03:28 +0200 Subject: [PATCH 054/104] Add verification service client and models - Introduced `Genocs.Core.Demo.WebApi.Options.VerificationServiceOptions` for API key configuration. - Added `IVerificationServiceClient` interface and `VerificationServiceClient` class in `Genocs.Core.Demo.WebApi.Infrastructure.Services` for user verification. - Implemented models `VerificationApiRequest`, `VerificationApiResponse`, and `PersonDetailsRequest` for request/response handling. - `VerificationServiceClient` handles HTTP communication with external verification service, including request serialization, header setting, and response deserialization. - Added error handling in `VerificationServiceClient` constructor for parameter validation and URL verification. - Configured dependency injection for `VerificationServiceClient` and its configurations. - Utilized `Newtonsoft.Json` for JSON serialization and deserialization. - Abstracted HTTP communication through `IHttpClient` to facilitate testing and decouple from concrete HTTP client library. --- .../VerificationServiceOptions.cs | 8 +++ .../IVerificationServiceClient.Models.cs | 66 +++++++++++++++++++ .../Services/IVerificationServiceClient.cs | 15 +++++ .../Services/VerificationServiceClient.cs | 65 ++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs diff --git a/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs b/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs new file mode 100644 index 00000000..2f847694 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs @@ -0,0 +1,8 @@ +namespace Genocs.Core.Demo.WebApi.Options; + +public class VerificationServiceOptions +{ + public const string Position = "VerificationService"; + + public string ApiKey { get; set; } = default!; +} diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs new file mode 100644 index 00000000..221a71f2 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs @@ -0,0 +1,66 @@ +using Newtonsoft.Json; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The Internal User verification request. +/// +public class VerificationApiRequest +{ + [JsonProperty("type")] + public string? Type { get; set; } + + [JsonProperty("joinedDate")] + public string? JoinedDate { get; set; } + + [JsonProperty("email")] + public string? Email { get; set; } + + [JsonProperty("personDetails")] + public PersonDetailsRequest? Details { get; set; } +} + +public class PersonDetailsRequest +{ + [JsonProperty("firstName")] + public string? FirstName { get; set; } + + [JsonProperty("lastName")] + public string? LastName { get; set; } + + [JsonProperty("dob")] + public string? DateOfBirth { get; set; } + + [JsonProperty("gender")] + public string? Gender { get; set; } + + [JsonProperty("nationality")] + public string? Nationality { get; set; } +} + +/// +/// The internal User verification response. +/// +public class VerificationApiResponse +{ + [JsonProperty("id")] + public string? Id { get; set; } + + [JsonProperty("createdAt")] + public string? CreatedAt { get; set; } + + [JsonProperty("updatedAt")] + public string? UpdatedAt { get; set; } + + [JsonProperty("type")] + public string? Type { get; set; } + + [JsonProperty("joinedDate")] + public string? JoinedDate { get; set; } + + [JsonProperty("email")] + public string? Email { get; set; } + + [JsonProperty("personDetails")] + public PersonDetailsRequest? Details { get; set; } +} \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs new file mode 100644 index 00000000..7129c59f --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs @@ -0,0 +1,15 @@ +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The External WebApi client definition. +/// This API client is used to verify the user. +/// +public interface IVerificationServiceClient +{ + /// + /// Send a request To verify the user. + /// + /// The request with the user data. + /// The user verification response. + Task VerifyAsync(VerificationApiRequest request); +} diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs new file mode 100644 index 00000000..e9840a86 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs @@ -0,0 +1,65 @@ +using Genocs.Core.Demo.WebApi.Options; +using Genocs.HTTP; +using Genocs.HTTP.Configurations; +using Newtonsoft.Json; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The Verification WebApi client implementation. +/// +public class VerificationServiceClient : IVerificationServiceClient +{ + private readonly IHttpClient _client; + private readonly string _url; + private readonly VerificationServiceOptions _externalServiceSettings; + + /// + /// The standard constructor. + /// + /// The http client. + /// The http client settings. + /// The security settings. + public VerificationServiceClient( + IHttpClient client, + HttpClientOptions httpClientSettings, + VerificationServiceOptions externalServiceSettings) + { + _client = client ?? throw new ArgumentNullException(nameof(client)); + _externalServiceSettings = externalServiceSettings ?? throw new ArgumentNullException(nameof(externalServiceSettings)); + + if (httpClientSettings is null) + { + throw new ArgumentNullException(nameof(httpClientSettings)); + } + + string? url = httpClientSettings?.Services?["user_verifier"]; + + if (string.IsNullOrWhiteSpace(url)) + { + throw new Exception("user_verifier http client settings cannot be null"); + } + + _url = url; + } + + private void SetHeaders() + { + _client.SetHeaders(h => h.TryAddWithoutValidation("Authorization", _externalServiceSettings.ApiKey)); + } + + /// + /// The method to verify the user. + /// + /// The verification api request. + /// The response. + public async Task VerifyAsync(VerificationApiRequest request) + { + SetHeaders(); + string serializedRequest = JsonConvert.SerializeObject(request); + using (var content = new StringContent(serializedRequest, System.Text.Encoding.UTF8, "application/json")) + { + return await _client.PostAsync($"{_url}/clients", request); + } + } +} \ No newline at end of file From 504fc40ee05a1ed6bc838a5b08195cb285feb8c1 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 7 Jul 2024 10:59:35 +0200 Subject: [PATCH 055/104] Refactor configs and update docs across projects - Standardized namespace changes from `Options` to `Configurations` for clarity. - Enhanced README_NUGET.md for better NuGet package documentation. - Introduced and updated settings classes for logging, security, Swagger, and more. - Added and refined configuration builders for services like Jaeger, Redis, and Azure Key Vault. - Removed obsolete classes and settings to streamline configuration management. - Adopted nullable reference types for improved code robustness. - Updated GitHub Actions to support CI on both main and develop branches. - Enhanced project files for .NET 8 compatibility and incremental build optimizations. - Simplified logging setup with `StaticLogger.EnsureInitialized()`. - Refactored and enhanced settings for JWT, external services, and service discovery. - General cleanup, including removal of unused using directives and minor code adjustments. --- .github/workflows/build_and_test.yml | 4 +- Directory.Build.props | 19 +- containers/infrastructure-bare.yml | 2 - containers/infrastructure-elk.yml | 2 - containers/infrastructure-ml.yml | 2 - containers/infrastructure-monitoring.yml | 2 - containers/infrastructure-scaling.yml | 2 - containers/infrastructure-security.yml | 2 - containers/infrastructure-sqlserver.yml | 2 - demo-docker-compose.yml | 2 - .../AccessTokenValidatorMiddleware.cs | 2 +- src/Genocs.Auth/Builders/JwtOptionsBuilder.cs | 2 +- .../JwtSettings.cs | 6 +- src/Genocs.Auth/Extensions.cs | 5 +- src/Genocs.Auth/Genocs.Auth.csproj | 4 +- src/Genocs.Auth/Handlers/JwtHandler.cs | 2 +- src/Genocs.Auth/IJwtOptionsBuilder.cs | 2 +- .../{README.md => README_NUGET.md} | 2 +- .../Services/InMemoryAccessTokenService.cs | 2 +- .../AppSettings.cs | 2 +- src/Genocs.Common/Genocs.Common.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../Genocs.Core.Demo.WebApi.csproj | 1 + .../Extensions/BuilderExtensions.cs | 15 +- .../Extensions/ServiceCollectionExtensions.cs | 2 +- .../Services/ExternalServiceClient.cs | 9 +- .../Options/ExternalServiceSettings.cs | 24 +- src/Genocs.Core.Demo.WebApi/Program.cs | 9 +- src/Genocs.Core.Demo.Worker/Program.cs | 2 +- src/Genocs.Core/Builders/Extensions.cs | 2 +- src/Genocs.Core/Genocs.Core.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 ...onsBuilder.cs => ConsulSettingsBuilder.cs} | 22 +- .../ConsulSettings.cs | 2 +- .../Configurations/IConsulSettingsBuilder.cs | 15 + src/Genocs.Discovery.Consul/Extensions.cs | 8 +- .../Genocs.Discovery.Consul.csproj | 4 +- .../Http/ConsulHttpClient.cs | 2 +- .../ConsulServiceDiscoveryMessageHandler.cs | 2 +- .../Options/IConsulOptionsBuilder.cs | 15 - .../{README.md => README_NUGET.md} | 0 .../RestEaseSettings.cs | 0 src/Genocs.HTTP.RestEase/Extensions.cs | 10 +- .../Genocs.HTTP.RestEase.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../HttpClientSettings.cs | 12 +- src/Genocs.HTTP/Extensions.cs | 2 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 4 +- src/Genocs.HTTP/GenocsHttpClient.cs | 26 +- src/Genocs.HTTP/GenocsHttpLoggingFilter.cs | 2 +- .../GenocsLoggingScopeHttpMessageHandler.cs | 12 +- .../{README.md => README_NUGET.md} | 0 .../Builders/FabioOptionsBuilder.cs | 50 --- .../Builders/FabioSettingsBuilder.cs | 50 +++ .../FabioSettings.cs | 2 +- .../IFabioSettingsBuilder.cs} | 26 +- src/Genocs.LoadBalancing.Fabio/Extensions.cs | 12 +- .../Genocs.LoadBalancing.Fabio.csproj | 4 +- .../Http/FabioHttpClient.cs | 10 +- .../MessageHandlers/FabioMessageHandler.cs | 19 +- .../{README.md => README_NUGET.md} | 0 .../AzureSettings.cs | 2 +- .../ConsoleSettings.cs | 2 +- .../ElkSettings.cs | 2 +- .../LocalFileSettings.cs | 2 +- .../LoggerSettings.cs | 2 +- .../LokiSettings.cs | 2 +- .../MongoSettings.cs | 2 +- .../SeqSettings.cs | 2 +- src/Genocs.Logging/Extensions.cs | 20 +- src/Genocs.Logging/Genocs.Logging.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 src/Genocs.Logging/Startup.cs | 29 ++ ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 4 +- .../Internals/MongoMessageOutbox.cs | 2 +- .../Internals/MongoOutboxInitializer.cs | 2 +- .../{README.md => README_NUGET.md} | 0 .../OutboxSettings.cs | 2 +- .../MessageOutboxConfigurator.cs | 2 +- .../Extensions.cs | 2 +- .../Genocs.MessageBrokers.Outbox.csproj | 4 +- .../IMessageOutboxConfigurator.cs | 2 +- .../Outbox/InMemoryMessageOutbox.cs | 2 +- .../Processors/OutboxProcessor.cs | 2 +- .../{README.md => README_NUGET.md} | 0 .../Genocs.MessageBrokers.RabbitMQ.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../Genocs.MessageBrokers.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 ...nsBuilder.cs => MetricsSettingsBuilder.cs} | 20 +- .../Configurations/IMetricsSettingsBuilder.cs | 14 + .../MetricsSettings.cs | 4 +- src/Genocs.Metrics/AppMetrics/Extensions.cs | 8 +- .../AppMetrics/IMetricsOptionsBuilder.cs | 16 - src/Genocs.Metrics/Genocs.Metrics.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../Genocs.Monitoring.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../EncryptionUnitTest.cs | 5 - .../Builders/MongoDbOptionsBuilder.cs | 2 +- .../MongoDbEncryptionSettings.cs | 69 ++++ .../MongoDbSettings.cs | 2 +- .../Encryptions/AzureInitializer.cs | 39 +- .../Extensions/MongoDbExtensions.cs | 2 +- .../Genocs.Persistence.MongoDb.csproj | 4 +- .../IMongoDatabaseProvider.cs | 3 +- .../Initializers/MongoDbInitializer.cs | 2 +- .../MongoDatabaseProvider.cs | 4 +- .../Options/MongoDbEncryptionSettings.cs | 70 ---- .../{README.md => README_NUGET.md} | 0 .../Repositories/IMongoDbOptionsBuilder.cs | 2 +- ...ionsBuilder.cs => RedisSettingsBuilder.cs} | 8 +- .../Configurations/IRedisSettingsBuilder.cs | 8 + .../RedisSettings.cs | 2 +- src/Genocs.Persistence.Redis/Extensions.cs | 12 +- .../Genocs.Persistence.Redis.csproj | 4 +- .../IRedisOptionsBuilder.cs | 10 - .../{README.md => README_NUGET.md} | 0 .../DynamicQuery/TreeTraverseUnitTests.cs | 6 - .../Genocs.QueryBuilder.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../AzureKeyVaultSettings.cs | 2 +- .../Extensions.cs | 7 +- .../Genocs.Secrets.AzureKeyVault.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../VaultSettings.cs | 2 +- src/Genocs.Secrets.Vault/Extensions.cs | 2 +- .../Genocs.Secrets.Vault.csproj | 4 +- .../Internals/CertificatesIssuer.cs | 2 +- .../Internals/KeyValueSecrets.cs | 2 +- .../Internals/VaultHostedService.cs | 22 +- .../{README.md => README_NUGET.md} | 0 src/Genocs.Security/Genocs.Security.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../AzureServiceBusQueueSettings.cs | 15 + .../AzureServiceBusTopicSettings.cs | 17 + .../Genocs.ServiceBusAzure.csproj | 4 +- .../Options/AzureServiceBusQueueSettings.cs | 16 - .../Options/AzureServiceBusTopicSettings.cs | 18 - .../Queues/AzureServiceBusQueue.cs | 6 +- .../Interfaces/IAzureServiceBusQueue.cs | 7 +- .../{README.md => README_NUGET.md} | 0 .../Topics/AzureServiceBusTopic.cs | 371 +++++++++--------- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 src/Genocs.Tracing/Extensions.cs | 6 +- src/Genocs.Tracing/Genocs.Tracing.csproj | 4 +- .../Jaeger/Builders/JaegerOptionsBuilder.cs | 2 +- .../IJaegerOptionsBuilder.cs | 2 +- .../JaegerSettings.cs | 6 +- src/Genocs.Tracing/Jaeger/Extensions.cs | 2 +- .../{README.md => README_NUGET.md} | 0 .../Genocs.WebApi.CQRS.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../CertificateMiddleware.cs | 1 + .../SecuritySettings.cs | 2 +- src/Genocs.WebApi.Security/Extensions.cs | 1 + .../Genocs.WebApi.Security.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../Docs/Builders/SwaggerOptionsBuilder.cs | 6 +- .../ISwaggerOptionsBuilder.cs | 4 +- .../SwaggerSettings.cs} | 4 +- src/Genocs.WebApi.Swagger/Docs/Extensions.cs | 7 +- src/Genocs.WebApi.Swagger/Extensions.cs | 3 +- .../Genocs.WebApi.Swagger.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../Configurations/WebApiOptions.cs | 27 ++ .../WebApiSettings.cs | 4 +- src/Genocs.WebApi/EndpointsBuilder.cs | 6 +- src/Genocs.WebApi/Extensions.cs | 9 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 4 +- .../{README.md => README_NUGET.md} | 0 .../Framework/CorrelationContextBuilder.cs | 4 +- .../api-gateway/Genocs.APIGateway/Startup.cs | 2 +- .../CorrelationIdFactory.cs | 25 +- .../OutboxCommandHandlerDecorator.cs | 2 +- .../Decorators/OutboxEventHandlerDecorator.cs | 2 +- .../Domain/Entities/User.cs | 13 +- .../Extensions.cs | 2 +- .../Genocs.Identities.WebApi/Program.cs | 9 +- .../orders/Genocs.Orders.WebApi/Program.cs | 9 +- .../Services/ProductServiceClient.cs | 6 +- .../Genocs.Products.WebApi/Domain/Product.cs | 3 +- .../Genocs.Products.WebApi/Program.cs | 9 +- .../signalr/Genocs.SignalR.WebApi/Program.cs | 9 +- 185 files changed, 833 insertions(+), 767 deletions(-) rename src/Genocs.Auth/{Options => Configurations}/JwtSettings.cs (94%) rename src/Genocs.Auth/{README.md => README_NUGET.md} (96%) rename src/Genocs.Common/{Options => Configurations}/AppSettings.cs (96%) rename src/Genocs.Common/{README.md => README_NUGET.md} (100%) rename src/Genocs.Core/{README.md => README_NUGET.md} (100%) rename src/Genocs.Discovery.Consul/Builders/{ConsulOptionsBuilder.cs => ConsulSettingsBuilder.cs} (53%) rename src/Genocs.Discovery.Consul/{Options => Configurations}/ConsulSettings.cs (93%) create mode 100644 src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs delete mode 100644 src/Genocs.Discovery.Consul/Options/IConsulOptionsBuilder.cs rename src/Genocs.Discovery.Consul/{README.md => README_NUGET.md} (100%) rename src/Genocs.HTTP.RestEase/{Options => Configurations}/RestEaseSettings.cs (100%) rename src/Genocs.HTTP.RestEase/{README.md => README_NUGET.md} (100%) rename src/Genocs.HTTP/{Options => Configurations}/HttpClientSettings.cs (69%) rename src/Genocs.HTTP/{README.md => README_NUGET.md} (100%) delete mode 100644 src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs create mode 100644 src/Genocs.LoadBalancing.Fabio/Builders/FabioSettingsBuilder.cs rename src/Genocs.LoadBalancing.Fabio/{Options => Configurations}/FabioSettings.cs (91%) rename src/Genocs.LoadBalancing.Fabio/{IFabioOptionsBuilder.cs => Configurations/IFabioSettingsBuilder.cs} (52%) rename src/Genocs.LoadBalancing.Fabio/{README.md => README_NUGET.md} (100%) rename src/Genocs.Logging/{Options => Configurations}/AzureSettings.cs (91%) rename src/Genocs.Logging/{Options => Configurations}/ConsoleSettings.cs (85%) rename src/Genocs.Logging/{Options => Configurations}/ElkSettings.cs (93%) rename src/Genocs.Logging/{Options => Configurations}/LocalFileSettings.cs (92%) rename src/Genocs.Logging/{Options => Configurations}/LoggerSettings.cs (96%) rename src/Genocs.Logging/{Options => Configurations}/LokiSettings.cs (97%) rename src/Genocs.Logging/{Options => Configurations}/MongoSettings.cs (85%) rename src/Genocs.Logging/{Options => Configurations}/SeqSettings.cs (77%) rename src/Genocs.Logging/{README.md => README_NUGET.md} (100%) create mode 100644 src/Genocs.Logging/Startup.cs rename src/Genocs.MessageBrokers.Outbox.MongoDB/{README.md => README_NUGET.md} (100%) rename src/Genocs.MessageBrokers.Outbox/{Options => Configurations}/OutboxSettings.cs (86%) rename src/Genocs.MessageBrokers.Outbox/{README.md => README_NUGET.md} (100%) rename src/Genocs.MessageBrokers.RabbitMQ/{README.md => README_NUGET.md} (100%) rename src/Genocs.MessageBrokers/{README.md => README_NUGET.md} (100%) rename src/Genocs.Metrics/AppMetrics/Builders/{MetricsOptionsBuilder.cs => MetricsSettingsBuilder.cs} (53%) create mode 100644 src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs rename src/Genocs.Metrics/AppMetrics/{Options => Configurations}/MetricsSettings.cs (92%) delete mode 100644 src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs rename src/Genocs.Metrics/{README.md => README_NUGET.md} (100%) rename src/Genocs.Monitoring/{README.md => README_NUGET.md} (100%) create mode 100644 src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs rename src/Genocs.Persistence.MongoDb/{Options => Configurations}/MongoDbSettings.cs (96%) delete mode 100644 src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs rename src/Genocs.Persistence.MongoDb/{README.md => README_NUGET.md} (100%) rename src/Genocs.Persistence.Redis/Builders/{RedisOptionsBuilder.cs => RedisSettingsBuilder.cs} (55%) create mode 100644 src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs rename src/Genocs.Persistence.Redis/{Options => Configurations}/RedisSettings.cs (91%) delete mode 100644 src/Genocs.Persistence.Redis/IRedisOptionsBuilder.cs rename src/Genocs.Persistence.Redis/{README.md => README_NUGET.md} (100%) rename src/Genocs.QueryBuilder/{README.md => README_NUGET.md} (100%) rename src/Genocs.Secrets.AzureKeyVault/{Options => Configurations}/AzureKeyVaultSettings.cs (90%) rename src/Genocs.Secrets.AzureKeyVault/{README.md => README_NUGET.md} (100%) rename src/Genocs.Secrets.Vault/{Options => Configurations}/VaultSettings.cs (97%) rename src/Genocs.Secrets.Vault/{README.md => README_NUGET.md} (100%) rename src/Genocs.Security/{README.md => README_NUGET.md} (100%) create mode 100644 src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueSettings.cs create mode 100644 src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicSettings.cs delete mode 100644 src/Genocs.ServiceBusAzure/Options/AzureServiceBusQueueSettings.cs delete mode 100644 src/Genocs.ServiceBusAzure/Options/AzureServiceBusTopicSettings.cs rename src/Genocs.ServiceBusAzure/{README.md => README_NUGET.md} (100%) rename src/Genocs.Tracing.Jaeger.RabbitMQ/{README.md => README_NUGET.md} (100%) rename src/Genocs.Tracing/Jaeger/{Options => Configurations}/IJaegerOptionsBuilder.cs (91%) rename src/Genocs.Tracing/Jaeger/{Options => Configurations}/JaegerSettings.cs (91%) rename src/Genocs.Tracing/{README.md => README_NUGET.md} (100%) rename src/Genocs.WebApi.CQRS/{README.md => README_NUGET.md} (100%) rename src/Genocs.WebApi.Security/{Options => Configurations}/SecuritySettings.cs (94%) rename src/Genocs.WebApi.Security/{README.md => README_NUGET.md} (100%) rename src/Genocs.WebApi.Swagger/Docs/{ => Configurations}/ISwaggerOptionsBuilder.cs (86%) rename src/Genocs.WebApi.Swagger/Docs/{SwaggerOptions.cs => Configurations/SwaggerSettings.cs} (80%) rename src/Genocs.WebApi.Swagger/{README.md => README_NUGET.md} (100%) create mode 100644 src/Genocs.WebApi/Configurations/WebApiOptions.cs rename src/Genocs.WebApi/{Options => Configurations}/WebApiSettings.cs (59%) rename src/Genocs.WebApi/{README.md => README_NUGET.md} (100%) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 5db7cfe0..536d0ea1 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -2,9 +2,9 @@ name: Build test and pack on: push: - branches: [ main ] + branches: [ main, develop ] pull_request: - branches: [ main ] + branches: [ main, develop ] jobs: build: diff --git a/Directory.Build.props b/Directory.Build.props index 984326b6..5b9ed5cc 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -22,9 +22,26 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + true + + + true + + \ No newline at end of file diff --git a/containers/infrastructure-bare.yml b/containers/infrastructure-bare.yml index ba8e929a..31e236da 100644 --- a/containers/infrastructure-bare.yml +++ b/containers/infrastructure-bare.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: rabbitmq: image: masstransit/rabbitmq diff --git a/containers/infrastructure-elk.yml b/containers/infrastructure-elk.yml index d87f8929..3d03dfe6 100644 --- a/containers/infrastructure-elk.yml +++ b/containers/infrastructure-elk.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.3.2 diff --git a/containers/infrastructure-ml.yml b/containers/infrastructure-ml.yml index eba6aa7f..e3f0e21d 100644 --- a/containers/infrastructure-ml.yml +++ b/containers/infrastructure-ml.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: image_labeling: image: heartexlabs/label-studio:latest diff --git a/containers/infrastructure-monitoring.yml b/containers/infrastructure-monitoring.yml index 6c6b3ab6..7e9bcdcf 100644 --- a/containers/infrastructure-monitoring.yml +++ b/containers/infrastructure-monitoring.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: grafana: image: grafana/grafana diff --git a/containers/infrastructure-scaling.yml b/containers/infrastructure-scaling.yml index a7247e96..99ecf424 100644 --- a/containers/infrastructure-scaling.yml +++ b/containers/infrastructure-scaling.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: consul: image: hashicorp/consul diff --git a/containers/infrastructure-security.yml b/containers/infrastructure-security.yml index 07f089bf..3ecfd2c5 100644 --- a/containers/infrastructure-security.yml +++ b/containers/infrastructure-security.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: vault: image: hashicorp/vault diff --git a/containers/infrastructure-sqlserver.yml b/containers/infrastructure-sqlserver.yml index c88354d2..be0d0e94 100644 --- a/containers/infrastructure-sqlserver.yml +++ b/containers/infrastructure-sqlserver.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: sqlserver: diff --git a/demo-docker-compose.yml b/demo-docker-compose.yml index 2cccfe6b..fb63a465 100644 --- a/demo-docker-compose.yml +++ b/demo-docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.9' - services: application.webapi: image: genocs/demo-webapi:2.0.0 diff --git a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs index bf4b93cb..74aaad37 100644 --- a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs +++ b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; using Microsoft.AspNetCore.Http; using System.Net; diff --git a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs index 9ef51792..090698db 100644 --- a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs +++ b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; namespace Genocs.Auth.Builders; diff --git a/src/Genocs.Auth/Options/JwtSettings.cs b/src/Genocs.Auth/Configurations/JwtSettings.cs similarity index 94% rename from src/Genocs.Auth/Options/JwtSettings.cs rename to src/Genocs.Auth/Configurations/JwtSettings.cs index 08dfb6de..8a0311f6 100644 --- a/src/Genocs.Auth/Options/JwtSettings.cs +++ b/src/Genocs.Auth/Configurations/JwtSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Auth.Options; +namespace Genocs.Auth.Configurations; public class JwtSettings { @@ -12,7 +12,7 @@ public class JwtSettings /// public bool Enabled { get; set; } public IEnumerable? AllowAnonymousEndpoints { get; set; } - public CertificateOptions? Certificate { get; set; } + public CertificateSettings? Certificate { get; set; } public string? Algorithm { get; set; } public string? Issuer { get; set; } public string? IssuerSigningKey { get; set; } @@ -48,7 +48,7 @@ public class JwtSettings public string? NameClaimType { get; set; } public string? RoleClaimType { get; set; } - public class CertificateOptions + public class CertificateSettings { public string? Location { get; set; } public string? RawData { get; set; } diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index 4f74c0dc..75e2ffb3 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -1,5 +1,5 @@ +using Genocs.Auth.Configurations; using Genocs.Auth.Handlers; -using Genocs.Auth.Options; using Genocs.Auth.Services; using Genocs.Core.Builders; using Genocs.Security.Services; @@ -83,7 +83,7 @@ private static IGenocsBuilder AddJwt( if (jwtSettings.Certificate is not null) { X509Certificate2? certificate = null; - string password = jwtSettings.Certificate.Password; + string? password = jwtSettings.Certificate.Password; bool hasPassword = !string.IsNullOrWhiteSpace(password); if (!string.IsNullOrWhiteSpace(jwtSettings.Certificate.Location)) { @@ -208,7 +208,6 @@ public static IGenocsBuilder AddOpenIdJwt( return builder; } - /// /// It adds the private key JWT authentication. /// diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index ce0c8e54..d90636d6 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Auth/Handlers/JwtHandler.cs b/src/Genocs.Auth/Handlers/JwtHandler.cs index f3ce917b..fe8ec6c3 100644 --- a/src/Genocs.Auth/Handlers/JwtHandler.cs +++ b/src/Genocs.Auth/Handlers/JwtHandler.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; diff --git a/src/Genocs.Auth/IJwtOptionsBuilder.cs b/src/Genocs.Auth/IJwtOptionsBuilder.cs index d3aa7cef..341a7542 100644 --- a/src/Genocs.Auth/IJwtOptionsBuilder.cs +++ b/src/Genocs.Auth/IJwtOptionsBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; namespace Genocs.Auth; diff --git a/src/Genocs.Auth/README.md b/src/Genocs.Auth/README_NUGET.md similarity index 96% rename from src/Genocs.Auth/README.md rename to src/Genocs.Auth/README_NUGET.md index 29459bfd..86096c0e 100644 --- a/src/Genocs.Auth/README.md +++ b/src/Genocs.Auth/README_NUGET.md @@ -3,7 +3,7 @@ This package contains a set of functionalities to handling authorization logic as JWT. First of all I have to say thanks to devmentors. -The libraries are built using .NET7. +The libraries are built using net8, net7, net6. ## Description diff --git a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs index 8e95a03f..07ebfce6 100644 --- a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs +++ b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs @@ -1,4 +1,4 @@ -using Genocs.Auth.Options; +using Genocs.Auth.Configurations; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Primitives; diff --git a/src/Genocs.Common/Options/AppSettings.cs b/src/Genocs.Common/Configurations/AppSettings.cs similarity index 96% rename from src/Genocs.Common/Options/AppSettings.cs rename to src/Genocs.Common/Configurations/AppSettings.cs index 3af8f1ef..70dedf7b 100644 --- a/src/Genocs.Common/Options/AppSettings.cs +++ b/src/Genocs.Common/Configurations/AppSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Common.Options; +namespace Genocs.Common.Configurations; /// /// The application settings. diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 2ab02e42..b18067f9 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Common/README.md b/src/Genocs.Common/README_NUGET.md similarity index 100% rename from src/Genocs.Common/README.md rename to src/Genocs.Common/README_NUGET.md diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 6a363384..dd2e6a27 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -40,6 +40,7 @@ + diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs index 0cdf5260..f41c1804 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs @@ -26,9 +26,18 @@ public static IGenocsBuilder AddApplicationServices(this IGenocsBuilder builder) builder.AddHttpClient(); // Add the External Service settings - var settings = new ExternalServiceSettings(); - builder.Configuration.GetSection(ExternalServiceSettings.Position).Bind(settings); - builder.Services.AddSingleton(settings); + // Option 1: In this way ExternalServiceSettings is available for dependency injection. + // var settings = new ExternalServiceSettings(); + // builder.Configuration.GetSection(ExternalServiceSettings.Position).Bind(settings); + // builder.Services.AddSingleton(settings); + + // Option 2: In this way ExternalServiceSettings is available for dependency injection. By using IOptions you can access the settings. + builder.Services.AddOptions() + .BindConfiguration(ExternalServiceSettings.Position) + .ValidateDataAnnotations() + .ValidateOnStart(); + + // builder.Services.AddSingleton, ConfigureWebApiSettings>(); // Add the External Service http Client builder.Services.AddTransient(); diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs index ef682b8b..ec7625ca 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs @@ -1,5 +1,5 @@ using Genocs.Core.Demo.WebApi.Options; -using Genocs.ServiceBusAzure.Options; +using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; using Genocs.ServiceBusAzure.Topics; diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs index 459ebd9c..0ea30e85 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs @@ -1,7 +1,8 @@ using Genocs.Core.Demo.WebApi.Options; using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.Security; +using Microsoft.Extensions.Options; using Newtonsoft.Json; namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; @@ -22,16 +23,16 @@ public class ExternalServiceClient : IExternalServiceClient /// The http client. /// The Hash service. /// The http client settings. - /// The security settings. + /// The security settings. public ExternalServiceClient( IHttpClient client, IHasher hasher, HttpClientSettings httpClientSettings, - ExternalServiceSettings externalServiceSettings) + IOptions options) { _client = client ?? throw new ArgumentNullException(nameof(client)); _hasher = hasher ?? throw new ArgumentNullException(nameof(hasher)); - _externalServiceSettings = externalServiceSettings ?? throw new ArgumentNullException(nameof(externalServiceSettings)); + _externalServiceSettings = options.Value ?? throw new ArgumentNullException(nameof(options)); if (httpClientSettings is null) { diff --git a/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs b/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs index 4a73893e..5b7386f4 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs @@ -1,10 +1,30 @@ -namespace Genocs.Core.Demo.WebApi.Options; +using System.ComponentModel.DataAnnotations; -public class ExternalServiceSettings +namespace Genocs.Core.Demo.WebApi.Options; + +public class ExternalServiceSettings : IValidatableObject { public const string Position = "ExternalService"; public string Caller { get; set; } = default!; public string Private { get; set; } = default!; public string Public { get; set; } = default!; + + public IEnumerable Validate(ValidationContext validationContext) + { + if (string.IsNullOrWhiteSpace(Caller)) + { + yield return new ValidationResult("No Caller defined in ExternalService config", new[] { nameof(Caller) }); + } + + if (string.IsNullOrWhiteSpace(Private)) + { + yield return new ValidationResult("No Private defined in ExternalService config", new[] { nameof(Private) }); + } + + if (string.IsNullOrWhiteSpace(Public)) + { + yield return new ValidationResult("No Public defined in ExternalService config", new[] { nameof(Public) }); + } + } } diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index a9436578..691a782d 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -8,17 +8,10 @@ using Genocs.Tracing; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; -using Serilog.Events; using System.Reflection; using System.Text.Json.Serialization; -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel.Override("MassTransit", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); +StaticLogger.EnsureInitialized(); var builder = WebApplication.CreateBuilder(args); diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index 03bcee15..49527388 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -11,7 +11,6 @@ using Genocs.Persistence.MongoDb.Extensions; using Genocs.Persistence.MongoDb.Repositories; using Genocs.Persistence.MongoDb.Repositories.Clean; -using Genocs.ServiceBusAzure.Options; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; using Genocs.ServiceBusAzure.Topics; @@ -21,6 +20,7 @@ using Serilog; using Serilog.Events; using System.Reflection; +using Genocs.ServiceBusAzure.Configurations; Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs index 6cd7ed22..1d951979 100644 --- a/src/Genocs.Core/Builders/Extensions.cs +++ b/src/Genocs.Core/Builders/Extensions.cs @@ -1,4 +1,4 @@ -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Common.Types; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 7613dec3..6e259383 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Updated to NET8 True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Core/README.md b/src/Genocs.Core/README_NUGET.md similarity index 100% rename from src/Genocs.Core/README.md rename to src/Genocs.Core/README_NUGET.md diff --git a/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs b/src/Genocs.Discovery.Consul/Builders/ConsulSettingsBuilder.cs similarity index 53% rename from src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs rename to src/Genocs.Discovery.Consul/Builders/ConsulSettingsBuilder.cs index 8c7e3685..23f1e1d8 100644 --- a/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs +++ b/src/Genocs.Discovery.Consul/Builders/ConsulSettingsBuilder.cs @@ -1,60 +1,60 @@ -using Genocs.Discovery.Consul.Options; +using Genocs.Discovery.Consul.Configurations; namespace Genocs.Discovery.Consul.Builders; -internal sealed class ConsulOptionsBuilder : IConsulOptionsBuilder +internal sealed class ConsulSettingsBuilder : IConsulSettingsBuilder { private readonly ConsulSettings _options = new(); - public IConsulOptionsBuilder Enable(bool enabled) + public IConsulSettingsBuilder Enable(bool enabled) { _options.Enabled = enabled; return this; } - public IConsulOptionsBuilder WithUrl(string url) + public IConsulSettingsBuilder WithUrl(string url) { _options.Url = url; return this; } - public IConsulOptionsBuilder WithService(string service) + public IConsulSettingsBuilder WithService(string service) { _options.Service = service; return this; } - public IConsulOptionsBuilder WithAddress(string address) + public IConsulSettingsBuilder WithAddress(string address) { _options.Address = address; return this; } - public IConsulOptionsBuilder WithEnabledPing(bool pingEnabled) + public IConsulSettingsBuilder WithEnabledPing(bool pingEnabled) { _options.PingEnabled = pingEnabled; return this; } - public IConsulOptionsBuilder WithPingEndpoint(string pingEndpoint) + public IConsulSettingsBuilder WithPingEndpoint(string pingEndpoint) { _options.PingEndpoint = pingEndpoint; return this; } - public IConsulOptionsBuilder WithPingInterval(string pingInterval) + public IConsulSettingsBuilder WithPingInterval(string pingInterval) { _options.PingInterval = pingInterval; return this; } - public IConsulOptionsBuilder WithRemoteAfterInterval(string remoteAfterInterval) + public IConsulSettingsBuilder WithRemoteAfterInterval(string remoteAfterInterval) { _options.RemoveAfterInterval = remoteAfterInterval; return this; } - public IConsulOptionsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace) + public IConsulSettingsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace) { _options.SkipLocalhostDockerDnsReplace = skipLocalhostDockerDnsReplace; return this; diff --git a/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs b/src/Genocs.Discovery.Consul/Configurations/ConsulSettings.cs similarity index 93% rename from src/Genocs.Discovery.Consul/Options/ConsulSettings.cs rename to src/Genocs.Discovery.Consul/Configurations/ConsulSettings.cs index d16f9642..a07ff2ef 100644 --- a/src/Genocs.Discovery.Consul/Options/ConsulSettings.cs +++ b/src/Genocs.Discovery.Consul/Configurations/ConsulSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Discovery.Consul.Options; +namespace Genocs.Discovery.Consul.Configurations; public class ConsulSettings { diff --git a/src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs b/src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs new file mode 100644 index 00000000..1288918d --- /dev/null +++ b/src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs @@ -0,0 +1,15 @@ +namespace Genocs.Discovery.Consul.Configurations; + +public interface IConsulSettingsBuilder +{ + IConsulSettingsBuilder Enable(bool enabled); + IConsulSettingsBuilder WithUrl(string url); + IConsulSettingsBuilder WithService(string service); + IConsulSettingsBuilder WithAddress(string address); + IConsulSettingsBuilder WithEnabledPing(bool pingEnabled); + IConsulSettingsBuilder WithPingEndpoint(string pingEndpoint); + IConsulSettingsBuilder WithPingInterval(string pingInterval); + IConsulSettingsBuilder WithRemoteAfterInterval(string remoteAfterInterval); + IConsulSettingsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace); + ConsulSettings Build(); +} \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/Extensions.cs b/src/Genocs.Discovery.Consul/Extensions.cs index ecebcb98..e412aa8b 100644 --- a/src/Genocs.Discovery.Consul/Extensions.cs +++ b/src/Genocs.Discovery.Consul/Extensions.cs @@ -1,12 +1,12 @@ using Genocs.Core.Builders; using Genocs.Discovery.Consul.Builders; +using Genocs.Discovery.Consul.Configurations; using Genocs.Discovery.Consul.Http; using Genocs.Discovery.Consul.MessageHandlers; using Genocs.Discovery.Consul.Models; -using Genocs.Discovery.Consul.Options; using Genocs.Discovery.Consul.Services; using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.DependencyInjection; namespace Genocs.Discovery.Consul; @@ -34,10 +34,10 @@ public static IGenocsBuilder AddConsul( public static IGenocsBuilder AddConsul( this IGenocsBuilder builder, - Func buildOptions, + Func buildOptions, HttpClientSettings httpClientOptions) { - var options = buildOptions(new ConsulOptionsBuilder()).Build(); + var options = buildOptions(new ConsulSettingsBuilder()).Build(); return builder.AddConsul(options, httpClientOptions); } diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index a488d839..a6861387 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs b/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs index 5b8691fe..ac4f97fa 100644 --- a/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs +++ b/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs @@ -1,5 +1,5 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; namespace Genocs.Discovery.Consul.Http; diff --git a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs index 162f57a7..0888cb6f 100644 --- a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs +++ b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs @@ -1,4 +1,4 @@ -using Genocs.Discovery.Consul.Options; +using Genocs.Discovery.Consul.Configurations; namespace Genocs.Discovery.Consul.MessageHandlers; diff --git a/src/Genocs.Discovery.Consul/Options/IConsulOptionsBuilder.cs b/src/Genocs.Discovery.Consul/Options/IConsulOptionsBuilder.cs deleted file mode 100644 index c4d8d850..00000000 --- a/src/Genocs.Discovery.Consul/Options/IConsulOptionsBuilder.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Genocs.Discovery.Consul.Options; - -public interface IConsulOptionsBuilder -{ - IConsulOptionsBuilder Enable(bool enabled); - IConsulOptionsBuilder WithUrl(string url); - IConsulOptionsBuilder WithService(string service); - IConsulOptionsBuilder WithAddress(string address); - IConsulOptionsBuilder WithEnabledPing(bool pingEnabled); - IConsulOptionsBuilder WithPingEndpoint(string pingEndpoint); - IConsulOptionsBuilder WithPingInterval(string pingInterval); - IConsulOptionsBuilder WithRemoteAfterInterval(string remoteAfterInterval); - IConsulOptionsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace); - ConsulSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/README.md b/src/Genocs.Discovery.Consul/README_NUGET.md similarity index 100% rename from src/Genocs.Discovery.Consul/README.md rename to src/Genocs.Discovery.Consul/README_NUGET.md diff --git a/src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs b/src/Genocs.HTTP.RestEase/Configurations/RestEaseSettings.cs similarity index 100% rename from src/Genocs.HTTP.RestEase/Options/RestEaseSettings.cs rename to src/Genocs.HTTP.RestEase/Configurations/RestEaseSettings.cs diff --git a/src/Genocs.HTTP.RestEase/Extensions.cs b/src/Genocs.HTTP.RestEase/Extensions.cs index 70020773..430ebc98 100644 --- a/src/Genocs.HTTP.RestEase/Extensions.cs +++ b/src/Genocs.HTTP.RestEase/Extensions.cs @@ -1,12 +1,12 @@ using Genocs.Core.Builders; using Genocs.Discovery.Consul; -using Genocs.Discovery.Consul.Options; -using Genocs.HTTP.Options; +using Genocs.Discovery.Consul.Configurations; +using Genocs.HTTP.Configurations; using Genocs.HTTP.RestEase.Builders; using Genocs.HTTP.RestEase.Options; using Genocs.HTTP.RestEase.Serializers; using Genocs.LoadBalancing.Fabio; -using Genocs.LoadBalancing.Fabio.Options; +using Genocs.LoadBalancing.Fabio.Configurations; using Microsoft.Extensions.DependencyInjection; using RestEase; @@ -34,8 +34,8 @@ public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, st public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, Func buildOptions, - Func buildConsulOptions, - Func buildFabioOptions, + Func buildConsulOptions, + Func buildFabioOptions, HttpClientSettings httpClientOptions) where T : class { diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index d0424313..1892fb7b 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.HTTP.RestEase/README.md b/src/Genocs.HTTP.RestEase/README_NUGET.md similarity index 100% rename from src/Genocs.HTTP.RestEase/README.md rename to src/Genocs.HTTP.RestEase/README_NUGET.md diff --git a/src/Genocs.HTTP/Options/HttpClientSettings.cs b/src/Genocs.HTTP/Configurations/HttpClientSettings.cs similarity index 69% rename from src/Genocs.HTTP/Options/HttpClientSettings.cs rename to src/Genocs.HTTP/Configurations/HttpClientSettings.cs index 42fde541..ebae8708 100644 --- a/src/Genocs.HTTP/Options/HttpClientSettings.cs +++ b/src/Genocs.HTTP/Configurations/HttpClientSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.HTTP.Options; +namespace Genocs.HTTP.Configurations; /// /// The HttpClient Settings class. @@ -20,15 +20,15 @@ public class HttpClientSettings /// It defines the list of services to be registered. /// public IDictionary? Services { get; set; } - public RequestMaskingSettings RequestMasking { get; set; } + public RequestMaskingSettings? RequestMasking { get; set; } public bool RemoveCharsetFromContentType { get; set; } - public string CorrelationContextHeader { get; set; } - public string CorrelationIdHeader { get; set; } + public string? CorrelationContextHeader { get; set; } + public string? CorrelationIdHeader { get; set; } public class RequestMaskingSettings { public bool Enabled { get; set; } - public IEnumerable UrlParts { get; set; } - public string MaskTemplate { get; set; } + public IEnumerable? UrlParts { get; set; } + public string? MaskTemplate { get; set; } } } \ No newline at end of file diff --git a/src/Genocs.HTTP/Extensions.cs b/src/Genocs.HTTP/Extensions.cs index 13238b93..85387b13 100644 --- a/src/Genocs.HTTP/Extensions.cs +++ b/src/Genocs.HTTP/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Core.Builders; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Http; diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 8179ec30..7260ea03 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.HTTP/GenocsHttpClient.cs b/src/Genocs.HTTP/GenocsHttpClient.cs index c407de2a..e5fd254d 100644 --- a/src/Genocs.HTTP/GenocsHttpClient.cs +++ b/src/Genocs.HTTP/GenocsHttpClient.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Polly; using System.Net.Http.Headers; using System.Text; @@ -12,32 +12,32 @@ public class GenocsHttpClient : IHttpClient { private const string JsonContentType = "application/json"; private readonly HttpClient _client; - private readonly HttpClientSettings _options; + private readonly HttpClientSettings _settings; private readonly IHttpClientSerializer _serializer; public GenocsHttpClient( HttpClient client, - HttpClientSettings options, + HttpClientSettings settings, IHttpClientSerializer serializer, ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) { _client = client; - _options = options; + _settings = settings; _serializer = serializer; - if (!string.IsNullOrWhiteSpace(_options.CorrelationContextHeader)) + if (!string.IsNullOrWhiteSpace(_settings.CorrelationContextHeader)) { string correlationContext = correlationContextFactory.Create(); _client.DefaultRequestHeaders.TryAddWithoutValidation( - _options.CorrelationContextHeader, + _settings.CorrelationContextHeader, correlationContext); } - if (!string.IsNullOrWhiteSpace(_options.CorrelationIdHeader)) + if (!string.IsNullOrWhiteSpace(_settings.CorrelationIdHeader)) { string? correlationId = correlationIdFactory.Create(); _client.DefaultRequestHeaders.TryAddWithoutValidation( - _options.CorrelationIdHeader, + _settings.CorrelationIdHeader, correlationId); } } @@ -116,12 +116,12 @@ public Task> DeleteResultAsync(string uri, IHttpClientSerialize public Task SendAsync(HttpRequestMessage request) => Policy.Handle() - .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) + .WaitAndRetryAsync(_settings.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(() => _client.SendAsync(request)); public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null) => Policy.Handle() - .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) + .WaitAndRetryAsync(_settings.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(async () => { var response = await _client.SendAsync(request); @@ -137,7 +137,7 @@ public Task SendAsync(HttpRequestMessage request, IHttpClientSerializer? s public Task> SendResultAsync(HttpRequestMessage request, IHttpClientSerializer? serializer = null) => Policy.Handle() - .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) + .WaitAndRetryAsync(_settings.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(async () => { var response = await _client.SendAsync(request); @@ -205,7 +205,7 @@ protected virtual async Task> SendResultAsync( protected virtual Task SendAsync(string uri, Method method, HttpContent? content = null) => Policy.Handle() - .WaitAndRetryAsync(_options.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) + .WaitAndRetryAsync(_settings.Retries, r => TimeSpan.FromSeconds(Math.Pow(2, r))) .ExecuteAsync(() => { string requestUri = uri.StartsWith("http") ? uri : $"http://{uri}"; @@ -233,7 +233,7 @@ protected virtual Task GetResponseAsync(string uri, Method serializer ??= _serializer; var content = new StringContent(serializer.Serialize(data), Encoding.UTF8, JsonContentType); - if (_options.RemoveCharsetFromContentType && content.Headers.ContentType is not null) + if (_settings.RemoveCharsetFromContentType && content.Headers.ContentType is not null) { content.Headers.ContentType.CharSet = null; } diff --git a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs index 7d30997a..a4b34417 100644 --- a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs +++ b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.Http; using Microsoft.Extensions.Logging; diff --git a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs index 529f245f..b354aa41 100644 --- a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs +++ b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Microsoft.Extensions.Logging; using System.Net; @@ -10,15 +10,15 @@ internal sealed class GenocsLoggingScopeHttpMessageHandler : DelegatingHandler private readonly HashSet _maskedRequestUrlParts; private readonly string _maskTemplate; - public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientSettings options) + public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientSettings settings) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _ = options ?? throw new ArgumentNullException(nameof(options)); + _ = settings ?? throw new ArgumentNullException(nameof(settings)); _maskedRequestUrlParts = - new HashSet(options.RequestMasking?.UrlParts ?? Enumerable.Empty()); - _maskTemplate = string.IsNullOrWhiteSpace(options.RequestMasking?.MaskTemplate) + new HashSet(settings.RequestMasking?.UrlParts ?? Enumerable.Empty()); + _maskTemplate = string.IsNullOrWhiteSpace(settings.RequestMasking?.MaskTemplate) ? "*****" - : options.RequestMasking.MaskTemplate; + : settings.RequestMasking.MaskTemplate; } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/src/Genocs.HTTP/README.md b/src/Genocs.HTTP/README_NUGET.md similarity index 100% rename from src/Genocs.HTTP/README.md rename to src/Genocs.HTTP/README_NUGET.md diff --git a/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs deleted file mode 100644 index ec923b1d..00000000 --- a/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Genocs.LoadBalancing.Fabio.Options; - -namespace Genocs.LoadBalancing.Fabio.Builders; - -/// -/// The Fabio options builder -/// -public class FabioOptionsBuilder : IFabioOptionsBuilder -{ - private readonly FabioSettings _options = new(); - - /// - /// Enable or disable the Fabio load balancer - /// - /// - /// The option builder to be used for chain the build - public IFabioOptionsBuilder Enable(bool enabled) - { - _options.Enabled = enabled; - return this; - } - - /// - /// Set the Fabio url - /// - /// The url - /// The option builder to be used for chain the build - public IFabioOptionsBuilder WithUrl(string url) - { - _options.Url = url; - return this; - } - - /// - /// Set the Fabio service name - /// - /// The service name - /// The option builder to be used for chain the build - public IFabioOptionsBuilder WithService(string service) - { - _options.Service = service; - return this; - } - - /// - /// Build the Fabio options - /// - /// The Fabio options - public FabioSettings Build() => _options; -} \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Builders/FabioSettingsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Builders/FabioSettingsBuilder.cs new file mode 100644 index 00000000..a1a8db29 --- /dev/null +++ b/src/Genocs.LoadBalancing.Fabio/Builders/FabioSettingsBuilder.cs @@ -0,0 +1,50 @@ +using Genocs.LoadBalancing.Fabio.Configurations; + +namespace Genocs.LoadBalancing.Fabio.Builders; + +/// +/// The Fabio options builder. +/// +public class FabioSettingsBuilder : IFabioSettingsBuilder +{ + private readonly FabioSettings _settings = new(); + + /// + /// Enable or disable the Fabio load balancer. + /// + /// + /// The option builder to be used for chain the build. + public IFabioSettingsBuilder Enable(bool enabled) + { + _settings.Enabled = enabled; + return this; + } + + /// + /// Set the Fabio url. + /// + /// The url. + /// The option builder to be used for chain the build. + public IFabioSettingsBuilder WithUrl(string url) + { + _settings.Url = url; + return this; + } + + /// + /// Set the Fabio service name. + /// + /// The service name + /// The option builder to be used for chain the build. + public IFabioSettingsBuilder WithService(string service) + { + _settings.Service = service; + return this; + } + + /// + /// Build the Fabio options. + /// + /// The Fabio options. + public FabioSettings Build() => _settings; +} \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioSettings.cs similarity index 91% rename from src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs rename to src/Genocs.LoadBalancing.Fabio/Configurations/FabioSettings.cs index f7e6d9ab..3419e0a2 100644 --- a/src/Genocs.LoadBalancing.Fabio/Options/FabioSettings.cs +++ b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.LoadBalancing.Fabio.Options; +namespace Genocs.LoadBalancing.Fabio.Configurations; /// /// The Fabio settings. diff --git a/src/Genocs.LoadBalancing.Fabio/IFabioOptionsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioSettingsBuilder.cs similarity index 52% rename from src/Genocs.LoadBalancing.Fabio/IFabioOptionsBuilder.cs rename to src/Genocs.LoadBalancing.Fabio/Configurations/IFabioSettingsBuilder.cs index 478c1cb3..14eb9d21 100644 --- a/src/Genocs.LoadBalancing.Fabio/IFabioOptionsBuilder.cs +++ b/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioSettingsBuilder.cs @@ -1,32 +1,30 @@ -using Genocs.LoadBalancing.Fabio.Options; - -namespace Genocs.LoadBalancing.Fabio; +namespace Genocs.LoadBalancing.Fabio.Configurations; /// -/// The Fabio options builder interface definition +/// The Fabio options builder interface definition. /// -public interface IFabioOptionsBuilder +public interface IFabioSettingsBuilder { /// - /// Enable or disable the Fabio load balancer + /// Enable or disable the Fabio load balancer. /// /// - /// The option builder to be used for chain the build - IFabioOptionsBuilder Enable(bool enabled); + /// The option builder to be used for chain the build. + IFabioSettingsBuilder Enable(bool enabled); /// - /// Set the Fabio url + /// Set the Fabio url. /// - /// The url - /// The option builder to be used for chain the build - IFabioOptionsBuilder WithUrl(string url); + /// The url. + /// The option builder to be used for chain the build. + IFabioSettingsBuilder WithUrl(string url); /// /// Set the Fabio service name /// - /// The service name + /// The service name. /// The option builder to be used for chain the build - IFabioOptionsBuilder WithService(string service); + IFabioSettingsBuilder WithService(string service); /// /// Build the Fabio options diff --git a/src/Genocs.LoadBalancing.Fabio/Extensions.cs b/src/Genocs.LoadBalancing.Fabio/Extensions.cs index e0e507f9..127a3581 100644 --- a/src/Genocs.LoadBalancing.Fabio/Extensions.cs +++ b/src/Genocs.LoadBalancing.Fabio/Extensions.cs @@ -1,13 +1,13 @@ using Genocs.Core.Builders; using Genocs.Discovery.Consul; +using Genocs.Discovery.Consul.Configurations; using Genocs.Discovery.Consul.Models; -using Genocs.Discovery.Consul.Options; using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.LoadBalancing.Fabio.Builders; +using Genocs.LoadBalancing.Fabio.Configurations; using Genocs.LoadBalancing.Fabio.Http; using Genocs.LoadBalancing.Fabio.MessageHandlers; -using Genocs.LoadBalancing.Fabio.Options; using Microsoft.Extensions.DependencyInjection; namespace Genocs.LoadBalancing.Fabio; @@ -32,11 +32,11 @@ public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, string sectio } public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, - Func buildOptions, - Func buildConsulOptions, + Func buildOptions, + Func buildConsulOptions, HttpClientSettings httpClientOptions) { - var fabioOptions = buildOptions(new FabioOptionsBuilder()).Build(); + var fabioOptions = buildOptions(new FabioSettingsBuilder()).Build(); return builder.AddFabio(fabioOptions, httpClientOptions, b => b.AddConsul(buildConsulOptions, httpClientOptions)); } diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index fcb8230f..5fbe8c12 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs b/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs index cb622682..4415fef0 100644 --- a/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs +++ b/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs @@ -1,12 +1,16 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; namespace Genocs.LoadBalancing.Fabio.Http; internal sealed class FabioHttpClient : GenocsHttpClient, IFabioHttpClient { - public FabioHttpClient(HttpClient client, HttpClientSettings options, IHttpClientSerializer serializer, - ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) + public FabioHttpClient( + HttpClient client, + HttpClientSettings options, + IHttpClientSerializer serializer, + ICorrelationContextFactory correlationContextFactory, + ICorrelationIdFactory correlationIdFactory) : base(client, options, serializer, correlationContextFactory, correlationIdFactory) { } diff --git a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs index 416fb18a..f9382130 100644 --- a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs +++ b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs @@ -1,27 +1,28 @@ -using Genocs.LoadBalancing.Fabio.Options; +using Genocs.LoadBalancing.Fabio.Configurations; namespace Genocs.LoadBalancing.Fabio.MessageHandlers; internal sealed class FabioMessageHandler : DelegatingHandler { - private readonly FabioSettings _options; + private readonly FabioSettings _settings; private readonly string _servicePath; - public FabioMessageHandler(FabioSettings options, string? serviceName = null) + public FabioMessageHandler(FabioSettings settings, string? serviceName = null) { - if (string.IsNullOrWhiteSpace(options.Url)) + if (string.IsNullOrWhiteSpace(settings.Url)) { throw new InvalidOperationException("Fabio URL was not provided."); } - _options = options; + _settings = settings; _servicePath = string.IsNullOrWhiteSpace(serviceName) ? string.Empty : $"{serviceName}/"; } - protected override Task SendAsync(HttpRequestMessage request, - CancellationToken cancellationToken) + protected override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) { - if (!_options.Enabled) + if (!_settings.Enabled) { return base.SendAsync(request, cancellationToken); } @@ -32,5 +33,5 @@ protected override Task SendAsync(HttpRequestMessage reques } private Uri GetRequestUri(HttpRequestMessage request) - => new($"{_options.Url}/{_servicePath}{request.RequestUri.Host}{request.RequestUri.PathAndQuery}"); + => new($"{_settings.Url}/{_servicePath}{request.RequestUri.Host}{request.RequestUri.PathAndQuery}"); } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/README.md b/src/Genocs.LoadBalancing.Fabio/README_NUGET.md similarity index 100% rename from src/Genocs.LoadBalancing.Fabio/README.md rename to src/Genocs.LoadBalancing.Fabio/README_NUGET.md diff --git a/src/Genocs.Logging/Options/AzureSettings.cs b/src/Genocs.Logging/Configurations/AzureSettings.cs similarity index 91% rename from src/Genocs.Logging/Options/AzureSettings.cs rename to src/Genocs.Logging/Configurations/AzureSettings.cs index 387881f8..8f09c72a 100644 --- a/src/Genocs.Logging/Options/AzureSettings.cs +++ b/src/Genocs.Logging/Configurations/AzureSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Azure application insights logging settings. diff --git a/src/Genocs.Logging/Options/ConsoleSettings.cs b/src/Genocs.Logging/Configurations/ConsoleSettings.cs similarity index 85% rename from src/Genocs.Logging/Options/ConsoleSettings.cs rename to src/Genocs.Logging/Configurations/ConsoleSettings.cs index a647aa26..34953b04 100644 --- a/src/Genocs.Logging/Options/ConsoleSettings.cs +++ b/src/Genocs.Logging/Configurations/ConsoleSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Console Settings. diff --git a/src/Genocs.Logging/Options/ElkSettings.cs b/src/Genocs.Logging/Configurations/ElkSettings.cs similarity index 93% rename from src/Genocs.Logging/Options/ElkSettings.cs rename to src/Genocs.Logging/Configurations/ElkSettings.cs index b67d082d..992a13bc 100644 --- a/src/Genocs.Logging/Options/ElkSettings.cs +++ b/src/Genocs.Logging/Configurations/ElkSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Elasticsearch Settings. diff --git a/src/Genocs.Logging/Options/LocalFileSettings.cs b/src/Genocs.Logging/Configurations/LocalFileSettings.cs similarity index 92% rename from src/Genocs.Logging/Options/LocalFileSettings.cs rename to src/Genocs.Logging/Configurations/LocalFileSettings.cs index bc5d0993..05bf923c 100644 --- a/src/Genocs.Logging/Options/LocalFileSettings.cs +++ b/src/Genocs.Logging/Configurations/LocalFileSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// File settings for local file logging. diff --git a/src/Genocs.Logging/Options/LoggerSettings.cs b/src/Genocs.Logging/Configurations/LoggerSettings.cs similarity index 96% rename from src/Genocs.Logging/Options/LoggerSettings.cs rename to src/Genocs.Logging/Configurations/LoggerSettings.cs index a604ae66..3348aa22 100644 --- a/src/Genocs.Logging/Options/LoggerSettings.cs +++ b/src/Genocs.Logging/Configurations/LoggerSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// diff --git a/src/Genocs.Logging/Options/LokiSettings.cs b/src/Genocs.Logging/Configurations/LokiSettings.cs similarity index 97% rename from src/Genocs.Logging/Options/LokiSettings.cs rename to src/Genocs.Logging/Configurations/LokiSettings.cs index 9c19d209..0b189abb 100644 --- a/src/Genocs.Logging/Options/LokiSettings.cs +++ b/src/Genocs.Logging/Configurations/LokiSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// Relevant options for the Serilog Loki sink. diff --git a/src/Genocs.Logging/Options/MongoSettings.cs b/src/Genocs.Logging/Configurations/MongoSettings.cs similarity index 85% rename from src/Genocs.Logging/Options/MongoSettings.cs rename to src/Genocs.Logging/Configurations/MongoSettings.cs index a8e2e47b..6f5beb87 100644 --- a/src/Genocs.Logging/Options/MongoSettings.cs +++ b/src/Genocs.Logging/Configurations/MongoSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; /// /// MongoDb logging settings. diff --git a/src/Genocs.Logging/Options/SeqSettings.cs b/src/Genocs.Logging/Configurations/SeqSettings.cs similarity index 77% rename from src/Genocs.Logging/Options/SeqSettings.cs rename to src/Genocs.Logging/Configurations/SeqSettings.cs index 26432556..57bc042c 100644 --- a/src/Genocs.Logging/Options/SeqSettings.cs +++ b/src/Genocs.Logging/Configurations/SeqSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Logging.Options; +namespace Genocs.Logging.Configurations; public class SeqSettings { diff --git a/src/Genocs.Logging/Extensions.cs b/src/Genocs.Logging/Extensions.cs index 76fe5817..0ba7ec8c 100644 --- a/src/Genocs.Logging/Extensions.cs +++ b/src/Genocs.Logging/Extensions.cs @@ -1,6 +1,6 @@ -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; -using Genocs.Logging.Options; +using Genocs.Logging.Configurations; using Microsoft.ApplicationInsights.Extensibility; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; @@ -23,8 +23,8 @@ public static class Extensions public static IHostBuilder UseLogging( this IHostBuilder hostBuilder, Action? configure = null, - string? loggerSectionName = null, - string? appSectionName = null) + string? loggerSectionName = LoggerSettings.Position, + string? appSectionName = AppSettings.Position) => hostBuilder .ConfigureServices(services => services.AddSingleton()) .UseSerilog((context, loggerConfiguration) => @@ -167,10 +167,12 @@ private static void Configure(LoggerConfiguration loggerConfiguration, LoggerSet // azure application insights if (azureOptions.Enabled) { - loggerConfiguration.WriteTo.ApplicationInsights(new TelemetryConfiguration - { - ConnectionString = azureOptions.ConnectionString, - }, TelemetryConverter.Traces); + loggerConfiguration.WriteTo.ApplicationInsights( + new TelemetryConfiguration + { + ConnectionString = azureOptions.ConnectionString, + }, + TelemetryConverter.Traces); } } @@ -203,7 +205,7 @@ private static async Task LevelSwitch(HttpContext context) return; } - var level = context.Request.Query["level"].ToString(); + string level = context.Request.Query["level"].ToString(); if (string.IsNullOrEmpty(level)) { diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 7e4d7cea..0cb22d85 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Logging/README.md b/src/Genocs.Logging/README_NUGET.md similarity index 100% rename from src/Genocs.Logging/README.md rename to src/Genocs.Logging/README_NUGET.md diff --git a/src/Genocs.Logging/Startup.cs b/src/Genocs.Logging/Startup.cs new file mode 100644 index 00000000..d12034a6 --- /dev/null +++ b/src/Genocs.Logging/Startup.cs @@ -0,0 +1,29 @@ +using Serilog.Events; +using Serilog; + +namespace Genocs.Logging; + +/// +/// This helper function ensures that the logger is initialized. +/// +public static class StaticLogger +{ + /// + /// This helper function ensures that the logger is initialized. + /// Call this function before using the logger. + /// Generally in the Program.cs file at the beginning of the application. + /// + public static void EnsureInitialized() + { + if (Log.Logger is not Serilog.Core.Logger) + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Override("MassTransit", LogEventLevel.Information) + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateLogger(); + } + } +} diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index b35fe693..f3243e6a 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs index 291ef5f6..779c376b 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs @@ -1,5 +1,5 @@ +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Messages; -using Genocs.MessageBrokers.Outbox.Options; using Genocs.Persistence.MongoDb.Repositories; using Genocs.Persistence.MongoDb.Repositories.Mentor; using Microsoft.Extensions.Logging; diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs index 05d67b59..ff0560f9 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs @@ -1,6 +1,6 @@ using Genocs.Common.Types; +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Messages; -using Genocs.MessageBrokers.Outbox.Options; using MongoDB.Driver; namespace Genocs.MessageBrokers.Outbox.MongoDB.Internals; diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/README.md b/src/Genocs.MessageBrokers.Outbox.MongoDB/README_NUGET.md similarity index 100% rename from src/Genocs.MessageBrokers.Outbox.MongoDB/README.md rename to src/Genocs.MessageBrokers.Outbox.MongoDB/README_NUGET.md diff --git a/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs b/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxSettings.cs similarity index 86% rename from src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs rename to src/Genocs.MessageBrokers.Outbox/Configurations/OutboxSettings.cs index f26273a7..52af1f3e 100644 --- a/src/Genocs.MessageBrokers.Outbox/Options/OutboxSettings.cs +++ b/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.MessageBrokers.Outbox.Options; +namespace Genocs.MessageBrokers.Outbox.Configurations; public class OutboxSettings { diff --git a/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs b/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs index 18aeb4dc..b03c9cfa 100644 --- a/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs +++ b/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs @@ -1,5 +1,5 @@ using Genocs.Core.Builders; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.MessageBrokers.Outbox.Configurators; diff --git a/src/Genocs.MessageBrokers.Outbox/Extensions.cs b/src/Genocs.MessageBrokers.Outbox/Extensions.cs index ce2d06c4..330fe6e9 100644 --- a/src/Genocs.MessageBrokers.Outbox/Extensions.cs +++ b/src/Genocs.MessageBrokers.Outbox/Extensions.cs @@ -1,6 +1,6 @@ using Genocs.Core.Builders; +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Configurators; -using Genocs.MessageBrokers.Outbox.Options; using Genocs.MessageBrokers.Outbox.Outbox; using Genocs.MessageBrokers.Outbox.Processors; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 67133bd3..7d8cff6c 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs b/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs index dfd18932..7ddbb1e9 100644 --- a/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs +++ b/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs @@ -1,5 +1,5 @@ using Genocs.Core.Builders; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.MessageBrokers.Outbox; diff --git a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs index 316b435f..eee56670 100644 --- a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs @@ -1,5 +1,5 @@ +using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Messages; -using Genocs.MessageBrokers.Outbox.Options; using Microsoft.Extensions.Logging; using System.Collections.Concurrent; diff --git a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs index 67f5b005..9e789cc8 100644 --- a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs +++ b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs @@ -1,4 +1,4 @@ -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; diff --git a/src/Genocs.MessageBrokers.Outbox/README.md b/src/Genocs.MessageBrokers.Outbox/README_NUGET.md similarity index 100% rename from src/Genocs.MessageBrokers.Outbox/README.md rename to src/Genocs.MessageBrokers.Outbox/README_NUGET.md diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 66f4cceb..e911d229 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.MessageBrokers.RabbitMQ/README.md b/src/Genocs.MessageBrokers.RabbitMQ/README_NUGET.md similarity index 100% rename from src/Genocs.MessageBrokers.RabbitMQ/README.md rename to src/Genocs.MessageBrokers.RabbitMQ/README_NUGET.md diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 08feee1d..49ee7be5 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.MessageBrokers/README.md b/src/Genocs.MessageBrokers/README_NUGET.md similarity index 100% rename from src/Genocs.MessageBrokers/README.md rename to src/Genocs.MessageBrokers/README_NUGET.md diff --git a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs similarity index 53% rename from src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs rename to src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs index ffd23f2e..1114bfc1 100644 --- a/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs +++ b/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs @@ -1,54 +1,54 @@ -using Genocs.Metrics.AppMetrics.Options; +using Genocs.Metrics.AppMetrics.Configurations; namespace Genocs.Metrics.AppMetrics.Builders; -internal sealed class MetricsOptionsBuilder : IMetricsOptionsBuilder +internal sealed class MetricsSettingsBuilder : IMetricsSettingsBuilder { private readonly MetricsSettings _options = new(); - public IMetricsOptionsBuilder Enable(bool enabled) + public IMetricsSettingsBuilder Enable(bool enabled) { _options.Enabled = enabled; return this; } - public IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled) + public IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled) { _options.InfluxEnabled = influxEnabled; return this; } - public IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled) + public IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled) { _options.PrometheusEnabled = prometheusEnabled; return this; } - public IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter) + public IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter) { _options.PrometheusFormatter = prometheusFormatter; return this; } - public IMetricsOptionsBuilder WithInfluxUrl(string influxUrl) + public IMetricsSettingsBuilder WithInfluxUrl(string influxUrl) { _options.InfluxUrl = influxUrl; return this; } - public IMetricsOptionsBuilder WithDatabase(string database) + public IMetricsSettingsBuilder WithDatabase(string database) { _options.Database = database; return this; } - public IMetricsOptionsBuilder WithInterval(int interval) + public IMetricsSettingsBuilder WithInterval(int interval) { _options.Interval = interval; return this; } - public IMetricsOptionsBuilder WithTags(IDictionary tags) + public IMetricsSettingsBuilder WithTags(IDictionary tags) { _options.Tags = tags; return this; diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs new file mode 100644 index 00000000..e9964080 --- /dev/null +++ b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs @@ -0,0 +1,14 @@ +namespace Genocs.Metrics.AppMetrics.Configurations; + +public interface IMetricsSettingsBuilder +{ + IMetricsSettingsBuilder Enable(bool enabled); + IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled); + IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled); + IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter); + IMetricsSettingsBuilder WithInfluxUrl(string influxUrl); + IMetricsSettingsBuilder WithDatabase(string database); + IMetricsSettingsBuilder WithInterval(int interval); + IMetricsSettingsBuilder WithTags(IDictionary tags); + MetricsSettings Build(); +} \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs similarity index 92% rename from src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs rename to src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs index 19f0144c..b633b797 100644 --- a/src/Genocs.Metrics/AppMetrics/Options/MetricsSettings.cs +++ b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Metrics.AppMetrics.Options; +namespace Genocs.Metrics.AppMetrics.Configurations; /// /// The MetricsSettings class. @@ -8,7 +8,7 @@ public class MetricsSettings /// /// Default section name. /// - public const string Position = "Metrics"; + public const string Position = "metrics"; /// /// It defines whether the section is enabled or not. diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index 4829b458..61253b08 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -4,11 +4,11 @@ using App.Metrics.AspNetCore.Health.Endpoints; using App.Metrics.AspNetCore.Tracking; using App.Metrics.Formatters.Prometheus; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; using Genocs.Metrics.AppMetrics; using Genocs.Metrics.AppMetrics.Builders; -using Genocs.Metrics.AppMetrics.Options; +using Genocs.Metrics.AppMetrics.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -49,7 +49,7 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - Func buildOptions, + Func buildOptions, string appSectionName = AppSectionName) { if (string.IsNullOrWhiteSpace(appSectionName)) @@ -57,7 +57,7 @@ public static IGenocsBuilder AddMetrics( appSectionName = AppSectionName; } - var metricsOptions = buildOptions(new MetricsOptionsBuilder()).Build(); + var metricsOptions = buildOptions(new MetricsSettingsBuilder()).Build(); var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); diff --git a/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs deleted file mode 100644 index dff0200c..00000000 --- a/src/Genocs.Metrics/AppMetrics/IMetricsOptionsBuilder.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Genocs.Metrics.AppMetrics.Options; - -namespace Genocs.Metrics.AppMetrics; - -public interface IMetricsOptionsBuilder -{ - IMetricsOptionsBuilder Enable(bool enabled); - IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled); - IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled); - IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter); - IMetricsOptionsBuilder WithInfluxUrl(string influxUrl); - IMetricsOptionsBuilder WithDatabase(string database); - IMetricsOptionsBuilder WithInterval(int interval); - IMetricsOptionsBuilder WithTags(IDictionary tags); - MetricsSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 9916ef03..665a067c 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Metrics/README.md b/src/Genocs.Metrics/README_NUGET.md similarity index 100% rename from src/Genocs.Metrics/README.md rename to src/Genocs.Metrics/README_NUGET.md diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 2a945cb1..2330c2f9 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Monitoring/README.md b/src/Genocs.Monitoring/README_NUGET.md similarity index 100% rename from src/Genocs.Monitoring/README.md rename to src/Genocs.Monitoring/README_NUGET.md diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs b/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs index c799988e..abced899 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs +++ b/src/Genocs.Persistence.MongoDb.UnitTests/EncryptionUnitTest.cs @@ -1,9 +1,4 @@ -using Genocs.Persistence.MongoDb.Encryptions; -using Genocs.Persistence.MongoDb.Options; using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Options; -using Moq; -using Xunit; namespace Genocs.Persistence.MongoDb.UnitTests; diff --git a/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs b/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs index 99e3a861..385114a5 100644 --- a/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs +++ b/src/Genocs.Persistence.MongoDb/Builders/MongoDbOptionsBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; using Genocs.Persistence.MongoDb.Repositories; namespace Genocs.Persistence.MongoDb.Builders; diff --git a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs new file mode 100644 index 00000000..3124e3a3 --- /dev/null +++ b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs @@ -0,0 +1,69 @@ +namespace Genocs.Persistence.MongoDb.Configurations; + +/// +/// MongoDb encryption database Settings. +/// +public class MongoDbEncryptionSettings +{ + + /// + /// Default Section name + /// + public const string Position = "MongoDbEncryption"; + + /// + /// The Database connection string + /// + public string ConnectionString { get; set; } = default!; + + /// + /// The shared library used to encrypt + /// + public string LibPath { get; set; } = default!; + + /// + /// Azure Tenant Id + /// + public string TenantId { get; set; } = default!; + + /// + /// Azure Client Id + /// + public string ClientId { get; set; } = default!; + + /// + /// Azure Client Secret + /// + public string ClientSecret { get; set; } = default!; + + /// + /// Azure Client Secret + /// + public string KeyName { get; set; } = default!; + + /// + /// Azure Client Secret + /// + public string KeyVersion { get; set; } = default!; + + /// + /// Azure Client Secret + /// + public string KeyVaultEndpoint { get; set; } = default!; + + /// + /// Check if the MongoDbSettings object contains valid data + /// + /// MongoDbSettings object + /// return true if valid otherwise false + public static bool IsValid(MongoDbEncryptionSettings settings) + { + if (settings is null) return false; + + if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; + if (string.IsNullOrWhiteSpace(settings.LibPath)) return false; + + return true; + + } +} diff --git a/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbSettings.cs similarity index 96% rename from src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs rename to src/Genocs.Persistence.MongoDb/Configurations/MongoDbSettings.cs index 6dc46179..4d7be7be 100644 --- a/src/Genocs.Persistence.MongoDb/Options/MongoDbSettings.cs +++ b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbSettings.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace Genocs.Persistence.MongoDb.Options; +namespace Genocs.Persistence.MongoDb.Configurations; /// /// MongoDb database Settings. diff --git a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs index ed2200f7..ff2f2be8 100644 --- a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs @@ -1,4 +1,4 @@ -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; @@ -46,10 +46,12 @@ DataKeyOptions GetDataKeyOptions(List altNames) }); return dataKeyOptions; } + // end-datakeyopts // start-key-vault var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault"); + // end-key-vault // start-create-index @@ -65,13 +67,14 @@ DataKeyOptions GetDataKeyOptions(List altNames) var indexKeysDocument = builder.Ascending("keyAltNames"); var indexModel = new CreateIndexModel(indexKeysDocument, indexOptions); var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName); + // Drop the Key Vault Collection in case you created this collection // in a previous run of this application. keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName); var keyVaultCollection = keyVaultDatabase.GetCollection(keyVaultNamespace.CollectionName); keyVaultCollection.Indexes.CreateOne(indexModel); - // end-create-index + // end-create-index // start-create-dek var clientEncryptionOptions = new ClientEncryptionOptions( @@ -96,12 +99,12 @@ BsonBinaryData CreateKeyGetID(DataKeyOptions options) var dataKeyId2 = CreateKeyGetID(dataKeyOptions2); var dataKeyId3 = CreateKeyGetID(dataKeyOptions3); var dataKeyId4 = CreateKeyGetID(dataKeyOptions4); + // end-create-dek // start-create-enc-collection var encryptedCollectionNamespace = CollectionNamespace.FromFullName("medicalRecords.patients"); - var encryptedFieldsMap = new Dictionary { { @@ -112,9 +115,9 @@ BsonBinaryData CreateKeyGetID(DataKeyOptions options) { new BsonDocument { - {"keyId", dataKeyId1}, - {"path", new BsonString("patientId")}, - {"bsonType", new BsonString("int")}, + { "keyId", dataKeyId1}, + { "path", new BsonString("patientId")}, + { "bsonType", new BsonString("int")}, { "queries", new BsonDocument { @@ -124,27 +127,27 @@ BsonBinaryData CreateKeyGetID(DataKeyOptions options) }, new BsonDocument { - {"keyId", dataKeyId2}, - {"path", new BsonString("medications")}, - {"bsonType", new BsonString("array")}, + { "keyId", dataKeyId2}, + { "path", new BsonString("medications")}, + { "bsonType", new BsonString("array")}, }, new BsonDocument { - {"keyId", dataKeyId3}, - {"path", new BsonString("patientRecord.ssn")}, - {"bsonType", new BsonString("string")}, + { "keyId", dataKeyId3}, + { "path", new BsonString("patientRecord.ssn")}, + { "bsonType", new BsonString("string")}, { "queries", new BsonDocument { - {"queryType", new BsonString("equality")} + { "queryType", new BsonString("equality")} } } }, new BsonDocument { - {"keyId", dataKeyId4}, - {"path", new BsonString("patientRecord.billing")}, - {"bsonType", new BsonString("object")}, + { "keyId", dataKeyId4}, + { "path", new BsonString("patientRecord.billing")}, + { "bsonType", new BsonString("object")}, }, } } @@ -154,8 +157,8 @@ BsonBinaryData CreateKeyGetID(DataKeyOptions options) var extraOptions = new Dictionary() { - {"cryptSharedLibPath", settings.LibPath}, - }; + { "cryptSharedLibPath", settings.LibPath }, + }; var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace, diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs index d418b605..693a8339 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs @@ -1,9 +1,9 @@ using Genocs.Common.Types; using Genocs.Core.Builders; using Genocs.Persistence.MongoDb.Builders; +using Genocs.Persistence.MongoDb.Configurations; using Genocs.Persistence.MongoDb.Factories; using Genocs.Persistence.MongoDb.Initializers; -using Genocs.Persistence.MongoDb.Options; using Genocs.Persistence.MongoDb.Repositories; using Genocs.Persistence.MongoDb.Repositories.Clean; using Genocs.Persistence.MongoDb.Repositories.Mentor; diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index eb912ede..08140949 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -20,7 +20,7 @@ icon.png git mongodb aggregate architecture boilerplate repository-patterns domain-driven-design dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Moved to NET8.0 True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Persistence.MongoDb/IMongoDatabaseProvider.cs b/src/Genocs.Persistence.MongoDb/IMongoDatabaseProvider.cs index d70620a1..5781822e 100644 --- a/src/Genocs.Persistence.MongoDb/IMongoDatabaseProvider.cs +++ b/src/Genocs.Persistence.MongoDb/IMongoDatabaseProvider.cs @@ -8,11 +8,10 @@ namespace Genocs.Persistence.MongoDb; public interface IMongoDatabaseProvider { /// - /// Gets the MongoClient + /// Gets the MongoClient. /// IMongoClient MongoClient { get; } - /// /// Gets the . /// diff --git a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs index 11b4c6ad..f917c935 100644 --- a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs @@ -1,4 +1,4 @@ -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; using Genocs.Persistence.MongoDb.Repositories; using MongoDB.Driver; diff --git a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs index 412c8475..df5ae963 100644 --- a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs +++ b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs @@ -1,5 +1,5 @@ -using Genocs.Persistence.MongoDb.Encryptions; -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; +using Genocs.Persistence.MongoDb.Encryptions; using Microsoft.Extensions.Options; using MongoDB.Driver; using MongoDB.Driver.Core.Extensions.DiagnosticSources; diff --git a/src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs b/src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs deleted file mode 100644 index 35e03b2c..00000000 --- a/src/Genocs.Persistence.MongoDb/Options/MongoDbEncryptionSettings.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace Genocs.Persistence.MongoDb.Options -{ - /// - /// MongoDb encryption database Settings - /// - public class MongoDbEncryptionSettings - { - - /// - /// Default Section name - /// - public const string Position = "MongoDbEncryption"; - - /// - /// The Database connection string - /// - public string ConnectionString { get; set; } = default!; - - /// - /// The shared library used to encrypt - /// - public string LibPath { get; set; } = default!; - - /// - /// Azure Tenant Id - /// - public string TenantId { get; set; } = default!; - - /// - /// Azure Client Id - /// - public string ClientId { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string ClientSecret { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyName { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyVersion { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyVaultEndpoint { get; set; } = default!; - - /// - /// Check if the MongoDbSettings object contains valid data - /// - /// MongoDbSettings object - /// return true if valid otherwise false - public static bool IsValid(MongoDbEncryptionSettings settings) - { - if (settings is null) return false; - - if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; - if (string.IsNullOrWhiteSpace(settings.LibPath)) return false; - - return true; - - } - } -} diff --git a/src/Genocs.Persistence.MongoDb/README.md b/src/Genocs.Persistence.MongoDb/README_NUGET.md similarity index 100% rename from src/Genocs.Persistence.MongoDb/README.md rename to src/Genocs.Persistence.MongoDb/README_NUGET.md diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs index 36e91713..bcd5ce69 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.Persistence.MongoDb.Options; +using Genocs.Persistence.MongoDb.Configurations; namespace Genocs.Persistence.MongoDb.Repositories; diff --git a/src/Genocs.Persistence.Redis/Builders/RedisOptionsBuilder.cs b/src/Genocs.Persistence.Redis/Builders/RedisSettingsBuilder.cs similarity index 55% rename from src/Genocs.Persistence.Redis/Builders/RedisOptionsBuilder.cs rename to src/Genocs.Persistence.Redis/Builders/RedisSettingsBuilder.cs index bd0b4846..e2d0cbb1 100644 --- a/src/Genocs.Persistence.Redis/Builders/RedisOptionsBuilder.cs +++ b/src/Genocs.Persistence.Redis/Builders/RedisSettingsBuilder.cs @@ -1,18 +1,18 @@ -using Genocs.Persistence.Redis.Options; +using Genocs.Persistence.Redis.Configurations; namespace Genocs.Persistence.Redis.Builders; -internal sealed class RedisOptionsBuilder : IRedisOptionsBuilder +internal sealed class RedisSettingsBuilder : IRedisSettingsBuilder { private readonly RedisSettings _options = new(); - public IRedisOptionsBuilder WithConnectionString(string connectionString) + public IRedisSettingsBuilder WithConnectionString(string connectionString) { _options.ConnectionString = connectionString; return this; } - public IRedisOptionsBuilder WithInstance(string instance) + public IRedisSettingsBuilder WithInstance(string instance) { _options.Instance = instance; return this; diff --git a/src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs b/src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs new file mode 100644 index 00000000..145fac47 --- /dev/null +++ b/src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs @@ -0,0 +1,8 @@ +namespace Genocs.Persistence.Redis.Configurations; + +public interface IRedisSettingsBuilder +{ + IRedisSettingsBuilder WithConnectionString(string connectionString); + IRedisSettingsBuilder WithInstance(string instance); + RedisSettings Build(); +} \ No newline at end of file diff --git a/src/Genocs.Persistence.Redis/Options/RedisSettings.cs b/src/Genocs.Persistence.Redis/Configurations/RedisSettings.cs similarity index 91% rename from src/Genocs.Persistence.Redis/Options/RedisSettings.cs rename to src/Genocs.Persistence.Redis/Configurations/RedisSettings.cs index 87d527ef..bd1176c0 100644 --- a/src/Genocs.Persistence.Redis/Options/RedisSettings.cs +++ b/src/Genocs.Persistence.Redis/Configurations/RedisSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Persistence.Redis.Options; +namespace Genocs.Persistence.Redis.Configurations; /// /// The Redis Options diff --git a/src/Genocs.Persistence.Redis/Extensions.cs b/src/Genocs.Persistence.Redis/Extensions.cs index e75eb044..87ffed86 100644 --- a/src/Genocs.Persistence.Redis/Extensions.cs +++ b/src/Genocs.Persistence.Redis/Extensions.cs @@ -1,14 +1,13 @@ using Genocs.Core.Builders; using Genocs.Persistence.Redis.Builders; -using Genocs.Persistence.Redis.Options; +using Genocs.Persistence.Redis.Configurations; using Microsoft.Extensions.DependencyInjection; using StackExchange.Redis; namespace Genocs.Persistence.Redis; - /// -/// The redis extensions +/// The redis extensions. /// public static class Extensions { @@ -37,10 +36,11 @@ public static IGenocsBuilder AddRedis(this IGenocsBuilder builder, string sectio /// The Genocs builder /// /// - public static IGenocsBuilder AddRedis(this IGenocsBuilder builder, - Func buildOptions) + public static IGenocsBuilder AddRedis( + this IGenocsBuilder builder, + Func buildOptions) { - var options = buildOptions(new RedisOptionsBuilder()).Build(); + var options = buildOptions(new RedisSettingsBuilder()).Build(); return builder.AddRedis(options); } diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 5c0474e4..afc1dc66 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Persistence.Redis/IRedisOptionsBuilder.cs b/src/Genocs.Persistence.Redis/IRedisOptionsBuilder.cs deleted file mode 100644 index dd692c01..00000000 --- a/src/Genocs.Persistence.Redis/IRedisOptionsBuilder.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Genocs.Persistence.Redis.Options; - -namespace Genocs.Persistence.Redis; - -public interface IRedisOptionsBuilder -{ - IRedisOptionsBuilder WithConnectionString(string connectionString); - IRedisOptionsBuilder WithInstance(string instance); - RedisSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Persistence.Redis/README.md b/src/Genocs.Persistence.Redis/README_NUGET.md similarity index 100% rename from src/Genocs.Persistence.Redis/README.md rename to src/Genocs.Persistence.Redis/README_NUGET.md diff --git a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/TreeTraverseUnitTests.cs b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/TreeTraverseUnitTests.cs index b43c6ed5..d03016b0 100644 --- a/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/TreeTraverseUnitTests.cs +++ b/src/Genocs.QueryBuilder.UnitTests/DynamicQuery/TreeTraverseUnitTests.cs @@ -53,10 +53,8 @@ private async Task BuildValidTreeLevel1() c01.ChildNodes = childrenLevel1; c02.ChildNodes = childrenLevel2; - List childrenLevel0 = new List { c01, c02 }; - TreeNode root = new TreeNode() { Name = "Root", Valid = true, ChildNodes = childrenLevel0 }; return await Task.Run(() => root); @@ -86,10 +84,8 @@ private async Task BuildInvalidTreeLevel1() c01.ChildNodes = childrenLevel1; c02.ChildNodes = childrenLevel2; - List childrenLevel0 = new List { c01, c02 }; - TreeNode root = new TreeNode() { Name = "Root", Valid = true, ChildNodes = childrenLevel0 }; return await Task.Run(() => root); @@ -156,7 +152,6 @@ private async Task BuildInvalidTreeLevel3() List childrenLevel4 = new List { c17, c18 }; List childrenLevel5 = new List { c19, c20 }; - c01.ChildNodes = childrenLevel1; c02.ChildNodes = childrenLevel2; @@ -167,7 +162,6 @@ private async Task BuildInvalidTreeLevel3() List childrenLevel0 = new List { c01, c02 }; - TreeNode root = new TreeNode() { Name = "Root", Valid = true, ChildNodes = childrenLevel0 }; return await Task.Run(() => root); diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index e4064be1..c66ba978 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.QueryBuilder/README.md b/src/Genocs.QueryBuilder/README_NUGET.md similarity index 100% rename from src/Genocs.QueryBuilder/README.md rename to src/Genocs.QueryBuilder/README_NUGET.md diff --git a/src/Genocs.Secrets.AzureKeyVault/Options/AzureKeyVaultSettings.cs b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultSettings.cs similarity index 90% rename from src/Genocs.Secrets.AzureKeyVault/Options/AzureKeyVaultSettings.cs rename to src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultSettings.cs index a5de48ac..b6ae8649 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Options/AzureKeyVaultSettings.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Secrets.AzureKeyVault.Options; +namespace Genocs.Secrets.AzureKeyVault.Configurations; /// /// The vault Setting definition. diff --git a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs index 5d5f3e36..fccbe0b5 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs @@ -1,6 +1,6 @@ using Azure.Identity; using Genocs.Core.Builders; -using Genocs.Secrets.AzureKeyVault.Options; +using Genocs.Secrets.AzureKeyVault.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -26,6 +26,11 @@ public static IHostBuilder UseAzureKeyVault( => builder.ConfigureAppConfiguration((ctx, cfg) => { // TODO Test + if (string.IsNullOrWhiteSpace(sectionName)) + { + sectionName = AzureKeyVaultSettings.Position; + } + var settings = ctx.Configuration.GetOptions(sectionName); if (!settings.Enabled) { diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index 0fcc66fa..64d97c8d 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Secrets.AzureKeyVault/README.md b/src/Genocs.Secrets.AzureKeyVault/README_NUGET.md similarity index 100% rename from src/Genocs.Secrets.AzureKeyVault/README.md rename to src/Genocs.Secrets.AzureKeyVault/README_NUGET.md diff --git a/src/Genocs.Secrets.Vault/Options/VaultSettings.cs b/src/Genocs.Secrets.Vault/Configurations/VaultSettings.cs similarity index 97% rename from src/Genocs.Secrets.Vault/Options/VaultSettings.cs rename to src/Genocs.Secrets.Vault/Configurations/VaultSettings.cs index 9d0bf271..993f64e8 100644 --- a/src/Genocs.Secrets.Vault/Options/VaultSettings.cs +++ b/src/Genocs.Secrets.Vault/Configurations/VaultSettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.Secrets.Vault.Options; +namespace Genocs.Secrets.Vault.Configurations; /// /// The vault Setting definition. diff --git a/src/Genocs.Secrets.Vault/Extensions.cs b/src/Genocs.Secrets.Vault/Extensions.cs index 914de108..b3bcb999 100644 --- a/src/Genocs.Secrets.Vault/Extensions.cs +++ b/src/Genocs.Secrets.Vault/Extensions.cs @@ -1,6 +1,6 @@ using Genocs.Core.Builders; +using Genocs.Secrets.Vault.Configurations; using Genocs.Secrets.Vault.Internals; -using Genocs.Secrets.Vault.Options; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Memory; diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index db18b217..82d4c858 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs b/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs index ef83211d..94b1d643 100644 --- a/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs +++ b/src/Genocs.Secrets.Vault/Internals/CertificatesIssuer.cs @@ -1,7 +1,7 @@ +using Genocs.Secrets.Vault.Configurations; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; -using Genocs.Secrets.Vault.Options; using VaultSharp; using VaultSharp.V1.SecretsEngines; using VaultSharp.V1.SecretsEngines.PKI; diff --git a/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs b/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs index a6d268f1..49016424 100644 --- a/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs +++ b/src/Genocs.Secrets.Vault/Internals/KeyValueSecrets.cs @@ -1,5 +1,5 @@ +using Genocs.Secrets.Vault.Configurations; using System.Text.Json; -using Genocs.Secrets.Vault.Options; using VaultSharp; namespace Genocs.Secrets.Vault.Internals; diff --git a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs index 94023818..4ba695fd 100644 --- a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs +++ b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs @@ -1,4 +1,4 @@ -using Genocs.Secrets.Vault.Options; +using Genocs.Secrets.Vault.Configurations; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using VaultSharp; @@ -11,7 +11,7 @@ internal sealed class VaultHostedService : BackgroundService private readonly ILeaseService _leaseService; private readonly ICertificatesIssuer _certificatesIssuer; private readonly ICertificatesService _certificatesService; - private readonly VaultSettings _options; + private readonly VaultSettings _settings; private readonly ILogger _logger; private readonly int _interval; @@ -20,28 +20,28 @@ public VaultHostedService( ILeaseService leaseService, ICertificatesIssuer certificatesIssuer, ICertificatesService certificatesService, - VaultSettings options, + VaultSettings settings, ILogger logger) { _client = client; _leaseService = leaseService; _certificatesIssuer = certificatesIssuer; _certificatesService = certificatesService; - _options = options; + _settings = settings; _logger = logger; - _interval = _options.RenewalsInterval <= 0 ? 10 : _options.RenewalsInterval; + _interval = _settings.RenewalsInterval <= 0 ? 10 : _settings.RenewalsInterval; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { - if (!_options.Enabled) + if (!_settings.Enabled) { return; } - if ((_options.Pki is null || !_options.Pki.Enabled) && - (_options.Lease is null || _options.Lease.All(l => !l.Value.Enabled) || - !_options.Lease.Any(l => l.Value.AutoRenewal))) + if ((_settings.Pki is null || !_settings.Pki.Enabled) && + (_settings.Lease is null || _settings.Lease.All(l => !l.Value.Enabled) || + !_settings.Lease.Any(l => l.Value.AutoRenewal))) { return; } @@ -53,7 +53,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) var now = DateTime.UtcNow; var nextIterationAt = now.AddSeconds(2 * _interval); - if (_options.Pki is not null && _options.Pki.Enabled) + if (_settings.Pki is not null && _settings.Pki.Enabled) { foreach (var (role, cert) in _certificatesService.All) { @@ -86,7 +86,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) await Task.Delay(interval.Subtract(DateTime.UtcNow - now), stoppingToken); } - if (!_options.RevokeLeaseOnShutdown) + if (!_settings.RevokeLeaseOnShutdown) { return; } diff --git a/src/Genocs.Secrets.Vault/README.md b/src/Genocs.Secrets.Vault/README_NUGET.md similarity index 100% rename from src/Genocs.Secrets.Vault/README.md rename to src/Genocs.Secrets.Vault/README_NUGET.md diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 3d20591b..9885aab3 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Moved tAligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Security/README.md b/src/Genocs.Security/README_NUGET.md similarity index 100% rename from src/Genocs.Security/README.md rename to src/Genocs.Security/README_NUGET.md diff --git a/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueSettings.cs b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueSettings.cs new file mode 100644 index 00000000..c7cd6781 --- /dev/null +++ b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueSettings.cs @@ -0,0 +1,15 @@ +using Microsoft.Azure.ServiceBus; + +namespace Genocs.ServiceBusAzure.Configurations; + +public class AzureServiceBusQueueSettings +{ + public const string Position = "AzureServiceBusQueue"; + public string? ConnectionString { get; set; } + public string? QueueName { get; set; } + public int MaxConcurrentCalls { get; set; } = 20; + public int PrefetchCount { get; set; } = 100; + public ReceiveMode ReceiveMode { get; set; } = ReceiveMode.PeekLock; + public RetryPolicy RetryPolicy { get; set; } = RetryPolicy.Default; + public bool AutoComplete { get; set; } = true; +} diff --git a/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicSettings.cs b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicSettings.cs new file mode 100644 index 00000000..26a16a4b --- /dev/null +++ b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicSettings.cs @@ -0,0 +1,17 @@ +using Microsoft.Azure.ServiceBus; + +namespace Genocs.ServiceBusAzure.Configurations; + +public class AzureServiceBusTopicSettings +{ + public const string Position = "AzureServiceBusTopic"; + public string? ConnectionString { get; set; } + public string? TopicName { get; set; } + public string? SubscriptionName { get; set; } + public int MaxConcurrentCalls { get; set; } = 20; + public int PrefetchCount { get; set; } = 100; + public ReceiveMode ReceiveMode { get; set; } = ReceiveMode.PeekLock; + public RetryPolicy RetryPolicy { get; set; } = RetryPolicy.Default; + public bool AutoComplete { get; set; } = true; +} + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 9dea0d80..4229ecf7 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.ServiceBusAzure/Options/AzureServiceBusQueueSettings.cs b/src/Genocs.ServiceBusAzure/Options/AzureServiceBusQueueSettings.cs deleted file mode 100644 index 815ad5ce..00000000 --- a/src/Genocs.ServiceBusAzure/Options/AzureServiceBusQueueSettings.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.Azure.ServiceBus; - -namespace Genocs.ServiceBusAzure.Options -{ - public class AzureServiceBusQueueSettings - { - public const string Position = "AzureServiceBusQueue"; - public string ConnectionString { get; set; } - public string QueueName { get; set; } - public int MaxConcurrentCalls { get; set; } = 20; - public int PrefetchCount { get; set; } = 100; - public ReceiveMode ReceiveMode { get; set; } = ReceiveMode.PeekLock; - public RetryPolicy RetryPolicy { get; set; } = RetryPolicy.Default; - public bool AutoComplete { get; set; } = true; - } -} diff --git a/src/Genocs.ServiceBusAzure/Options/AzureServiceBusTopicSettings.cs b/src/Genocs.ServiceBusAzure/Options/AzureServiceBusTopicSettings.cs deleted file mode 100644 index f66d4283..00000000 --- a/src/Genocs.ServiceBusAzure/Options/AzureServiceBusTopicSettings.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Azure.ServiceBus; - -namespace Genocs.ServiceBusAzure.Options -{ - public class AzureServiceBusTopicSettings - { - public const string Position = "AzureServiceBusTopic"; - public string ConnectionString { get; set; } - public string TopicName { get; set; } - public string SubscriptionName { get; set; } - public int MaxConcurrentCalls { get; set; } = 20; - public int PrefetchCount { get; set; } = 100; - public ReceiveMode ReceiveMode { get; set; } = ReceiveMode.PeekLock; - public RetryPolicy RetryPolicy { get; set; } = RetryPolicy.Default; - public bool AutoComplete { get; set; } = true; - } -} - diff --git a/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs b/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs index 6d17d772..04a2c8d5 100644 --- a/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs +++ b/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs @@ -1,15 +1,12 @@ using Genocs.Core.CQRS.Commands; -using Genocs.ServiceBusAzure.Options; +using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Queues.Interfaces; using Microsoft.Azure.ServiceBus; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; -using System; -using System.Collections.Generic; using System.Text; -using System.Threading.Tasks; namespace Genocs.ServiceBusAzure.Queues; @@ -70,6 +67,7 @@ public AzureServiceBusQueue(AzureServiceBusQueueSettings options, { throw new ArgumentNullException(nameof(options)); } + _options = options; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Genocs.ServiceBusAzure/Queues/Interfaces/IAzureServiceBusQueue.cs b/src/Genocs.ServiceBusAzure/Queues/Interfaces/IAzureServiceBusQueue.cs index f544d3fc..2748c189 100644 --- a/src/Genocs.ServiceBusAzure/Queues/Interfaces/IAzureServiceBusQueue.cs +++ b/src/Genocs.ServiceBusAzure/Queues/Interfaces/IAzureServiceBusQueue.cs @@ -2,13 +2,14 @@ namespace Genocs.ServiceBusAzure.Queues.Interfaces; - /// -/// Azure Service bus +/// Azure Service bus. /// public interface IAzureServiceBusQueue { Task SendAsync(ICommand command); Task ScheduleAsync(ICommand command, DateTimeOffset offset); - void Consume() where T : ICommand where TH : ICommandHandlerLegacy; + void Consume() + where T : ICommand + where TH : ICommandHandlerLegacy; } diff --git a/src/Genocs.ServiceBusAzure/README.md b/src/Genocs.ServiceBusAzure/README_NUGET.md similarity index 100% rename from src/Genocs.ServiceBusAzure/README.md rename to src/Genocs.ServiceBusAzure/README_NUGET.md diff --git a/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs b/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs index 46367ca4..1684af7e 100644 --- a/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs +++ b/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs @@ -1,5 +1,5 @@ using Genocs.Core.CQRS.Events; -using Genocs.ServiceBusAzure.Options; +using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Topics.Interfaces; using Microsoft.Azure.ServiceBus; using Microsoft.Extensions.DependencyInjection; @@ -8,240 +8,239 @@ using Newtonsoft.Json; using System.Text; -namespace Genocs.ServiceBusAzure.Topics +namespace Genocs.ServiceBusAzure.Topics; + +public class AzureServiceBusTopic : IAzureServiceBusTopic { - public class AzureServiceBusTopic : IAzureServiceBusTopic + private readonly TopicClient _topicClient; + private readonly AzureServiceBusTopicSettings _options; + private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; + private const string EVENT_SUFFIX = "Event"; + private readonly Dictionary> _handlers; + private readonly SubscriptionClient _subscriptionClient; + private readonly List _eventTypes; + + public AzureServiceBusTopic( + IOptions options, + IServiceProvider serviceProvider, + ILogger logger) { - private readonly TopicClient _topicClient; - private readonly AzureServiceBusTopicSettings _options; - private readonly ILogger _logger; - private readonly IServiceProvider _serviceProvider; - private const string EVENT_SUFFIX = "Event"; - private readonly Dictionary> _handlers; - private readonly SubscriptionClient _subscriptionClient; - private readonly List _eventTypes; - - public AzureServiceBusTopic(IOptions options, - IServiceProvider serviceProvider, - ILogger logger) + if (options == null) { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - _options = options.Value; - - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); - - ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder = new ServiceBusConnectionStringBuilder(_options.ConnectionString); - serviceBusConnectionStringBuilder.EntityPath = _options.TopicName; - _topicClient = new TopicClient(serviceBusConnectionStringBuilder, _options.RetryPolicy); - _handlers = new Dictionary>(); - _eventTypes = new List(); - if (!string.IsNullOrEmpty(_options.SubscriptionName)) - { - _subscriptionClient = new SubscriptionClient(serviceBusConnectionStringBuilder, _options.SubscriptionName); - RegisterSubscriptionClientMessageHandler(); - } + throw new ArgumentNullException(nameof(options)); } + _options = options.Value; + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); - public AzureServiceBusTopic(AzureServiceBusTopicSettings options, - IServiceProvider serviceProvider, - ILogger logger) + ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder = new ServiceBusConnectionStringBuilder(_options.ConnectionString); + serviceBusConnectionStringBuilder.EntityPath = _options.TopicName; + _topicClient = new TopicClient(serviceBusConnectionStringBuilder, _options.RetryPolicy); + _handlers = new Dictionary>(); + _eventTypes = new List(); + if (!string.IsNullOrEmpty(_options.SubscriptionName)) { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - _options = options; + _subscriptionClient = new SubscriptionClient(serviceBusConnectionStringBuilder, _options.SubscriptionName); + RegisterSubscriptionClientMessageHandler(); + } + } + public AzureServiceBusTopic( + AzureServiceBusTopicSettings options, + IServiceProvider serviceProvider, + ILogger logger) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + _options = options; - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); - ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder = new ServiceBusConnectionStringBuilder(_options.ConnectionString); - serviceBusConnectionStringBuilder.EntityPath = _options.TopicName; - _topicClient = new TopicClient(serviceBusConnectionStringBuilder, _options.RetryPolicy); - _handlers = new Dictionary>(); - _eventTypes = new List(); - if (!string.IsNullOrEmpty(_options.SubscriptionName)) - { - _subscriptionClient = new SubscriptionClient(serviceBusConnectionStringBuilder, _options.SubscriptionName); - RegisterSubscriptionClientMessageHandler(); - } + ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder = new ServiceBusConnectionStringBuilder(_options.ConnectionString); + serviceBusConnectionStringBuilder.EntityPath = _options.TopicName; + _topicClient = new TopicClient(serviceBusConnectionStringBuilder, _options.RetryPolicy); + _handlers = new Dictionary>(); + _eventTypes = new List(); + if (!string.IsNullOrEmpty(_options.SubscriptionName)) + { + _subscriptionClient = new SubscriptionClient(serviceBusConnectionStringBuilder, _options.SubscriptionName); + RegisterSubscriptionClientMessageHandler(); } + } + + public async Task PublishAsync(IEvent @event) + { + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); - public async Task PublishAsync(IEvent @event) + var message = new Message { - string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); - string jsonMessage = JsonConvert.SerializeObject(@event); - byte[] body = Encoding.UTF8.GetBytes(jsonMessage); + MessageId = Guid.NewGuid().ToString(), + Body = body, + Label = eventName, + }; - var message = new Message - { - MessageId = Guid.NewGuid().ToString(), - Body = body, - Label = eventName, - }; + await _topicClient.SendAsync(message); - await _topicClient.SendAsync(message); + } - } + public async Task PublishAsync(IEvent @event, Dictionary filters) + { + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); - public async Task PublishAsync(IEvent @event, Dictionary filters) + var message = new Message { - string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); - string jsonMessage = JsonConvert.SerializeObject(@event); - byte[] body = Encoding.UTF8.GetBytes(jsonMessage); + MessageId = Guid.NewGuid().ToString(), + Body = body, + Label = eventName, + }; - var message = new Message - { - MessageId = Guid.NewGuid().ToString(), - Body = body, - Label = eventName, - }; + foreach (KeyValuePair filter in filters) + { + message.UserProperties.Add(filter); + } - foreach (KeyValuePair filter in filters) - { - message.UserProperties.Add(filter); - } + await _topicClient.SendAsync(message); + } - await _topicClient.SendAsync(message); - } + public async Task ScheduleAsync(IEvent @event, DateTimeOffset offset) + { + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); - public async Task ScheduleAsync(IEvent @event, DateTimeOffset offset) + var message = new Message { - string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); - string jsonMessage = JsonConvert.SerializeObject(@event); - byte[] body = Encoding.UTF8.GetBytes(jsonMessage); + MessageId = Guid.NewGuid().ToString(), + Body = body, + Label = eventName, + }; + await _topicClient.ScheduleMessageAsync(message, offset); + } - var message = new Message - { - MessageId = Guid.NewGuid().ToString(), - Body = body, - Label = eventName, - }; - await _topicClient.ScheduleMessageAsync(message, offset); - } + public async Task ScheduleAsync(IEvent @event, DateTimeOffset offset, Dictionary filters) + { + string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); + string jsonMessage = JsonConvert.SerializeObject(@event); + byte[] body = Encoding.UTF8.GetBytes(jsonMessage); - public async Task ScheduleAsync(IEvent @event, DateTimeOffset offset, Dictionary filters) + var message = new Message { - string eventName = @event.GetType().Name.Replace(EVENT_SUFFIX, string.Empty); - string jsonMessage = JsonConvert.SerializeObject(@event); - byte[] body = Encoding.UTF8.GetBytes(jsonMessage); + MessageId = Guid.NewGuid().ToString(), + Body = body, + Label = eventName, + }; - var message = new Message - { - MessageId = Guid.NewGuid().ToString(), - Body = body, - Label = eventName, - }; + foreach (KeyValuePair filter in filters) + { + message.UserProperties.Add(filter); + } - foreach (KeyValuePair filter in filters) - { - message.UserProperties.Add(filter); - } + await _topicClient.ScheduleMessageAsync(message, offset); + } + + /// + /// Todo + /// + /// + /// + /// + public void Subscribe() + where T : IEvent + where TH : IEventHandlerLegacy + { + string eventName = typeof(T).Name.Replace(EVENT_SUFFIX, ""); + string key = typeof(T).Name; + if (!_handlers.ContainsKey(key)) + { + _handlers.Add(key, new List()); - await _topicClient.ScheduleMessageAsync(message, offset); + //_subscriptionClient.AddRuleAsync(new RuleDescription + //{ + // Filter = new CorrelationFilter { Label = eventName.ToLower() }, + // Name = eventName + //}).GetAwaiter().GetResult(); } - /// - /// Todo - /// - /// - /// - /// - public void Subscribe() - where T : IEvent - where TH : IEventHandlerLegacy - { - string eventName = typeof(T).Name.Replace(EVENT_SUFFIX, ""); - string key = typeof(T).Name; - if (!_handlers.ContainsKey(key)) - { - _handlers.Add(key, new List()); + Type handlerType = typeof(TH); - //_subscriptionClient.AddRuleAsync(new RuleDescription - //{ - // Filter = new CorrelationFilter { Label = eventName.ToLower() }, - // Name = eventName - //}).GetAwaiter().GetResult(); - } + if (_handlers[key].Any(s => s.HandlerType == handlerType)) + { + throw new ArgumentException( + $"Handler Type '{typeof(TH).Name}' already registered for '{key}'", nameof(handlerType)); + } - Type handlerType = typeof(TH); + if (!_eventTypes.Contains(typeof(T))) + { + _eventTypes.Add(typeof(T)); + } - if (_handlers[key].Any(s => s.HandlerType == handlerType)) - { - throw new ArgumentException( - $"Handler Type '{typeof(TH).Name}' already registered for '{key}'", nameof(handlerType)); - } + _handlers[key].Add(SubscriptionInfo.Typed(handlerType)); + } - if (!_eventTypes.Contains(typeof(T))) + private void RegisterSubscriptionClientMessageHandler() + { + _subscriptionClient.RegisterMessageHandler( + async (message, token) => { - _eventTypes.Add(typeof(T)); - } + string eventName = $"{message.Label}{EVENT_SUFFIX}"; + string messageData = Encoding.UTF8.GetString(message.Body); - _handlers[key].Add(SubscriptionInfo.Typed(handlerType)); - } - - private void RegisterSubscriptionClientMessageHandler() - { - _subscriptionClient.RegisterMessageHandler( - async (message, token) => + // Complete the message so that it is not received again. + if (await ProcessEvent(eventName, messageData)) { - string eventName = $"{message.Label}{EVENT_SUFFIX}"; - string messageData = Encoding.UTF8.GetString(message.Body); - - // Complete the message so that it is not received again. - if (await ProcessEvent(eventName, messageData)) - { - await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); - } - }, - new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = _options.MaxConcurrentCalls, AutoComplete = false }); - } + await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken); + } + }, + new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = _options.MaxConcurrentCalls, AutoComplete = false }); + } - private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs) - { - var ex = exceptionReceivedEventArgs.Exception; - var context = exceptionReceivedEventArgs.ExceptionReceivedContext; + private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs) + { + var ex = exceptionReceivedEventArgs.Exception; + var context = exceptionReceivedEventArgs.ExceptionReceivedContext; - _logger.LogError(ex, "ERROR handling message: {ExceptionMessage} - Context: {@ExceptionContext}", ex.Message, context); + _logger.LogError(ex, "ERROR handling message: {ExceptionMessage} - Context: {@ExceptionContext}", ex.Message, context); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - private async Task ProcessEvent(string eventName, string message) + private async Task ProcessEvent(string eventName, string message) + { + bool processed = false; + if (_handlers.ContainsKey(eventName)) { - bool processed = false; - if (_handlers.ContainsKey(eventName)) + using (var scope = _serviceProvider.CreateScope()) { - using (var scope = _serviceProvider.CreateScope()) - { - var subscriptions = _handlers[eventName]; + var subscriptions = _handlers[eventName]; - foreach (var subscription in subscriptions) + foreach (var subscription in subscriptions) + { + object handler = scope.ServiceProvider.GetRequiredService(subscription.HandlerType); + if (handler != null) { - object handler = scope.ServiceProvider.GetRequiredService(subscription.HandlerType); - if (handler != null) - { - var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); - object command = JsonConvert.DeserializeObject(message, eventType); - var concreteType = typeof(IEventHandler<>).MakeGenericType(eventType); - await (Task)concreteType.GetMethod("HandleEvent").Invoke(handler, new object[] { command }); - } + var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); + object command = JsonConvert.DeserializeObject(message, eventType); + var concreteType = typeof(IEventHandler<>).MakeGenericType(eventType); + await (Task)concreteType.GetMethod("HandleEvent").Invoke(handler, new object[] { command }); } } - - processed = true; - } - else - { - _logger.LogError($"Event '{eventName}' do not contains handlers. Check whether Subscribe is set"); } - return processed; + processed = true; + } + else + { + _logger.LogError($"Event '{eventName}' do not contains handlers. Check whether Subscribe is set"); } + + return processed; } } diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index a2b2c3ff..a9fe3afe 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/README.md b/src/Genocs.Tracing.Jaeger.RabbitMQ/README_NUGET.md similarity index 100% rename from src/Genocs.Tracing.Jaeger.RabbitMQ/README.md rename to src/Genocs.Tracing.Jaeger.RabbitMQ/README_NUGET.md diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index beb99dfb..96ae78e0 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -1,8 +1,8 @@ using Azure.Monitor.OpenTelemetry.Exporter; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; -using Genocs.Logging.Options; -using Genocs.Tracing.Jaeger.Options; +using Genocs.Logging.Configurations; +using Genocs.Tracing.Jaeger.Configurations; using Jaeger.Samplers; using Jaeger.Senders.Thrift; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 10143fd3..66524a87 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs index 831f4f07..1bb7c940 100644 --- a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.Tracing.Jaeger.Options; +using Genocs.Tracing.Jaeger.Configurations; namespace Genocs.Tracing.Jaeger.Builders; diff --git a/src/Genocs.Tracing/Jaeger/Options/IJaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs similarity index 91% rename from src/Genocs.Tracing/Jaeger/Options/IJaegerOptionsBuilder.cs rename to src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs index a1792dc6..5e9ab003 100644 --- a/src/Genocs.Tracing/Jaeger/Options/IJaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs @@ -1,4 +1,4 @@ -namespace Genocs.Tracing.Jaeger.Options; +namespace Genocs.Tracing.Jaeger.Configurations; public interface IJaegerOptionsBuilder { diff --git a/src/Genocs.Tracing/Jaeger/Options/JaegerSettings.cs b/src/Genocs.Tracing/Jaeger/Configurations/JaegerSettings.cs similarity index 91% rename from src/Genocs.Tracing/Jaeger/Options/JaegerSettings.cs rename to src/Genocs.Tracing/Jaeger/Configurations/JaegerSettings.cs index 94ef5b0b..59528f09 100644 --- a/src/Genocs.Tracing/Jaeger/Options/JaegerSettings.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/JaegerSettings.cs @@ -1,12 +1,12 @@ -namespace Genocs.Tracing.Jaeger.Options; +namespace Genocs.Tracing.Jaeger.Configurations; /// -/// Jaeger Settings +/// Jaeger Settings. /// public class JaegerSettings { /// - /// Default section name + /// Default section name. /// public const string Position = "jaeger"; diff --git a/src/Genocs.Tracing/Jaeger/Extensions.cs b/src/Genocs.Tracing/Jaeger/Extensions.cs index 664f1c6a..59d3af36 100644 --- a/src/Genocs.Tracing/Jaeger/Extensions.cs +++ b/src/Genocs.Tracing/Jaeger/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Core.Builders; -using Genocs.Tracing.Jaeger.Options; +using Genocs.Tracing.Jaeger.Configurations; using Genocs.Tracing.Jaeger.Tracers; using Jaeger; using Jaeger.Reporters; diff --git a/src/Genocs.Tracing/README.md b/src/Genocs.Tracing/README_NUGET.md similarity index 100% rename from src/Genocs.Tracing/README.md rename to src/Genocs.Tracing/README_NUGET.md diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index c985d721..e3b0e060 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.WebApi.CQRS/README.md b/src/Genocs.WebApi.CQRS/README_NUGET.md similarity index 100% rename from src/Genocs.WebApi.CQRS/README.md rename to src/Genocs.WebApi.CQRS/README_NUGET.md diff --git a/src/Genocs.WebApi.Security/CertificateMiddleware.cs b/src/Genocs.WebApi.Security/CertificateMiddleware.cs index ea5e18d8..3111aed3 100644 --- a/src/Genocs.WebApi.Security/CertificateMiddleware.cs +++ b/src/Genocs.WebApi.Security/CertificateMiddleware.cs @@ -1,3 +1,4 @@ +using Genocs.WebApi.Security.Configurations; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System.Security.Cryptography.X509Certificates; diff --git a/src/Genocs.WebApi.Security/Options/SecuritySettings.cs b/src/Genocs.WebApi.Security/Configurations/SecuritySettings.cs similarity index 94% rename from src/Genocs.WebApi.Security/Options/SecuritySettings.cs rename to src/Genocs.WebApi.Security/Configurations/SecuritySettings.cs index 08fb937a..bab3c180 100644 --- a/src/Genocs.WebApi.Security/Options/SecuritySettings.cs +++ b/src/Genocs.WebApi.Security/Configurations/SecuritySettings.cs @@ -1,4 +1,4 @@ -namespace Genocs.WebApi.Security; +namespace Genocs.WebApi.Security.Configurations; public class SecuritySettings { diff --git a/src/Genocs.WebApi.Security/Extensions.cs b/src/Genocs.WebApi.Security/Extensions.cs index a615b8c6..957802e4 100644 --- a/src/Genocs.WebApi.Security/Extensions.cs +++ b/src/Genocs.WebApi.Security/Extensions.cs @@ -1,4 +1,5 @@ using Genocs.Core.Builders; +using Genocs.WebApi.Security.Configurations; using Microsoft.AspNetCore.Authentication.Certificate; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 6b36bd67..f3664774 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.WebApi.Security/README.md b/src/Genocs.WebApi.Security/README_NUGET.md similarity index 100% rename from src/Genocs.WebApi.Security/README.md rename to src/Genocs.WebApi.Security/README_NUGET.md diff --git a/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs index 90e21984..7c34637a 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs @@ -1,8 +1,10 @@ +using Genocs.WebApi.Swagger.Docs.Configurations; + namespace Genocs.WebApi.Swagger.Docs.Builders; internal sealed class SwaggerOptionsBuilder : ISwaggerOptionsBuilder { - private readonly SwaggerOptions _options = new(); + private readonly SwaggerSettings _options = new(); public ISwaggerOptionsBuilder Enable(bool enabled) { @@ -52,5 +54,5 @@ public ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2) return this; } - public SwaggerOptions Build() => _options; + public SwaggerSettings Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/ISwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs similarity index 86% rename from src/Genocs.WebApi.Swagger/Docs/ISwaggerOptionsBuilder.cs rename to src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs index 1527d2a4..e500e9e7 100644 --- a/src/Genocs.WebApi.Swagger/Docs/ISwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs @@ -1,4 +1,4 @@ -namespace Genocs.WebApi.Swagger.Docs; +namespace Genocs.WebApi.Swagger.Docs.Configurations; public interface ISwaggerOptionsBuilder { @@ -10,5 +10,5 @@ public interface ISwaggerOptionsBuilder ISwaggerOptionsBuilder WithRoutePrefix(string routePrefix); ISwaggerOptionsBuilder IncludeSecurity(bool includeSecurity); ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2); - SwaggerOptions Build(); + SwaggerSettings Build(); } \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerSettings.cs similarity index 80% rename from src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs rename to src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerSettings.cs index 30e30d6c..4045b00b 100644 --- a/src/Genocs.WebApi.Swagger/Docs/SwaggerOptions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerSettings.cs @@ -1,6 +1,6 @@ -namespace Genocs.WebApi.Swagger.Docs; +namespace Genocs.WebApi.Swagger.Docs.Configurations; -public class SwaggerOptions +public class SwaggerSettings { public bool Enabled { get; set; } public bool ReDocEnabled { get; set; } diff --git a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs index b752a211..1f6d8ce7 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs @@ -1,5 +1,6 @@ using Genocs.Core.Builders; using Genocs.WebApi.Swagger.Docs.Builders; +using Genocs.WebApi.Swagger.Docs.Configurations; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; @@ -18,7 +19,7 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, string sectionName = SectionName; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); return builder.AddSwaggerDocs(options); } @@ -28,7 +29,7 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, Func(); + var options = builder.ApplicationServices.GetRequiredService(); if (!options.Enabled) { return builder; diff --git a/src/Genocs.WebApi.Swagger/Extensions.cs b/src/Genocs.WebApi.Swagger/Extensions.cs index 585d9ceb..1282e417 100644 --- a/src/Genocs.WebApi.Swagger/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Extensions.cs @@ -1,5 +1,6 @@ using Genocs.Core.Builders; using Genocs.WebApi.Swagger.Docs; +using Genocs.WebApi.Swagger.Docs.Configurations; using Genocs.WebApi.Swagger.Filters; using Microsoft.Extensions.DependencyInjection; @@ -22,7 +23,7 @@ public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, s public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) => builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(buildOptions)); - public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, SwaggerOptions options) + public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, SwaggerSettings options) => builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(options)); private static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Action registerSwagger) diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 1bf96a4b..53bbdc00 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.WebApi.Swagger/README.md b/src/Genocs.WebApi.Swagger/README_NUGET.md similarity index 100% rename from src/Genocs.WebApi.Swagger/README.md rename to src/Genocs.WebApi.Swagger/README_NUGET.md diff --git a/src/Genocs.WebApi/Configurations/WebApiOptions.cs b/src/Genocs.WebApi/Configurations/WebApiOptions.cs new file mode 100644 index 00000000..ce60fd06 --- /dev/null +++ b/src/Genocs.WebApi/Configurations/WebApiOptions.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Options; + +namespace Genocs.WebApi.Configurations; + +/// +/// The WebApiSettings definition. +/// Move to WebApiSettings.cs. +/// +public class WebApiOptions : IConfigureNamedOptions +{ + private readonly WebApiSettings _jwtSettings; + + public WebApiOptions(IOptions jwtSettings) + { + _jwtSettings = jwtSettings.Value; + } + + public void Configure(string? name, WebApiSettings options) + { + Configure(options); + } + + public void Configure(WebApiSettings options) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/Genocs.WebApi/Options/WebApiSettings.cs b/src/Genocs.WebApi/Configurations/WebApiSettings.cs similarity index 59% rename from src/Genocs.WebApi/Options/WebApiSettings.cs rename to src/Genocs.WebApi/Configurations/WebApiSettings.cs index f7429c94..805f7fe3 100644 --- a/src/Genocs.WebApi/Options/WebApiSettings.cs +++ b/src/Genocs.WebApi/Configurations/WebApiSettings.cs @@ -1,7 +1,7 @@ -namespace Genocs.WebApi.Options; +namespace Genocs.WebApi.Configurations; /// -/// The WebApiSettings definiiton. +/// The WebApiSettings definition. /// public class WebApiSettings { diff --git a/src/Genocs.WebApi/EndpointsBuilder.cs b/src/Genocs.WebApi/EndpointsBuilder.cs index 1173be2b..12bb2d69 100644 --- a/src/Genocs.WebApi/EndpointsBuilder.cs +++ b/src/Genocs.WebApi/EndpointsBuilder.cs @@ -108,7 +108,7 @@ public IEndpointsBuilder Put(string path, Func context return this; } - public IEndpointsBuilder Delete(string path, Func context = null, + public IEndpointsBuilder Delete(string path, Func? context = null, Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) { @@ -120,8 +120,8 @@ public IEndpointsBuilder Delete(string path, Func context = n return this; } - public IEndpointsBuilder Delete(string path, Func context = null, - Action endpoint = null, bool auth = false, string roles = null, + public IEndpointsBuilder Delete(string path, Func? context = null, + Action endpoint = null, bool auth = false, string? roles = null, params string[] policies) where T : class { diff --git a/src/Genocs.WebApi/Extensions.cs b/src/Genocs.WebApi/Extensions.cs index cdbec57e..cc7f9c40 100644 --- a/src/Genocs.WebApi/Extensions.cs +++ b/src/Genocs.WebApi/Extensions.cs @@ -1,9 +1,9 @@ using Genocs.Common.Types; using Genocs.Core.Builders; using Genocs.WebApi; +using Genocs.WebApi.Configurations; using Genocs.WebApi.Exceptions; using Genocs.WebApi.Formatters; -using Genocs.WebApi.Options; using Genocs.WebApi.Requests; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; @@ -53,8 +53,11 @@ public static IApplicationBuilder UseEndpoints(this IApplicationBuilder app, Act } [Description("By default System JSON serializer is being used. If Newtonsoft JSON serializer is used then it sets Kestrel's and IIS ServerOptions AllowSynchronousIO = true")] - public static IGenocsBuilder AddWebApi(this IGenocsBuilder builder, Action configureMvc = null, - IJsonSerializer jsonSerializer = null, string sectionName = SectionName) + public static IGenocsBuilder AddWebApi( + this IGenocsBuilder builder, + Action? configureMvc = null, + IJsonSerializer? jsonSerializer = null, + string sectionName = SectionName) { if (string.IsNullOrWhiteSpace(sectionName)) { diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index ededa441..e820915c 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -20,7 +20,7 @@ icon.png git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles - README.md + README_NUGET.md Aligned to the ecosystem True latest @@ -35,7 +35,7 @@ True \ - + True \ diff --git a/src/Genocs.WebApi/README.md b/src/Genocs.WebApi/README_NUGET.md similarity index 100% rename from src/Genocs.WebApi/README.md rename to src/Genocs.WebApi/README_NUGET.md diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs index c8299cf4..0b96c4a2 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/CorrelationContextBuilder.cs @@ -8,8 +8,8 @@ public CorrelationContext Build( HttpContext context, string correlationId, string spanContext, - string name = null, - string resourceId = null) + string? name = null, + string? resourceId = null) => new CorrelationContext { CorrelationId = correlationId, diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index a2dae299..3c29680f 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -1,7 +1,7 @@ using Genocs.APIGateway.Framework; using Genocs.APIGateway.Options; using Genocs.Auth; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; using Genocs.MessageBrokers.RabbitMQ; using Genocs.Metrics.Prometheus; diff --git a/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs b/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs index b9231895..a279c762 100644 --- a/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs +++ b/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs @@ -1,5 +1,5 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.MessageBrokers; using Microsoft.AspNetCore.Http; @@ -11,17 +11,24 @@ internal class CorrelationIdFactory : ICorrelationIdFactory private readonly IMessagePropertiesAccessor _messagePropertiesAccessor; private readonly IHttpContextAccessor _httpContextAccessor; - private readonly string _header; + private readonly string? _header; - public CorrelationIdFactory(IMessagePropertiesAccessor messagePropertiesAccessor, - IHttpContextAccessor httpContextAccessor, HttpClientSettings httpClientOptions) + public CorrelationIdFactory( + IMessagePropertiesAccessor messagePropertiesAccessor, + IHttpContextAccessor httpContextAccessor, + HttpClientSettings httpClientOptions) { - _messagePropertiesAccessor = messagePropertiesAccessor; - _httpContextAccessor = httpContextAccessor; + if (httpClientOptions is null) + { + throw new ArgumentNullException(nameof(httpClientOptions)); + } + + _messagePropertiesAccessor = messagePropertiesAccessor ?? throw new ArgumentNullException(nameof(messagePropertiesAccessor)); + _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _header = httpClientOptions.CorrelationIdHeader; } - private static string CorrelationId + private static string? CorrelationId { get => Holder.Value?.Id; set @@ -41,7 +48,7 @@ private static string CorrelationId private class CorrelationIdHolder { - public string Id; + public string? Id; } public string Create() @@ -51,7 +58,7 @@ public string Create() return CorrelationId; } - var correlationId = _messagePropertiesAccessor.MessageProperties?.CorrelationId; + string? correlationId = _messagePropertiesAccessor.MessageProperties?.CorrelationId; if (!string.IsNullOrWhiteSpace(correlationId)) { CorrelationId = correlationId; diff --git a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs index 27216af2..a7eb7f09 100644 --- a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs +++ b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs @@ -2,7 +2,7 @@ using Genocs.Core.CQRS.Commands; using Genocs.MessageBrokers; using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.Identities.Application.Decorators; diff --git a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs index 1c3ef1dd..06e73609 100644 --- a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs +++ b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs @@ -2,7 +2,7 @@ using Genocs.Core.CQRS.Events; using Genocs.MessageBrokers; using Genocs.MessageBrokers.Outbox; -using Genocs.MessageBrokers.Outbox.Options; +using Genocs.MessageBrokers.Outbox.Configurations; namespace Genocs.Identities.Application.Decorators; diff --git a/src/apps/identity/Genocs.Identities.Application/Domain/Entities/User.cs b/src/apps/identity/Genocs.Identities.Application/Domain/Entities/User.cs index 46bbe004..9e69be07 100644 --- a/src/apps/identity/Genocs.Identities.Application/Domain/Entities/User.cs +++ b/src/apps/identity/Genocs.Identities.Application/Domain/Entities/User.cs @@ -12,8 +12,16 @@ public class User : AggregateRoot public IEnumerable? Permissions { get; private set; } public bool Locked { get; private set; } - public User(Guid id, string email, string name, string password, string role, DateTime createdAt, - IEnumerable? permissions = null, bool locked = false) : base(id) + public User( + Guid id, + string email, + string name, + string password, + string role, + DateTime createdAt, + IEnumerable? permissions = null, + bool locked = false) + : base(id) { if (string.IsNullOrWhiteSpace(email)) { @@ -45,7 +53,6 @@ public User(Guid id, string email, string name, string password, string role, Da Locked = locked; } - public bool Lock() { if (Locked) diff --git a/src/apps/identity/Genocs.Identities.Application/Extensions.cs b/src/apps/identity/Genocs.Identities.Application/Extensions.cs index 593c58a1..ae8f138d 100644 --- a/src/apps/identity/Genocs.Identities.Application/Extensions.cs +++ b/src/apps/identity/Genocs.Identities.Application/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Auth; -using Genocs.Common.Options; +using Genocs.Common.Configurations; using Genocs.Core.Builders; using Genocs.Core.CQRS.Commands; using Genocs.Core.CQRS.Events; diff --git a/src/apps/identity/Genocs.Identities.WebApi/Program.cs b/src/apps/identity/Genocs.Identities.WebApi/Program.cs index b19e5aa5..afd5507a 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Program.cs +++ b/src/apps/identity/Genocs.Identities.WebApi/Program.cs @@ -9,15 +9,8 @@ using Genocs.WebApi; using Genocs.WebApi.CQRS; using Serilog; -using Serilog.Events; -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel.Override("MassTransit", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); +StaticLogger.EnsureInitialized(); var builder = WebApplication.CreateBuilder(args); diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index 45e41f78..9d14e35f 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -30,15 +30,8 @@ using Genocs.WebApi.Swagger; using Genocs.WebApi.Swagger.Docs; using Serilog; -using Serilog.Events; -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel.Override("MassTransit", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); +StaticLogger.EnsureInitialized(); var builder = WebApplication.CreateBuilder(args); diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs index 1577cb9b..77f0cda4 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs @@ -1,9 +1,9 @@ using Genocs.HTTP; -using Genocs.HTTP.Options; +using Genocs.HTTP.Configurations; using Genocs.Orders.WebApi.DTO; using Genocs.Secrets.Vault; -using Genocs.Secrets.Vault.Options; -using Genocs.WebApi.Security; +using Genocs.Secrets.Vault.Configurations; +using Genocs.WebApi.Security.Configurations; namespace Genocs.Orders.WebApi.Services; diff --git a/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs b/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs index 65f3dbec..986e8262 100644 --- a/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs +++ b/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs @@ -2,9 +2,8 @@ namespace Genocs.Products.WebApi.Domain; - /// -/// The product definition +/// The product definition. /// public class Product : IIdentifiable { diff --git a/src/apps/products/Genocs.Products.WebApi/Program.cs b/src/apps/products/Genocs.Products.WebApi/Program.cs index 684c6646..f8f71171 100644 --- a/src/apps/products/Genocs.Products.WebApi/Program.cs +++ b/src/apps/products/Genocs.Products.WebApi/Program.cs @@ -28,15 +28,8 @@ using Genocs.WebApi.Swagger; using Genocs.WebApi.Swagger.Docs; using Serilog; -using Serilog.Events; -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel.Override("MassTransit", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); +StaticLogger.EnsureInitialized(); var builder = WebApplication.CreateBuilder(args); diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs index 6ddbe92a..627bca5a 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs @@ -22,15 +22,8 @@ using Genocs.WebApi.Swagger; using Genocs.WebApi.Swagger.Docs; using Serilog; -using Serilog.Events; -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .MinimumLevel.Override("MassTransit", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); +StaticLogger.EnsureInitialized(); var builder = WebApplication.CreateBuilder(args); From cc6c097d28854b584d3df34f9dc3ea6c4be78db9 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 7 Jul 2024 14:51:21 +0200 Subject: [PATCH 056/104] Merge issues --- .../AccessTokenValidatorMiddleware.cs | 2 +- src/Genocs.Auth/Builders/JwtOptionsBuilder.cs | 4 +- .../IJwtOptionsBuilder.cs | 6 +- .../{JwtSettings.cs => JwtOptions.cs} | 6 +- src/Genocs.Auth/Extensions.cs | 150 +++++++++--------- src/Genocs.Auth/Handlers/JwtHandler.cs | 4 +- .../Services/InMemoryAccessTokenService.cs | 2 +- .../{AppSettings.cs => AppOptions.cs} | 2 +- .../ExternalServiceOptions.cs} | 5 +- .../RabbitMQOptions.cs} | 2 +- .../SecretOptions.cs} | 2 +- .../VerificationServiceOptions.cs | 8 + .../Controllers/HomeController.cs | 4 +- .../Extensions/BuilderExtensions.cs | 6 +- .../Extensions/ServiceCollectionExtensions.cs | 14 +- .../Services/ExternalServiceClient.cs | 14 +- .../IVerificationServiceClient.Models.cs | 66 ++++++++ .../Services/IVerificationServiceClient.cs | 15 ++ .../Services/VerificationServiceClient.cs | 65 ++++++++ src/Genocs.Core.Demo.WebApi/Program.cs | 7 +- src/Genocs.Core/Builders/Extensions.cs | 10 +- src/Genocs.Core/README_NUGET.md | 6 +- ...ingsBuilder.cs => ConsulOptionsBuilder.cs} | 24 +-- .../{ConsulSettings.cs => ConsulOptions.cs} | 11 +- .../Configurations/IConsulOptionsBuilder.cs | 15 ++ .../Configurations/IConsulSettingsBuilder.cs | 15 -- src/Genocs.Discovery.Consul/Extensions.cs | 18 +-- .../Http/ConsulHttpClient.cs | 8 +- .../ConsulServiceDiscoveryMessageHandler.cs | 19 ++- ...eBuilders.cs => RestEaseOptionsBuilder.cs} | 18 +-- .../Configurations/IRestEaseOptionsBuilder.cs | 8 + ...RestEaseSettings.cs => RestEaseOptions.cs} | 0 src/Genocs.HTTP.RestEase/Extensions.cs | 31 ++-- .../IRestEaseServiceBuilder.cs | 4 +- .../IRestEaseSettingsBuilder.cs | 10 -- ...ClientSettings.cs => HttpClientOptions.cs} | 9 +- src/Genocs.HTTP/Extensions.cs | 2 +- src/Genocs.HTTP/GenocsHttpClient.cs | 4 +- src/Genocs.HTTP/GenocsHttpLoggingFilter.cs | 4 +- .../GenocsLoggingScopeHttpMessageHandler.cs | 2 +- ...tingsBuilder.cs => FabioOptionsBuilder.cs} | 12 +- .../{FabioSettings.cs => FabioOptions.cs} | 4 +- ...ingsBuilder.cs => IFabioOptionsBuilder.cs} | 18 +-- src/Genocs.LoadBalancing.Fabio/Extensions.cs | 22 ++- .../Http/FabioHttpClient.cs | 2 +- .../MessageHandlers/FabioMessageHandler.cs | 4 +- .../{AzureSettings.cs => AzureOptions.cs} | 0 .../{ConsoleSettings.cs => ConsoleOptions.cs} | 0 .../{ElkSettings.cs => ElkOptions.cs} | 0 ...calFileSettings.cs => LocalFileOptions.cs} | 0 .../{LoggerSettings.cs => LoggerOptions.cs} | 4 - .../{LokiSettings.cs => LokiOptions.cs} | 0 .../{MongoSettings.cs => MongoOptions.cs} | 0 .../{SeqSettings.cs => SeqOptions.cs} | 0 src/Genocs.Logging/Extensions.cs | 30 ++-- .../Internals/MongoMessageOutbox.cs | 5 +- .../Internals/MongoOutboxInitializer.cs | 4 +- .../{OutboxSettings.cs => OutboxOptions.cs} | 2 +- .../MessageOutboxConfigurator.cs | 4 +- .../Extensions.cs | 2 +- .../IMessageOutboxConfigurator.cs | 2 +- .../Messages/OutboxMessage.cs | 4 +- .../Outbox/InMemoryMessageOutbox.cs | 2 +- .../Processors/OutboxProcessor.cs | 4 +- .../Builders/MetricsSettingsBuilder.cs | 20 +-- src/Genocs.Metrics/AppMetrics/Extensions.cs | 8 +- .../MongoDbEncryptionOptions.cs | 69 ++++++++ .../Encryptions/AzureInitializer.cs | 6 +- .../Extensions/MongoDbExtensions.cs | 28 ++-- .../Initializers/MongoDbInitializer.cs | 2 +- .../Repositories/IMongoDbOptionsBuilder.cs | 36 ----- .../Extensions.cs | 9 +- src/Genocs.Secrets.Vault/Extensions.cs | 38 +++-- .../Internals/VaultHostedService.cs | 4 +- .../Builders/DispatcherEndpointsBuilder.cs | 24 ++- .../Genocs.WebApi.Security.csproj | 4 + .../Docs/Builders/SwaggerOptionsBuilder.cs | 58 ------- .../Configurations/ISwaggerOptionsBuilder.cs | 1 - .../MessagingOptions.cs} | 10 +- .../Framework/MessagingMiddleware.cs | 8 +- .../api-gateway/Genocs.APIGateway/Startup.cs | 6 +- .../CorrelationIdFactory.cs | 2 +- .../OutboxCommandHandlerDecorator.cs | 2 +- .../Decorators/OutboxEventHandlerDecorator.cs | 2 +- .../Extensions.cs | 2 +- .../Services/ProductServiceClient.cs | 4 +- .../SignalROptions.cs} | 4 +- .../Framework/Extensions.cs | 6 +- testEnvironments.json | 17 ++ 89 files changed, 640 insertions(+), 457 deletions(-) rename src/Genocs.Auth/{ => Configurations}/IJwtOptionsBuilder.cs (83%) rename src/Genocs.Auth/Configurations/{JwtSettings.cs => JwtOptions.cs} (94%) rename src/Genocs.Common/Configurations/{AppSettings.cs => AppOptions.cs} (97%) rename src/Genocs.Core.Demo.WebApi/{Options/ExternalServiceSettings.cs => Configurations/ExternalServiceOptions.cs} (87%) rename src/Genocs.Core.Demo.WebApi/{Options/RabbitMQSettings.cs => Configurations/RabbitMQOptions.cs} (92%) rename src/Genocs.Core.Demo.WebApi/{Options/SecretSettings.cs => Configurations/SecretOptions.cs} (92%) create mode 100644 src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs rename src/Genocs.Discovery.Consul/Builders/{ConsulSettingsBuilder.cs => ConsulOptionsBuilder.cs} (50%) rename src/Genocs.Discovery.Consul/Configurations/{ConsulSettings.cs => ConsulOptions.cs} (75%) create mode 100644 src/Genocs.Discovery.Consul/Configurations/IConsulOptionsBuilder.cs delete mode 100644 src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs rename src/Genocs.HTTP.RestEase/Builders/{RestEaseBuilders.cs => RestEaseOptionsBuilder.cs} (62%) create mode 100644 src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs rename src/Genocs.HTTP.RestEase/Configurations/{RestEaseSettings.cs => RestEaseOptions.cs} (100%) delete mode 100644 src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs rename src/Genocs.HTTP/Configurations/{HttpClientSettings.cs => HttpClientOptions.cs} (81%) rename src/Genocs.LoadBalancing.Fabio/Builders/{FabioSettingsBuilder.cs => FabioOptionsBuilder.cs} (76%) rename src/Genocs.LoadBalancing.Fabio/Configurations/{FabioSettings.cs => FabioOptions.cs} (91%) rename src/Genocs.LoadBalancing.Fabio/Configurations/{IFabioSettingsBuilder.cs => IFabioOptionsBuilder.cs} (68%) rename src/Genocs.Logging/Configurations/{AzureSettings.cs => AzureOptions.cs} (100%) rename src/Genocs.Logging/Configurations/{ConsoleSettings.cs => ConsoleOptions.cs} (100%) rename src/Genocs.Logging/Configurations/{ElkSettings.cs => ElkOptions.cs} (100%) rename src/Genocs.Logging/Configurations/{LocalFileSettings.cs => LocalFileOptions.cs} (100%) rename src/Genocs.Logging/Configurations/{LoggerSettings.cs => LoggerOptions.cs} (86%) rename src/Genocs.Logging/Configurations/{LokiSettings.cs => LokiOptions.cs} (100%) rename src/Genocs.Logging/Configurations/{MongoSettings.cs => MongoOptions.cs} (100%) rename src/Genocs.Logging/Configurations/{SeqSettings.cs => SeqOptions.cs} (100%) rename src/Genocs.MessageBrokers.Outbox/Configurations/{OutboxSettings.cs => OutboxOptions.cs} (93%) create mode 100644 src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs delete mode 100644 src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs delete mode 100644 src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs rename src/apps/api-gateway/Genocs.APIGateway/{Options/MessagingSettings.cs => Configurations/MessagingOptions.cs} (51%) rename src/apps/signalr/Genocs.SignalR.WebApi/{Options/SignalRSettings.cs => Configurations/SignalROptions.cs} (66%) create mode 100644 testEnvironments.json diff --git a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs index 74aaad37..b0de9341 100644 --- a/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs +++ b/src/Genocs.Auth/AccessTokenValidatorMiddleware.cs @@ -17,7 +17,7 @@ public class AccessTokenValidatorMiddleware : IMiddleware /// /// The access token service. /// The options. - public AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtSettings options) + public AccessTokenValidatorMiddleware(IAccessTokenService accessTokenService, JwtOptions options) { _accessTokenService = accessTokenService; _endpoints = options.AllowAnonymousEndpoints ?? Enumerable.Empty(); diff --git a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs index 090698db..c81ab262 100644 --- a/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs +++ b/src/Genocs.Auth/Builders/JwtOptionsBuilder.cs @@ -4,7 +4,7 @@ namespace Genocs.Auth.Builders; internal sealed class JwtOptionsBuilder : IJwtOptionsBuilder { - private readonly JwtSettings _options = new(); + private readonly JwtOptions _options = new(); public IJwtOptionsBuilder WithIssuerSigningKey(string issuerSigningKey) { @@ -48,6 +48,6 @@ public IJwtOptionsBuilder WithValidAudience(string validAudience) return this; } - public JwtSettings Build() + public JwtOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Auth/IJwtOptionsBuilder.cs b/src/Genocs.Auth/Configurations/IJwtOptionsBuilder.cs similarity index 83% rename from src/Genocs.Auth/IJwtOptionsBuilder.cs rename to src/Genocs.Auth/Configurations/IJwtOptionsBuilder.cs index 341a7542..9675c881 100644 --- a/src/Genocs.Auth/IJwtOptionsBuilder.cs +++ b/src/Genocs.Auth/Configurations/IJwtOptionsBuilder.cs @@ -1,6 +1,4 @@ -using Genocs.Auth.Configurations; - -namespace Genocs.Auth; +namespace Genocs.Auth.Configurations; public interface IJwtOptionsBuilder { @@ -10,5 +8,5 @@ public interface IJwtOptionsBuilder IJwtOptionsBuilder WithLifetimeValidation(bool validateLifetime); IJwtOptionsBuilder WithAudienceValidation(bool validateAudience); IJwtOptionsBuilder WithValidAudience(string validAudience); - JwtSettings Build(); + JwtOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.Auth/Configurations/JwtSettings.cs b/src/Genocs.Auth/Configurations/JwtOptions.cs similarity index 94% rename from src/Genocs.Auth/Configurations/JwtSettings.cs rename to src/Genocs.Auth/Configurations/JwtOptions.cs index 8a0311f6..cc181c18 100644 --- a/src/Genocs.Auth/Configurations/JwtSettings.cs +++ b/src/Genocs.Auth/Configurations/JwtOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.Auth.Configurations; -public class JwtSettings +public class JwtOptions { /// /// Default section name. @@ -12,7 +12,7 @@ public class JwtSettings /// public bool Enabled { get; set; } public IEnumerable? AllowAnonymousEndpoints { get; set; } - public CertificateSettings? Certificate { get; set; } + public CertificateOptions? Certificate { get; set; } public string? Algorithm { get; set; } public string? Issuer { get; set; } public string? IssuerSigningKey { get; set; } @@ -48,7 +48,7 @@ public class JwtSettings public string? NameClaimType { get; set; } public string? RoleClaimType { get; set; } - public class CertificateSettings + public class CertificateOptions { public string? Location { get; set; } public string? RawData { get; set; } diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index 75e2ffb3..27b6a1d6 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -23,21 +23,21 @@ public static class Extensions public static IGenocsBuilder AddJwt( this IGenocsBuilder builder, - string sectionName = JwtSettings.Position, + string sectionName = JwtOptions.Position, Action? optionsFactory = null) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = JwtSettings.Position; + sectionName = JwtOptions.Position; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); return builder.AddJwt(options, optionsFactory); } private static IGenocsBuilder AddJwt( this IGenocsBuilder builder, - JwtSettings jwtSettings, + JwtOptions options, Action? optionsFactory = null) { if (!builder.TryRegister(RegistryName)) @@ -50,53 +50,53 @@ private static IGenocsBuilder AddJwt( builder.Services.AddSingleton(); builder.Services.AddTransient(); - if (!jwtSettings.Enabled) + if (!options.Enabled) { builder.Services.AddSingleton(); } var tokenValidationParameters = new TokenValidationParameters { - RequireAudience = jwtSettings.RequireAudience, - ValidIssuer = jwtSettings.ValidIssuer, - ValidIssuers = jwtSettings.ValidIssuers, - ValidateActor = jwtSettings.ValidateActor, - ValidAudience = jwtSettings.ValidAudience, - ValidAudiences = jwtSettings.ValidAudiences, - ValidateAudience = jwtSettings.ValidateAudience, - ValidateIssuer = jwtSettings.ValidateIssuer, - ValidateLifetime = jwtSettings.ValidateLifetime, - ValidateTokenReplay = jwtSettings.ValidateTokenReplay, - ValidateIssuerSigningKey = jwtSettings.ValidateIssuerSigningKey, - SaveSigninToken = jwtSettings.SaveSigninToken, - RequireExpirationTime = jwtSettings.RequireExpirationTime, - RequireSignedTokens = jwtSettings.RequireSignedTokens, + RequireAudience = options.RequireAudience, + ValidIssuer = options.ValidIssuer, + ValidIssuers = options.ValidIssuers, + ValidateActor = options.ValidateActor, + ValidAudience = options.ValidAudience, + ValidAudiences = options.ValidAudiences, + ValidateAudience = options.ValidateAudience, + ValidateIssuer = options.ValidateIssuer, + ValidateLifetime = options.ValidateLifetime, + ValidateTokenReplay = options.ValidateTokenReplay, + ValidateIssuerSigningKey = options.ValidateIssuerSigningKey, + SaveSigninToken = options.SaveSigninToken, + RequireExpirationTime = options.RequireExpirationTime, + RequireSignedTokens = options.RequireSignedTokens, ClockSkew = TimeSpan.Zero }; - if (!string.IsNullOrWhiteSpace(jwtSettings.AuthenticationType)) + if (!string.IsNullOrWhiteSpace(options.AuthenticationType)) { - tokenValidationParameters.AuthenticationType = jwtSettings.AuthenticationType; + tokenValidationParameters.AuthenticationType = options.AuthenticationType; } bool hasCertificate = false; - if (jwtSettings.Certificate is not null) + if (options.Certificate is not null) { X509Certificate2? certificate = null; - string? password = jwtSettings.Certificate.Password; + string? password = options.Certificate.Password; bool hasPassword = !string.IsNullOrWhiteSpace(password); - if (!string.IsNullOrWhiteSpace(jwtSettings.Certificate.Location)) + if (!string.IsNullOrWhiteSpace(options.Certificate.Location)) { certificate = hasPassword - ? new X509Certificate2(jwtSettings.Certificate.Location, password) - : new X509Certificate2(jwtSettings.Certificate.Location); + ? new X509Certificate2(options.Certificate.Location, password) + : new X509Certificate2(options.Certificate.Location); string keyType = certificate.HasPrivateKey ? "with private key" : "with public key only"; - Console.WriteLine($"Loaded X.509 certificate from location: '{jwtSettings.Certificate.Location}' {keyType}."); + Console.WriteLine($"Loaded X.509 certificate from location: '{options.Certificate.Location}' {keyType}."); } - if (!string.IsNullOrWhiteSpace(jwtSettings.Certificate.RawData)) + if (!string.IsNullOrWhiteSpace(options.Certificate.RawData)) { - byte[] rawData = Convert.FromBase64String(jwtSettings.Certificate.RawData); + byte[] rawData = Convert.FromBase64String(options.Certificate.RawData); certificate = hasPassword ? new X509Certificate2(rawData, password) : new X509Certificate2(rawData); @@ -106,9 +106,9 @@ private static IGenocsBuilder AddJwt( if (certificate is not null) { - if (string.IsNullOrWhiteSpace(jwtSettings.Algorithm)) + if (string.IsNullOrWhiteSpace(options.Algorithm)) { - jwtSettings.Algorithm = SecurityAlgorithms.RsaSha256; + options.Algorithm = SecurityAlgorithms.RsaSha256; } hasCertificate = true; @@ -118,54 +118,54 @@ private static IGenocsBuilder AddJwt( } } - if (!string.IsNullOrWhiteSpace(jwtSettings.IssuerSigningKey) && !hasCertificate) + if (!string.IsNullOrWhiteSpace(options.IssuerSigningKey) && !hasCertificate) { - if (string.IsNullOrWhiteSpace(jwtSettings.Algorithm) || hasCertificate) + if (string.IsNullOrWhiteSpace(options.Algorithm) || hasCertificate) { - jwtSettings.Algorithm = SecurityAlgorithms.HmacSha256; + options.Algorithm = SecurityAlgorithms.HmacSha256; } - byte[] rawKey = Encoding.UTF8.GetBytes(jwtSettings.IssuerSigningKey); + byte[] rawKey = Encoding.UTF8.GetBytes(options.IssuerSigningKey); tokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(rawKey); Console.WriteLine("Using symmetric encryption for issuing tokens."); } - if (!string.IsNullOrWhiteSpace(jwtSettings.NameClaimType)) + if (!string.IsNullOrWhiteSpace(options.NameClaimType)) { - tokenValidationParameters.NameClaimType = jwtSettings.NameClaimType; + tokenValidationParameters.NameClaimType = options.NameClaimType; } - if (!string.IsNullOrWhiteSpace(jwtSettings.RoleClaimType)) + if (!string.IsNullOrWhiteSpace(options.RoleClaimType)) { - tokenValidationParameters.RoleClaimType = jwtSettings.RoleClaimType; + tokenValidationParameters.RoleClaimType = options.RoleClaimType; } builder.Services .AddAuthentication(o => { - o.DefaultAuthenticateScheme = jwtSettings.Challenge; - o.DefaultChallengeScheme = jwtSettings.Challenge; - o.DefaultScheme = jwtSettings.Challenge; + o.DefaultAuthenticateScheme = options.Challenge; + o.DefaultChallengeScheme = options.Challenge; + o.DefaultScheme = options.Challenge; }) .AddJwtBearer(o => { - o.Authority = jwtSettings.Authority; - o.Audience = jwtSettings.Audience; - o.MetadataAddress = jwtSettings.MetadataAddress; - o.SaveToken = jwtSettings.SaveToken; - o.RefreshOnIssuerKeyNotFound = jwtSettings.RefreshOnIssuerKeyNotFound; - o.RequireHttpsMetadata = jwtSettings.RequireHttpsMetadata; - o.IncludeErrorDetails = jwtSettings.IncludeErrorDetails; + o.Authority = options.Authority; + o.Audience = options.Audience; + o.MetadataAddress = options.MetadataAddress; + o.SaveToken = options.SaveToken; + o.RefreshOnIssuerKeyNotFound = options.RefreshOnIssuerKeyNotFound; + o.RequireHttpsMetadata = options.RequireHttpsMetadata; + o.IncludeErrorDetails = options.IncludeErrorDetails; o.TokenValidationParameters = tokenValidationParameters; - if (!string.IsNullOrWhiteSpace(jwtSettings.Challenge)) + if (!string.IsNullOrWhiteSpace(options.Challenge)) { - o.Challenge = jwtSettings.Challenge; + o.Challenge = options.Challenge; } optionsFactory?.Invoke(o); }); - builder.Services.AddSingleton(jwtSettings); + builder.Services.AddSingleton(options); builder.Services.AddSingleton(tokenValidationParameters); return builder; @@ -180,29 +180,28 @@ private static IGenocsBuilder AddJwt( /// The Genocs builder you can use for chain. public static IGenocsBuilder AddOpenIdJwt( this IGenocsBuilder builder, - string sectionName = JwtSettings.Position) + string sectionName = JwtOptions.Position) { - var jwtSettings = new JwtSettings(); - builder.Configuration.GetSection(sectionName).Bind(jwtSettings); + JwtOptions options = builder.Configuration.GetOptions(sectionName); - string metadataAddress = $"{jwtSettings.Issuer}{jwtSettings.MetadataAddress}"; + string metadataAddress = $"{options.Issuer}{options.MetadataAddress}"; var configurationManager = new ConfigurationManager(metadataAddress, new OpenIdConnectConfigurationRetriever()); builder.Services .AddAuthentication(o => { - o.DefaultAuthenticateScheme = jwtSettings.Challenge; - o.DefaultChallengeScheme = jwtSettings.Challenge; - o.DefaultScheme = jwtSettings.Challenge; + o.DefaultAuthenticateScheme = options.Challenge; + o.DefaultChallengeScheme = options.Challenge; + o.DefaultScheme = options.Challenge; }) .AddJwtBearer(o => { - o.IncludeErrorDetails = jwtSettings.IncludeErrorDetails; - o.RefreshOnIssuerKeyNotFound = jwtSettings.RefreshOnIssuerKeyNotFound; + o.IncludeErrorDetails = options.IncludeErrorDetails; + o.RefreshOnIssuerKeyNotFound = options.RefreshOnIssuerKeyNotFound; o.MetadataAddress = metadataAddress; o.ConfigurationManager = configurationManager; - o.Audience = jwtSettings.Audience; + o.Audience = options.Audience; }); return builder; @@ -217,22 +216,21 @@ public static IGenocsBuilder AddOpenIdJwt( /// Whenever mandatory data like 'IssuerSigningKey' is missing. public static IGenocsBuilder AddPrivateKeyJwt( this IGenocsBuilder builder, - string sectionName = JwtSettings.Position) + string sectionName = JwtOptions.Position) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = JwtSettings.Position; + sectionName = JwtOptions.Position; } - var jwtSettings = new JwtSettings(); - builder.Configuration.GetSection(sectionName).Bind(jwtSettings); + JwtOptions options = builder.Configuration.GetOptions(sectionName); - if (string.IsNullOrWhiteSpace(jwtSettings.IssuerSigningKey)) + if (string.IsNullOrWhiteSpace(options.IssuerSigningKey)) { throw new InvalidOperationException("Issuer signing key is missing."); } - SecurityKey signingKey = SecurityKeyBuilder.CreateRsaSecurityKey(jwtSettings.IssuerSigningKey); + SecurityKey signingKey = SecurityKeyBuilder.CreateRsaSecurityKey(options.IssuerSigningKey); builder.Services .AddAuthentication(o => @@ -241,17 +239,17 @@ public static IGenocsBuilder AddPrivateKeyJwt( }) .AddJwtBearer(o => { - o.SaveToken = jwtSettings.SaveToken; - o.RequireHttpsMetadata = jwtSettings.RequireHttpsMetadata; + o.SaveToken = options.SaveToken; + o.RequireHttpsMetadata = options.RequireHttpsMetadata; o.TokenValidationParameters = new TokenValidationParameters() { IssuerSigningKey = signingKey, - ValidateAudience = jwtSettings.ValidateAudience, - ValidAudience = jwtSettings.ValidAudience, - ValidateIssuer = jwtSettings.ValidateIssuer, - ValidIssuer = jwtSettings.ValidIssuer, - ValidateLifetime = jwtSettings.ValidateLifetime, - ValidateIssuerSigningKey = jwtSettings.ValidateIssuerSigningKey + ValidateAudience = options.ValidateAudience, + ValidAudience = options.ValidAudience, + ValidateIssuer = options.ValidateIssuer, + ValidIssuer = options.ValidIssuer, + ValidateLifetime = options.ValidateLifetime, + ValidateIssuerSigningKey = options.ValidateIssuerSigningKey }; }); diff --git a/src/Genocs.Auth/Handlers/JwtHandler.cs b/src/Genocs.Auth/Handlers/JwtHandler.cs index fe8ec6c3..36e197e0 100644 --- a/src/Genocs.Auth/Handlers/JwtHandler.cs +++ b/src/Genocs.Auth/Handlers/JwtHandler.cs @@ -20,12 +20,12 @@ internal sealed class JwtHandler : IJwtHandler }; private readonly JwtSecurityTokenHandler _jwtSecurityTokenHandler = new(); - private readonly JwtSettings _options; + private readonly JwtOptions _options; private readonly TokenValidationParameters _tokenValidationParameters; private readonly SigningCredentials _signingCredentials; private readonly string? _issuer; - public JwtHandler(JwtSettings options, TokenValidationParameters tokenValidationParameters) + public JwtHandler(JwtOptions options, TokenValidationParameters tokenValidationParameters) { var issuerSigningKey = tokenValidationParameters.IssuerSigningKey; if (issuerSigningKey is null) diff --git a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs index 07ebfce6..8ce4fb58 100644 --- a/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs +++ b/src/Genocs.Auth/Services/InMemoryAccessTokenService.cs @@ -14,7 +14,7 @@ internal sealed class InMemoryAccessTokenService : IAccessTokenService public InMemoryAccessTokenService( IMemoryCache cache, IHttpContextAccessor httpContextAccessor, - JwtSettings jwtOptions) + JwtOptions jwtOptions) { _cache = cache; _httpContextAccessor = httpContextAccessor; diff --git a/src/Genocs.Common/Configurations/AppSettings.cs b/src/Genocs.Common/Configurations/AppOptions.cs similarity index 97% rename from src/Genocs.Common/Configurations/AppSettings.cs rename to src/Genocs.Common/Configurations/AppOptions.cs index 70dedf7b..a5596f68 100644 --- a/src/Genocs.Common/Configurations/AppSettings.cs +++ b/src/Genocs.Common/Configurations/AppOptions.cs @@ -3,7 +3,7 @@ namespace Genocs.Common.Configurations; /// /// The application settings. /// -public class AppSettings +public class AppOptions { /// /// Default section name. diff --git a/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs b/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs similarity index 87% rename from src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs rename to src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs index 5b7386f4..c52cacaa 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/ExternalServiceSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs @@ -2,7 +2,10 @@ namespace Genocs.Core.Demo.WebApi.Options; -public class ExternalServiceSettings : IValidatableObject +/// +/// This class implements Options pattern with Validation. +/// +public class ExternalServiceOptions : IValidatableObject { public const string Position = "ExternalService"; diff --git a/src/Genocs.Core.Demo.WebApi/Options/RabbitMQSettings.cs b/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs similarity index 92% rename from src/Genocs.Core.Demo.WebApi/Options/RabbitMQSettings.cs rename to src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs index 0afe6136..92bc8656 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/RabbitMQSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.Core.Demo.WebApi.Options; -public class RabbitMQSettings +public class RabbitMQOptions { public const string Position = "RabbitMQ"; diff --git a/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs b/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs similarity index 92% rename from src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs rename to src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs index 08d05a8a..51ef9d67 100644 --- a/src/Genocs.Core.Demo.WebApi/Options/SecretSettings.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.Core.Demo.WebApi.Options; -public class SecretSettings +public class SecretOptions { /// /// Default section name. diff --git a/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs b/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs new file mode 100644 index 00000000..2f847694 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs @@ -0,0 +1,8 @@ +namespace Genocs.Core.Demo.WebApi.Options; + +public class VerificationServiceOptions +{ + public const string Position = "VerificationService"; + + public string ApiKey { get; set; } = default!; +} diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs index 44726b15..9aaea49b 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs @@ -7,9 +7,9 @@ namespace Genocs.Core.Demo.WebApi.Controllers; [Route("")] public class HomeController : ControllerBase { - public readonly SecretSettings _secretSettings; + public readonly SecretOptions _secretSettings; - public HomeController(SecretSettings secretSettings) + public HomeController(SecretOptions secretSettings) { _secretSettings = secretSettings ?? throw new ArgumentNullException(nameof(secretSettings)); } diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs index f41c1804..f4fe8d8d 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs @@ -32,12 +32,14 @@ public static IGenocsBuilder AddApplicationServices(this IGenocsBuilder builder) // builder.Services.AddSingleton(settings); // Option 2: In this way ExternalServiceSettings is available for dependency injection. By using IOptions you can access the settings. - builder.Services.AddOptions() - .BindConfiguration(ExternalServiceSettings.Position) + builder.Services.AddOptions() + .BindConfiguration(ExternalServiceOptions.Position) .ValidateDataAnnotations() .ValidateOnStart(); // builder.Services.AddSingleton, ConfigureWebApiSettings>(); + ExternalServiceOptions settings = builder.Configuration.GetOptions(ExternalServiceOptions.Position); + builder.Services.AddSingleton(settings); // Add the External Service http Client builder.Services.AddTransient(); diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs index ec7625ca..4d0f1984 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using Genocs.Core.Demo.WebApi.Options; +using Genocs.Core.Builders; +using Genocs.Core.Demo.WebApi.Options; using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; @@ -50,10 +51,9 @@ public static IServiceCollection AddAzureServiceBusQueue(this IServiceCollection public static IServiceCollection AddCustomMassTransit(this IServiceCollection services, IConfiguration configuration) { - var rabbitMQSettings = new RabbitMQSettings(); - configuration.GetSection(RabbitMQSettings.Position).Bind(rabbitMQSettings); + RabbitMQOptions options = configuration.GetOptions(RabbitMQOptions.Position); - services.AddSingleton(rabbitMQSettings); + services.AddSingleton(options); services.AddMassTransit(x => { @@ -63,11 +63,11 @@ public static IServiceCollection AddCustomMassTransit(this IServiceCollection se { cfg.ConfigureEndpoints(context); //cfg.UseHealthCheck(context); - cfg.Host(rabbitMQSettings.HostName, rabbitMQSettings.VirtualHost, + cfg.Host(options.HostName, options.VirtualHost, h => { - h.Username(rabbitMQSettings.UserName); - h.Password(rabbitMQSettings.Password); + h.Username(options.UserName); + h.Password(options.Password); } ); }); diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs index 0bce6027..f7716aff 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs @@ -15,7 +15,7 @@ public class ExternalServiceClient : IExternalServiceClient private readonly IHttpClient _client; private readonly string _url; private readonly IHasher _hasher; - private readonly ExternalServiceOptions _externalServiceSettings; + private readonly ExternalServiceOptions _externalServiceOptions; /// /// The standard constructor. @@ -27,12 +27,12 @@ public class ExternalServiceClient : IExternalServiceClient public ExternalServiceClient( IHttpClient client, IHasher hasher, - HttpClientSettings httpClientSettings, - IOptions options) + HttpClientOptions httpClientSettings, + IOptions options) { _client = client ?? throw new ArgumentNullException(nameof(client)); _hasher = hasher ?? throw new ArgumentNullException(nameof(hasher)); - _externalServiceSettings = options.Value ?? throw new ArgumentNullException(nameof(options)); + _externalServiceOptions = options.Value ?? throw new ArgumentNullException(nameof(options)); if (httpClientSettings is null) { @@ -51,8 +51,8 @@ public ExternalServiceClient( private void SetHeaders(string request) { - string hash = _hasher.Hash(request, _externalServiceSettings.Private); - string headerData = $"Credential={_externalServiceSettings.Public}, Signature={hash}"; + string hash = _hasher.Hash(request, _externalServiceOptions.Private); + string headerData = $"Credential={_externalServiceOptions.Public}, Signature={hash}"; _client.SetHeaders(h => h.TryAddWithoutValidation("Authorization", headerData)); } @@ -67,7 +67,7 @@ public async Task IssueAsync(IssuingRequest request) SetHeaders(serializedRequest); using (var content = new StringContent(serializedRequest, System.Text.Encoding.UTF8, "application/json")) { - return await _client.PostAsync($"{_url}/redemptions/gift-cards/{_externalServiceSettings.Caller}/direct-issue", content); + return await _client.PostAsync($"{_url}/redemptions/gift-cards/{_externalServiceOptions.Caller}/direct-issue", content); } } diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs new file mode 100644 index 00000000..221a71f2 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.Models.cs @@ -0,0 +1,66 @@ +using Newtonsoft.Json; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The Internal User verification request. +/// +public class VerificationApiRequest +{ + [JsonProperty("type")] + public string? Type { get; set; } + + [JsonProperty("joinedDate")] + public string? JoinedDate { get; set; } + + [JsonProperty("email")] + public string? Email { get; set; } + + [JsonProperty("personDetails")] + public PersonDetailsRequest? Details { get; set; } +} + +public class PersonDetailsRequest +{ + [JsonProperty("firstName")] + public string? FirstName { get; set; } + + [JsonProperty("lastName")] + public string? LastName { get; set; } + + [JsonProperty("dob")] + public string? DateOfBirth { get; set; } + + [JsonProperty("gender")] + public string? Gender { get; set; } + + [JsonProperty("nationality")] + public string? Nationality { get; set; } +} + +/// +/// The internal User verification response. +/// +public class VerificationApiResponse +{ + [JsonProperty("id")] + public string? Id { get; set; } + + [JsonProperty("createdAt")] + public string? CreatedAt { get; set; } + + [JsonProperty("updatedAt")] + public string? UpdatedAt { get; set; } + + [JsonProperty("type")] + public string? Type { get; set; } + + [JsonProperty("joinedDate")] + public string? JoinedDate { get; set; } + + [JsonProperty("email")] + public string? Email { get; set; } + + [JsonProperty("personDetails")] + public PersonDetailsRequest? Details { get; set; } +} \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs new file mode 100644 index 00000000..7129c59f --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/IVerificationServiceClient.cs @@ -0,0 +1,15 @@ +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The External WebApi client definition. +/// This API client is used to verify the user. +/// +public interface IVerificationServiceClient +{ + /// + /// Send a request To verify the user. + /// + /// The request with the user data. + /// The user verification response. + Task VerifyAsync(VerificationApiRequest request); +} diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs new file mode 100644 index 00000000..e9840a86 --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs @@ -0,0 +1,65 @@ +using Genocs.Core.Demo.WebApi.Options; +using Genocs.HTTP; +using Genocs.HTTP.Configurations; +using Newtonsoft.Json; + +namespace Genocs.Core.Demo.WebApi.Infrastructure.Services; + +/// +/// The Verification WebApi client implementation. +/// +public class VerificationServiceClient : IVerificationServiceClient +{ + private readonly IHttpClient _client; + private readonly string _url; + private readonly VerificationServiceOptions _externalServiceSettings; + + /// + /// The standard constructor. + /// + /// The http client. + /// The http client settings. + /// The security settings. + public VerificationServiceClient( + IHttpClient client, + HttpClientOptions httpClientSettings, + VerificationServiceOptions externalServiceSettings) + { + _client = client ?? throw new ArgumentNullException(nameof(client)); + _externalServiceSettings = externalServiceSettings ?? throw new ArgumentNullException(nameof(externalServiceSettings)); + + if (httpClientSettings is null) + { + throw new ArgumentNullException(nameof(httpClientSettings)); + } + + string? url = httpClientSettings?.Services?["user_verifier"]; + + if (string.IsNullOrWhiteSpace(url)) + { + throw new Exception("user_verifier http client settings cannot be null"); + } + + _url = url; + } + + private void SetHeaders() + { + _client.SetHeaders(h => h.TryAddWithoutValidation("Authorization", _externalServiceSettings.ApiKey)); + } + + /// + /// The method to verify the user. + /// + /// The verification api request. + /// The response. + public async Task VerifyAsync(VerificationApiRequest request) + { + SetHeaders(); + string serializedRequest = JsonConvert.SerializeObject(request); + using (var content = new StringContent(serializedRequest, System.Text.Encoding.UTF8, "application/json")) + { + return await _client.PostAsync($"{_url}/clients", request); + } + } +} \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index 691a782d..6fbac463 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -6,6 +6,7 @@ using Genocs.Persistence.MongoDb.Extensions; using Genocs.Secrets.AzureKeyVault; using Genocs.Tracing; +using Genocs.WebApi.Security; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; using System.Reflection; @@ -23,7 +24,6 @@ services .AddGenocs(builder.Configuration) - .AddPrivateKeyJwt() .AddOpenTelemetry() .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()) @@ -39,10 +39,9 @@ services.AddHealthChecks(); -services.Configure(builder.Configuration.GetSection(SecretSettings.Position)); +services.Configure(builder.Configuration.GetSection(SecretOptions.Position)); -var settings = new SecretSettings(); -builder.Configuration.GetSection(SecretSettings.Position).Bind(settings); +SecretOptions settings = builder.Configuration.GetOptions(SecretOptions.Position); services.AddSingleton(settings); services.Configure(options => diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs index 1d951979..8436b812 100644 --- a/src/Genocs.Core/Builders/Extensions.cs +++ b/src/Genocs.Core/Builders/Extensions.cs @@ -20,18 +20,18 @@ public static class Extensions public static IGenocsBuilder AddGenocs(this IServiceCollection services, IConfiguration? configuration = null) { var builder = GenocsBuilder.Create(services, configuration); - var options = builder.GetOptions(AppSettings.Position); - services.AddSingleton(options); + var settings = builder.GetOptions(AppOptions.Position); + services.AddSingleton(settings); builder.Services.AddMemoryCache(); services.AddSingleton(); - if (!options.DisplayBanner || string.IsNullOrWhiteSpace(options.Name)) + if (!settings.DisplayBanner || string.IsNullOrWhiteSpace(settings.Name)) { return builder; } - string version = options.DisplayVersion ? $" {options.Version}" : string.Empty; - Console.WriteLine(Figgle.FiggleFonts.Doom.Render(options.Name + version)); + string version = settings.DisplayVersion ? $" {settings.Version}" : string.Empty; + Console.WriteLine(Figgle.FiggleFonts.Doom.Render(settings.Name + version)); ConsoleColor current = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("Runtime Version: {0}", Environment.Version.ToString()); diff --git a/src/Genocs.Core/README_NUGET.md b/src/Genocs.Core/README_NUGET.md index 2683d26d..7aebc35c 100644 --- a/src/Genocs.Core/README_NUGET.md +++ b/src/Genocs.Core/README_NUGET.md @@ -1,7 +1,7 @@ # .NET Core library This package contains a set of base functionalities designed by Genocs. -The library is built to be used on .NET standard 2.1 and NET6 or NET7 as well. +The library is built to be used on .NET standard 2.1 and NET6, NET7 NET8. ## Description @@ -15,6 +15,10 @@ Please check the GitHub repository getting more info. ## Release notes +### [2024-06-22] 6.0.0-preview.1.0 +- Upgrade toward Version 6.0.0 +- + ### [2024-01-23] 5.0.6 - Refactory Settings - Updated nuget packages diff --git a/src/Genocs.Discovery.Consul/Builders/ConsulSettingsBuilder.cs b/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs similarity index 50% rename from src/Genocs.Discovery.Consul/Builders/ConsulSettingsBuilder.cs rename to src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs index 23f1e1d8..f5b29178 100644 --- a/src/Genocs.Discovery.Consul/Builders/ConsulSettingsBuilder.cs +++ b/src/Genocs.Discovery.Consul/Builders/ConsulOptionsBuilder.cs @@ -2,63 +2,63 @@ namespace Genocs.Discovery.Consul.Builders; -internal sealed class ConsulSettingsBuilder : IConsulSettingsBuilder +internal sealed class ConsulOptionsBuilder : IConsulOptionsBuilder { - private readonly ConsulSettings _options = new(); + private readonly ConsulOptions _options = new(); - public IConsulSettingsBuilder Enable(bool enabled) + public IConsulOptionsBuilder Enable(bool enabled) { _options.Enabled = enabled; return this; } - public IConsulSettingsBuilder WithUrl(string url) + public IConsulOptionsBuilder WithUrl(string url) { _options.Url = url; return this; } - public IConsulSettingsBuilder WithService(string service) + public IConsulOptionsBuilder WithService(string service) { _options.Service = service; return this; } - public IConsulSettingsBuilder WithAddress(string address) + public IConsulOptionsBuilder WithAddress(string address) { _options.Address = address; return this; } - public IConsulSettingsBuilder WithEnabledPing(bool pingEnabled) + public IConsulOptionsBuilder WithEnabledPing(bool pingEnabled) { _options.PingEnabled = pingEnabled; return this; } - public IConsulSettingsBuilder WithPingEndpoint(string pingEndpoint) + public IConsulOptionsBuilder WithPingEndpoint(string pingEndpoint) { _options.PingEndpoint = pingEndpoint; return this; } - public IConsulSettingsBuilder WithPingInterval(string pingInterval) + public IConsulOptionsBuilder WithPingInterval(string pingInterval) { _options.PingInterval = pingInterval; return this; } - public IConsulSettingsBuilder WithRemoteAfterInterval(string remoteAfterInterval) + public IConsulOptionsBuilder WithRemoteAfterInterval(string remoteAfterInterval) { _options.RemoveAfterInterval = remoteAfterInterval; return this; } - public IConsulSettingsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace) + public IConsulOptionsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace) { _options.SkipLocalhostDockerDnsReplace = skipLocalhostDockerDnsReplace; return this; } - public ConsulSettings Build() => _options; + public ConsulOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/Configurations/ConsulSettings.cs b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs similarity index 75% rename from src/Genocs.Discovery.Consul/Configurations/ConsulSettings.cs rename to src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs index a07ff2ef..3f1f6cc9 100644 --- a/src/Genocs.Discovery.Consul/Configurations/ConsulSettings.cs +++ b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs @@ -1,7 +1,12 @@ namespace Genocs.Discovery.Consul.Configurations; -public class ConsulSettings +public class ConsulOptions { + /// + /// Default section name. + /// + public const string Position = "consul"; + public bool Enabled { get; set; } public string? Url { get; set; } public string? Service { get; set; } @@ -15,9 +20,9 @@ public class ConsulSettings public IDictionary? Meta { get; set; } public bool EnableTagOverride { get; set; } public bool SkipLocalhostDockerDnsReplace { get; set; } - public ConnectSettings? Connect { get; set; } + public ConnectOptions? Connect { get; set; } - public class ConnectSettings + public class ConnectOptions { public bool Enabled { get; set; } } diff --git a/src/Genocs.Discovery.Consul/Configurations/IConsulOptionsBuilder.cs b/src/Genocs.Discovery.Consul/Configurations/IConsulOptionsBuilder.cs new file mode 100644 index 00000000..63b5aeda --- /dev/null +++ b/src/Genocs.Discovery.Consul/Configurations/IConsulOptionsBuilder.cs @@ -0,0 +1,15 @@ +namespace Genocs.Discovery.Consul.Configurations; + +public interface IConsulOptionsBuilder +{ + IConsulOptionsBuilder Enable(bool enabled); + IConsulOptionsBuilder WithUrl(string url); + IConsulOptionsBuilder WithService(string service); + IConsulOptionsBuilder WithAddress(string address); + IConsulOptionsBuilder WithEnabledPing(bool pingEnabled); + IConsulOptionsBuilder WithPingEndpoint(string pingEndpoint); + IConsulOptionsBuilder WithPingInterval(string pingInterval); + IConsulOptionsBuilder WithRemoteAfterInterval(string remoteAfterInterval); + IConsulOptionsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace); + ConsulOptions Build(); +} \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs b/src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs deleted file mode 100644 index 1288918d..00000000 --- a/src/Genocs.Discovery.Consul/Configurations/IConsulSettingsBuilder.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Genocs.Discovery.Consul.Configurations; - -public interface IConsulSettingsBuilder -{ - IConsulSettingsBuilder Enable(bool enabled); - IConsulSettingsBuilder WithUrl(string url); - IConsulSettingsBuilder WithService(string service); - IConsulSettingsBuilder WithAddress(string address); - IConsulSettingsBuilder WithEnabledPing(bool pingEnabled); - IConsulSettingsBuilder WithPingEndpoint(string pingEndpoint); - IConsulSettingsBuilder WithPingInterval(string pingInterval); - IConsulSettingsBuilder WithRemoteAfterInterval(string remoteAfterInterval); - IConsulSettingsBuilder WithSkippingLocalhostDockerDnsReplace(bool skipLocalhostDockerDnsReplace); - ConsulSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Discovery.Consul/Extensions.cs b/src/Genocs.Discovery.Consul/Extensions.cs index e412aa8b..a8a8c511 100644 --- a/src/Genocs.Discovery.Consul/Extensions.cs +++ b/src/Genocs.Discovery.Consul/Extensions.cs @@ -27,24 +27,24 @@ public static IGenocsBuilder AddConsul( sectionName = SectionName; } - var consulOptions = builder.GetOptions(sectionName); - var httpClientOptions = builder.GetOptions(httpClientSectionName); + var consulOptions = builder.GetOptions(sectionName); + var httpClientOptions = builder.GetOptions(httpClientSectionName); return builder.AddConsul(consulOptions, httpClientOptions); } public static IGenocsBuilder AddConsul( this IGenocsBuilder builder, - Func buildOptions, - HttpClientSettings httpClientOptions) + Func buildOptions, + HttpClientOptions httpClientOptions) { - var options = buildOptions(new ConsulSettingsBuilder()).Build(); + var options = buildOptions(new ConsulOptionsBuilder()).Build(); return builder.AddConsul(options, httpClientOptions); } public static IGenocsBuilder AddConsul( this IGenocsBuilder builder, - ConsulSettings options, - HttpClientSettings httpClientOptions) + ConsulOptions options, + HttpClientOptions httpClientOptions) { builder.Services.AddSingleton(options); if (!options.Enabled || !builder.TryRegister(RegistryName)) @@ -78,9 +78,9 @@ public static void AddConsulHttpClient(this IGenocsBuilder builder, string clien => builder.Services.AddHttpClient(clientName) .AddHttpMessageHandler(c => new ConsulServiceDiscoveryMessageHandler( c.GetRequiredService(), - c.GetRequiredService(), serviceName, true)); + c.GetRequiredService(), serviceName, true)); - private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulSettings options) + private static ServiceRegistration CreateConsulAgentRegistration(this IGenocsBuilder builder, ConsulOptions options) { bool enabled = options.Enabled; string? consulEnabled = Environment.GetEnvironmentVariable("CONSUL_ENABLED")?.ToLowerInvariant(); diff --git a/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs b/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs index ac4f97fa..23bef586 100644 --- a/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs +++ b/src/Genocs.Discovery.Consul/Http/ConsulHttpClient.cs @@ -5,8 +5,12 @@ namespace Genocs.Discovery.Consul.Http; internal sealed class ConsulHttpClient : GenocsHttpClient, IConsulHttpClient { - public ConsulHttpClient(HttpClient client, HttpClientSettings options, IHttpClientSerializer serializer, - ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) + public ConsulHttpClient( + HttpClient client, + HttpClientOptions options, + IHttpClientSerializer serializer, + ICorrelationContextFactory correlationContextFactory, + ICorrelationIdFactory correlationIdFactory) : base(client, options, serializer, correlationContextFactory, correlationIdFactory) { } diff --git a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs index 0888cb6f..481db53f 100644 --- a/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs +++ b/src/Genocs.Discovery.Consul/MessageHandlers/ConsulServiceDiscoveryMessageHandler.cs @@ -5,25 +5,30 @@ namespace Genocs.Discovery.Consul.MessageHandlers; internal sealed class ConsulServiceDiscoveryMessageHandler : DelegatingHandler { private readonly IConsulServicesRegistry _servicesRegistry; - private readonly ConsulSettings _options; + private readonly ConsulOptions _options; private readonly string? _serviceName; private readonly bool? _overrideRequestUri; public ConsulServiceDiscoveryMessageHandler( IConsulServicesRegistry servicesRegistry, - ConsulSettings options, + ConsulOptions options, string? serviceName = null, bool? overrideRequestUri = null) { - if (string.IsNullOrWhiteSpace(options.Url)) - { - throw new InvalidOperationException("Consul URL was not provided."); - } - _servicesRegistry = servicesRegistry; _options = options; _serviceName = serviceName; _overrideRequestUri = overrideRequestUri; + + if (!options.Enabled) + { + return; + } + + if (string.IsNullOrWhiteSpace(options.Url)) + { + throw new InvalidOperationException("Consul URL was not provided."); + } } protected override async Task SendAsync( diff --git a/src/Genocs.HTTP.RestEase/Builders/RestEaseBuilders.cs b/src/Genocs.HTTP.RestEase/Builders/RestEaseOptionsBuilder.cs similarity index 62% rename from src/Genocs.HTTP.RestEase/Builders/RestEaseBuilders.cs rename to src/Genocs.HTTP.RestEase/Builders/RestEaseOptionsBuilder.cs index da1d0b69..55bb2367 100644 --- a/src/Genocs.HTTP.RestEase/Builders/RestEaseBuilders.cs +++ b/src/Genocs.HTTP.RestEase/Builders/RestEaseOptionsBuilder.cs @@ -1,26 +1,26 @@ -using Genocs.HTTP.RestEase.Options; +using Genocs.HTTP.RestEase.Configurations; namespace Genocs.HTTP.RestEase.Builders; -internal sealed class RestEaseSettingsBuilder : IRestEaseSettingsBuilder +internal sealed class RestEaseOptionsBuilder : IRestEaseOptionsBuilder { - private readonly RestEaseSettings _options = new(); - private readonly List _services = new(); + private readonly RestEaseOptions _options = new(); + private readonly List _services = new(); - public IRestEaseSettingsBuilder WithLoadBalancer(string loadBalancer) + public IRestEaseOptionsBuilder WithLoadBalancer(string loadBalancer) { _options.LoadBalancer = loadBalancer; return this; } - public IRestEaseSettingsBuilder WithService(Func buildService) + public IRestEaseOptionsBuilder WithService(Func buildService) { var service = buildService(new RestEaseServiceBuilder()).Build(); _services.Add(service); return this; } - public RestEaseSettings Build() + public RestEaseOptions Build() { _options.Services = _services; return _options; @@ -28,7 +28,7 @@ public RestEaseSettings Build() private class RestEaseServiceBuilder : IRestEaseServiceBuilder { - private readonly RestEaseSettings.Service _service = new(); + private readonly RestEaseOptions.Service _service = new(); public IRestEaseServiceBuilder WithName(string name) { @@ -54,6 +54,6 @@ public IRestEaseServiceBuilder WithPort(int port) return this; } - public RestEaseSettings.Service Build() => _service; + public RestEaseOptions.Service Build() => _service; } } \ No newline at end of file diff --git a/src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs b/src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs new file mode 100644 index 00000000..f013109a --- /dev/null +++ b/src/Genocs.HTTP.RestEase/Configurations/IRestEaseOptionsBuilder.cs @@ -0,0 +1,8 @@ +namespace Genocs.HTTP.RestEase.Configurations; + +public interface IRestEaseOptionsBuilder +{ + IRestEaseOptionsBuilder WithLoadBalancer(string loadBalancer); + IRestEaseOptionsBuilder WithService(Func buildService); + RestEaseOptions Build(); +} \ No newline at end of file diff --git a/src/Genocs.HTTP.RestEase/Configurations/RestEaseSettings.cs b/src/Genocs.HTTP.RestEase/Configurations/RestEaseOptions.cs similarity index 100% rename from src/Genocs.HTTP.RestEase/Configurations/RestEaseSettings.cs rename to src/Genocs.HTTP.RestEase/Configurations/RestEaseOptions.cs diff --git a/src/Genocs.HTTP.RestEase/Extensions.cs b/src/Genocs.HTTP.RestEase/Extensions.cs index d22e4477..d37c8ce0 100644 --- a/src/Genocs.HTTP.RestEase/Extensions.cs +++ b/src/Genocs.HTTP.RestEase/Extensions.cs @@ -17,9 +17,13 @@ public static class Extensions private const string SectionName = "restEase"; private const string RegistryName = "http.restEase"; - public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, - string sectionName = SectionName, string consulSectionName = "consul", string fabioSectionName = "fabio", - string httpClientSectionName = "httpClient") + public static IGenocsBuilder AddServiceClient( + this IGenocsBuilder builder, + string serviceName, + string sectionName = SectionName, + string consulSectionName = "consul", + string fabioSectionName = "fabio", + string httpClientSectionName = "httpClient") where T : class { if (string.IsNullOrWhiteSpace(sectionName)) @@ -33,10 +37,10 @@ public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, st } public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, - Func buildOptions, - Func buildConsulOptions, - Func buildFabioOptions, - HttpClientSettings httpClientOptions) + Func buildOptions, + Func buildConsulOptions, + Func buildFabioOptions, + HttpClientOptions httpClientOptions) where T : class { var options = buildOptions(new RestEaseOptionsBuilder()).Build(); @@ -44,12 +48,15 @@ public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, st b => b.AddFabio(buildFabioOptions, buildConsulOptions, httpClientOptions)); } - public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, - RestEaseOptions options, ConsulOptions consulOptions, FabioOptions fabioOptions, - HttpClientOptions httpClientOptions) + public static IGenocsBuilder AddServiceClient( + this IGenocsBuilder builder, + string serviceName, + RestEaseOptions options, + ConsulOptions consulOptions, + FabioOptions fabioOptions, + HttpClientOptions httpClientOptions) where T : class - => builder.AddServiceClient(serviceName, options, - b => b.AddFabio(fabioOptions, consulOptions, httpClientOptions)); + => builder.AddServiceClient(serviceName, options, b => b.AddFabio(fabioOptions, consulOptions, httpClientOptions)); private static IGenocsBuilder AddServiceClient( this IGenocsBuilder builder, diff --git a/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs b/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs index 680728ac..bcbdae00 100644 --- a/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs +++ b/src/Genocs.HTTP.RestEase/IRestEaseServiceBuilder.cs @@ -1,4 +1,4 @@ -using Genocs.HTTP.RestEase.Options; +using Genocs.HTTP.RestEase.Configurations; namespace Genocs.HTTP.RestEase; @@ -8,5 +8,5 @@ public interface IRestEaseServiceBuilder IRestEaseServiceBuilder WithScheme(string scheme); IRestEaseServiceBuilder WithHost(string host); IRestEaseServiceBuilder WithPort(int port); - RestEaseSettings.Service Build(); + RestEaseOptions.Service Build(); } \ No newline at end of file diff --git a/src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs b/src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs deleted file mode 100644 index 15353665..00000000 --- a/src/Genocs.HTTP.RestEase/IRestEaseSettingsBuilder.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Genocs.HTTP.RestEase.Options; - -namespace Genocs.HTTP.RestEase; - -public interface IRestEaseSettingsBuilder -{ - IRestEaseSettingsBuilder WithLoadBalancer(string loadBalancer); - IRestEaseSettingsBuilder WithService(Func buildService); - RestEaseSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.HTTP/Configurations/HttpClientSettings.cs b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs similarity index 81% rename from src/Genocs.HTTP/Configurations/HttpClientSettings.cs rename to src/Genocs.HTTP/Configurations/HttpClientOptions.cs index d7aac11a..1310bfaf 100644 --- a/src/Genocs.HTTP/Configurations/HttpClientSettings.cs +++ b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs @@ -5,6 +5,11 @@ namespace Genocs.HTTP.Configurations; /// public class HttpClientOptions { + /// + /// Default section name. + /// + public const string Position = "httpClient"; + /// /// It defines if set consul as service discovery or Fabio as load balancer. /// Allowed values are: consul, Fabio. @@ -20,11 +25,7 @@ public class HttpClientOptions /// It defines the list of services to be registered. /// public IDictionary? Services { get; set; } -<<<<<<<< HEAD:src/Genocs.HTTP/Configurations/HttpClientSettings.cs - public RequestMaskingSettings? RequestMasking { get; set; } -======== public RequestMaskingOptions? RequestMasking { get; set; } ->>>>>>>> 3b27e463fa91d72fe87473c7d6918114896433cd:src/Genocs.HTTP/Configurations/HttpClientOptions.cs public bool RemoveCharsetFromContentType { get; set; } public string? CorrelationContextHeader { get; set; } public string? CorrelationIdHeader { get; set; } diff --git a/src/Genocs.HTTP/Extensions.cs b/src/Genocs.HTTP/Extensions.cs index 85387b13..908bb7d1 100644 --- a/src/Genocs.HTTP/Extensions.cs +++ b/src/Genocs.HTTP/Extensions.cs @@ -38,7 +38,7 @@ public static IGenocsBuilder AddHttpClient( throw new ArgumentException("HTTP client name cannot be empty.", nameof(clientName)); } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); if (maskedRequestUrlParts is not null && options.RequestMasking is not null) { options.RequestMasking.UrlParts = maskedRequestUrlParts; diff --git a/src/Genocs.HTTP/GenocsHttpClient.cs b/src/Genocs.HTTP/GenocsHttpClient.cs index e5fd254d..63d02470 100644 --- a/src/Genocs.HTTP/GenocsHttpClient.cs +++ b/src/Genocs.HTTP/GenocsHttpClient.cs @@ -12,12 +12,12 @@ public class GenocsHttpClient : IHttpClient { private const string JsonContentType = "application/json"; private readonly HttpClient _client; - private readonly HttpClientSettings _settings; + private readonly HttpClientOptions _settings; private readonly IHttpClientSerializer _serializer; public GenocsHttpClient( HttpClient client, - HttpClientSettings settings, + HttpClientOptions settings, IHttpClientSerializer serializer, ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) diff --git a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs index a4b34417..8ba7d583 100644 --- a/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs +++ b/src/Genocs.HTTP/GenocsHttpLoggingFilter.cs @@ -8,9 +8,9 @@ namespace Genocs.HTTP; internal sealed class GenocsHttpLoggingFilter : IHttpMessageHandlerBuilderFilter { private readonly ILoggerFactory _loggerFactory; - private readonly HttpClientSettings _options; + private readonly HttpClientOptions _options; - public GenocsHttpLoggingFilter(ILoggerFactory loggerFactory, HttpClientSettings options) + public GenocsHttpLoggingFilter(ILoggerFactory loggerFactory, HttpClientOptions options) { _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _options = options; diff --git a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs index b354aa41..0753c680 100644 --- a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs +++ b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs @@ -10,7 +10,7 @@ internal sealed class GenocsLoggingScopeHttpMessageHandler : DelegatingHandler private readonly HashSet _maskedRequestUrlParts; private readonly string _maskTemplate; - public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientSettings settings) + public GenocsLoggingScopeHttpMessageHandler(ILogger logger, HttpClientOptions settings) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _ = settings ?? throw new ArgumentNullException(nameof(settings)); diff --git a/src/Genocs.LoadBalancing.Fabio/Builders/FabioSettingsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs similarity index 76% rename from src/Genocs.LoadBalancing.Fabio/Builders/FabioSettingsBuilder.cs rename to src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs index a1a8db29..559c03cb 100644 --- a/src/Genocs.LoadBalancing.Fabio/Builders/FabioSettingsBuilder.cs +++ b/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs @@ -5,16 +5,16 @@ namespace Genocs.LoadBalancing.Fabio.Builders; /// /// The Fabio options builder. /// -public class FabioSettingsBuilder : IFabioSettingsBuilder +public class FabioOptionsBuilder : IFabioOptionsBuilder { - private readonly FabioSettings _settings = new(); + private readonly FabioOptions _settings = new(); /// /// Enable or disable the Fabio load balancer. /// /// /// The option builder to be used for chain the build. - public IFabioSettingsBuilder Enable(bool enabled) + public IFabioOptionsBuilder Enable(bool enabled) { _settings.Enabled = enabled; return this; @@ -25,7 +25,7 @@ public IFabioSettingsBuilder Enable(bool enabled) /// /// The url. /// The option builder to be used for chain the build. - public IFabioSettingsBuilder WithUrl(string url) + public IFabioOptionsBuilder WithUrl(string url) { _settings.Url = url; return this; @@ -36,7 +36,7 @@ public IFabioSettingsBuilder WithUrl(string url) /// /// The service name /// The option builder to be used for chain the build. - public IFabioSettingsBuilder WithService(string service) + public IFabioOptionsBuilder WithService(string service) { _settings.Service = service; return this; @@ -46,5 +46,5 @@ public IFabioSettingsBuilder WithService(string service) /// Build the Fabio options. /// /// The Fabio options. - public FabioSettings Build() => _settings; + public FabioOptions Build() => _settings; } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Configurations/FabioSettings.cs b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs similarity index 91% rename from src/Genocs.LoadBalancing.Fabio/Configurations/FabioSettings.cs rename to src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs index 3419e0a2..28803892 100644 --- a/src/Genocs.LoadBalancing.Fabio/Configurations/FabioSettings.cs +++ b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs @@ -3,7 +3,7 @@ namespace Genocs.LoadBalancing.Fabio.Configurations; /// /// The Fabio settings. /// -public class FabioSettings +public class FabioOptions { /// /// The default Fabio section name. @@ -11,7 +11,7 @@ public class FabioSettings public const string Position = "fabio"; /// - /// Gets or sets a value indicating whether this is enabled. + /// Gets or sets a value indicating whether this is enabled. /// public bool Enabled { get; set; } diff --git a/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioSettingsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioOptionsBuilder.cs similarity index 68% rename from src/Genocs.LoadBalancing.Fabio/Configurations/IFabioSettingsBuilder.cs rename to src/Genocs.LoadBalancing.Fabio/Configurations/IFabioOptionsBuilder.cs index 14eb9d21..e0f711fe 100644 --- a/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioSettingsBuilder.cs +++ b/src/Genocs.LoadBalancing.Fabio/Configurations/IFabioOptionsBuilder.cs @@ -3,32 +3,32 @@ namespace Genocs.LoadBalancing.Fabio.Configurations; /// /// The Fabio options builder interface definition. /// -public interface IFabioSettingsBuilder +public interface IFabioOptionsBuilder { /// /// Enable or disable the Fabio load balancer. /// /// /// The option builder to be used for chain the build. - IFabioSettingsBuilder Enable(bool enabled); + IFabioOptionsBuilder Enable(bool enabled); /// /// Set the Fabio url. /// /// The url. /// The option builder to be used for chain the build. - IFabioSettingsBuilder WithUrl(string url); + IFabioOptionsBuilder WithUrl(string url); /// - /// Set the Fabio service name + /// Set the Fabio service name. /// /// The service name. - /// The option builder to be used for chain the build - IFabioSettingsBuilder WithService(string service); + /// The option builder to be used for chain the build. + IFabioOptionsBuilder WithService(string service); /// - /// Build the Fabio options + /// Build the Fabio options. /// - /// The Fabio options - FabioSettings Build(); + /// The Fabio options. + FabioOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/Extensions.cs b/src/Genocs.LoadBalancing.Fabio/Extensions.cs index 01284147..ba3ded7a 100644 --- a/src/Genocs.LoadBalancing.Fabio/Extensions.cs +++ b/src/Genocs.LoadBalancing.Fabio/Extensions.cs @@ -16,8 +16,11 @@ public static class Extensions { private const string RegistryName = "loadBalancing.fabio"; - public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, string sectionName = FabioOptions.Position, - string consulSectionName = "consul", string httpClientSectionName = "httpClient") + public static IGenocsBuilder AddFabio( + this IGenocsBuilder builder, + string sectionName = FabioOptions.Position, + string consulSectionName = ConsulOptions.Position, + string httpClientSectionName = HttpClientOptions.Position) { if (string.IsNullOrWhiteSpace(sectionName)) { @@ -27,16 +30,19 @@ public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, string sectio var fabioOptions = builder.GetOptions(sectionName); var consulOptions = builder.GetOptions(consulSectionName); var httpClientOptions = builder.GetOptions(httpClientSectionName); - return builder.AddFabio(fabioOptions, httpClientOptions, - b => b.AddConsul(consulOptions, httpClientOptions)); + + return builder.AddFabio( + fabioOptions, + httpClientOptions, + b => b.AddConsul(consulOptions, httpClientOptions)); } public static IGenocsBuilder AddFabio(this IGenocsBuilder builder, - Func buildOptions, - Func buildConsulOptions, - HttpClientSettings httpClientOptions) + Func buildOptions, + Func buildConsulOptions, + HttpClientOptions httpClientOptions) { - var fabioOptions = buildOptions(new FabioSettingsBuilder()).Build(); + var fabioOptions = buildOptions(new FabioOptionsBuilder()).Build(); return builder.AddFabio(fabioOptions, httpClientOptions, b => b.AddConsul(buildConsulOptions, httpClientOptions)); } diff --git a/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs b/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs index 4415fef0..f3517a66 100644 --- a/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs +++ b/src/Genocs.LoadBalancing.Fabio/Http/FabioHttpClient.cs @@ -7,7 +7,7 @@ internal sealed class FabioHttpClient : GenocsHttpClient, IFabioHttpClient { public FabioHttpClient( HttpClient client, - HttpClientSettings options, + HttpClientOptions options, IHttpClientSerializer serializer, ICorrelationContextFactory correlationContextFactory, ICorrelationIdFactory correlationIdFactory) diff --git a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs index f9382130..a7304722 100644 --- a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs +++ b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs @@ -4,10 +4,10 @@ namespace Genocs.LoadBalancing.Fabio.MessageHandlers; internal sealed class FabioMessageHandler : DelegatingHandler { - private readonly FabioSettings _settings; + private readonly FabioOptions _settings; private readonly string _servicePath; - public FabioMessageHandler(FabioSettings settings, string? serviceName = null) + public FabioMessageHandler(FabioOptions settings, string? serviceName = null) { if (string.IsNullOrWhiteSpace(settings.Url)) { diff --git a/src/Genocs.Logging/Configurations/AzureSettings.cs b/src/Genocs.Logging/Configurations/AzureOptions.cs similarity index 100% rename from src/Genocs.Logging/Configurations/AzureSettings.cs rename to src/Genocs.Logging/Configurations/AzureOptions.cs diff --git a/src/Genocs.Logging/Configurations/ConsoleSettings.cs b/src/Genocs.Logging/Configurations/ConsoleOptions.cs similarity index 100% rename from src/Genocs.Logging/Configurations/ConsoleSettings.cs rename to src/Genocs.Logging/Configurations/ConsoleOptions.cs diff --git a/src/Genocs.Logging/Configurations/ElkSettings.cs b/src/Genocs.Logging/Configurations/ElkOptions.cs similarity index 100% rename from src/Genocs.Logging/Configurations/ElkSettings.cs rename to src/Genocs.Logging/Configurations/ElkOptions.cs diff --git a/src/Genocs.Logging/Configurations/LocalFileSettings.cs b/src/Genocs.Logging/Configurations/LocalFileOptions.cs similarity index 100% rename from src/Genocs.Logging/Configurations/LocalFileSettings.cs rename to src/Genocs.Logging/Configurations/LocalFileOptions.cs diff --git a/src/Genocs.Logging/Configurations/LoggerSettings.cs b/src/Genocs.Logging/Configurations/LoggerOptions.cs similarity index 86% rename from src/Genocs.Logging/Configurations/LoggerSettings.cs rename to src/Genocs.Logging/Configurations/LoggerOptions.cs index aebbd380..087f9da8 100644 --- a/src/Genocs.Logging/Configurations/LoggerSettings.cs +++ b/src/Genocs.Logging/Configurations/LoggerOptions.cs @@ -1,8 +1,4 @@ namespace Genocs.Logging.Configurations; -<<<<<<<< HEAD:src/Genocs.Logging/Configurations/LoggerSettings.cs - -======== ->>>>>>>> 3b27e463fa91d72fe87473c7d6918114896433cd:src/Genocs.Logging/Configurations/LoggerOptions.cs /// /// Logger Settings. diff --git a/src/Genocs.Logging/Configurations/LokiSettings.cs b/src/Genocs.Logging/Configurations/LokiOptions.cs similarity index 100% rename from src/Genocs.Logging/Configurations/LokiSettings.cs rename to src/Genocs.Logging/Configurations/LokiOptions.cs diff --git a/src/Genocs.Logging/Configurations/MongoSettings.cs b/src/Genocs.Logging/Configurations/MongoOptions.cs similarity index 100% rename from src/Genocs.Logging/Configurations/MongoSettings.cs rename to src/Genocs.Logging/Configurations/MongoOptions.cs diff --git a/src/Genocs.Logging/Configurations/SeqSettings.cs b/src/Genocs.Logging/Configurations/SeqOptions.cs similarity index 100% rename from src/Genocs.Logging/Configurations/SeqSettings.cs rename to src/Genocs.Logging/Configurations/SeqOptions.cs diff --git a/src/Genocs.Logging/Extensions.cs b/src/Genocs.Logging/Extensions.cs index 0ba7ec8c..41997920 100644 --- a/src/Genocs.Logging/Extensions.cs +++ b/src/Genocs.Logging/Extensions.cs @@ -23,24 +23,24 @@ public static class Extensions public static IHostBuilder UseLogging( this IHostBuilder hostBuilder, Action? configure = null, - string? loggerSectionName = LoggerSettings.Position, - string? appSectionName = AppSettings.Position) + string? loggerSectionName = LoggerOptions.Position, + string? appSectionName = AppOptions.Position) => hostBuilder .ConfigureServices(services => services.AddSingleton()) .UseSerilog((context, loggerConfiguration) => { if (string.IsNullOrWhiteSpace(loggerSectionName)) { - loggerSectionName = LoggerSettings.Position; + loggerSectionName = LoggerOptions.Position; } if (string.IsNullOrWhiteSpace(appSectionName)) { - appSectionName = AppSettings.Position; + appSectionName = AppOptions.Position; } - var loggerOptions = context.Configuration.GetOptions(loggerSectionName); - var appOptions = context.Configuration.GetOptions(appSectionName); + var loggerOptions = context.Configuration.GetOptions(loggerSectionName); + var appOptions = context.Configuration.GetOptions(appSectionName); MapOptions(loggerOptions, appOptions, loggerConfiguration, context.HostingEnvironment.EnvironmentName); configure?.Invoke(context, loggerConfiguration); @@ -52,8 +52,8 @@ public static IEndpointConventionBuilder MapLogLevelHandler( => builder.MapPost(endpointRoute, LevelSwitch); private static void MapOptions( - LoggerSettings loggerOptions, - AppSettings appOptions, + LoggerOptions loggerOptions, + AppOptions appOptions, LoggerConfiguration loggerConfiguration, string environmentName) { @@ -86,14 +86,14 @@ private static void MapOptions( Configure(loggerConfiguration, loggerOptions); } - private static void Configure(LoggerConfiguration loggerConfiguration, LoggerSettings options) + private static void Configure(LoggerConfiguration loggerConfiguration, LoggerOptions options) { - var consoleOptions = options.Console ?? new ConsoleSettings(); - var fileOptions = options.File ?? new LocalFileSettings(); - var elkOptions = options.Elk ?? new ElkSettings(); - var seqOptions = options.Seq ?? new SeqSettings(); - var lokiOptions = options.Loki ?? new LokiSettings(); - var azureOptions = options.Azure ?? new AzureSettings(); + var consoleOptions = options.Console ?? new ConsoleOptions(); + var fileOptions = options.File ?? new LocalFileOptions(); + var elkOptions = options.Elk ?? new ElkOptions(); + var seqOptions = options.Seq ?? new SeqOptions(); + var lokiOptions = options.Loki ?? new LokiOptions(); + var azureOptions = options.Azure ?? new AzureOptions(); // console if (consoleOptions.Enabled) diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs index 779c376b..f6a04267 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs @@ -11,6 +11,8 @@ namespace Genocs.MessageBrokers.Outbox.MongoDB.Internals; internal sealed class MongoMessageOutbox : IMessageOutbox, IMessageOutboxAccessor { + private const string EmptyJsonObject = "{}"; + private static readonly JsonSerializerOptions SerializerOptions = new() { PropertyNameCaseInsensitive = true, @@ -19,7 +21,6 @@ internal sealed class MongoMessageOutbox : IMessageOutbox, IMessageOutboxAccesso Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } }; - private const string EmptyJsonObject = "{}"; private readonly IMongoSessionFactory _sessionFactory; private readonly IMongoRepository _inboxRepository; private readonly IMongoRepository _outboxRepository; @@ -31,7 +32,7 @@ internal sealed class MongoMessageOutbox : IMessageOutbox, IMessageOutboxAccesso public MongoMessageOutbox(IMongoSessionFactory sessionFactory, IMongoRepository inboxRepository, IMongoRepository outboxRepository, - OutboxSettings options, ILogger logger) + OutboxOptions options, ILogger logger) { _sessionFactory = sessionFactory; _inboxRepository = inboxRepository; diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs index ff0560f9..2fd0ea9d 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs @@ -8,9 +8,9 @@ namespace Genocs.MessageBrokers.Outbox.MongoDB.Internals; internal sealed class MongoOutboxInitializer : IInitializer { private readonly IMongoDatabase _database; - private readonly OutboxSettings _options; + private readonly OutboxOptions _options; - public MongoOutboxInitializer(IMongoDatabase database, OutboxSettings options) + public MongoOutboxInitializer(IMongoDatabase database, OutboxOptions options) { _database = database; _options = options; diff --git a/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxSettings.cs b/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxOptions.cs similarity index 93% rename from src/Genocs.MessageBrokers.Outbox/Configurations/OutboxSettings.cs rename to src/Genocs.MessageBrokers.Outbox/Configurations/OutboxOptions.cs index 52af1f3e..da6aaec7 100644 --- a/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxSettings.cs +++ b/src/Genocs.MessageBrokers.Outbox/Configurations/OutboxOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.MessageBrokers.Outbox.Configurations; -public class OutboxSettings +public class OutboxOptions { public bool Enabled { get; set; } public int Expiry { get; set; } diff --git a/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs b/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs index b03c9cfa..c5db113f 100644 --- a/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs +++ b/src/Genocs.MessageBrokers.Outbox/Configurators/MessageOutboxConfigurator.cs @@ -6,9 +6,9 @@ namespace Genocs.MessageBrokers.Outbox.Configurators; internal sealed class MessageOutboxConfigurator : IMessageOutboxConfigurator { public IGenocsBuilder Builder { get; } - public OutboxSettings Options { get; } + public OutboxOptions Options { get; } - public MessageOutboxConfigurator(IGenocsBuilder builder, OutboxSettings options) + public MessageOutboxConfigurator(IGenocsBuilder builder, OutboxOptions options) { Builder = builder; Options = options; diff --git a/src/Genocs.MessageBrokers.Outbox/Extensions.cs b/src/Genocs.MessageBrokers.Outbox/Extensions.cs index 330fe6e9..2a966f11 100644 --- a/src/Genocs.MessageBrokers.Outbox/Extensions.cs +++ b/src/Genocs.MessageBrokers.Outbox/Extensions.cs @@ -27,7 +27,7 @@ public static IGenocsBuilder AddMessageOutbox( return builder; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); var configurator = new MessageOutboxConfigurator(builder, options); diff --git a/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs b/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs index 7ddbb1e9..ddf94a6f 100644 --- a/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs +++ b/src/Genocs.MessageBrokers.Outbox/IMessageOutboxConfigurator.cs @@ -6,5 +6,5 @@ namespace Genocs.MessageBrokers.Outbox; public interface IMessageOutboxConfigurator { IGenocsBuilder Builder { get; } - OutboxSettings Options { get; } + OutboxOptions Options { get; } } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs b/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs index 5d0f2e16..6c4ce817 100644 --- a/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs +++ b/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs @@ -11,8 +11,8 @@ public sealed class OutboxMessage : IIdentifiable public Dictionary Headers { get; set; } = new(); public string MessageType { get; set; } public string MessageContextType { get; set; } - public object Message { get; set; } - public object MessageContext { get; set; } + public object? Message { get; set; } + public object? MessageContext { get; set; } public string SerializedMessage { get; set; } public string SerializedMessageContext { get; set; } public DateTime SentAt { get; set; } diff --git a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs index eee56670..82624406 100644 --- a/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox/Outbox/InMemoryMessageOutbox.cs @@ -14,7 +14,7 @@ internal sealed class InMemoryMessageOutbox : IMessageOutbox, IMessageOutboxAcce private readonly ILogger _logger; private readonly int _expiry; - public InMemoryMessageOutbox(OutboxSettings options, ILogger logger) + public InMemoryMessageOutbox(OutboxOptions options, ILogger logger) { _logger = logger; _expiry = options.Expiry; diff --git a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs index 9e789cc8..a9799d06 100644 --- a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs +++ b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs @@ -10,13 +10,13 @@ internal sealed class OutboxProcessor : IHostedService { private readonly IServiceProvider _serviceProvider; private readonly IBusPublisher _publisher; - private readonly OutboxSettings _options; + private readonly OutboxOptions _options; private readonly ILogger _logger; private readonly TimeSpan _interval; private readonly OutboxType _type; private Timer _timer; - public OutboxProcessor(IServiceProvider serviceProvider, IBusPublisher publisher, OutboxSettings options, + public OutboxProcessor(IServiceProvider serviceProvider, IBusPublisher publisher, OutboxOptions options, ILogger logger) { if (options.Enabled && options.IntervalMilliseconds <= 0) diff --git a/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs index 1114bfc1..44dca3e8 100644 --- a/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs +++ b/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs @@ -4,56 +4,56 @@ namespace Genocs.Metrics.AppMetrics.Builders; internal sealed class MetricsSettingsBuilder : IMetricsSettingsBuilder { - private readonly MetricsSettings _options = new(); + private readonly MetricsSettings _settings = new(); public IMetricsSettingsBuilder Enable(bool enabled) { - _options.Enabled = enabled; + _settings.Enabled = enabled; return this; } public IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled) { - _options.InfluxEnabled = influxEnabled; + _settings.InfluxEnabled = influxEnabled; return this; } public IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled) { - _options.PrometheusEnabled = prometheusEnabled; + _settings.PrometheusEnabled = prometheusEnabled; return this; } public IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter) { - _options.PrometheusFormatter = prometheusFormatter; + _settings.PrometheusFormatter = prometheusFormatter; return this; } public IMetricsSettingsBuilder WithInfluxUrl(string influxUrl) { - _options.InfluxUrl = influxUrl; + _settings.InfluxUrl = influxUrl; return this; } public IMetricsSettingsBuilder WithDatabase(string database) { - _options.Database = database; + _settings.Database = database; return this; } public IMetricsSettingsBuilder WithInterval(int interval) { - _options.Interval = interval; + _settings.Interval = interval; return this; } public IMetricsSettingsBuilder WithTags(IDictionary tags) { - _options.Tags = tags; + _settings.Tags = tags; return this; } public MetricsSettings Build() - => _options; + => _settings; } \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index 06801cd2..292e0c13 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -40,7 +40,7 @@ public static IGenocsBuilder AddMetrics( appSectionName = AppOptions.Position; } - var metricsOptions = builder.GetOptions(metricsSectionName); + var metricsOptions = builder.GetOptions(metricsSectionName); var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); @@ -58,7 +58,7 @@ public static IGenocsBuilder AddMetrics( } var metricsOptions = buildOptions(new MetricsSettingsBuilder()).Build(); - var appOptions = builder.GetOptions(appSectionName); + var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); } @@ -66,7 +66,7 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's and IIS ServerOptions AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - Configurations.MetricsOptions metricsSettings, + Configurations.MetricsSettings metricsSettings, AppOptions appSettings) { builder.Services.AddSingleton(metricsSettings); @@ -161,7 +161,7 @@ public static IApplicationBuilder UseMetrics(this IApplicationBuilder app) .UseMetricsAllMiddleware(); } - private static MetricsWebHostOptions GetMetricsWebHostOptions(Configurations.MetricsOptions metricsOptions) + private static MetricsWebHostOptions GetMetricsWebHostOptions(MetricsSettings metricsOptions) { var options = new MetricsWebHostOptions(); diff --git a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs new file mode 100644 index 00000000..70db85df --- /dev/null +++ b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs @@ -0,0 +1,69 @@ +namespace Genocs.Persistence.MongoDb.Configurations; + +/// +/// MongoDb encryption database Settings. +/// +public class MongoDbEncryptionOptions +{ + + /// + /// Default Section name. + /// + public const string Position = "MongoDbEncryption"; + + /// + /// The Database connection string. + /// + public string ConnectionString { get; set; } = default!; + + /// + /// The shared library used to encrypt. + /// + public string LibPath { get; set; } = default!; + + /// + /// Azure Tenant Id. + /// + public string TenantId { get; set; } = default!; + + /// + /// Azure Client Id. + /// + public string ClientId { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string ClientSecret { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string KeyName { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string KeyVersion { get; set; } = default!; + + /// + /// Azure Client Secret. + /// + public string KeyVaultEndpoint { get; set; } = default!; + + /// + /// Check if the MongoDbSettings object contains valid data. + /// + /// MongoDbSettings object. + /// return true if valid otherwise false. + public static bool IsValid(MongoDbEncryptionOptions settings) + { + if (settings is null) return false; + + if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; + if (string.IsNullOrWhiteSpace(settings.LibPath)) return false; + + return true; + + } +} diff --git a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs index ff2f2be8..eb5222e5 100644 --- a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs @@ -15,11 +15,11 @@ public class AzureInitializer /// Setup the client /// /// - public AutoEncryptionOptions EncryptionOptions(IOptions options) + public AutoEncryptionOptions EncryptionOptions(IOptions options) { // Ge settings - MongoDbEncryptionSettings settings = options.Value; - MongoDbEncryptionSettings.IsValid(settings); + MongoDbEncryptionOptions settings = options.Value; + MongoDbEncryptionOptions.IsValid(settings); // start-kmsproviders var kmsProviders = new Dictionary>(); diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs index 693a8339..06d4b5a4 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs @@ -34,16 +34,16 @@ public static class MongoDbExtensions /// The Genocs builder. public static IGenocsBuilder AddMongo( this IGenocsBuilder builder, - string sectionName = MongoDbSettings.Position, + string sectionName = MongoDbOptions.Position, Type? seederType = null, bool registerConventions = true) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = MongoDbSettings.Position; + sectionName = MongoDbOptions.Position; } - var mongoOptions = builder.GetOptions(sectionName); + var mongoOptions = builder.GetOptions(sectionName); return builder.AddMongo(mongoOptions, seederType, registerConventions); } @@ -70,32 +70,32 @@ public static IGenocsBuilder AddMongo( /// Setup MongoDb support. /// /// The Genocs builder. - /// The settings. + /// The settings. /// /// /// The Genocs builder. public static IGenocsBuilder AddMongo( this IGenocsBuilder builder, - MongoDbSettings mongoOptions, + MongoDbOptions options, Type? seederType = null, bool registerConventions = true) { - if (!builder.TryRegister(MongoDbSettings.Position)) + if (!builder.TryRegister(MongoDbOptions.Position)) { return builder; } - if (mongoOptions.SetRandomDatabaseSuffix) + if (options.SetRandomDatabaseSuffix) { string suffix = $"{Guid.NewGuid():N}"; Console.WriteLine($"Setting a random MongoDB database suffix: '{suffix}'."); - mongoOptions.Database = $"{mongoOptions.Database}_{suffix}"; + options.Database = $"{options.Database}_{suffix}"; } - builder.Services.AddSingleton(mongoOptions); + builder.Services.AddSingleton(options); builder.Services.AddSingleton(sp => { - var options = sp.GetRequiredService(); + var options = sp.GetRequiredService(); MongoClientSettings clientSettings = MongoClientSettings.FromConnectionString(options.ConnectionString); @@ -109,7 +109,7 @@ public static IGenocsBuilder AddMongo( builder.Services.AddTransient(sp => { - var options = sp.GetRequiredService(); + var options = sp.GetRequiredService(); var client = sp.GetRequiredService(); return client.GetDatabase(options.Database); }); @@ -168,13 +168,13 @@ public static IGenocsBuilder AddMongoRepository( /// The Genocs builder. public static IGenocsBuilder AddMongoFast( this IGenocsBuilder builder, - string sectionName = MongoDbSettings.Position, + string sectionName = MongoDbOptions.Position, bool registerConventions = true) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = MongoDbSettings.Position; + sectionName = MongoDbOptions.Position; } var section = builder.Configuration.GetSection(sectionName); @@ -184,7 +184,7 @@ public static IGenocsBuilder AddMongoFast( return builder; } - builder.Services.Configure(section); + builder.Services.Configure(section); builder.Services.AddSingleton(); builder.Services.AddScoped(typeof(IMongoDbRepository<>), typeof(MongoDbRepository<>)); diff --git a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs index f917c935..dd60928e 100644 --- a/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Initializers/MongoDbInitializer.cs @@ -11,7 +11,7 @@ internal sealed class MongoDbInitializer : IMongoDbInitializer private readonly IMongoDatabase _database; private readonly IMongoDbSeeder _seeder; - public MongoDbInitializer(IMongoDatabase database, IMongoDbSeeder seeder, MongoDbSettings options) + public MongoDbInitializer(IMongoDatabase database, IMongoDbSeeder seeder, MongoDbOptions options) { _database = database; _seeder = seeder; diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs deleted file mode 100644 index bcd5ce69..00000000 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbOptionsBuilder.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Genocs.Persistence.MongoDb.Configurations; - -namespace Genocs.Persistence.MongoDb.Repositories; - -/// -/// The MongoDB Options Builder. -/// -public interface IMongoDbOptionsBuilder -{ - /// - /// Setup the Connection string. - /// - /// - /// - IMongoDbOptionsBuilder WithConnectionString(string connectionString); - - /// - /// Setup the Database name. - /// - /// - /// - IMongoDbOptionsBuilder WithDatabase(string database); - - /// - /// Setup the database Seed. - /// - /// - /// - IMongoDbOptionsBuilder WithSeed(bool seed); - - /// - /// Get the settings. - /// - /// MongoDbSettings instance. - MongoDbSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs index fccbe0b5..907cf7de 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs @@ -15,7 +15,8 @@ namespace Genocs.Secrets.AzureKeyVault; public static class Extensions { /// - /// UseVault. + /// This method is used to add the Azure Key Vault to the Host builder. + /// You can use the Azure Key Vault to store and manage application secrets. /// /// The builder. /// The section name. @@ -56,8 +57,7 @@ public static IWebHostBuilder UseAzureKeyVault( string sectionName = AzureKeyVaultSettings.Position) => builder.ConfigureAppConfiguration((ctx, cfg) => { - var settings = new AzureKeyVaultSettings(); - ctx.Configuration.GetSection(sectionName).Bind(settings); + AzureKeyVaultSettings settings = ctx.Configuration.GetOptions(sectionName); if (!settings.Enabled) { return; @@ -74,8 +74,7 @@ public static IWebHostBuilder UseAzureKeyVault( public static WebApplicationBuilder UseAzureKeyVault(this WebApplicationBuilder builder) { - var settings = new AzureKeyVaultSettings(); - builder.Configuration.GetSection(AzureKeyVaultSettings.Position).Bind(settings); + AzureKeyVaultSettings settings = builder.Configuration.GetOptions(AzureKeyVaultSettings.Position); if (!settings.Enabled) { return builder; diff --git a/src/Genocs.Secrets.Vault/Extensions.cs b/src/Genocs.Secrets.Vault/Extensions.cs index b3bcb999..166aa19e 100644 --- a/src/Genocs.Secrets.Vault/Extensions.cs +++ b/src/Genocs.Secrets.Vault/Extensions.cs @@ -39,7 +39,7 @@ public static IHostBuilder UseVault( .ConfigureAppConfiguration((ctx, cfg) => { // TODO Test - VaultSettings options = ctx.Configuration.GetOptions(sectionName); + VaultOptions options = ctx.Configuration.GetOptions(sectionName); if (!options.Enabled) { return; @@ -49,7 +49,7 @@ public static IHostBuilder UseVault( }); /// - /// UseVault + /// UseVault. /// /// /// @@ -63,8 +63,7 @@ public static IWebHostBuilder UseVault( .ConfigureAppConfiguration((ctx, cfg) => { // TODO Test - var options = new VaultSettings(); - ctx.Configuration.GetSection(sectionName).Bind(options); + VaultOptions options = ctx.Configuration.GetOptions(sectionName); if (!options.Enabled) { return; @@ -86,8 +85,7 @@ private static IServiceCollection AddVault(this IServiceCollection services, str configuration = serviceProvider.GetRequiredService(); } - var options = new VaultSettings(); - configuration.GetSection(sectionName).Bind(options); + VaultOptions options = configuration.GetOptions(sectionName); if (!options.Enabled) { return services; @@ -114,13 +112,13 @@ private static IServiceCollection AddVault(this IServiceCollection services, str return services; } - private static void VerifyOptions(VaultSettings options) + private static void VerifyOptions(VaultOptions options) { if (options.Kv is null) { if (!string.IsNullOrWhiteSpace(options.Key)) { - options.Kv = new VaultSettings.KeyValueSettings + options.Kv = new VaultOptions.KeyValueOptions { Enabled = options.Enabled, Path = options.Key @@ -143,7 +141,7 @@ private static void VerifyOptions(VaultSettings options) private static async Task AddVaultAsync( this IConfigurationBuilder builder, - VaultSettings options, + VaultOptions options, string? keyValuePath) { VerifyOptions(options); @@ -194,7 +192,7 @@ private static async Task AddVaultAsync( private static Task InitLeaseAsync( string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) => options.Type.ToLowerInvariant() switch { @@ -209,7 +207,7 @@ private static Task InitLeaseAsync( private static async Task SetActiveDirectorySecretsAsync( string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.ActiveDirectory; @@ -225,7 +223,7 @@ private static async Task SetActiveDirectorySecretsAsync( } private static async Task SetAzureSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Azure; @@ -240,7 +238,7 @@ private static async Task SetAzureSecretsAsync(string key, IVaultClient client, } private static async Task SetConsulSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Consul; @@ -254,7 +252,7 @@ private static async Task SetConsulSecretsAsync(string key, IVaultClient client, } private static async Task SetDatabaseSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Database; @@ -268,7 +266,7 @@ private static async Task SetDatabaseSecretsAsync(string key, IVaultClient clien }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static async Task SetPkiSecretsAsync(IVaultClient client, VaultSettings options) + private static async Task SetPkiSecretsAsync(IVaultClient client, VaultOptions options) { var issuer = new CertificatesIssuer(client, options); var certificate = await issuer.IssueAsync(); @@ -276,7 +274,7 @@ private static async Task SetPkiSecretsAsync(IVaultClient client, VaultSettings } private static async Task SetRabbitMqSecretsAsync(string key, IVaultClient client, - VaultSettings.LeaseSettings options, + VaultOptions.LeaseOptions options, IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.RabbitMQ; @@ -290,7 +288,7 @@ private static async Task SetRabbitMqSecretsAsync(string key, IVaultClient clien }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static void SetSecrets(string key, VaultSettings.LeaseSettings options, + private static void SetSecrets(string key, VaultOptions.LeaseOptions options, IDictionary configuration, string name, Func<(object, Dictionary, string, int, bool)> lease) { @@ -301,7 +299,7 @@ private static void SetSecrets(string key, VaultSettings.LeaseSettings options, LeaseService.Set(key, leaseData); } - private static (IVaultClient client, VaultClientSettings settings) GetClientAndSettings(VaultSettings options) + private static (IVaultClient client, VaultClientSettings settings) GetClientAndSettings(VaultOptions options) { var settings = new VaultClientSettings(options.Url, GetAuthMethod(options)); var client = new VaultClient(settings); @@ -309,7 +307,7 @@ private static (IVaultClient client, VaultClientSettings settings) GetClientAndS return (client, settings); } - private static void SetTemplates(string key, VaultSettings.LeaseSettings lease, + private static void SetTemplates(string key, VaultOptions.LeaseOptions lease, IDictionary configuration, IDictionary values) { if (lease.Templates is null || !lease.Templates.Any()) @@ -331,7 +329,7 @@ private static void SetTemplates(string key, VaultSettings.LeaseSettings lease, } } - private static IAuthMethodInfo GetAuthMethod(VaultSettings options) + private static IAuthMethodInfo GetAuthMethod(VaultOptions options) => options.AuthType?.ToLowerInvariant() switch { "token" => new TokenAuthMethodInfo(options.Token), diff --git a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs index 4ba695fd..3ccf06e6 100644 --- a/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs +++ b/src/Genocs.Secrets.Vault/Internals/VaultHostedService.cs @@ -11,7 +11,7 @@ internal sealed class VaultHostedService : BackgroundService private readonly ILeaseService _leaseService; private readonly ICertificatesIssuer _certificatesIssuer; private readonly ICertificatesService _certificatesService; - private readonly VaultSettings _settings; + private readonly VaultOptions _settings; private readonly ILogger _logger; private readonly int _interval; @@ -20,7 +20,7 @@ public VaultHostedService( ILeaseService leaseService, ICertificatesIssuer certificatesIssuer, ICertificatesService certificatesService, - VaultSettings settings, + VaultOptions settings, ILogger logger) { _client = client; diff --git a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs index 52a4864a..24036299 100644 --- a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs +++ b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs @@ -15,20 +15,28 @@ public DispatcherEndpointsBuilder(IEndpointsBuilder builder) _builder = builder; } - public IDispatcherEndpointsBuilder Get(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) + public IDispatcherEndpointsBuilder Get( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) { _builder.Get(path, context, endpoint, auth, roles, policies); return this; } - public IDispatcherEndpointsBuilder Get(string path, - Func? beforeDispatch = null, - Func? afterDispatch = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) where TQuery : class, IQuery + public IDispatcherEndpointsBuilder Get( + string path, + Func? beforeDispatch = null, + Func? afterDispatch = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) + where TQuery : class, IQuery { _builder.Get(path, async (query, ctx) => { diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index f3664774..4c964e2c 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -61,4 +61,8 @@ + + + + diff --git a/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs deleted file mode 100644 index 7c34637a..00000000 --- a/src/Genocs.WebApi.Swagger/Docs/Builders/SwaggerOptionsBuilder.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Genocs.WebApi.Swagger.Docs.Configurations; - -namespace Genocs.WebApi.Swagger.Docs.Builders; - -internal sealed class SwaggerOptionsBuilder : ISwaggerOptionsBuilder -{ - private readonly SwaggerSettings _options = new(); - - public ISwaggerOptionsBuilder Enable(bool enabled) - { - _options.Enabled = enabled; - return this; - } - - public ISwaggerOptionsBuilder ReDocEnable(bool reDocEnabled) - { - _options.ReDocEnabled = reDocEnabled; - return this; - } - - public ISwaggerOptionsBuilder WithName(string name) - { - _options.Name = name; - return this; - } - - public ISwaggerOptionsBuilder WithTitle(string title) - { - _options.Title = title; - return this; - } - - public ISwaggerOptionsBuilder WithVersion(string version) - { - _options.Version = version; - return this; - } - - public ISwaggerOptionsBuilder WithRoutePrefix(string routePrefix) - { - _options.RoutePrefix = routePrefix; - return this; - } - - public ISwaggerOptionsBuilder IncludeSecurity(bool includeSecurity) - { - _options.IncludeSecurity = includeSecurity; - return this; - } - - public ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2) - { - _options.SerializeAsOpenApiV2 = serializeAsOpenApiV2; - return this; - } - - public SwaggerSettings Build() => _options; -} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs index e500e9e7..64c1b28b 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs @@ -1,5 +1,4 @@ namespace Genocs.WebApi.Swagger.Docs.Configurations; - public interface ISwaggerOptionsBuilder { ISwaggerOptionsBuilder Enable(bool enabled); diff --git a/src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs b/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs similarity index 51% rename from src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs rename to src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs index 113498cc..af2f8db1 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Options/MessagingSettings.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs @@ -1,11 +1,13 @@ -namespace Genocs.APIGateway.Options; +namespace Genocs.APIGateway.Configurations; -internal class MessagingSettings +internal class MessagingOptions { + public const string Position = "messaging"; + public bool Enabled { get; set; } - public IEnumerable? Endpoints { get; set; } + public IEnumerable? Endpoints { get; set; } - internal class EndpointSettings + internal class EndpointOptions { public string? Method { get; set; } public string? Path { get; set; } diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs index 5575cb06..d9665a2b 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs @@ -1,4 +1,4 @@ -using Genocs.APIGateway.Options; +using Genocs.APIGateway.Configurations; using Genocs.MessageBrokers.RabbitMQ; using Genocs.MessageBrokers.RabbitMQ.Conventions; using Microsoft.Extensions.Options; @@ -16,7 +16,7 @@ internal class MessagingMiddleware : IMiddleware private readonly ITracer _tracer; private readonly ICorrelationContextBuilder _correlationContextBuilder; private readonly CorrelationIdFactory _correlationIdFactory; - private readonly IDictionary> _endpoints; + private readonly IDictionary> _endpoints; public MessagingMiddleware( IRabbitMQClient rabbitMQClient, @@ -24,7 +24,7 @@ public MessagingMiddleware( ITracer tracer, ICorrelationContextBuilder correlationContextBuilder, CorrelationIdFactory correlationIdFactory, - IOptions messagingOptions) + IOptions messagingOptions) { if (messagingOptions is null) { @@ -39,7 +39,7 @@ public MessagingMiddleware( _endpoints = messagingOptions.Value.Endpoints?.Any() is true ? messagingOptions.Value.Endpoints.GroupBy(e => e.Method.ToUpperInvariant()) .ToDictionary(e => e.Key, e => e.ToList()) - : new Dictionary>(); + : new Dictionary>(); } public async Task InvokeAsync(HttpContext context, RequestDelegate next) diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index 3c29680f..8810e46a 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -1,5 +1,5 @@ +using Genocs.APIGateway.Configurations; using Genocs.APIGateway.Framework; -using Genocs.APIGateway.Options; using Genocs.Auth; using Genocs.Common.Configurations; using Genocs.Core.Builders; @@ -32,7 +32,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.Configure(Configuration.GetSection("messaging")); + services.Configure(Configuration.GetSection(MessagingOptions.Position)); services.AddReverseProxy() .LoadFromConfig(Configuration.GetSection("ReverseProxy")); services.AddSingleton(); @@ -90,7 +90,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { endpoints.MapGet("/", async context => { - await context.Response.WriteAsync(context.RequestServices.GetService()?.Name ?? "Service"); + await context.Response.WriteAsync(context.RequestServices.GetService()?.Name ?? "Service"); }); endpoints.MapReverseProxy(); diff --git a/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs b/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs index a279c762..c535997a 100644 --- a/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs +++ b/src/apps/identity/Genocs.Identities.Application/CorrelationIdFactory.cs @@ -16,7 +16,7 @@ internal class CorrelationIdFactory : ICorrelationIdFactory public CorrelationIdFactory( IMessagePropertiesAccessor messagePropertiesAccessor, IHttpContextAccessor httpContextAccessor, - HttpClientSettings httpClientOptions) + HttpClientOptions httpClientOptions) { if (httpClientOptions is null) { diff --git a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs index a7eb7f09..5401d00c 100644 --- a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs +++ b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxCommandHandlerDecorator.cs @@ -16,7 +16,7 @@ internal sealed class OutboxCommandHandlerDecorator : ICommandHandler< private readonly bool _enabled; public OutboxCommandHandlerDecorator(ICommandHandler handler, IMessageOutbox outbox, - OutboxSettings outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) + OutboxOptions outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) { _handler = handler; _outbox = outbox; diff --git a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs index 06e73609..0bad3e59 100644 --- a/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs +++ b/src/apps/identity/Genocs.Identities.Application/Decorators/OutboxEventHandlerDecorator.cs @@ -16,7 +16,7 @@ internal sealed class OutboxEventHandlerDecorator : IEventHandler handler, IMessageOutbox outbox, - OutboxSettings outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) + OutboxOptions outboxOptions, IMessagePropertiesAccessor messagePropertiesAccessor) { _handler = handler; _outbox = outbox; diff --git a/src/apps/identity/Genocs.Identities.Application/Extensions.cs b/src/apps/identity/Genocs.Identities.Application/Extensions.cs index ae8f138d..0d19358d 100644 --- a/src/apps/identity/Genocs.Identities.Application/Extensions.cs +++ b/src/apps/identity/Genocs.Identities.Application/Extensions.cs @@ -106,7 +106,7 @@ public static IApplicationBuilder UseCore(this IApplicationBuilder app) } public static async Task GetAppName(this HttpContext httpContext) - => await httpContext.Response.WriteAsync(httpContext.RequestServices?.GetService()?.Name ?? string.Empty); + => await httpContext.Response.WriteAsync(httpContext.RequestServices?.GetService()?.Name ?? string.Empty); internal static CorrelationContext GetCorrelationContext(this IHttpContextAccessor accessor) => accessor.HttpContext?.Request.Headers.TryGetValue("Correlation-Context", out var json) is true diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs index 77f0cda4..7deb8fb5 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs @@ -26,8 +26,8 @@ public class ProductServiceClient : IProductServiceClient public ProductServiceClient( IHttpClient client, ICertificatesService certificatesService, - HttpClientSettings httpClientOptions, - VaultSettings vaultOptions, + HttpClientOptions httpClientOptions, + VaultOptions vaultOptions, SecuritySettings securitySettings) { _client = client ?? throw new ArgumentNullException(nameof(client)); diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs similarity index 66% rename from src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs rename to src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs index 1b1572fa..6dc84226 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Options/SignalRSettings.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs @@ -1,9 +1,9 @@ -namespace Genocs.SignalR.WebApi.Options; +namespace Genocs.SignalR.WebApi.Configurations; /// /// The signalR Settings definition. /// -public class SignalRSettings +public class SignalROptions { public string? Backplane { get; set; } public string? Hub { get; set; } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs index 4339e3f3..4a8d6756 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Framework/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Core.Builders; -using Genocs.SignalR.WebApi.Options; +using Genocs.SignalR.WebApi.Configurations; namespace Genocs.SignalR.WebApi.Framework; @@ -10,7 +10,7 @@ public static string ToUserGroup(this Guid userId) public static IGenocsBuilder AddSignalR(this IGenocsBuilder builder) { - var options = builder.Configuration.GetOptions("signalr"); + var options = builder.Configuration.GetOptions("signalr"); if (options is not null) { @@ -22,7 +22,7 @@ public static IGenocsBuilder AddSignalR(this IGenocsBuilder builder) public static IGenocsBuilder UseSignalR(this IGenocsBuilder builder) { - var options = builder.GetOptions("signalr"); + var options = builder.GetOptions("signalr"); if (options is not null) { diff --git a/testEnvironments.json b/testEnvironments.json new file mode 100644 index 00000000..a110b57d --- /dev/null +++ b/testEnvironments.json @@ -0,0 +1,17 @@ +{ + "version": "1", + "environments": [ + // See https://aka.ms/remotetesting for more details + // about how to configure remote environments. + //{ + // "name": "WSL Ubuntu", + // "type": "wsl", + // "wslDistribution": "Ubuntu" + //}, + //{ + // "name": "Docker dotnet/sdk", + // "type": "docker", + // "dockerImage": "mcr.microsoft.com/dotnet/sdk" + //} + ] +} \ No newline at end of file From 5977b8c49236a78a209519de00deb6e9865d7b57 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 7 Jul 2024 15:29:01 +0200 Subject: [PATCH 057/104] Refactor config naming and add new options This commit encompasses a broad range of changes aimed at improving the clarity, consistency, and flexibility of configuration management within the application. Key changes include: - Renaming the `Genocs.Core.Demo.WebApi.Options` namespace to `Genocs.Core.Demo.WebApi.Configurations` to standardize the naming convention for configuration-related classes. - Updating property descriptions in options classes (e.g., `JwtOptions`, `AppOptions`) to more accurately reflect their purposes and adding a new property `AllowAnonymousEndpoints` to `JwtOptions`. - Modifying the `Position` constants in various options classes to use camelCase, aligning with common JSON and configuration naming conventions. - Updating references in `BuilderExtensions.cs`, `ServiceCollectionExtensions.cs`, and various client classes to use the new `Configurations` namespace. - Renaming settings classes to options (e.g., `AzureServiceBusQueueSettings` to `AzureServiceBusQueueOptions`, `SecuritySettings` to `SecurityOptions`) across the application to follow a consistent naming convention. - Introducing new configuration classes (`JaegerOptions`, `SecurityOptions`, `SwaggerOptions`, `WebApiConfigureOptions`) to better structure and manage configurations for Jaeger tracing, security, Swagger documentation, and Web API settings. - Removing or renaming various settings and builder classes related to metrics, Redis, and Azure Key Vault to reflect a shift in configuration management strategy. These changes aim to enhance the application's configuration management by adopting best practices for naming conventions and configuration patterns, thereby making the codebase easier to understand and maintain. --- src/Genocs.Auth/Configurations/JwtOptions.cs | 3 +- .../Configurations/AppOptions.cs | 6 ++ .../Configurations/ExternalServiceOptions.cs | 12 +++- .../Configurations/RabbitMQOptions.cs | 12 +++- .../Configurations/SecretOptions.cs | 6 +- .../VerificationServiceOptions.cs | 12 +++- .../Extensions/BuilderExtensions.cs | 4 +- .../Extensions/ServiceCollectionExtensions.cs | 21 +++--- .../Services/ExternalServiceClient.cs | 2 +- .../Services/VerificationServiceClient.cs | 2 +- src/Genocs.Core.Demo.Worker/Program.cs | 4 +- .../Configurations/ConsulOptions.cs | 4 ++ .../Configurations/HttpClientOptions.cs | 5 ++ .../Configurations/FabioOptions.cs | 4 +- .../Configurations/LoggerOptions.cs | 5 ++ ...ngsBuilder.cs => MetricsOptionsBuilder.cs} | 22 +++--- .../Configurations/IMetricsOptionsBuilder.cs | 14 ++++ .../Configurations/IMetricsSettingsBuilder.cs | 14 ---- .../{MetricsSettings.cs => MetricsOptions.cs} | 4 +- src/Genocs.Metrics/AppMetrics/Extensions.cs | 10 +-- src/Genocs.Metrics/Prometheus/Extensions.cs | 4 +- .../Prometheus/Internals/PrometheusJob.cs | 2 +- .../Internals/PrometheusMiddleware.cs | 2 +- ...etheusSettings.cs => PrometheusOptions.cs} | 7 +- .../MongoDbEncryptionOptions.cs | 8 ++- .../MongoDbEncryptionSettings.cs | 69 ------------------- .../{MongoDbSettings.cs => MongoDbOptions.cs} | 0 .../Builders/RedisSettingsBuilder.cs | 10 +-- .../Configurations/IRedisOptionsBuilder.cs | 8 +++ .../Configurations/IRedisSettingsBuilder.cs | 8 --- .../{RedisSettings.cs => RedisOptions.cs} | 17 +++-- src/Genocs.Persistence.Redis/Extensions.cs | 10 +-- ...ultSettings.cs => AzureKeyVaultOptions.cs} | 9 ++- .../Extensions.cs | 13 ++-- ...ings.cs => AzureServiceBusQueueOptions.cs} | 13 +++- ...ings.cs => AzureServiceBusTopicOptions.cs} | 12 +++- .../Queues/AzureServiceBusQueue.cs | 6 +- .../Topics/AzureServiceBusTopic.cs | 6 +- src/Genocs.Tracing/Extensions.cs | 6 +- .../Jaeger/Builders/JaegerOptionsBuilder.cs | 4 +- .../Configurations/IJaegerOptionsBuilder.cs | 2 +- .../{JaegerSettings.cs => JaegerOptions.cs} | 5 +- src/Genocs.Tracing/Jaeger/Extensions.cs | 10 +-- .../CertificateMiddleware.cs | 10 +-- ...SecuritySettings.cs => SecurityOptions.cs} | 10 +-- src/Genocs.WebApi.Security/Extensions.cs | 4 +- .../Genocs.WebApi.Security.csproj | 4 -- .../Builders/SwaggerOptionsBuilder.cs | 4 +- .../Configurations/ISwaggerOptionsBuilder.cs | 2 +- .../{SwaggerSettings.cs => SwaggerOptions.cs} | 2 +- src/Genocs.WebApi.Swagger/Docs/Extensions.cs | 6 +- src/Genocs.WebApi.Swagger/Extensions.cs | 2 +- .../Configurations/WebApiConfigureOptions.cs | 26 +++++++ .../Configurations/WebApiOptions.cs | 24 +------ .../Configurations/WebApiSettings.cs | 9 --- src/Genocs.WebApi/Extensions.cs | 2 +- .../Configurations/MessagingOptions.cs | 7 ++ .../Services/ProductServiceClient.cs | 12 ++-- .../Configurations/SignalROptions.cs | 12 +++- 59 files changed, 281 insertions(+), 252 deletions(-) rename src/Genocs.Metrics/AppMetrics/Builders/{MetricsSettingsBuilder.cs => MetricsOptionsBuilder.cs} (50%) create mode 100644 src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs delete mode 100644 src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs rename src/Genocs.Metrics/AppMetrics/Configurations/{MetricsSettings.cs => MetricsOptions.cs} (95%) rename src/Genocs.Metrics/Prometheus/Options/{PrometheusSettings.cs => PrometheusOptions.cs} (80%) delete mode 100644 src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs rename src/Genocs.Persistence.MongoDb/Configurations/{MongoDbSettings.cs => MongoDbOptions.cs} (100%) create mode 100644 src/Genocs.Persistence.Redis/Configurations/IRedisOptionsBuilder.cs delete mode 100644 src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs rename src/Genocs.Persistence.Redis/Configurations/{RedisSettings.cs => RedisOptions.cs} (59%) rename src/Genocs.Secrets.AzureKeyVault/Configurations/{AzureKeyVaultSettings.cs => AzureKeyVaultOptions.cs} (67%) rename src/Genocs.ServiceBusAzure/Configurations/{AzureServiceBusQueueSettings.cs => AzureServiceBusQueueOptions.cs} (61%) rename src/Genocs.ServiceBusAzure/Configurations/{AzureServiceBusTopicSettings.cs => AzureServiceBusTopicOptions.cs} (64%) rename src/Genocs.Tracing/Jaeger/Configurations/{JaegerSettings.cs => JaegerOptions.cs} (92%) rename src/Genocs.WebApi.Security/Configurations/{SecuritySettings.cs => SecurityOptions.cs} (76%) rename src/Genocs.WebApi.Swagger/Docs/Configurations/{SwaggerSettings.cs => SwaggerOptions.cs} (93%) create mode 100644 src/Genocs.WebApi/Configurations/WebApiConfigureOptions.cs delete mode 100644 src/Genocs.WebApi/Configurations/WebApiSettings.cs diff --git a/src/Genocs.Auth/Configurations/JwtOptions.cs b/src/Genocs.Auth/Configurations/JwtOptions.cs index cc181c18..44a21d08 100644 --- a/src/Genocs.Auth/Configurations/JwtOptions.cs +++ b/src/Genocs.Auth/Configurations/JwtOptions.cs @@ -8,9 +8,10 @@ public class JwtOptions public const string Position = "jwt"; /// - /// It is used to enable or disable the authentication. + /// It defines whether the section is enabled or not. /// public bool Enabled { get; set; } + public IEnumerable? AllowAnonymousEndpoints { get; set; } public CertificateOptions? Certificate { get; set; } public string? Algorithm { get; set; } diff --git a/src/Genocs.Common/Configurations/AppOptions.cs b/src/Genocs.Common/Configurations/AppOptions.cs index a5596f68..da9f08c3 100644 --- a/src/Genocs.Common/Configurations/AppOptions.cs +++ b/src/Genocs.Common/Configurations/AppOptions.cs @@ -10,6 +10,12 @@ public class AppOptions /// public const string Position = "app"; + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } + + /// /// Application name. /// diff --git a/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs b/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs index c52cacaa..ef8b1db6 100644 --- a/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/ExternalServiceOptions.cs @@ -1,13 +1,21 @@ using System.ComponentModel.DataAnnotations; -namespace Genocs.Core.Demo.WebApi.Options; +namespace Genocs.Core.Demo.WebApi.Configurations; /// /// This class implements Options pattern with Validation. /// public class ExternalServiceOptions : IValidatableObject { - public const string Position = "ExternalService"; + /// + /// Default section name. + /// + public const string Position = "externalService"; + + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } public string Caller { get; set; } = default!; public string Private { get; set; } = default!; diff --git a/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs b/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs index 92bc8656..029daa12 100644 --- a/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/RabbitMQOptions.cs @@ -1,8 +1,16 @@ -namespace Genocs.Core.Demo.WebApi.Options; +namespace Genocs.Core.Demo.WebApi.Configurations; public class RabbitMQOptions { - public const string Position = "RabbitMQ"; + /// + /// Default section name. + /// + public const string Position = "rabbitMQ"; + + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } public string HostName { get; set; } = default!; public string VirtualHost { get; set; } = default!; diff --git a/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs b/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs index 51ef9d67..367033fc 100644 --- a/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/SecretOptions.cs @@ -1,4 +1,4 @@ -namespace Genocs.Core.Demo.WebApi.Options; +namespace Genocs.Core.Demo.WebApi.Configurations; public class SecretOptions { @@ -7,6 +7,10 @@ public class SecretOptions /// public const string Position = "secrets"; + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } /// /// This is an example of a secret. That should be stored in a secure way. diff --git a/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs b/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs index 2f847694..d33ab6a4 100644 --- a/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs +++ b/src/Genocs.Core.Demo.WebApi/Configurations/VerificationServiceOptions.cs @@ -1,8 +1,16 @@ -namespace Genocs.Core.Demo.WebApi.Options; +namespace Genocs.Core.Demo.WebApi.Configurations; public class VerificationServiceOptions { - public const string Position = "VerificationService"; + /// + /// Default section name. + /// + public const string Position = "verificationService"; + + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } public string ApiKey { get; set; } = default!; } diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs index f4fe8d8d..3d955bc0 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/BuilderExtensions.cs @@ -1,6 +1,6 @@ using Genocs.Core.Builders; +using Genocs.Core.Demo.WebApi.Configurations; using Genocs.Core.Demo.WebApi.Infrastructure.Services; -using Genocs.Core.Demo.WebApi.Options; using Genocs.HTTP; using Genocs.Security; using Genocs.WebApi.Security; @@ -37,7 +37,7 @@ public static IGenocsBuilder AddApplicationServices(this IGenocsBuilder builder) .ValidateDataAnnotations() .ValidateOnStart(); - // builder.Services.AddSingleton, ConfigureWebApiSettings>(); + // builder.Services.AddSingleton, ConfigureWebApiSettings>(); ExternalServiceOptions settings = builder.Configuration.GetOptions(ExternalServiceOptions.Position); builder.Services.AddSingleton(settings); diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs index 4d0f1984..a5d833bf 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs @@ -1,5 +1,4 @@ -using Genocs.Core.Builders; -using Genocs.Core.Demo.WebApi.Options; +using Genocs.Core.Demo.WebApi.Configurations; using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; @@ -22,7 +21,7 @@ public static IServiceCollection AddAzureServiceBus(this IServiceCollection serv public static IServiceCollection AddAzureServiceBusTopic(this IServiceCollection services, IConfiguration configuration) { // Register IOptions - services.Configure(configuration.GetSection(AzureServiceBusTopicSettings.Position)); + services.Configure(configuration.GetSection(AzureServiceBusTopicOptions.Position)); // HOW to Register TopicSettings instead of IOptions ////var topicSetting = new TopicOptions(); @@ -37,7 +36,7 @@ public static IServiceCollection AddAzureServiceBusTopic(this IServiceCollection public static IServiceCollection AddAzureServiceBusQueue(this IServiceCollection services, IConfiguration configuration) { // Register IOptions - services.Configure(configuration.GetSection(AzureServiceBusQueueSettings.Position)); + services.Configure(configuration.GetSection(AzureServiceBusQueueOptions.Position)); // HOW to Register QueueSettings instead of IOptions ////var queueSetting = new QueueSettings(); @@ -51,9 +50,13 @@ public static IServiceCollection AddAzureServiceBusQueue(this IServiceCollection public static IServiceCollection AddCustomMassTransit(this IServiceCollection services, IConfiguration configuration) { - RabbitMQOptions options = configuration.GetOptions(RabbitMQOptions.Position); + RabbitMQOptions rabbitMQSettings = new RabbitMQOptions(); + configuration.GetSection(RabbitMQOptions.Position).Bind(rabbitMQSettings); - services.AddSingleton(options); + // This is another way to get the RabbitMQOptions + // RabbitMQOptions? rabbitMQSettingsV2 = configuration.GetSection(RabbitMQOptions.Position).Get(); + + services.AddSingleton(rabbitMQSettings); services.AddMassTransit(x => { @@ -63,11 +66,11 @@ public static IServiceCollection AddCustomMassTransit(this IServiceCollection se { cfg.ConfigureEndpoints(context); //cfg.UseHealthCheck(context); - cfg.Host(options.HostName, options.VirtualHost, + cfg.Host(rabbitMQSettings.HostName, rabbitMQSettings.VirtualHost, h => { - h.Username(options.UserName); - h.Password(options.Password); + h.Username(rabbitMQSettings.UserName); + h.Password(rabbitMQSettings.Password); } ); }); diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs index f7716aff..6ca25116 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/ExternalServiceClient.cs @@ -1,4 +1,4 @@ -using Genocs.Core.Demo.WebApi.Options; +using Genocs.Core.Demo.WebApi.Configurations; using Genocs.HTTP; using Genocs.HTTP.Configurations; using Genocs.Security; diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs index e9840a86..4820e3ae 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Services/VerificationServiceClient.cs @@ -1,4 +1,4 @@ -using Genocs.Core.Demo.WebApi.Options; +using Genocs.Core.Demo.WebApi.Configurations; using Genocs.HTTP; using Genocs.HTTP.Configurations; using Newtonsoft.Json; diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index 49527388..6f6931c9 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -98,7 +98,7 @@ static void ConfigureBus(IBusRegistrationContext context, IRabbitMqBusFactoryCon static void ConfigureAzureServiceBusTopic(IServiceCollection services, IConfiguration configuration) { - services.Configure(configuration.GetSection(AzureServiceBusTopicSettings.Position)); + services.Configure(configuration.GetSection(AzureServiceBusTopicOptions.Position)); services.AddSingleton(); @@ -110,7 +110,7 @@ static void ConfigureAzureServiceBusTopic(IServiceCollection services, IConfigur static void ConfigureAzureServiceBusQueue(IServiceCollection services, IConfiguration configuration) { - services.Configure(configuration.GetSection(AzureServiceBusQueueSettings.Position)); + services.Configure(configuration.GetSection(AzureServiceBusQueueOptions.Position)); services.AddSingleton(); diff --git a/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs index 3f1f6cc9..f370ef4a 100644 --- a/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs +++ b/src/Genocs.Discovery.Consul/Configurations/ConsulOptions.cs @@ -7,7 +7,11 @@ public class ConsulOptions /// public const string Position = "consul"; + /// + /// It defines whether the section is enabled or not. + /// public bool Enabled { get; set; } + public string? Url { get; set; } public string? Service { get; set; } public string? Address { get; set; } diff --git a/src/Genocs.HTTP/Configurations/HttpClientOptions.cs b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs index 1310bfaf..91bd72e7 100644 --- a/src/Genocs.HTTP/Configurations/HttpClientOptions.cs +++ b/src/Genocs.HTTP/Configurations/HttpClientOptions.cs @@ -10,6 +10,11 @@ public class HttpClientOptions /// public const string Position = "httpClient"; + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } + /// /// It defines if set consul as service discovery or Fabio as load balancer. /// Allowed values are: consul, Fabio. diff --git a/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs index 28803892..69b78ceb 100644 --- a/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs +++ b/src/Genocs.LoadBalancing.Fabio/Configurations/FabioOptions.cs @@ -6,12 +6,12 @@ namespace Genocs.LoadBalancing.Fabio.Configurations; public class FabioOptions { /// - /// The default Fabio section name. + /// Default section name. /// public const string Position = "fabio"; /// - /// Gets or sets a value indicating whether this is enabled. + /// It defines whether the section is enabled or not. /// public bool Enabled { get; set; } diff --git a/src/Genocs.Logging/Configurations/LoggerOptions.cs b/src/Genocs.Logging/Configurations/LoggerOptions.cs index 087f9da8..59afbad2 100644 --- a/src/Genocs.Logging/Configurations/LoggerOptions.cs +++ b/src/Genocs.Logging/Configurations/LoggerOptions.cs @@ -10,6 +10,11 @@ public class LoggerOptions /// public const string Position = "logger"; + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } + public string? Level { get; set; } /// diff --git a/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs similarity index 50% rename from src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs rename to src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs index 44dca3e8..a28c97f2 100644 --- a/src/Genocs.Metrics/AppMetrics/Builders/MetricsSettingsBuilder.cs +++ b/src/Genocs.Metrics/AppMetrics/Builders/MetricsOptionsBuilder.cs @@ -2,58 +2,58 @@ namespace Genocs.Metrics.AppMetrics.Builders; -internal sealed class MetricsSettingsBuilder : IMetricsSettingsBuilder +internal sealed class MetricsOptionsBuilder : IMetricsOptionsBuilder { - private readonly MetricsSettings _settings = new(); + private readonly MetricsOptions _settings = new(); - public IMetricsSettingsBuilder Enable(bool enabled) + public IMetricsOptionsBuilder Enable(bool enabled) { _settings.Enabled = enabled; return this; } - public IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled) + public IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled) { _settings.InfluxEnabled = influxEnabled; return this; } - public IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled) + public IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled) { _settings.PrometheusEnabled = prometheusEnabled; return this; } - public IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter) + public IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter) { _settings.PrometheusFormatter = prometheusFormatter; return this; } - public IMetricsSettingsBuilder WithInfluxUrl(string influxUrl) + public IMetricsOptionsBuilder WithInfluxUrl(string influxUrl) { _settings.InfluxUrl = influxUrl; return this; } - public IMetricsSettingsBuilder WithDatabase(string database) + public IMetricsOptionsBuilder WithDatabase(string database) { _settings.Database = database; return this; } - public IMetricsSettingsBuilder WithInterval(int interval) + public IMetricsOptionsBuilder WithInterval(int interval) { _settings.Interval = interval; return this; } - public IMetricsSettingsBuilder WithTags(IDictionary tags) + public IMetricsOptionsBuilder WithTags(IDictionary tags) { _settings.Tags = tags; return this; } - public MetricsSettings Build() + public MetricsOptions Build() => _settings; } \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs new file mode 100644 index 00000000..750b1d4b --- /dev/null +++ b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsOptionsBuilder.cs @@ -0,0 +1,14 @@ +namespace Genocs.Metrics.AppMetrics.Configurations; + +public interface IMetricsOptionsBuilder +{ + IMetricsOptionsBuilder Enable(bool enabled); + IMetricsOptionsBuilder WithInfluxEnabled(bool influxEnabled); + IMetricsOptionsBuilder WithPrometheusEnabled(bool prometheusEnabled); + IMetricsOptionsBuilder WithPrometheusFormatter(string prometheusFormatter); + IMetricsOptionsBuilder WithInfluxUrl(string influxUrl); + IMetricsOptionsBuilder WithDatabase(string database); + IMetricsOptionsBuilder WithInterval(int interval); + IMetricsOptionsBuilder WithTags(IDictionary tags); + MetricsOptions Build(); +} \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs b/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs deleted file mode 100644 index e9964080..00000000 --- a/src/Genocs.Metrics/AppMetrics/Configurations/IMetricsSettingsBuilder.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Genocs.Metrics.AppMetrics.Configurations; - -public interface IMetricsSettingsBuilder -{ - IMetricsSettingsBuilder Enable(bool enabled); - IMetricsSettingsBuilder WithInfluxEnabled(bool influxEnabled); - IMetricsSettingsBuilder WithPrometheusEnabled(bool prometheusEnabled); - IMetricsSettingsBuilder WithPrometheusFormatter(string prometheusFormatter); - IMetricsSettingsBuilder WithInfluxUrl(string influxUrl); - IMetricsSettingsBuilder WithDatabase(string database); - IMetricsSettingsBuilder WithInterval(int interval); - IMetricsSettingsBuilder WithTags(IDictionary tags); - MetricsSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsOptions.cs similarity index 95% rename from src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs rename to src/Genocs.Metrics/AppMetrics/Configurations/MetricsOptions.cs index b633b797..17de484d 100644 --- a/src/Genocs.Metrics/AppMetrics/Configurations/MetricsSettings.cs +++ b/src/Genocs.Metrics/AppMetrics/Configurations/MetricsOptions.cs @@ -1,9 +1,9 @@ namespace Genocs.Metrics.AppMetrics.Configurations; /// -/// The MetricsSettings class. +/// The Metrics settings class. /// -public class MetricsSettings +public class MetricsOptions { /// /// Default section name. diff --git a/src/Genocs.Metrics/AppMetrics/Extensions.cs b/src/Genocs.Metrics/AppMetrics/Extensions.cs index 292e0c13..94e769c3 100644 --- a/src/Genocs.Metrics/AppMetrics/Extensions.cs +++ b/src/Genocs.Metrics/AppMetrics/Extensions.cs @@ -40,7 +40,7 @@ public static IGenocsBuilder AddMetrics( appSectionName = AppOptions.Position; } - var metricsOptions = builder.GetOptions(metricsSectionName); + var metricsOptions = builder.GetOptions(metricsSectionName); var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); @@ -49,7 +49,7 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - Func buildOptions, + Func buildOptions, string appSectionName = AppSectionName) { if (string.IsNullOrWhiteSpace(appSectionName)) @@ -57,7 +57,7 @@ public static IGenocsBuilder AddMetrics( appSectionName = AppSectionName; } - var metricsOptions = buildOptions(new MetricsSettingsBuilder()).Build(); + var metricsOptions = buildOptions(new MetricsOptionsBuilder()).Build(); var appOptions = builder.GetOptions(appSectionName); return builder.AddMetrics(metricsOptions, appOptions); @@ -66,7 +66,7 @@ public static IGenocsBuilder AddMetrics( [Description("For the time being it sets Kestrel's and IIS ServerOptions AllowSynchronousIO = true, see https://github.com/AppMetrics/AppMetrics/issues/396")] public static IGenocsBuilder AddMetrics( this IGenocsBuilder builder, - Configurations.MetricsSettings metricsSettings, + Configurations.MetricsOptions metricsSettings, AppOptions appSettings) { builder.Services.AddSingleton(metricsSettings); @@ -161,7 +161,7 @@ public static IApplicationBuilder UseMetrics(this IApplicationBuilder app) .UseMetricsAllMiddleware(); } - private static MetricsWebHostOptions GetMetricsWebHostOptions(MetricsSettings metricsOptions) + private static MetricsWebHostOptions GetMetricsWebHostOptions(Configurations.MetricsOptions metricsOptions) { var options = new MetricsWebHostOptions(); diff --git a/src/Genocs.Metrics/Prometheus/Extensions.cs b/src/Genocs.Metrics/Prometheus/Extensions.cs index 0e7e4bec..59904afe 100644 --- a/src/Genocs.Metrics/Prometheus/Extensions.cs +++ b/src/Genocs.Metrics/Prometheus/Extensions.cs @@ -12,7 +12,7 @@ public static class Extensions { public static IGenocsBuilder AddPrometheus(this IGenocsBuilder builder) { - var prometheusOptions = builder.GetOptions("prometheus"); + var prometheusOptions = builder.GetOptions(PrometheusOptions.Position); builder.Services.AddSingleton(prometheusOptions); if (!prometheusOptions.Enabled) { @@ -28,7 +28,7 @@ public static IGenocsBuilder AddPrometheus(this IGenocsBuilder builder) public static IApplicationBuilder UsePrometheus(this IApplicationBuilder app) { - var options = app.ApplicationServices.GetRequiredService(); + var options = app.ApplicationServices.GetRequiredService(); if (!options.Enabled) { return app; diff --git a/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs b/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs index ac4f209e..08232aaf 100644 --- a/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs +++ b/src/Genocs.Metrics/Prometheus/Internals/PrometheusJob.cs @@ -19,7 +19,7 @@ internal sealed class PrometheusJob : IHostedService /// /// /// - public PrometheusJob(PrometheusSettings options, ILogger logger) + public PrometheusJob(PrometheusOptions options, ILogger logger) { _enabled = options.Enabled; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs b/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs index e4b90a57..1c5464e8 100644 --- a/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs +++ b/src/Genocs.Metrics/Prometheus/Internals/PrometheusMiddleware.cs @@ -9,7 +9,7 @@ internal sealed class PrometheusMiddleware : IMiddleware private readonly string _endpoint; private readonly string? _apiKey; - public PrometheusMiddleware(PrometheusSettings options) + public PrometheusMiddleware(PrometheusOptions options) { _allowedHosts = new HashSet(options.AllowedHosts ?? Array.Empty()); _endpoint = string.IsNullOrWhiteSpace(options.Endpoint) ? "/metrics" : diff --git a/src/Genocs.Metrics/Prometheus/Options/PrometheusSettings.cs b/src/Genocs.Metrics/Prometheus/Options/PrometheusOptions.cs similarity index 80% rename from src/Genocs.Metrics/Prometheus/Options/PrometheusSettings.cs rename to src/Genocs.Metrics/Prometheus/Options/PrometheusOptions.cs index c8c68104..2b54fc5c 100644 --- a/src/Genocs.Metrics/Prometheus/Options/PrometheusSettings.cs +++ b/src/Genocs.Metrics/Prometheus/Options/PrometheusOptions.cs @@ -3,8 +3,13 @@ /// /// The Prometheus Setting definition. /// -public class PrometheusSettings +public class PrometheusOptions { + /// + /// Default section name. + /// + public const string Position = "prometheus"; + /// /// It defines whether the section is enabled or not. /// diff --git a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs index 70db85df..dca2d18b 100644 --- a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs +++ b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionOptions.cs @@ -5,11 +5,15 @@ /// public class MongoDbEncryptionOptions { + /// + /// Default section name. + /// + public const string Position = "mongoDbEncryption"; /// - /// Default Section name. + /// It defines whether the section is enabled or not. /// - public const string Position = "MongoDbEncryption"; + public bool Enabled { get; set; } /// /// The Database connection string. diff --git a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs deleted file mode 100644 index 3124e3a3..00000000 --- a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbEncryptionSettings.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace Genocs.Persistence.MongoDb.Configurations; - -/// -/// MongoDb encryption database Settings. -/// -public class MongoDbEncryptionSettings -{ - - /// - /// Default Section name - /// - public const string Position = "MongoDbEncryption"; - - /// - /// The Database connection string - /// - public string ConnectionString { get; set; } = default!; - - /// - /// The shared library used to encrypt - /// - public string LibPath { get; set; } = default!; - - /// - /// Azure Tenant Id - /// - public string TenantId { get; set; } = default!; - - /// - /// Azure Client Id - /// - public string ClientId { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string ClientSecret { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyName { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyVersion { get; set; } = default!; - - /// - /// Azure Client Secret - /// - public string KeyVaultEndpoint { get; set; } = default!; - - /// - /// Check if the MongoDbSettings object contains valid data - /// - /// MongoDbSettings object - /// return true if valid otherwise false - public static bool IsValid(MongoDbEncryptionSettings settings) - { - if (settings is null) return false; - - if (string.IsNullOrWhiteSpace(settings.ConnectionString)) return false; - if (string.IsNullOrWhiteSpace(settings.LibPath)) return false; - - return true; - - } -} diff --git a/src/Genocs.Persistence.MongoDb/Configurations/MongoDbSettings.cs b/src/Genocs.Persistence.MongoDb/Configurations/MongoDbOptions.cs similarity index 100% rename from src/Genocs.Persistence.MongoDb/Configurations/MongoDbSettings.cs rename to src/Genocs.Persistence.MongoDb/Configurations/MongoDbOptions.cs diff --git a/src/Genocs.Persistence.Redis/Builders/RedisSettingsBuilder.cs b/src/Genocs.Persistence.Redis/Builders/RedisSettingsBuilder.cs index e2d0cbb1..38bbb955 100644 --- a/src/Genocs.Persistence.Redis/Builders/RedisSettingsBuilder.cs +++ b/src/Genocs.Persistence.Redis/Builders/RedisSettingsBuilder.cs @@ -2,22 +2,22 @@ namespace Genocs.Persistence.Redis.Builders; -internal sealed class RedisSettingsBuilder : IRedisSettingsBuilder +internal sealed class RedisSettingsBuilder : IRedisOptionsBuilder { - private readonly RedisSettings _options = new(); + private readonly RedisOptions _options = new(); - public IRedisSettingsBuilder WithConnectionString(string connectionString) + public IRedisOptionsBuilder WithConnectionString(string connectionString) { _options.ConnectionString = connectionString; return this; } - public IRedisSettingsBuilder WithInstance(string instance) + public IRedisOptionsBuilder WithInstance(string instance) { _options.Instance = instance; return this; } - public RedisSettings Build() + public RedisOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Persistence.Redis/Configurations/IRedisOptionsBuilder.cs b/src/Genocs.Persistence.Redis/Configurations/IRedisOptionsBuilder.cs new file mode 100644 index 00000000..8d2000ea --- /dev/null +++ b/src/Genocs.Persistence.Redis/Configurations/IRedisOptionsBuilder.cs @@ -0,0 +1,8 @@ +namespace Genocs.Persistence.Redis.Configurations; + +public interface IRedisOptionsBuilder +{ + IRedisOptionsBuilder WithConnectionString(string connectionString); + IRedisOptionsBuilder WithInstance(string instance); + RedisOptions Build(); +} \ No newline at end of file diff --git a/src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs b/src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs deleted file mode 100644 index 145fac47..00000000 --- a/src/Genocs.Persistence.Redis/Configurations/IRedisSettingsBuilder.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Genocs.Persistence.Redis.Configurations; - -public interface IRedisSettingsBuilder -{ - IRedisSettingsBuilder WithConnectionString(string connectionString); - IRedisSettingsBuilder WithInstance(string instance); - RedisSettings Build(); -} \ No newline at end of file diff --git a/src/Genocs.Persistence.Redis/Configurations/RedisSettings.cs b/src/Genocs.Persistence.Redis/Configurations/RedisOptions.cs similarity index 59% rename from src/Genocs.Persistence.Redis/Configurations/RedisSettings.cs rename to src/Genocs.Persistence.Redis/Configurations/RedisOptions.cs index bd1176c0..5f256db9 100644 --- a/src/Genocs.Persistence.Redis/Configurations/RedisSettings.cs +++ b/src/Genocs.Persistence.Redis/Configurations/RedisOptions.cs @@ -1,27 +1,32 @@ namespace Genocs.Persistence.Redis.Configurations; /// -/// The Redis Options +/// The Redis Options. /// -public class RedisSettings +public class RedisOptions { /// - /// The section name + /// Default section name. /// public const string Position = "redis"; /// - /// The connection string + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } + + /// + /// The connection string. /// public string ConnectionString { get; set; } = "localhost"; /// - /// Redis instance + /// Redis instance. /// public string? Instance { get; set; } /// - /// The database Id + /// The database Id. /// public int Database { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Persistence.Redis/Extensions.cs b/src/Genocs.Persistence.Redis/Extensions.cs index 87ffed86..248df998 100644 --- a/src/Genocs.Persistence.Redis/Extensions.cs +++ b/src/Genocs.Persistence.Redis/Extensions.cs @@ -19,14 +19,14 @@ public static class Extensions /// The Genocs builder /// /// - public static IGenocsBuilder AddRedis(this IGenocsBuilder builder, string sectionName = RedisSettings.Position) + public static IGenocsBuilder AddRedis(this IGenocsBuilder builder, string sectionName = RedisOptions.Position) { if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = RedisSettings.Position; + sectionName = RedisOptions.Position; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); return builder.AddRedis(options); } @@ -38,7 +38,7 @@ public static IGenocsBuilder AddRedis(this IGenocsBuilder builder, string sectio /// public static IGenocsBuilder AddRedis( this IGenocsBuilder builder, - Func buildOptions) + Func buildOptions) { var options = buildOptions(new RedisSettingsBuilder()).Build(); return builder.AddRedis(options); @@ -50,7 +50,7 @@ public static IGenocsBuilder AddRedis( /// The Genocs builder /// /// - public static IGenocsBuilder AddRedis(this IGenocsBuilder builder, RedisSettings options) + public static IGenocsBuilder AddRedis(this IGenocsBuilder builder, RedisOptions options) { if (!builder.TryRegister(RegistryName)) { diff --git a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultSettings.cs b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs similarity index 67% rename from src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultSettings.cs rename to src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs index b6ae8649..62ca3c4f 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultSettings.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs @@ -3,12 +3,15 @@ namespace Genocs.Secrets.AzureKeyVault.Configurations; /// /// The vault Setting definition. /// -public class AzureKeyVaultSettings +public class AzureKeyVaultOptions { - public const string Position = "AzureKeyVault"; + /// + /// Default section name. + /// + public const string Position = "azureKeyVault"; /// - /// The flag to enable or disable the Azure Key Vault. + /// It defines whether the section is enabled or not. /// public bool Enabled { get; set; } diff --git a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs index 907cf7de..7daa3896 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Genocs.Secrets.AzureKeyVault; @@ -23,16 +22,16 @@ public static class Extensions /// The Host builder. public static IHostBuilder UseAzureKeyVault( this IHostBuilder builder, - string sectionName = AzureKeyVaultSettings.Position) + string sectionName = AzureKeyVaultOptions.Position) => builder.ConfigureAppConfiguration((ctx, cfg) => { // TODO Test if (string.IsNullOrWhiteSpace(sectionName)) { - sectionName = AzureKeyVaultSettings.Position; + sectionName = AzureKeyVaultOptions.Position; } - var settings = ctx.Configuration.GetOptions(sectionName); + var settings = ctx.Configuration.GetOptions(sectionName); if (!settings.Enabled) { return; @@ -54,10 +53,10 @@ public static IHostBuilder UseAzureKeyVault( /// The Web Host builder. public static IWebHostBuilder UseAzureKeyVault( this IWebHostBuilder builder, - string sectionName = AzureKeyVaultSettings.Position) + string sectionName = AzureKeyVaultOptions.Position) => builder.ConfigureAppConfiguration((ctx, cfg) => { - AzureKeyVaultSettings settings = ctx.Configuration.GetOptions(sectionName); + AzureKeyVaultOptions settings = ctx.Configuration.GetOptions(sectionName); if (!settings.Enabled) { return; @@ -74,7 +73,7 @@ public static IWebHostBuilder UseAzureKeyVault( public static WebApplicationBuilder UseAzureKeyVault(this WebApplicationBuilder builder) { - AzureKeyVaultSettings settings = builder.Configuration.GetOptions(AzureKeyVaultSettings.Position); + AzureKeyVaultOptions settings = builder.Configuration.GetOptions(AzureKeyVaultOptions.Position); if (!settings.Enabled) { return builder; diff --git a/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueSettings.cs b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueOptions.cs similarity index 61% rename from src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueSettings.cs rename to src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueOptions.cs index c7cd6781..1ff80237 100644 --- a/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueSettings.cs +++ b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusQueueOptions.cs @@ -2,9 +2,18 @@ namespace Genocs.ServiceBusAzure.Configurations; -public class AzureServiceBusQueueSettings +public class AzureServiceBusQueueOptions { - public const string Position = "AzureServiceBusQueue"; + /// + /// Default section name. + /// + public const string Position = "azureServiceBusQueue"; + + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } + public string? ConnectionString { get; set; } public string? QueueName { get; set; } public int MaxConcurrentCalls { get; set; } = 20; diff --git a/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicSettings.cs b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicOptions.cs similarity index 64% rename from src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicSettings.cs rename to src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicOptions.cs index 26a16a4b..f830f97f 100644 --- a/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicSettings.cs +++ b/src/Genocs.ServiceBusAzure/Configurations/AzureServiceBusTopicOptions.cs @@ -2,9 +2,17 @@ namespace Genocs.ServiceBusAzure.Configurations; -public class AzureServiceBusTopicSettings +public class AzureServiceBusTopicOptions { - public const string Position = "AzureServiceBusTopic"; + /// + /// Default section name. + /// + public const string Position = "azureServiceBusTopic"; + + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } public string? ConnectionString { get; set; } public string? TopicName { get; set; } public string? SubscriptionName { get; set; } diff --git a/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs b/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs index 04a2c8d5..b0522451 100644 --- a/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs +++ b/src/Genocs.ServiceBusAzure/Queues/AzureServiceBusQueue.cs @@ -16,7 +16,7 @@ namespace Genocs.ServiceBusAzure.Queues; public class AzureServiceBusQueue : IAzureServiceBusQueue { private readonly IQueueClient _queueClient; - private readonly AzureServiceBusQueueSettings _options; + private readonly AzureServiceBusQueueOptions _options; private readonly ILogger _logger; private Dictionary> _handlers = new Dictionary>(); private const string COMMAND_SUFFIX = "Command"; @@ -29,7 +29,7 @@ public class AzureServiceBusQueue : IAzureServiceBusQueue /// /// /// - public AzureServiceBusQueue(IOptions options, + public AzureServiceBusQueue(IOptions options, IServiceProvider serviceProvider, ILogger logger) { @@ -59,7 +59,7 @@ public AzureServiceBusQueue(IOptions options, /// /// /// - public AzureServiceBusQueue(AzureServiceBusQueueSettings options, + public AzureServiceBusQueue(AzureServiceBusQueueOptions options, IServiceProvider serviceProvider, ILogger logger) { diff --git a/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs b/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs index 1684af7e..9686274b 100644 --- a/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs +++ b/src/Genocs.ServiceBusAzure/Topics/AzureServiceBusTopic.cs @@ -13,7 +13,7 @@ namespace Genocs.ServiceBusAzure.Topics; public class AzureServiceBusTopic : IAzureServiceBusTopic { private readonly TopicClient _topicClient; - private readonly AzureServiceBusTopicSettings _options; + private readonly AzureServiceBusTopicOptions _options; private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; private const string EVENT_SUFFIX = "Event"; @@ -22,7 +22,7 @@ public class AzureServiceBusTopic : IAzureServiceBusTopic private readonly List _eventTypes; public AzureServiceBusTopic( - IOptions options, + IOptions options, IServiceProvider serviceProvider, ILogger logger) { @@ -47,7 +47,7 @@ public AzureServiceBusTopic( } } public AzureServiceBusTopic( - AzureServiceBusTopicSettings options, + AzureServiceBusTopicOptions options, IServiceProvider serviceProvider, ILogger logger) { diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index 130635e8..44a9bc0f 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -75,7 +75,7 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) } } - var jaegerOptions = builder.GetOptions(JaegerSettings.Position); + var jaegerOptions = builder.GetOptions(JaegerOptions.Position); if (jaegerOptions != null && jaegerOptions.Enabled) { @@ -121,7 +121,7 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) return builder; } - private static ISampler GetSampler(JaegerSettings options) + private static ISampler GetSampler(JaegerOptions options) { switch (options.Sampler) { @@ -132,7 +132,7 @@ private static ISampler GetSampler(JaegerSettings options) } } - private static HttpSender BuildHttpSender(JaegerSettings.HttpSenderSettings? options) + private static HttpSender BuildHttpSender(JaegerOptions.HttpSenderSettings? options) { if (options is null) { diff --git a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs index 1bb7c940..7bb3b3de 100644 --- a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs @@ -4,7 +4,7 @@ namespace Genocs.Tracing.Jaeger.Builders; internal sealed class JaegerOptionsBuilder : IJaegerOptionsBuilder { - private readonly JaegerSettings _options = new(); + private readonly JaegerOptions _options = new(); public IJaegerOptionsBuilder Enable(bool enabled) { @@ -54,6 +54,6 @@ public IJaegerOptionsBuilder WithSamplingRate(double samplingRate) return this; } - public JaegerSettings Build() + public JaegerOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs index 5e9ab003..e19ae13a 100644 --- a/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs @@ -10,5 +10,5 @@ public interface IJaegerOptionsBuilder IJaegerOptionsBuilder WithSampler(string sampler); IJaegerOptionsBuilder WithMaxTracesPerSecond(double maxTracesPerSecond); IJaegerOptionsBuilder WithSamplingRate(double samplingRate); - JaegerSettings Build(); + JaegerOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/Configurations/JaegerSettings.cs b/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs similarity index 92% rename from src/Genocs.Tracing/Jaeger/Configurations/JaegerSettings.cs rename to src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs index 59528f09..b1d9c379 100644 --- a/src/Genocs.Tracing/Jaeger/Configurations/JaegerSettings.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs @@ -3,7 +3,7 @@ namespace Genocs.Tracing.Jaeger.Configurations; /// /// Jaeger Settings. /// -public class JaegerSettings +public class JaegerOptions { /// /// Default section name. @@ -11,9 +11,10 @@ public class JaegerSettings public const string Position = "jaeger"; /// - /// + /// It defines whether the section is enabled or not. /// public bool Enabled { get; set; } + public string? ServiceName { get; set; } public string? UdpHost { get; set; } public int UdpPort { get; set; } diff --git a/src/Genocs.Tracing/Jaeger/Extensions.cs b/src/Genocs.Tracing/Jaeger/Extensions.cs index 59d3af36..a5aa4065 100644 --- a/src/Genocs.Tracing/Jaeger/Extensions.cs +++ b/src/Genocs.Tracing/Jaeger/Extensions.cs @@ -29,14 +29,14 @@ public static class Extensions /// /// /// - public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string sectionName = JaegerSettings.Position) + public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string sectionName = JaegerOptions.Position) { if (Interlocked.Exchange(ref _initialized, 1) == 1) { return builder; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); @@ -85,7 +85,7 @@ public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string secti return builder; } - private static HttpSender BuildHttpSender(JaegerSettings.HttpSenderSettings? options) + private static HttpSender BuildHttpSender(JaegerOptions.HttpSenderSettings? options) { if (options is null) { @@ -125,12 +125,12 @@ public static IApplicationBuilder UseJaeger(this IApplicationBuilder app) { // Could be extended with some additional middleware using var scope = app.ApplicationServices.CreateScope(); - var options = scope.ServiceProvider.GetRequiredService(); + var options = scope.ServiceProvider.GetRequiredService(); return app; } - private static ISampler GetSampler(JaegerSettings options) + private static ISampler GetSampler(JaegerOptions options) { return options.Sampler switch { diff --git a/src/Genocs.WebApi.Security/CertificateMiddleware.cs b/src/Genocs.WebApi.Security/CertificateMiddleware.cs index 3111aed3..e976c994 100644 --- a/src/Genocs.WebApi.Security/CertificateMiddleware.cs +++ b/src/Genocs.WebApi.Security/CertificateMiddleware.cs @@ -9,16 +9,16 @@ internal sealed class CertificateMiddleware : IMiddleware { private readonly ICertificatePermissionValidator _certificatePermissionValidator; private readonly ILogger _logger; - private readonly SecuritySettings.CertificateSettings _options; + private readonly SecurityOptions.CertificateOptions _options; private readonly HashSet _allowedHosts; - private readonly IDictionary _acl; + private readonly IDictionary _acl; private readonly IDictionary _subjects = new Dictionary(); private readonly bool _validateAcl; private readonly bool _skipRevocationCheck; public CertificateMiddleware( ICertificatePermissionValidator certificatePermissionValidator, - SecuritySettings options, + SecurityOptions options, ILogger logger) { _certificatePermissionValidator = certificatePermissionValidator; @@ -33,7 +33,7 @@ public CertificateMiddleware( return; } - _acl = new Dictionary(); + _acl = new Dictionary(); foreach (var (key, acl) in _options.Acl) { if (!string.IsNullOrWhiteSpace(acl.ValidIssuer) && !acl.ValidIssuer.StartsWith("CN=")) @@ -78,7 +78,7 @@ public Task InvokeAsync(HttpContext context, RequestDelegate next) return next(context); } - SecuritySettings.CertificateSettings.AclSettings acl; + SecurityOptions.CertificateOptions.AclOptions acl; if (_subjects.TryGetValue(certificate.Subject, out string? subject)) { if (!_acl.TryGetValue(subject, out var existingAcl)) diff --git a/src/Genocs.WebApi.Security/Configurations/SecuritySettings.cs b/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs similarity index 76% rename from src/Genocs.WebApi.Security/Configurations/SecuritySettings.cs rename to src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs index bab3c180..dc4c04ee 100644 --- a/src/Genocs.WebApi.Security/Configurations/SecuritySettings.cs +++ b/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs @@ -1,22 +1,22 @@ namespace Genocs.WebApi.Security.Configurations; -public class SecuritySettings +public class SecurityOptions { - public CertificateSettings? Certificate { get; set; } + public CertificateOptions? Certificate { get; set; } - public class CertificateSettings + public class CertificateOptions { public bool Enabled { get; set; } public string? Header { get; set; } public bool AllowSubdomains { get; set; } public IEnumerable? AllowedDomains { get; set; } public IEnumerable? AllowedHosts { get; set; } - public IDictionary? Acl { get; set; } + public IDictionary? Acl { get; set; } public bool SkipRevocationCheck { get; set; } public string GetHeaderName() => string.IsNullOrWhiteSpace(Header) ? "Certificate" : Header; - public class AclSettings + public class AclOptions { public string? ValidIssuer { get; set; } public string? ValidThumbprint { get; set; } diff --git a/src/Genocs.WebApi.Security/Extensions.cs b/src/Genocs.WebApi.Security/Extensions.cs index 957802e4..d81de65b 100644 --- a/src/Genocs.WebApi.Security/Extensions.cs +++ b/src/Genocs.WebApi.Security/Extensions.cs @@ -17,7 +17,7 @@ public static IGenocsBuilder AddCertificateAuthentication( string sectionName = SectionName, Type? permissionValidatorType = null) { - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); if (!builder.TryRegister(RegistryName)) { @@ -57,7 +57,7 @@ public static IGenocsBuilder AddCertificateAuthentication( public static IApplicationBuilder UseCertificateAuthentication(this IApplicationBuilder app) { - var options = app.ApplicationServices.GetRequiredService(); + var options = app.ApplicationServices.GetRequiredService(); if (options.Certificate is null || !options.Certificate.Enabled) { return app; diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 4c964e2c..f3664774 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -61,8 +61,4 @@ - - - - diff --git a/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs index 7c34637a..36173a5b 100644 --- a/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs @@ -4,7 +4,7 @@ namespace Genocs.WebApi.Swagger.Docs.Builders; internal sealed class SwaggerOptionsBuilder : ISwaggerOptionsBuilder { - private readonly SwaggerSettings _options = new(); + private readonly SwaggerOptions _options = new(); public ISwaggerOptionsBuilder Enable(bool enabled) { @@ -54,5 +54,5 @@ public ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2) return this; } - public SwaggerSettings Build() => _options; + public SwaggerOptions Build() => _options; } \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs index 64c1b28b..420554f2 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs @@ -9,5 +9,5 @@ public interface ISwaggerOptionsBuilder ISwaggerOptionsBuilder WithRoutePrefix(string routePrefix); ISwaggerOptionsBuilder IncludeSecurity(bool includeSecurity); ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2); - SwaggerSettings Build(); + SwaggerOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerSettings.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs similarity index 93% rename from src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerSettings.cs rename to src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs index 4045b00b..22af3c8b 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerSettings.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs @@ -1,6 +1,6 @@ namespace Genocs.WebApi.Swagger.Docs.Configurations; -public class SwaggerSettings +public class SwaggerOptions { public bool Enabled { get; set; } public bool ReDocEnabled { get; set; } diff --git a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs index 1f6d8ce7..b8a177c0 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs @@ -19,7 +19,7 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, string sectionName = SectionName; } - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); return builder.AddSwaggerDocs(options); } @@ -29,7 +29,7 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, Func(); + var options = builder.ApplicationServices.GetRequiredService(); if (!options.Enabled) { return builder; diff --git a/src/Genocs.WebApi.Swagger/Extensions.cs b/src/Genocs.WebApi.Swagger/Extensions.cs index 1282e417..43e09e75 100644 --- a/src/Genocs.WebApi.Swagger/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Extensions.cs @@ -23,7 +23,7 @@ public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, s public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) => builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(buildOptions)); - public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, SwaggerSettings options) + public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, SwaggerOptions options) => builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(options)); private static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Action registerSwagger) diff --git a/src/Genocs.WebApi/Configurations/WebApiConfigureOptions.cs b/src/Genocs.WebApi/Configurations/WebApiConfigureOptions.cs new file mode 100644 index 00000000..6b43b8e4 --- /dev/null +++ b/src/Genocs.WebApi/Configurations/WebApiConfigureOptions.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Options; + +namespace Genocs.WebApi.Configurations; + +/// +/// The WebApiOptions definition. +/// +public class WebApiConfigureOptions : IConfigureNamedOptions +{ + private readonly WebApiOptions _options; + + public WebApiConfigureOptions(IOptions options) + { + _options = options.Value; + } + + public void Configure(string? name, WebApiOptions options) + { + Configure(options); + } + + public void Configure(WebApiOptions options) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/Genocs.WebApi/Configurations/WebApiOptions.cs b/src/Genocs.WebApi/Configurations/WebApiOptions.cs index ce60fd06..677c055e 100644 --- a/src/Genocs.WebApi/Configurations/WebApiOptions.cs +++ b/src/Genocs.WebApi/Configurations/WebApiOptions.cs @@ -1,27 +1,9 @@ -using Microsoft.Extensions.Options; - namespace Genocs.WebApi.Configurations; /// -/// The WebApiSettings definition. -/// Move to WebApiSettings.cs. +/// The WebApiOptions definition. /// -public class WebApiOptions : IConfigureNamedOptions +public class WebApiOptions { - private readonly WebApiSettings _jwtSettings; - - public WebApiOptions(IOptions jwtSettings) - { - _jwtSettings = jwtSettings.Value; - } - - public void Configure(string? name, WebApiSettings options) - { - Configure(options); - } - - public void Configure(WebApiSettings options) - { - throw new NotImplementedException(); - } + public bool BindRequestFromRoute { get; set; } } \ No newline at end of file diff --git a/src/Genocs.WebApi/Configurations/WebApiSettings.cs b/src/Genocs.WebApi/Configurations/WebApiSettings.cs deleted file mode 100644 index 805f7fe3..00000000 --- a/src/Genocs.WebApi/Configurations/WebApiSettings.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Genocs.WebApi.Configurations; - -/// -/// The WebApiSettings definition. -/// -public class WebApiSettings -{ - public bool BindRequestFromRoute { get; set; } -} \ No newline at end of file diff --git a/src/Genocs.WebApi/Extensions.cs b/src/Genocs.WebApi/Extensions.cs index cc7f9c40..ff9a67d5 100644 --- a/src/Genocs.WebApi/Extensions.cs +++ b/src/Genocs.WebApi/Extensions.cs @@ -95,7 +95,7 @@ public static IGenocsBuilder AddWebApi( builder.Services.AddSingleton(jsonSerializer); builder.Services.AddSingleton(); builder.Services.AddSingleton(new WebApiEndpointDefinitions()); - var options = builder.GetOptions(sectionName); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); _bindRequestFromRoute = options.BindRequestFromRoute; diff --git a/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs b/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs index af2f8db1..1db1d293 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Configurations/MessagingOptions.cs @@ -2,9 +2,16 @@ namespace Genocs.APIGateway.Configurations; internal class MessagingOptions { + /// + /// Default section name. + /// public const string Position = "messaging"; + /// + /// It defines whether the section is enabled or not. + /// public bool Enabled { get; set; } + public IEnumerable? Endpoints { get; set; } internal class EndpointOptions diff --git a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs index 7deb8fb5..4530716a 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Services/ProductServiceClient.cs @@ -22,13 +22,13 @@ public class ProductServiceClient : IProductServiceClient /// The certification service. /// /// - /// + /// public ProductServiceClient( IHttpClient client, ICertificatesService certificatesService, HttpClientOptions httpClientOptions, VaultOptions vaultOptions, - SecuritySettings securitySettings) + SecurityOptions securityOptions) { _client = client ?? throw new ArgumentNullException(nameof(client)); @@ -43,9 +43,9 @@ public ProductServiceClient( throw new ArgumentNullException(nameof(vaultOptions)); } - if (securitySettings is null) + if (securityOptions is null) { - throw new ArgumentNullException(nameof(securitySettings)); + throw new ArgumentNullException(nameof(securityOptions)); } string? url = httpClientOptions?.Services?["products"]; @@ -58,7 +58,7 @@ public ProductServiceClient( _url = url; if (!vaultOptions.Enabled || vaultOptions.Pki?.Enabled != true || - securitySettings.Certificate?.Enabled != true) + securityOptions.Certificate?.Enabled != true) { return; } @@ -69,7 +69,7 @@ public ProductServiceClient( return; } - string header = securitySettings.Certificate.GetHeaderName(); + string header = securityOptions.Certificate.GetHeaderName(); string certificateData = certificate.GetRawCertDataString(); _client.SetHeaders(h => h.Add(header, certificateData)); } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs index 6dc84226..b0dfd4f1 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Configurations/SignalROptions.cs @@ -1,10 +1,20 @@ namespace Genocs.SignalR.WebApi.Configurations; /// -/// The signalR Settings definition. +/// The signalR settings definition. /// public class SignalROptions { + /// + /// Default section name. + /// + public const string Position = "signalR"; + + /// + /// It defines whether the section is enabled or not. + /// + public bool Enabled { get; set; } + public string? Backplane { get; set; } public string? Hub { get; set; } } \ No newline at end of file From 0cde64fba30a987d5be4062d6ab167945629b8bc Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 7 Jul 2024 17:33:09 +0200 Subject: [PATCH 058/104] Update dependencies and refactor namespaces - Updated various package versions across multiple projects to ensure the latest features and security patches are utilized. This includes major updates for `Serilog.Sinks.*` packages and minor updates for others like `System.IdentityModel.Tokens.Jwt`, `MassTransit.RabbitMQ`, and `MongoDB.Driver`. - Introduced wildcard versioning for `Microsoft.AspNetCore.Authentication.JwtBearer` and `Microsoft.Extensions.Hosting.Abstractions` to adopt more flexible dependency management. - Refactored namespaces and using directives in `HomeController.cs` and `Program.cs`, moving from `.Options` to `.Configurations` to improve project structure clarity. - General maintenance to keep dependencies up-to-date and refactor project organization for better readability and functionality. --- src/Genocs.Auth/Genocs.Auth.csproj | 2 +- src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs | 2 +- src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj | 2 +- src/Genocs.Core.Demo.WebApi/Program.cs | 4 +--- src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj | 2 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 6 +++--- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 2 +- .../Genocs.Secrets.AzureKeyVault.csproj | 2 +- src/Genocs.Security/Genocs.Security.csproj | 6 +++--- src/Genocs.Tracing/Genocs.Tracing.csproj | 6 +++--- 14 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index d90636d6..18988efe 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -68,7 +68,7 @@ - + diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs index 9aaea49b..d9a29280 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/HomeController.cs @@ -1,4 +1,4 @@ -using Genocs.Core.Demo.WebApi.Options; +using Genocs.Core.Demo.WebApi.Configurations; using Microsoft.AspNetCore.Mvc; namespace Genocs.Core.Demo.WebApi.Controllers; diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index dd2e6a27..149a6af0 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index 6fbac463..9a80f8a1 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -1,12 +1,10 @@ -using Genocs.Auth; using Genocs.Core.Builders; +using Genocs.Core.Demo.WebApi.Configurations; using Genocs.Core.Demo.WebApi.Infrastructure.Extensions; -using Genocs.Core.Demo.WebApi.Options; using Genocs.Logging; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Secrets.AzureKeyVault; using Genocs.Tracing; -using Genocs.WebApi.Security; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; using System.Reflection; diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 71210be0..c765a4f7 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index a6861387..22cd38c5 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -53,6 +53,6 @@ - + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 7260ea03..b6da6319 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 0cb22d85..b85b5d30 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -53,10 +53,10 @@ - - + + - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index e911d229..b04f3130 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 08140949..58d5d725 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 59c8adcc..8c493814 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -13,7 +13,7 @@ - + all diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index 64d97c8d..83ca3e64 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 9885aab3..2f37fd4a 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -51,15 +51,15 @@ - + - + - + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 66524a87..ae5c2a94 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -60,10 +60,10 @@ - + - - + + From 1058ea157068e99bb9e08dbe71350d574d9b8d7f Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 7 Jul 2024 18:59:12 +0200 Subject: [PATCH 059/104] Update app config for logging, security, and more - Added new logger configuration with detailed settings for console and file logging, including log rotation and exclusions for specific paths. Placeholder for Azure logging added but disabled. - Introduced monitoring configuration with Jaeger for distributed tracing. - Updated JWT configuration for improved token validation. - Standardized configuration keys to camelCase for RabbitMQ, Azure Service Bus Topic, and Queue without altering their values. - Enhanced MongoDB configuration with tracing capabilities. - Enabled Azure Key Vault integration for secure management of secrets. - Removed and replaced outdated configurations to streamline and adopt new naming conventions. --- src/Genocs.Core.Demo.WebApi/appsettings.json | 65 +++++++++----------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 750cbaac..1e0d3a92 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -7,59 +7,54 @@ "displayBanner": true, "displayVersion": true }, - "RabbitMQ": { + "logger": { + "level": "information", + "applicationName": "demo-service", + "excludePaths": [ "/ping", "/metrics" ], + "console": { + "enabled": true + }, + "file": { + "enabled": true, + "path": "logs/logs.txt", + "interval": "day" + }, + "azure": { + "enabled": false, + "connectionString": "<>" + } + }, + "monitoring": { + "jaeger": "localhost" + }, + "jwt": { + "ValidIssuer": "http://localhost/Auth", + "ValidAudience": "https://localhost:5000", + "Secret": "" + }, + "rabbitMQ": { "HostName": "localhost", "VirtualHost": "/", "UserName": "guest", "Password": "guest" }, - "AzureServiceBusTopic": { + "azureServiceBusTopic": { "ConnectionString": "Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RMQ-xxxx;SharedAccessKey=xxxx", "TopicName": "topic-name", "SubscriptionName": "subscription-name" }, - "AzureServiceBusQueue": { + "azureServiceBusQueue": { "ConnectionString": "Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RMQ-xxxx;SharedAccessKey=xxxx", "QueueName": "queue-name" }, - "Mongo": { - "ConnectionString": "mongodb://localhost", - "Database": "demo" - }, "mongodb": { "ConnectionString": "mongodb://localhost", "Database": "demo", "enableTracing": true }, - "jwt": { - "ValidIssuer": "http://localhost/Auth", - "ValidAudience": "https://localhost:5000", - "Secret": "<<>>" - }, - "Monitoring": { - "Jaeger": "localhost" - }, - "logger": { - "applicationName": "demo-service", - "excludePaths": [ "/ping", "/metrics" ], - "level": "debug", - "console": { - "enabled": true - }, - "file": { - "enabled": true, - "path": "logs/logs.txt", - "interval": "day" - }, - "azure": { - "enabled": false, - "connectionString": "<>" - } - }, "azureKeyVault": { - "enabled": false, - "name": "<<>>", - "managedIdentityId": "<<>>" + "enabled": true, + "name": "kv-genocs" }, "secrets": { "Secret": "This is a secret coming from the appsettings.json file" From bf42a88da74ce68b2aaef9c3463ac698cc01a145 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 7 Jul 2024 21:00:31 +0200 Subject: [PATCH 060/104] Enhanced app config and documentation - Updated the README.md to clearly list basic infrastructure components including RabbitMQ, Redis, MongoDB, and Postgres. - Standardized MongoDB configuration keys to lowercase in appsettings.json for consistency. - Added Azure Key Vault configuration settings for secure management of secrets. - Modified JWT options in JwtOptions.cs for enhanced flexibility in configuration. - Refactored Prometheus metrics configuration for clarity and set default enabled state to false in development settings. - Enhanced appsettings.json with application instance/version info, improved logging levels, and disabled Prometheus metrics endpoint across configurations for a clearer, more secure, and better-monitored application setup. --- README.md | 13 +++++++++++-- src/Genocs.Auth/Configurations/JwtOptions.cs | 2 +- src/Genocs.Core.Demo.WebApi/appsettings.json | 4 ++-- src/Genocs.Core.Demo.Worker/appsettings.json | 4 ++-- src/Genocs.Metrics/Prometheus/Extensions.cs | 8 ++++---- .../Genocs.APIGateway/appsettings.development.json | 2 +- .../api-gateway/Genocs.APIGateway/appsettings.json | 12 ++++++++---- .../Genocs.Products.WebApi/appsettings.json | 4 ++-- .../signalr/Genocs.SignalR.WebApi/appsettings.json | 4 ++-- 9 files changed, 33 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e8486356..17ecb458 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,11 @@ docker compose -f ./infrastructure-elk.yml --env-file ./.env --project-name geno docker compose -f ./infrastructure-ml.yml --env-file ./.env --project-name genocs up -d ``` -`infrastructure-bare.yml` allows to install the basic infrastructure components. Basic components are the [RabbitMQ](https://rabbitmq.com), [Redis](https://redis.io), [Mongo](https://mongodb.com), [Postgres](https://www.postgresql.org/). +`infrastructure-bare.yml` allows to install the basic infrastructure components. They are: +- [RabbitMQ](https://rabbitmq.com) +- [Redis](https://redis.io) +- [MongoDB](https://mongodb.com) +- [Postgres](https://www.postgresql.org/). - [rabbitmq](http://localhost:15672/) @@ -260,7 +264,7 @@ Use [**api-workbench**](./api-workbench.rest) inside Visual Studio code with [RE "enabled": false, "endpoint": "/metrics" }, - "mongo": { + "mongodb": { "connectionString": "mongodb://localhost:27017", "database": "genocs-users-service", "seed": false @@ -335,6 +339,11 @@ Use [**api-workbench**](./api-workbench.rest) inside Visual Studio code with [RE "header": "Certificate" } }, + "azureKeyVault": { + "enabled": false, + "name": "gnx-keyvault", + "managedIdentityId": "secret", + }, "vault": { "enabled": false, "url": "http://localhost:8200", diff --git a/src/Genocs.Auth/Configurations/JwtOptions.cs b/src/Genocs.Auth/Configurations/JwtOptions.cs index 44a21d08..615f0c5f 100644 --- a/src/Genocs.Auth/Configurations/JwtOptions.cs +++ b/src/Genocs.Auth/Configurations/JwtOptions.cs @@ -28,7 +28,7 @@ public class JwtOptions public bool SaveToken { get; set; } = true; public bool SaveSigninToken { get; set; } public bool RequireAudience { get; set; } = true; - public bool RequireHttpsMetadata { get; set; } = true; + public bool RequireHttpsMetadata { get; set; } public bool RequireExpirationTime { get; set; } = true; public bool RequireSignedTokens { get; set; } = true; public int ExpiryMinutes { get; set; } diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 1e0d3a92..9b1118fd 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -48,8 +48,8 @@ "QueueName": "queue-name" }, "mongodb": { - "ConnectionString": "mongodb://localhost", - "Database": "demo", + "connectionString": "mongodb://localhost:27017", + "database": "demo", "enableTracing": true }, "azureKeyVault": { diff --git a/src/Genocs.Core.Demo.Worker/appsettings.json b/src/Genocs.Core.Demo.Worker/appsettings.json index 1993b991..9ebf71e1 100644 --- a/src/Genocs.Core.Demo.Worker/appsettings.json +++ b/src/Genocs.Core.Demo.Worker/appsettings.json @@ -24,8 +24,8 @@ "QueueName": "queue-name" }, "mongodb": { - "ConnectionString": "mongodb://localhost", - "Database": "demo", + "connectionString": "mongodb://localhost:27017", + "database": "demo", "enableTracing": true }, "Monitoring": { diff --git a/src/Genocs.Metrics/Prometheus/Extensions.cs b/src/Genocs.Metrics/Prometheus/Extensions.cs index 59904afe..022afe56 100644 --- a/src/Genocs.Metrics/Prometheus/Extensions.cs +++ b/src/Genocs.Metrics/Prometheus/Extensions.cs @@ -12,9 +12,9 @@ public static class Extensions { public static IGenocsBuilder AddPrometheus(this IGenocsBuilder builder) { - var prometheusOptions = builder.GetOptions(PrometheusOptions.Position); - builder.Services.AddSingleton(prometheusOptions); - if (!prometheusOptions.Enabled) + PrometheusOptions options = builder.GetOptions(PrometheusOptions.Position); + builder.Services.AddSingleton(options); + if (!options.Enabled) { return builder; } @@ -28,7 +28,7 @@ public static IGenocsBuilder AddPrometheus(this IGenocsBuilder builder) public static IApplicationBuilder UsePrometheus(this IApplicationBuilder app) { - var options = app.ApplicationServices.GetRequiredService(); + PrometheusOptions options = app.ApplicationServices.GetRequiredService(); if (!options.Enabled) { return app; diff --git a/src/apps/api-gateway/Genocs.APIGateway/appsettings.development.json b/src/apps/api-gateway/Genocs.APIGateway/appsettings.development.json index c428f22c..12ee80a7 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/appsettings.development.json +++ b/src/apps/api-gateway/Genocs.APIGateway/appsettings.development.json @@ -12,7 +12,7 @@ "enabled": true }, "prometheus": { - "enabled": true + "enabled": false }, "vault": { "enabled": false, diff --git a/src/apps/api-gateway/Genocs.APIGateway/appsettings.json b/src/apps/api-gateway/Genocs.APIGateway/appsettings.json index 3d4010c7..58a302ed 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/appsettings.json +++ b/src/apps/api-gateway/Genocs.APIGateway/appsettings.json @@ -1,7 +1,11 @@ { "app": { "name": "API Gateway", - "service": "api-gateway" + "service": "api-gateway", + "instance": "000001", + "version": "v1.0", + "displayBanner": true, + "displayVersion": true }, "jaeger": { "enabled": true, @@ -28,7 +32,7 @@ "expiry": "01:00:00" }, "logger": { - "level": "information", + "level": "debug", "excludePaths": [ "/", "/ping", @@ -49,7 +53,7 @@ "Token" ], "console": { - "enabled": false + "enabled": true }, "elk": { "enabled": false, @@ -85,7 +89,7 @@ ] }, "prometheus": { - "enabled": true, + "enabled": false, "endpoint": "/metrics" }, "rabbitMq": { diff --git a/src/apps/products/Genocs.Products.WebApi/appsettings.json b/src/apps/products/Genocs.Products.WebApi/appsettings.json index f91c5997..b8b59a9f 100644 --- a/src/apps/products/Genocs.Products.WebApi/appsettings.json +++ b/src/apps/products/Genocs.Products.WebApi/appsettings.json @@ -31,11 +31,11 @@ } }, "logger": { + "level": "information", "applicationName": "products-service", "excludePaths": [ "/ping", "/metrics" ], - "level": "information", "console": { - "enabled": false + "enabled": true }, "file": { "enabled": true, diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json b/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json index 85b6c681..dead120e 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json +++ b/src/apps/signalr/Genocs.SignalR.WebApi/appsettings.json @@ -66,14 +66,14 @@ "expiry": "01:00:00" }, "logger": { + "level": "information", "applicationName": "signalr-service", "excludePaths": [ "/ping", "/metrics" ], - "level": "information", "console": { - "enabled": false + "enabled": true }, "file": { "enabled": true, From ede9ad3256c1ad948b89dddc789d6734ae2eed1a Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 7 Jul 2024 21:01:46 +0200 Subject: [PATCH 061/104] Refactor configuration naming conventions and add new options --- README.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 17ecb458..4aa02b70 100644 --- a/README.md +++ b/README.md @@ -89,11 +89,12 @@ docker compose -f ./infrastructure-ml.yml --env-file ./.env --project-name genoc - [MongoDB](https://mongodb.com) - [Postgres](https://www.postgresql.org/). +You can run them locally: -- [rabbitmq](http://localhost:15672/) -- Redis -- MongoDb -- PostgreSQL +- RrabbitMQ]: `localhost:15672` +- Redis: `localhost:6379` +- MongoDb: `localhost:27017` +- PostgreSQL: `localhost:5432` `infrastructure-monitoring.yml` allows to install the monitoring infrastructure components. @@ -106,6 +107,14 @@ Inside the file you can find: - jaeger - seq + +- Prometheus: `localhost:9090` +- Grafana: `localhost:3000` +- influxdb: `localhost:8086` +- jaeger: `localhost:16686` +- seq: `localhost:5341` + + `infrastructure-scaling.yml` allows to install the scaling infrastructure components. Inside the file you can find: From 06bb32ff452e1e32e94dc5554aa38c7bf7ce5ec8 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 11 Jul 2024 10:13:36 +0200 Subject: [PATCH 062/104] Refactor auth and update docs - Updated README.md to improve documentation formatting, clarity, and added proper markdown links for MongoDB, Postgres, Prometheus, Grafana, InfluxDB, Jaeger, and Seq. Enhanced descriptions for `infrastructure-monitoring.yml`, `infrastructure-scaling.yml`, and `infrastructure-security.yml`. - Removed unused `using` directives in Extensions.cs and commented out in Program.cs for cleanup. - Removed `System.IdentityModel.Tokens.Jwt` package from Genocs.Auth.csproj, indicating a shift in JWT handling. - Added `UseFirebaseAuthentication` extension method in ServiceCollectionExtensions.cs and updated Program.cs to guide its conditional use, marking a significant update in the application's authentication strategy towards Firebase. - Introduced FirebaseAuthenticationMiddleware.cs to implement Firebase JWT token authentication, integrating Firebase into the application's security mechanisms. - Replaced direct Serilog configuration with `StaticLogger.EnsureInitialized()` in Program.cs for centralized logging setup. --- README.md | 38 ++++++------- src/Genocs.Auth/Extensions.cs | 1 - src/Genocs.Auth/Genocs.Auth.csproj | 5 -- .../Extensions/ServiceCollectionExtensions.cs | 5 ++ .../FirebaseAuthenticationMiddleware.cs | 55 +++++++++++++++++++ src/Genocs.Core.Demo.WebApi/Program.cs | 5 ++ src/Genocs.Core.Demo.Worker/Program.cs | 12 +--- 7 files changed, 85 insertions(+), 36 deletions(-) create mode 100644 src/Genocs.Core.Demo.WebApi/Infrastructure/FirebaseAuthenticationMiddleware.cs diff --git a/README.md b/README.md index 4aa02b70..f5956b24 100644 --- a/README.md +++ b/README.md @@ -91,36 +91,32 @@ docker compose -f ./infrastructure-ml.yml --env-file ./.env --project-name genoc You can run them locally: -- RrabbitMQ]: `localhost:15672` +- [RabbitMQ](http://localhost:15672): `localhost:15672` - Redis: `localhost:6379` -- MongoDb: `localhost:27017` -- PostgreSQL: `localhost:5432` +- MongoDB: `localhost:27017` +- Postgres: `localhost:5432` -`infrastructure-monitoring.yml` allows to install the monitoring infrastructure components. - -Inside the file you can find: - -- Prometheus -- Grafana -- influxdb -- jaeger -- seq +`infrastructure-monitoring.yml` allows to install the monitoring infrastructure components. They are: +- [Prometheus](https://prometheus.io/) +- [Grafana](https://grafana.com/) +- [InfluxDB](https://www.influxdata.com/) +- [Jaeger](https://www.jaegertracing.io/) +- [Seq](https://datalust.co/seq) -- Prometheus: `localhost:9090` -- Grafana: `localhost:3000` -- influxdb: `localhost:8086` -- jaeger: `localhost:16686` -- seq: `localhost:5341` - +You can run them locally: -`infrastructure-scaling.yml` allows to install the scaling infrastructure components. +- [Prometheus](localhost:9090): `localhost:9090` +- [Grafana](localhost:3000): `localhost:3000` +- [InfluxDB](localhost:8086): `localhost:8086` +- [Jaeger](localhost:16686): `localhost:16686` +- [Seq](localhost:5341): `localhost:5341` -Inside the file you can find: +`infrastructure-scaling.yml` allows to install the scaling infrastructure components. They are: - Fabio -- consul +- Consul `infrastructure-security.yml` allows to install the security infrastructure components. diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index 27b6a1d6..b7baabe3 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -7,7 +7,6 @@ using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 18988efe..4a7fdde9 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -66,9 +66,4 @@ - - - - - diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs index a5d833bf..c1ccbee7 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs @@ -78,4 +78,9 @@ public static IServiceCollection AddCustomMassTransit(this IServiceCollection se return services; } + + public static IApplicationBuilder UseFirebaseAuthentication(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } } diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/FirebaseAuthenticationMiddleware.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/FirebaseAuthenticationMiddleware.cs new file mode 100644 index 00000000..5d0e953a --- /dev/null +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/FirebaseAuthenticationMiddleware.cs @@ -0,0 +1,55 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; + +namespace Genocs.Core.Demo.WebApi.Infrastructure; + +/// +/// Middleware authentication. Used to implement OpenId JWT implementation. +/// +public class FirebaseAuthenticationMiddleware +{ + private readonly RequestDelegate _next; + + public FirebaseAuthenticationMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task Invoke(HttpContext context) + { + string authHeader = context.Request.Headers["Authorization"].ToString(); + + if (authHeader != null && authHeader.StartsWith("Bearer ")) + { + string token = authHeader.Substring("Bearer ".Length).Trim(); + + try + { + var handler = new JwtSecurityTokenHandler(); + var jsonToken = handler.ReadToken(token) as JwtSecurityToken; + + var jwtToken = new JwtSecurityToken(token); + var payload = jwtToken.Payload; + var claims = new[] + { + new Claim(ClaimTypes.NameIdentifier, payload["user_id"].ToString()), + new Claim(ClaimTypes.Name, payload["name"].ToString()), + + // Add more claims as needed + }; + + var identity = new ClaimsIdentity(claims, "Firebase"); + context.User = new ClaimsPrincipal(identity); + } + catch (Exception ex) + { + // Token validation failed + context.Response.StatusCode = 401; + await context.Response.WriteAsync("Unauthorized"); + return; + } + } + + await _next(context); + } +} \ No newline at end of file diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index 9a80f8a1..e49b96f9 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -1,3 +1,4 @@ +// using Genocs.Auth; using Genocs.Core.Builders; using Genocs.Core.Demo.WebApi.Configurations; using Genocs.Core.Demo.WebApi.Infrastructure.Extensions; @@ -22,6 +23,7 @@ services .AddGenocs(builder.Configuration) +// .AddOpenIdJwt() .AddOpenTelemetry() .AddMongoFast() .RegisterMongoRepositories(Assembly.GetExecutingAssembly()) @@ -79,6 +81,9 @@ app.UseAuthorization(); +// Use it only if you need to authenticate with Firebase +// app.UseFirebaseAuthentication(); + app.MapControllers(); app.MapHealthChecks("/hc"); diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index 6f6931c9..5e752d01 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -7,27 +7,21 @@ using Genocs.Core.Demo.Worker.Consumers; using Genocs.Core.Demo.Worker.Handlers; using Genocs.Logging; -using Genocs.Tracing; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Persistence.MongoDb.Repositories; using Genocs.Persistence.MongoDb.Repositories.Clean; +using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; using Genocs.ServiceBusAzure.Topics; using Genocs.ServiceBusAzure.Topics.Interfaces; +using Genocs.Tracing; using MassTransit; using Microsoft.Extensions.DependencyInjection.Extensions; using Serilog; -using Serilog.Events; using System.Reflection; -using Genocs.ServiceBusAzure.Configurations; -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Information() - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); +StaticLogger.EnsureInitialized(); IHost host = Host.CreateDefaultBuilder(args) .UseLogging() From 85198fbd504da2e98499783f0d85eb6fcccab91d Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 19 Jul 2024 21:14:00 +0200 Subject: [PATCH 063/104] Refactor auth and update docs --- README.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f5956b24..cfa62317 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ # Genocs .NET library -This repo contains a set of libraries designed by Genocs. The library is built on top of .NET8. +This repo contains a set of libraries to build LOB (Line Of Business) applications. The library is open source and built to be PRODUCTION READY. The library is built on top of .NET8, it is designed and maintained by Genocs. Packages are available on [NuGet Genocs](https://www.nuget.org/profiles/gioema_nocco). @@ -59,10 +59,16 @@ Building a software library to be cloud agnostic has several advantages. First, The advantages of using containers are numerous. Containers provide a lightweight, portable, and isolated environment for applications to run in, allowing them to be easily moved between different systems. This makes it easier to deploy applications quickly and reliably across different environments. Additionally, containers can help reduce resource consumption by running multiple applications on the same host, as each container is isolated from the others. This helps to improve efficiency and scalability. Finally, containers provide an additional layer of security, as they are isolated from the underlying operating system and other applications. +## Documentation + +You can find a useful documentation about how to use the library. The documentation contains the complete set of libraries, template, CLI that altogether make the *genocs ecosystem* a comprensive set of tools to build enterprise solutions. + +Documentation available at [Genocs Blog](https://genocs-blog.netlify.app/library/) + ## Infrastructure -In this section you can find the infrastructure components to setup the environment. -You will use ***Docker compose*** to setup the infrastructure components. +In this section you can find the infrastructure components you need to execute the solution. Infrastucture components are the database, the enterprice servise bus, the distributed logging, monitoring, tracing systems along with database and many more. +You can use **Docker compose** to setup the infrastructure components just by running few commands. ``` bash @@ -145,16 +151,8 @@ You can setup the application inside a Kubernetes cluster. Check the repo [enterprise-containers](https://github.com/Genocs/enterprise-containers) to setup a Kubernetes cluster. There you can find scripts, configuration files and documentation to setup a cluster from scratch. -## **Libraries** -You can find a full documentation on: -[**Documentation**](https://genocs-blog.netlify.app/library/) - - - ## Support - - Use [**api-workbench**](./api-workbench.rest) inside Visual Studio code with [REST Client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) plugin ## Configuration @@ -385,7 +383,8 @@ Use [**api-workbench**](./api-workbench.rest) inside Visual Studio code with [RE ## Demo Application Inside the library there is a simple demo application you can use to test the library. -Some commands +Following are the commands to build and run the demo application. + ``` bash # Build the solution dotnet build @@ -425,13 +424,11 @@ docker build -t genocs/demo-worker:2.0.0 -t genocs/demo-worker:latest -f ./demo- docker push genocs/demo-worker:2.0.0 docker push genocs/demo-worker:latest ``` - - --- +--- ## Enterprise Application - -Take a look inside **./src/apps** folder. There you can find a full-fledged application composed by: +Inside **./src/apps** folder you can find a full-fledged application composed by: - ApiGateway - Identity Service - Order Service @@ -440,6 +437,7 @@ Take a look inside **./src/apps** folder. There you can find a full-fledged appl In that way you can test the entire flow. +**TODO**: Add a architecture diagram to show the components and how they interact with each other. ### How to BUILD & RUN the application @@ -509,9 +507,9 @@ You can deploy Demo Application with one click in Heroku, Microsoft Azure, or Go This project is licensed with the [MIT license](LICENSE). -## Changelogs +## Changelog -View Complete [Changelogs](https://github.com/Genocs/microservice-template/blob/main/CHANGELOGS.md). +View Complete [Changelog](https://github.com/Genocs/microservice-template/blob/main/CHANGELOG.md). ## Community From a63d816a4b617246ec99b3400d019a1b46ff40b0 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 19 Jul 2024 21:23:52 +0200 Subject: [PATCH 064/104] Refactor auth and update docs --- CHANGELOG.md | 60 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45949c32..d248da67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,27 +1,59 @@ -### Changelog +# Changelog -All notable changes to this project will be documented in this file. Dates are displayed in UTC. +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +## [6.0.0-preview.2.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.4.0...6.0.0-preview.2.0) - 2024-07-19 + +### Merged + +- Bump prometheus-net from 5.0.2 to 8.2.1 [`#54`](https://github.com/Genocs/genocs-library/pull/54) +- Bump System.IdentityModel.Tokens.Jwt from 7.0.3 to 7.1.2 in /src/Genocs.Auth [`#56`](https://github.com/Genocs/genocs-library/pull/56) +- Bump Polly from 8.2.0 to 8.2.1 [`#55`](https://github.com/Genocs/genocs-library/pull/55) +- Bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets from 1.19.5 to 1.19.6 [`#53`](https://github.com/Genocs/genocs-library/pull/53) +- Bump Moq from 4.20.69 to 4.20.70 [`#52`](https://github.com/Genocs/genocs-library/pull/52) +- Net8 [`#35`](https://github.com/Genocs/genocs-library/pull/35) +- Bump Serilog.Sinks.Seq from 5.1.0 to 5.2.3 [`#21`](https://github.com/Genocs/genocs-library/pull/21) +- Bump Serilog.Sinks.ElasticSearch from 8.4.1 to 9.0.3 [`#18`](https://github.com/Genocs/genocs-library/pull/18) + +### Commits + +- Added documentation and more control over types [`3d4c17e`](https://github.com/Genocs/genocs-library/commit/3d4c17e0e501d9174160f01569d2523472085a04) +- Refactor configs and update docs across projects [`504fc40`](https://github.com/Genocs/genocs-library/commit/504fc40ee05a1ed6bc838a5b08195cb285feb8c1) +- Merge issues [`cc6c097`](https://github.com/Genocs/genocs-library/commit/cc6c097d28854b584d3df34f9dc3ea6c4be78db9) + +## [v5.0.0-preview.4.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.3.0...v5.0.0-preview.4.0) - 2023-07-15 -## [0.0.1](https://github.com/Genocs/telegram-integration/compare/v0.1.0...v0.1.1) (2023-06-02) +### Merged -### Features +- April 2023 [`#17`](https://github.com/Genocs/genocs-library/pull/17) +- Create ml.yml [`#14`](https://github.com/Genocs/genocs-library/pull/14) +- April 2023 [`#12`](https://github.com/Genocs/genocs-library/pull/12) +- April 2023 [`#11`](https://github.com/Genocs/genocs-library/pull/11) -- Added [editorconfig](https://editorconfig.org/) -- Added StyleCop -- Updated logo -- Updated readme +### Commits -### Bug Fixes +- Preview 4.x [`d619840`](https://github.com/Genocs/genocs-library/commit/d619840033c146a60bdb5fe6f37ea7e6e7ae5de7) +- Start removing legacy MongoDB legacy database [`f4ca960`](https://github.com/Genocs/genocs-library/commit/f4ca9609ef11ad550c789e05dbfd6c0984fa312b) +- Refactory to remove legacy Mongodb [`7accdcb`](https://github.com/Genocs/genocs-library/commit/7accdcba26edb9e38ebf0583966348f80a2d31b1) -* +## v5.0.0-preview.3.0 - 2023-05-13 -### Documentation +### Merged -* +- March 2023 [`#9`](https://github.com/Genocs/genocs-library/pull/9) +- Create docker-image.yml [`#6`](https://github.com/Genocs/genocs-library/pull/6) +- Create nuget-deploy.yml [`#5`](https://github.com/Genocs/genocs-library/pull/5) +- Added explicitly build [`#3`](https://github.com/Genocs/genocs-library/pull/3) +- Develop [`#2`](https://github.com/Genocs/genocs-library/pull/2) +- Bump Microsoft.AspNetCore.Authentication.JwtBearer from 5.0.6 to 5.0.9 in /src/Genocs.Core.Demo.WebApi [`#1`](https://github.com/Genocs/genocs-library/pull/1) -### Dependencies +### Commits -* +- Added SignalR service [`8a6faee`](https://github.com/Genocs/genocs-library/commit/8a6faeef4c6c2dec473abb1e86fe55a9e24f87c5) +- Added template [`98884b0`](https://github.com/Genocs/genocs-library/commit/98884b034910bc8d4c912344fe2ce0f54b4e7aaa) +- Upated to net7 [`2cbc3f8`](https://github.com/Genocs/genocs-library/commit/2cbc3f8b6cefb5cfe153b3aba8a28d5f425804dc) From c61eab254c53920f94c575503c41c4e623fd1b36 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 24 Jul 2024 21:15:41 +0200 Subject: [PATCH 065/104] Update various NuGet packages across multiple projects Updated the `xunit` package from version `2.8.1` to `2.9.0` and the `xunit.runner.visualstudio` package from version `2.8.1` to `2.8.2` in the following projects: - `Genocs.Core.UnitTests.csproj` - `Genocs.Persistence.MongoDB.UnitTests.csproj` - `Genocs.QueryBuilder.UnitTests.csproj` - `Genocs.ServiceBusAzure.UnitTests.csproj` Updated the `Microsoft.Extensions.Configuration.Binder` package from version `8.0.1` to `8.0.2` and the `System.Text.Json` package from version `8.0.3` to `8.0.4` in `Genocs.Core.csproj`. Updated the `MongoDB.Driver` package from version `2.27.0` to `2.28.0` in `Genocs.Persistence.MongoDb.csproj`. --- src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj | 4 ++-- src/Genocs.Core/Genocs.Core.csproj | 4 ++-- .../Genocs.Persistence.MongoDB.UnitTests.csproj | 4 ++-- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 ++-- .../Genocs.ServiceBusAzure.UnitTests.csproj | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index b9975502..8642f97e 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 6e259383..98c15645 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -70,9 +70,9 @@ - + - + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 71219a19..1c501e5e 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -12,8 +12,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 58d5d725..07a11a04 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 8c493814..2b3c6d9b 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -14,8 +14,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 52ee0ab7..52a49d87 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -8,8 +8,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all From 63533a2ccfb64106dd81e296ca1a1de55c556f48 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 27 Jul 2024 08:42:51 +0200 Subject: [PATCH 066/104] Refactor and update dependencies and logging level - Changed logging level in `appsettings.json` from "information" to "debug". - Downgraded `MongoDB.Driver` in `Genocs.Persistence.MongoDb.csproj` from 2.28.0 to 2.27.0. - Made `Role` and `AccessToken` properties nullable in `AuthDto.cs` and added a class-level comment. - Reformatted constructors in `RefreshToken.cs`, `InvalidNameException.cs`, and `AppException.cs` for readability. - Updated `GetCode` method in `ExceptionToResponseMapper.cs` to return a nullable string and reformatted the method. - Added null check for `users` in `Extensions.cs` and reformatted the code. - Reformatted `IJwtProvider.cs`, `JwtProvider.cs`, `MessageBroker.cs`, `Program.cs`, `CreateProductHandler.cs`, and `HubService.cs` for readability. - Updated comments in `GetOrderHandler.cs` for clarity. - Removed constructor from `CreateProduct.cs`. - Removed namespace declaration from `BrowseProductsHandler.cs`. - Added closing brace in `OperationUpdatedHandler.cs`. --- src/Genocs.Core.Demo.WebApi/appsettings.json | 2 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../DTO/AuthDto.cs | 7 ++- .../Domain/Entities/RefreshToken.cs | 9 ++- .../Domain/Exceptions/InvalidNameException.cs | 3 +- .../Exceptions/AppException.cs | 3 +- .../Exceptions/ExceptionToResponseMapper.cs | 20 +++---- .../Mongo/Extensions.cs | 15 ++++- .../Services/IJwtProvider.cs | 11 +++- .../Services/JwtProvider.cs | 11 ++-- .../Services/MessageBroker.cs | 40 +++++++------ .../orders/Genocs.Orders.WebApi/Program.cs | 3 +- .../Queries/Handlers/GetOrderHandler.cs | 6 +- .../Commands/CreateProduct.cs | 1 - .../Commands/Handlers/CreateProductHandler.cs | 13 +++-- .../Genocs.Products.WebApi/Program.cs | 5 +- .../Queries/Handlers/BrowseProductsHandler.cs | 2 - .../Exceptions/ExceptionToResponseMapper.cs | 17 +++--- .../Handlers/OperationUpdatedHandler.cs | 1 - .../signalr/Genocs.SignalR.WebApi/Program.cs | 3 +- .../Services/HubService.cs | 57 ++++++++++--------- 21 files changed, 131 insertions(+), 100 deletions(-) diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 9b1118fd..950182b6 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -8,7 +8,7 @@ "displayVersion": true }, "logger": { - "level": "information", + "level": "debug", "applicationName": "demo-service", "excludePaths": [ "/ping", "/metrics" ], "console": { diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 07a11a04..58d5d725 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/apps/identity/Genocs.Identities.Application/DTO/AuthDto.cs b/src/apps/identity/Genocs.Identities.Application/DTO/AuthDto.cs index 403e9fd5..a5652115 100644 --- a/src/apps/identity/Genocs.Identities.Application/DTO/AuthDto.cs +++ b/src/apps/identity/Genocs.Identities.Application/DTO/AuthDto.cs @@ -1,11 +1,14 @@ namespace Genocs.Identities.Application.DTO; +/// +/// The AuthDto class. +/// public class AuthDto { public Guid UserId { get; set; } public string Username { get; set; } - public string Role { get; set; } - public string AccessToken { get; set; } + public string? Role { get; set; } + public string? AccessToken { get; set; } public string RefreshToken { get; set; } public long Expires { get; set; } } \ No newline at end of file diff --git a/src/apps/identity/Genocs.Identities.Application/Domain/Entities/RefreshToken.cs b/src/apps/identity/Genocs.Identities.Application/Domain/Entities/RefreshToken.cs index 7b17070e..5f0835ba 100644 --- a/src/apps/identity/Genocs.Identities.Application/Domain/Entities/RefreshToken.cs +++ b/src/apps/identity/Genocs.Identities.Application/Domain/Entities/RefreshToken.cs @@ -10,8 +10,13 @@ public class RefreshToken : AggregateRoot public DateTime? RevokedAt { get; private set; } public bool Revoked => RevokedAt.HasValue; - public RefreshToken(AggregateId id, AggregateId userId, string token, DateTime createdAt, - DateTime? revokedAt = null) : base(id) + public RefreshToken( + AggregateId id, + AggregateId userId, + string token, + DateTime createdAt, + DateTime? revokedAt = null) + : base(id) { if (string.IsNullOrWhiteSpace(token)) { diff --git a/src/apps/identity/Genocs.Identities.Application/Domain/Exceptions/InvalidNameException.cs b/src/apps/identity/Genocs.Identities.Application/Domain/Exceptions/InvalidNameException.cs index f0f3fb66..4d64eb2e 100644 --- a/src/apps/identity/Genocs.Identities.Application/Domain/Exceptions/InvalidNameException.cs +++ b/src/apps/identity/Genocs.Identities.Application/Domain/Exceptions/InvalidNameException.cs @@ -2,7 +2,8 @@ namespace Genocs.Identities.Application.Domain.Exceptions; public class InvalidNameException : DomainException { - public InvalidNameException(string name) : base($"Invalid name: {name}.") + public InvalidNameException(string name) + : base($"Invalid name: {name}.") { } } \ No newline at end of file diff --git a/src/apps/identity/Genocs.Identities.Application/Exceptions/AppException.cs b/src/apps/identity/Genocs.Identities.Application/Exceptions/AppException.cs index cb4315e1..f9336e85 100644 --- a/src/apps/identity/Genocs.Identities.Application/Exceptions/AppException.cs +++ b/src/apps/identity/Genocs.Identities.Application/Exceptions/AppException.cs @@ -2,7 +2,8 @@ namespace Genocs.Identities.Application.Exceptions; public abstract class AppException : Exception { - protected AppException(string message) : base(message) + protected AppException(string message) + : base(message) { } } \ No newline at end of file diff --git a/src/apps/identity/Genocs.Identities.Application/Exceptions/ExceptionToResponseMapper.cs b/src/apps/identity/Genocs.Identities.Application/Exceptions/ExceptionToResponseMapper.cs index 1175fb72..e11452f4 100644 --- a/src/apps/identity/Genocs.Identities.Application/Exceptions/ExceptionToResponseMapper.cs +++ b/src/apps/identity/Genocs.Identities.Application/Exceptions/ExceptionToResponseMapper.cs @@ -13,24 +13,24 @@ public class ExceptionToResponseMapper : IExceptionToResponseMapper public ExceptionResponse Map(Exception exception) => exception switch { - DomainException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, - HttpStatusCode.BadRequest), - AppException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, - HttpStatusCode.BadRequest), - _ => new ExceptionResponse(new { code = "error", reason = "There was an error." }, - HttpStatusCode.BadRequest) + DomainException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, HttpStatusCode.BadRequest), + AppException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, HttpStatusCode.BadRequest), + _ => new ExceptionResponse(new { code = "error", reason = "There was an error." }, HttpStatusCode.BadRequest) }; - private static string GetCode(Exception exception) + private static string? GetCode(Exception exception) { var type = exception.GetType(); - if (Codes.TryGetValue(type, out var code)) + if (Codes.TryGetValue(type, out string? code)) { return code; } - var exceptionCode = exception.GetType().Name.Underscore().Replace("_exception", string.Empty); - Codes.TryAdd(type, exceptionCode); + string? exceptionCode = exception.GetType().Name.Underscore()?.Replace("_exception", string.Empty); + if (!string.IsNullOrWhiteSpace(exceptionCode)) + { + Codes.TryAdd(type, exceptionCode); + } return exceptionCode; } diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs index 435ed3c6..70ce9a88 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs @@ -11,17 +11,26 @@ public static class Extensions public static IApplicationBuilder UseMongo(this IApplicationBuilder builder) { using var scope = builder.ApplicationServices.CreateScope(); - var users = scope.ServiceProvider.GetService>().Collection; + var users = scope.ServiceProvider.GetService>()?.Collection; + + if (users is null) + { + return builder; + } + var userBuilder = Builders.IndexKeys; + Task.Run(async () => await users.Indexes.CreateManyAsync( new[] { - new CreateIndexModel(userBuilder.Ascending(i => i.Email), + new CreateIndexModel( + userBuilder.Ascending(i => i.Email), new CreateIndexOptions { Unique = true }), - new CreateIndexModel(userBuilder.Ascending(i => i.Name), + new CreateIndexModel( + userBuilder.Ascending(i => i.Name), new CreateIndexOptions { Unique = true diff --git a/src/apps/identity/Genocs.Identities.Application/Services/IJwtProvider.cs b/src/apps/identity/Genocs.Identities.Application/Services/IJwtProvider.cs index b06d8093..eca33933 100644 --- a/src/apps/identity/Genocs.Identities.Application/Services/IJwtProvider.cs +++ b/src/apps/identity/Genocs.Identities.Application/Services/IJwtProvider.cs @@ -3,10 +3,15 @@ namespace Genocs.Identities.Application.Services; /// -/// JwtProvider interface definition +/// JwtProvider interface definition. /// public interface IJwtProvider { - AuthDto Create(Guid userId, string username, string role, string? audience = null, - IDictionary>? claims = null); + AuthDto Create( + Guid userId, + string username, + string role, + string? audience = null, + IDictionary>? claims = null); } \ No newline at end of file diff --git a/src/apps/identity/Genocs.Identities.Application/Services/JwtProvider.cs b/src/apps/identity/Genocs.Identities.Application/Services/JwtProvider.cs index ff76ec60..093b1a16 100644 --- a/src/apps/identity/Genocs.Identities.Application/Services/JwtProvider.cs +++ b/src/apps/identity/Genocs.Identities.Application/Services/JwtProvider.cs @@ -12,11 +12,12 @@ public JwtProvider(IJwtHandler jwtHandler) _jwtHandler = jwtHandler; } - public AuthDto Create(Guid userId, - string username, - string role, - string? audience = null, - IDictionary>? claims = null) + public AuthDto Create( + Guid userId, + string username, + string role, + string? audience = null, + IDictionary>? claims = null) { var jwt = _jwtHandler.CreateToken(userId.ToString("N"), role, audience, claims); diff --git a/src/apps/identity/Genocs.Identities.Application/Services/MessageBroker.cs b/src/apps/identity/Genocs.Identities.Application/Services/MessageBroker.cs index 653bf74f..d2ae9507 100644 --- a/src/apps/identity/Genocs.Identities.Application/Services/MessageBroker.cs +++ b/src/apps/identity/Genocs.Identities.Application/Services/MessageBroker.cs @@ -21,10 +21,15 @@ internal class MessageBroker : IMessageBroker private readonly ILogger _logger; private readonly string _spanContextHeader; - public MessageBroker(IBusPublisher busPublisher, IMessageOutbox outbox, - ICorrelationContextAccessor contextAccessor, IHttpContextAccessor httpContextAccessor, - IMessagePropertiesAccessor messagePropertiesAccessor, ICorrelationIdFactory correlationIdFactory, - RabbitMQOptions options, ILogger logger) + public MessageBroker( + IBusPublisher busPublisher, + IMessageOutbox outbox, + ICorrelationContextAccessor contextAccessor, + IHttpContextAccessor httpContextAccessor, + IMessagePropertiesAccessor messagePropertiesAccessor, + ICorrelationIdFactory correlationIdFactory, + RabbitMQOptions options, + ILogger logger) { if (options is null) { @@ -53,11 +58,12 @@ private async Task PublishAsync(IEnumerable? events) } var messageProperties = _messagePropertiesAccessor.MessageProperties; - var originatedMessageId = messageProperties?.MessageId; - var correlationId = _correlationIdFactory.Create(); - var spanContext = messageProperties?.GetSpanContext(_spanContextHeader); - var correlationContext = _contextAccessor.CorrelationContext ?? + string? originatedMessageId = messageProperties?.MessageId; + string? correlationId = _correlationIdFactory.Create(); + string? spanContext = messageProperties?.GetSpanContext(_spanContextHeader); + object correlationContext = _contextAccessor.CorrelationContext ?? _httpContextAccessor.GetCorrelationContext(); + var headers = new Dictionary(); foreach (var @event in events) @@ -67,11 +73,12 @@ private async Task PublishAsync(IEnumerable? events) continue; } - var messageId = Guid.NewGuid().ToString("N"); + string messageId = Guid.NewGuid().ToString("N"); _logger.LogTrace($"Publishing integration event: {@event.GetType().Name.Underscore()} [ID: '{messageId}']."); if (_outbox.Enabled) { - await _outbox.SendAsync(@event, + await _outbox.SendAsync( + @event, originatedMessageId, messageId, correlationId, @@ -81,12 +88,13 @@ await _outbox.SendAsync(@event, continue; } - await _busPublisher.PublishAsync(@event, - messageId, - correlationId, - spanContext, - correlationContext, - headers); + await _busPublisher.PublishAsync( + @event, + messageId, + correlationId, + spanContext, + correlationContext, + headers); } } } \ No newline at end of file diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index 9d14e35f..545d4589 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -81,8 +81,7 @@ .Get(string.Empty, ctx => ctx.Response.WriteAsync("Orders Service")) .Get("ping", ctx => ctx.Response.WriteAsync("pong")) .Get("orders/{orderId}") - .Post("orders", - afterDispatch: (cmd, ctx) => ctx.Response.Created($"orders/{cmd.OrderId}"))) + .Post("orders", afterDispatch: (cmd, ctx) => ctx.Response.Created($"orders/{cmd.OrderId}"))) .UseJaeger() .UseSwaggerDocs() .UseRabbitMq() diff --git a/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs b/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs index 4f98dbcb..f6d07ca8 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs @@ -15,10 +15,10 @@ public GetOrderHandler(IMongoRepository repository) } /// - /// GetOrder query handler + /// GetOrder query handler. /// - /// The query - /// The cancellation token + /// The query. + /// The cancellation token. /// public async Task HandleAsync(GetOrder query, CancellationToken cancellationToken = default) { diff --git a/src/apps/products/Genocs.Products.WebApi/Commands/CreateProduct.cs b/src/apps/products/Genocs.Products.WebApi/Commands/CreateProduct.cs index b8857be4..4f101e6c 100644 --- a/src/apps/products/Genocs.Products.WebApi/Commands/CreateProduct.cs +++ b/src/apps/products/Genocs.Products.WebApi/Commands/CreateProduct.cs @@ -8,7 +8,6 @@ public class CreateProduct : ICommand public string SKU { get; } public decimal UnitPrice { get; } - public CreateProduct(Guid productId, string sku, decimal unitPrice) { ProductId = productId == Guid.Empty ? Guid.NewGuid() : productId; diff --git a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs index ae2474c4..ca6c727a 100644 --- a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs +++ b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs @@ -16,9 +16,12 @@ public class CreateProductHandler : ICommandHandler private readonly ILogger _logger; private readonly ITracer _tracer; - public CreateProductHandler(IMongoRepository repository, IBusPublisher publisher, - IMessageOutbox outbox, ITracer tracer, - ILogger logger) + public CreateProductHandler( + IMongoRepository repository, + IBusPublisher publisher, + IMessageOutbox outbox, + ITracer tracer, + ILogger logger) { _repository = repository; _publisher = publisher; @@ -29,7 +32,7 @@ public CreateProductHandler(IMongoRepository repository, IBusPubl public async Task HandleAsync(CreateProduct command, CancellationToken cancellationToken = default) { - var exists = await _repository.ExistsAsync(o => o.Id == command.ProductId); + bool exists = await _repository.ExistsAsync(o => o.Id == command.ProductId); if (exists) { throw new InvalidOperationException($"Product with given id: {command.ProductId} already exists!"); @@ -40,7 +43,7 @@ public async Task HandleAsync(CreateProduct command, CancellationToken cancellat _logger.LogInformation($"Created a product with id: {command.ProductId}, sku: {command.SKU}, unitPrice: {command.UnitPrice}."); - var spanContext = _tracer.ActiveSpan?.Context.ToString(); + string? spanContext = _tracer.ActiveSpan?.Context.ToString(); var @event = new ProductCreated(product.Id); if (_outbox.Enabled) { diff --git a/src/apps/products/Genocs.Products.WebApi/Program.cs b/src/apps/products/Genocs.Products.WebApi/Program.cs index f8f71171..ceea0f0b 100644 --- a/src/apps/products/Genocs.Products.WebApi/Program.cs +++ b/src/apps/products/Genocs.Products.WebApi/Program.cs @@ -76,12 +76,11 @@ .UseCertificateAuthentication() .UseEndpoints(r => r.MapControllers()) .UseDispatcherEndpoints(endpoints => endpoints - .Get("", ctx => ctx.Response.WriteAsync("Products Service")) + .Get(string.Empty, ctx => ctx.Response.WriteAsync("Products Service")) .Get("ping", ctx => ctx.Response.WriteAsync("pong")) .Get>("products") .Get("products/{productId}") - .Post("products", - afterDispatch: (cmd, ctx) => ctx.Response.Created($"products/{cmd.ProductId}"))) + .Post("products", afterDispatch: (cmd, ctx) => ctx.Response.Created($"products/{cmd.ProductId}"))) .UseJaeger() .UseSwaggerDocs() .UseRabbitMq(); diff --git a/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/BrowseProductsHandler.cs b/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/BrowseProductsHandler.cs index 2f410736..5ce5f85a 100644 --- a/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/BrowseProductsHandler.cs +++ b/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/BrowseProductsHandler.cs @@ -4,7 +4,6 @@ using Genocs.Products.WebApi.DTO; using MongoDB.Driver; - namespace Genocs.Products.WebApi.Queries.Handlers; public class BrowseProductsHandler : IQueryHandler> @@ -25,7 +24,6 @@ public BrowseProductsHandler(IMongoDatabase database) var pagedResult = PagedResult.From(result, result.Items.Select(x => Map(x))); return pagedResult; - } private static ProductDto Map(Product product) diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs index 8ad5af5b..e8b11061 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Exceptions/ExceptionToResponseMapper.cs @@ -14,22 +14,23 @@ public ExceptionResponse Map(Exception exception) { // DomainException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, // HttpStatusCode.BadRequest), - AppException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, - HttpStatusCode.BadRequest), - _ => new ExceptionResponse(new { code = "error", reason = "There was an error." }, - HttpStatusCode.BadRequest) + AppException ex => new ExceptionResponse(new { code = GetCode(ex), reason = ex.Message }, HttpStatusCode.BadRequest), + _ => new ExceptionResponse(new { code = "error", reason = "There was an error." }, HttpStatusCode.BadRequest) }; - private static string GetCode(Exception exception) + private static string? GetCode(Exception exception) { var type = exception.GetType(); - if (Codes.TryGetValue(type, out var code)) + if (Codes.TryGetValue(type, out string? code)) { return code; } - string exceptionCode = exception.GetType().Name.Underscore().Replace("_exception", string.Empty); - Codes.TryAdd(type, exceptionCode); + string? exceptionCode = exception.GetType().Name.Underscore()?.Replace("_exception", string.Empty); + if (!string.IsNullOrWhiteSpace(exceptionCode)) + { + Codes.TryAdd(type, exceptionCode); + } return exceptionCode; } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs index 34617883..f1870b46 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Handlers/OperationUpdatedHandler.cs @@ -21,5 +21,4 @@ public async Task HandleAsync(OperationCompleted @event, CancellationToken cance public async Task HandleAsync(OperationRejected @event, CancellationToken cancellationToken = default) => await _hubService.PublishOperationRejectedAsync(@event); - } \ No newline at end of file diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs index 627bca5a..36481219 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs @@ -73,8 +73,7 @@ .UseDispatcherEndpoints(endpoints => endpoints .Get("", ctx => ctx.Response.WriteAsync("SignalR Service")) .Get("ping", ctx => ctx.Response.WriteAsync("pong")) - .Post("notifications", - afterDispatch: (cmd, ctx) => ctx.Response.Created($"notifications/{cmd.NotificationId}"))) + .Post("notifications", afterDispatch: (cmd, ctx) => ctx.Response.Created($"notifications/{cmd.NotificationId}"))) .UseJaeger() .UseSwaggerDocs() .UseRabbitMq(); diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs index 257bdb90..99ae7aeb 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Services/HubService.cs @@ -10,36 +10,37 @@ public HubService(IHubWrapper hubContextWrapper) => _hubContextWrapper = hubContextWrapper ?? throw new ArgumentNullException(nameof(hubContextWrapper)); public async Task PublishOperationPendingAsync(OperationPending @event) - => await _hubContextWrapper.PublishToUserAsync(@event.UserId, - "operation_pending", - new - { - id = @event.Id, - name = @event.Name, - resource = @event.Resource - } - ); + => await _hubContextWrapper.PublishToUserAsync( + @event.UserId, + "operation_pending", + new + { + id = @event.Id, + name = @event.Name, + resource = @event.Resource + }); public async Task PublishOperationCompletedAsync(OperationCompleted @event) - => await _hubContextWrapper.PublishToUserAsync(@event.UserId, - "operation_completed", - new - { - id = @event.Id, - name = @event.Name, - resource = @event.Resource - } - ); + => await _hubContextWrapper.PublishToUserAsync( + @event.UserId, + "operation_completed", + new + { + id = @event.Id, + name = @event.Name, + resource = @event.Resource + }); public async Task PublishOperationRejectedAsync(OperationRejected @event) - => await _hubContextWrapper.PublishToUserAsync(@event.UserId, - "operation_rejected", - new - { - id = @event.Id, - name = @event.Name, - resource = @event.Resource, - code = @event.Code, - reason = @event.Message - }); + => await _hubContextWrapper.PublishToUserAsync( + @event.UserId, + "operation_rejected", + new + { + id = @event.Id, + name = @event.Name, + resource = @event.Resource, + code = @event.Code, + reason = @event.Message + }); } \ No newline at end of file From d6346942c88195b831bd66f4ff8a1e039695e0b2 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 31 Jul 2024 20:04:29 +0200 Subject: [PATCH 067/104] Update packages, fix typos, and improve code formatting Updated the `Microsoft.VisualStudio.Azure.Containers.Tools.Targets` package from version `1.20.1` to `1.21.0` in `Genocs.Core.Demo.Worker.csproj`. Updated the `SmartFormat.NET` package from version `3.4.0` to `3.5.0` in `Genocs.Logging.csproj`. Updated the `System.Linq.Dynamic.Core` package from version `1.4.3` to `1.4.4` in `Genocs.QueryBuilder.UnitTests.csproj`. Corrected a typo in the comment within `AzureKeyVaultOptions.cs` from "The vault Setting definition." to "The Azure Key Vault setting definition." Fixed indentation in the `AddAzureKeyVault` method within `Extensions.cs` to ensure proper formatting. Added a null or whitespace check for the `sectionName` parameter in the `UseAzureKeyVault` method within `Extensions.cs` and set it to `AzureKeyVaultOptions.Position` if it is null or whitespace. --- .../Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 2 +- .../Configurations/AzureKeyVaultOptions.cs | 2 +- src/Genocs.Secrets.AzureKeyVault/Extensions.cs | 15 ++++++++++----- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index c765a4f7..c84a28cb 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index b85b5d30..ab8b4c62 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -60,7 +60,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 2b3c6d9b..d68c3f84 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -13,7 +13,7 @@ - + all diff --git a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs index 62ca3c4f..3ccab105 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs @@ -1,7 +1,7 @@ namespace Genocs.Secrets.AzureKeyVault.Configurations; /// -/// The vault Setting definition. +/// The Azure Kay Vault setting definition. /// public class AzureKeyVaultOptions { diff --git a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs index 7daa3896..5615cd88 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs @@ -38,11 +38,11 @@ public static IHostBuilder UseAzureKeyVault( } cfg.AddAzureKeyVault( - new Uri($"https://{settings.Name}.vault.azure.net/"), - new DefaultAzureCredential(new DefaultAzureCredentialOptions - { - ManagedIdentityClientId = settings.ManagedIdentityId - })); + new Uri($"https://{settings.Name}.vault.azure.net/"), + new DefaultAzureCredential(new DefaultAzureCredentialOptions + { + ManagedIdentityClientId = settings.ManagedIdentityId + })); }); /// @@ -56,6 +56,11 @@ public static IWebHostBuilder UseAzureKeyVault( string sectionName = AzureKeyVaultOptions.Position) => builder.ConfigureAppConfiguration((ctx, cfg) => { + if (string.IsNullOrWhiteSpace(sectionName)) + { + sectionName = AzureKeyVaultOptions.Position; + } + AzureKeyVaultOptions settings = ctx.Configuration.GetOptions(sectionName); if (!settings.Enabled) { From 318ca61f46bb69fd29b13346576373d4d0cedd2c Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 31 Jul 2024 20:12:31 +0200 Subject: [PATCH 068/104] Refactor and update dependencies, fix typos, and improve code formatting --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d248da67..9175d26a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +## [v6.0.0](https://github.com/Genocs/genocs-library/compare/6.0.0-preview.2.0...v6.0.0) - 2024-07-31 + +### Commits + +- Refactor and update dependencies and logging level [`63533a2`](https://github.com/Genocs/genocs-library/commit/63533a2ccfb64106dd81e296ca1a1de55c556f48) +- Refactor auth and update docs [`a63d816`](https://github.com/Genocs/genocs-library/commit/a63d816a4b617246ec99b3400d019a1b46ff40b0) +- Update packages, fix typos, and improve code formatting [`d634694`](https://github.com/Genocs/genocs-library/commit/d6346942c88195b831bd66f4ff8a1e039695e0b2) + ## [6.0.0-preview.2.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.4.0...6.0.0-preview.2.0) - 2024-07-19 ### Merged From 6e091e5fa20f0a2d1dda34468675d6fbe787792c Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 6 Aug 2024 17:01:48 +0200 Subject: [PATCH 069/104] Make properties nullable and improve code readability - JwtOptions: Remove default values from ValidateAudience and ValidateIssuer, making them nullable. - AuthorizedController: Include Authorization header in PostSubmitDemoCommand response. - VaultOptions: Make Templates and nested PkiOptions properties nullable. - Extensions: Reformat method signatures, make string variables nullable, rename tuple elements in SetSecrets, and use PascalCase for tuple elements in GetClientAndSettings. - Documentation: Add period in ServiceCollectionExtensions comment and clarify return value in AddOpenTelemetry method. --- src/Genocs.Auth/Configurations/JwtOptions.cs | 4 +- .../Controllers/AuthorizedController.cs | 2 +- .../Extensions/ServiceCollectionExtensions.cs | 2 +- .../Configurations/VaultSettings.cs | 22 +++--- src/Genocs.Secrets.Vault/Extensions.cs | 68 +++++++++++-------- src/Genocs.Tracing/Extensions.cs | 2 +- 6 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/Genocs.Auth/Configurations/JwtOptions.cs b/src/Genocs.Auth/Configurations/JwtOptions.cs index 615f0c5f..150a7a52 100644 --- a/src/Genocs.Auth/Configurations/JwtOptions.cs +++ b/src/Genocs.Auth/Configurations/JwtOptions.cs @@ -38,8 +38,8 @@ public class JwtOptions public string? ValidIssuer { get; set; } public IEnumerable? ValidIssuers { get; set; } public bool ValidateActor { get; set; } - public bool ValidateAudience { get; set; } = true; - public bool ValidateIssuer { get; set; } = true; + public bool ValidateAudience { get; set; } + public bool ValidateIssuer { get; set; } public bool ValidateLifetime { get; set; } = true; public bool ValidateTokenReplay { get; set; } public bool ValidateIssuerSigningKey { get; set; } diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs index 0f922b23..8d496c13 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/AuthorizedController.cs @@ -21,6 +21,6 @@ public AuthorizedController(ILogger logger) [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] public async Task PostSubmitDemoCommand() { - return await Task.Run(() => Ok("Done")); + return await Task.Run(() => Ok($"Done! Authorization is: {HttpContext.Request.Headers["Authorization"]}")); } } diff --git a/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs index ea2aab66..f3ed6582 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs @@ -6,7 +6,7 @@ namespace Genocs.Persistence.MongoDb.Extensions; /// -/// Service Collection Extension for MongoDb Repository setup +/// Service Collection Extension for MongoDb Repository setup. /// public static class ServiceCollectionExtensions { diff --git a/src/Genocs.Secrets.Vault/Configurations/VaultSettings.cs b/src/Genocs.Secrets.Vault/Configurations/VaultSettings.cs index f2775730..87889279 100644 --- a/src/Genocs.Secrets.Vault/Configurations/VaultSettings.cs +++ b/src/Genocs.Secrets.Vault/Configurations/VaultSettings.cs @@ -34,23 +34,23 @@ public class LeaseOptions public string? RoleName { get; set; } public string? MountPoint { get; set; } public bool AutoRenewal { get; set; } - public IDictionary Templates { get; set; } + public IDictionary? Templates { get; set; } } public class PkiOptions { public bool Enabled { get; set; } - public string RoleName { get; set; } - public string MountPoint { get; set; } - public string CertificateFormat { get; set; } - public string PrivateKeyFormat { get; set; } - public string CommonName { get; set; } - public string TTL { get; set; } - public string SubjectAlternativeNames { get; set; } - public string OtherSubjectAlternativeNames { get; set; } + public string? RoleName { get; set; } + public string? MountPoint { get; set; } + public string? CertificateFormat { get; set; } + public string? PrivateKeyFormat { get; set; } + public string? CommonName { get; set; } + public string? TTL { get; set; } + public string? SubjectAlternativeNames { get; set; } + public string? OtherSubjectAlternativeNames { get; set; } public bool ExcludeCommonNameFromSubjectAlternativeNames { get; set; } - public string IPSubjectAlternativeNames { get; set; } - public string URISubjectAlternativeNames { get; set; } + public string? IPSubjectAlternativeNames { get; set; } + public string? URISubjectAlternativeNames { get; set; } public bool ImportPrivateKey { get; set; } } } \ No newline at end of file diff --git a/src/Genocs.Secrets.Vault/Extensions.cs b/src/Genocs.Secrets.Vault/Extensions.cs index 166aa19e..6fa05898 100644 --- a/src/Genocs.Secrets.Vault/Extensions.cs +++ b/src/Genocs.Secrets.Vault/Extensions.cs @@ -222,14 +222,17 @@ private static async Task SetActiveDirectorySecretsAsync( }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static async Task SetAzureSecretsAsync(string key, IVaultClient client, - VaultOptions.LeaseOptions options, - IDictionary configuration) + private static async Task SetAzureSecretsAsync( + string key, + IVaultClient client, + VaultOptions.LeaseOptions options, + IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Azure; - var mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; - var credentials = - await client.V1.Secrets.Azure.GetCredentialsAsync(options.RoleName, mountPoint); + string? mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; + + var credentials = await client.V1.Secrets.Azure.GetCredentialsAsync(options.RoleName, mountPoint); + SetSecrets(key, options, configuration, name, () => (credentials, new Dictionary { ["clientId"] = credentials.Data.ClientId, @@ -237,28 +240,32 @@ private static async Task SetAzureSecretsAsync(string key, IVaultClient client, }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static async Task SetConsulSecretsAsync(string key, IVaultClient client, - VaultOptions.LeaseOptions options, - IDictionary configuration) + private static async Task SetConsulSecretsAsync( + string key, + IVaultClient client, + VaultOptions.LeaseOptions options, + IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Consul; - var mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; - var credentials = - await client.V1.Secrets.Consul.GetCredentialsAsync(options.RoleName, mountPoint); + string? mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; + var credentials = await client.V1.Secrets.Consul.GetCredentialsAsync(options.RoleName, mountPoint); + SetSecrets(key, options, configuration, name, () => (credentials, new Dictionary { ["token"] = credentials.Data.Token }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static async Task SetDatabaseSecretsAsync(string key, IVaultClient client, - VaultOptions.LeaseOptions options, - IDictionary configuration) + private static async Task SetDatabaseSecretsAsync( + string key, + IVaultClient client, + VaultOptions.LeaseOptions options, + IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.Database; - var mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; - var credentials = - await client.V1.Secrets.Database.GetCredentialsAsync(options.RoleName, mountPoint); + string? mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; + var credentials = await client.V1.Secrets.Database.GetCredentialsAsync(options.RoleName, mountPoint); + SetSecrets(key, options, configuration, name, () => (credentials, new Dictionary { ["username"] = credentials.Data.Username, @@ -273,14 +280,16 @@ private static async Task SetPkiSecretsAsync(IVaultClient client, VaultOptions o CertificatesService.Set(options.Pki.RoleName, certificate); } - private static async Task SetRabbitMqSecretsAsync(string key, IVaultClient client, - VaultOptions.LeaseOptions options, - IDictionary configuration) + private static async Task SetRabbitMqSecretsAsync( + string key, + IVaultClient client, + VaultOptions.LeaseOptions options, + IDictionary configuration) { const string name = SecretsEngineMountPoints.Defaults.RabbitMQ; - var mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; - var credentials = - await client.V1.Secrets.RabbitMQ.GetCredentialsAsync(options.RoleName, mountPoint); + string? mountPoint = string.IsNullOrWhiteSpace(options.MountPoint) ? name : options.MountPoint; + var credentials = await client.V1.Secrets.RabbitMQ.GetCredentialsAsync(options.RoleName, mountPoint); + SetSecrets(key, options, configuration, name, () => (credentials, new Dictionary { ["username"] = credentials.Data.Username, @@ -288,9 +297,12 @@ private static async Task SetRabbitMqSecretsAsync(string key, IVaultClient clien }, credentials.LeaseId, credentials.LeaseDurationSeconds, credentials.Renewable)); } - private static void SetSecrets(string key, VaultOptions.LeaseOptions options, - IDictionary configuration, string name, - Func<(object, Dictionary, string, int, bool)> lease) + private static void SetSecrets( + string key, + VaultOptions.LeaseOptions options, + IDictionary configuration, + string name, + Func<(object Credentials, Dictionary Values, string LeaseId, int Duration, bool Renewable)> lease) { var createdAt = DateTime.UtcNow; var (credentials, values, leaseId, duration, renewable) = lease(); @@ -299,7 +311,7 @@ private static void SetSecrets(string key, VaultOptions.LeaseOptions options, LeaseService.Set(key, leaseData); } - private static (IVaultClient client, VaultClientSettings settings) GetClientAndSettings(VaultOptions options) + private static (IVaultClient Client, VaultClientSettings Settings) GetClientAndSettings(VaultOptions options) { var settings = new VaultClientSettings(options.Url, GetAuthMethod(options)); var client = new VaultClient(settings); diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index 44a9bc0f..75c312e6 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -24,7 +24,7 @@ public static class Extensions /// Custom settings for OpenTelemetry. /// /// The Genocs builder. - /// The builder. + /// The Genocs builder you can use for chain. public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) { From 87edca186850db3cbe17398229335012308fb814 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 10 Aug 2024 16:05:51 +0200 Subject: [PATCH 070/104] Refactor interfaces and update Azure Key Vault options Refactored various interfaces for better readability and added XML documentation comments. Introduced new generic interface `IDeletionAudited`. Removed unnecessary `using` statements. Updated `OutboxProcessor` and `ServiceBusMessageDispatcher` for readability. Made several properties nullable in different classes and interfaces. Added new properties to `AzureKeyVaultOptions` and introduced `ExtensionsCertificates` for Azure Key Vault integration. Removed `UseAzureKeyVault` method from `Extensions` class. --- .../Entities/Auditing/IDeletionAudited.cs | 37 +++-- .../Domain/Entities/Auditing/IFullAudited.cs | 3 +- .../Entities/Auditing/IHasCreationTime.cs | 2 - .../IMessageOutbox.cs | 18 ++- .../Processors/OutboxProcessor.cs | 9 +- .../Extensions.cs | 6 +- .../FailedMessage.cs | 8 +- .../IConventionsBuilder.cs | 2 - .../Subscribers/MessageSubscriber.cs | 8 +- .../ServiceBusMessageDispatcher.cs | 6 +- src/Genocs.MessageBrokers/CQRS/Extensions.cs | 6 +- .../CorrelationContextAccessor.cs | 2 +- src/Genocs.MessageBrokers/IBusSubscriber.cs | 3 +- .../ICorrelationContextAccessor.cs | 2 +- .../IMessageProperties.cs | 6 +- .../IMessagePropertiesAccessor.cs | 2 +- src/Genocs.MessageBrokers/MessageAttribute.cs | 2 +- .../MessagePropertiesAccessor.cs | 7 +- .../Configurations/AzureKeyVaultOptions.cs | 6 +- .../Extensions.cs | 1 - .../ExtensionsCertificates.cs | 143 ++++++++++++++++++ 21 files changed, 215 insertions(+), 64 deletions(-) create mode 100644 src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificates.cs diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs index 17b56ca1..bfa83bab 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs @@ -1,26 +1,25 @@ -namespace Genocs.Core.Domain.Entities.Auditing +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// This interface is implemented by entities which wanted to store deletion information (who and when deleted). +/// +public interface IDeletionAudited : IHasDeletionTime { /// - /// This interface is implemented by entities which wanted to store deletion information (who and when deleted). + /// Which user deleted this entity. /// - public interface IDeletionAudited : IHasDeletionTime - { - /// - /// Which user deleted this entity? - /// - long? DeleterUserId { get; set; } - } + long? DeleterUserId { get; set; } +} +/// +/// Adds navigation properties to interface for user. +/// +/// Type of the user. +public interface IDeletionAudited : IDeletionAudited + where TUser : IEntity +{ /// - /// Adds navigation properties to interface for user. + /// Reference to the deleter user of this entity. /// - /// Type of the user - public interface IDeletionAudited : IDeletionAudited - where TUser : IEntity - { - /// - /// Reference to the deleter user of this entity. - /// - TUser DeleterUser { get; set; } - } + TUser DeleterUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs index 3cce8e74..aa902887 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IFullAudited.cs @@ -5,13 +5,12 @@ namespace Genocs.Core.Domain.Entities.Auditing; /// public interface IFullAudited : IAudited, IDeletionAudited { - } /// /// Adds navigation properties to interface for user. /// -/// Type of the user +/// Type of the user. public interface IFullAudited : IAudited, IFullAudited, IDeletionAudited where TUser : IEntity { diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs index 660e0003..8e0ca32f 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs @@ -1,7 +1,5 @@ namespace Genocs.Core.Domain.Entities.Auditing; -using System; - /// /// An entity can implement this interface if of this entity must be stored. /// is automatically set when saving to database. diff --git a/src/Genocs.MessageBrokers.Outbox/IMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox/IMessageOutbox.cs index 4561d56c..b5b699e4 100644 --- a/src/Genocs.MessageBrokers.Outbox/IMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox/IMessageOutbox.cs @@ -1,7 +1,7 @@ namespace Genocs.MessageBrokers.Outbox; /// -/// The Message Outbox interface definition +/// The Message Outbox interface definition. /// public interface IMessageOutbox { @@ -9,11 +9,13 @@ public interface IMessageOutbox Task HandleAsync(string messageId, Func handler); - Task SendAsync(T message, - string? originatedMessageId = null, - string? messageId = null, - string? correlationId = null, - string? spanContext = null, - object? messageContext = null, - IDictionary? headers = null) where T : class; + Task SendAsync( + T message, + string? originatedMessageId = null, + string? messageId = null, + string? correlationId = null, + string? spanContext = null, + object? messageContext = null, + IDictionary? headers = null) + where T : class; } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs index a9799d06..4f36445b 100644 --- a/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs +++ b/src/Genocs.MessageBrokers.Outbox/Processors/OutboxProcessor.cs @@ -16,8 +16,11 @@ internal sealed class OutboxProcessor : IHostedService private readonly OutboxType _type; private Timer _timer; - public OutboxProcessor(IServiceProvider serviceProvider, IBusPublisher publisher, OutboxOptions options, - ILogger logger) + public OutboxProcessor( + IServiceProvider serviceProvider, + IBusPublisher publisher, + OutboxOptions options, + ILogger logger) { if (options.Enabled && options.IntervalMilliseconds <= 0) { @@ -79,7 +82,7 @@ private void SendOutboxMessages(object state) private async Task SendOutboxMessagesAsync() { - var jobId = Guid.NewGuid().ToString("N"); + string jobId = Guid.NewGuid().ToString("N"); _logger.LogTrace($"Started processing outbox messages... [job id: '{jobId}']"); var stopwatch = new Stopwatch(); stopwatch.Start(); diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs index 18093103..15c93d89 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/Extensions.cs @@ -30,9 +30,9 @@ public static class Extensions /// /// The builder. /// the default section name. - /// - /// - /// + /// The plugin action method. + /// The configurator. + /// The serializer. /// /// Raised when configuration is incorrect. public static IGenocsBuilder AddRabbitMq( diff --git a/src/Genocs.MessageBrokers.RabbitMQ/FailedMessage.cs b/src/Genocs.MessageBrokers.RabbitMQ/FailedMessage.cs index 6af3ed3a..e3ac8ea1 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/FailedMessage.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/FailedMessage.cs @@ -4,19 +4,19 @@ namespace Genocs.MessageBrokers.RabbitMQ; public class FailedMessage { - public object Message { get; } + public object? Message { get; } public bool ShouldRetry { get; } [Description("This will only work if 'deadLetter' is enabled in RabbitMQ options." + "For more information, see https://www.rabbitmq.com/dlx.html")] public bool MoveToDeadLetter { get; } - public FailedMessage(bool shouldRetry = true, bool moveToDeadLetter = true) : this(null, shouldRetry, - moveToDeadLetter) + public FailedMessage(bool shouldRetry = true, bool moveToDeadLetter = true) + : this(null, shouldRetry, moveToDeadLetter) { } - public FailedMessage(object message, bool shouldRetry = true, bool moveToDeadLetter = true) + public FailedMessage(object? message, bool shouldRetry = true, bool moveToDeadLetter = true) { Message = message; ShouldRetry = shouldRetry; diff --git a/src/Genocs.MessageBrokers.RabbitMQ/IConventionsBuilder.cs b/src/Genocs.MessageBrokers.RabbitMQ/IConventionsBuilder.cs index 78a3e9b5..6d90b2a1 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/IConventionsBuilder.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/IConventionsBuilder.cs @@ -1,5 +1,3 @@ -using System; - namespace Genocs.MessageBrokers.RabbitMQ; public interface IConventionsBuilder diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Subscribers/MessageSubscriber.cs b/src/Genocs.MessageBrokers.RabbitMQ/Subscribers/MessageSubscriber.cs index fc8128cf..d1432617 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Subscribers/MessageSubscriber.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/Subscribers/MessageSubscriber.cs @@ -4,10 +4,12 @@ internal class MessageSubscriber : IMessageSubscriber { public MessageSubscriberAction Action { get; } public Type Type { get; } - public Func Handle { get; } + public Func? Handle { get; } - private MessageSubscriber(MessageSubscriberAction action, Type type, - Func handle = null) + private MessageSubscriber( + MessageSubscriberAction action, + Type type, + Func? handle = null) { Action = action; Type = type; diff --git a/src/Genocs.MessageBrokers/CQRS/Dispatchers/ServiceBusMessageDispatcher.cs b/src/Genocs.MessageBrokers/CQRS/Dispatchers/ServiceBusMessageDispatcher.cs index 4a7138b0..98a558c0 100644 --- a/src/Genocs.MessageBrokers/CQRS/Dispatchers/ServiceBusMessageDispatcher.cs +++ b/src/Genocs.MessageBrokers/CQRS/Dispatchers/ServiceBusMessageDispatcher.cs @@ -14,9 +14,11 @@ public ServiceBusMessageDispatcher(IBusPublisher busPublisher, ICorrelationConte _accessor = accessor; } - public Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand + public Task SendAsync(T command, CancellationToken cancellationToken = default) + where T : class, ICommand => _busPublisher.SendAsync(command, _accessor.CorrelationContext); - public Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent + public Task PublishAsync(T @event, CancellationToken cancellationToken = default) + where T : class, IEvent => _busPublisher.PublishAsync(@event, _accessor.CorrelationContext); } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers/CQRS/Extensions.cs b/src/Genocs.MessageBrokers/CQRS/Extensions.cs index 364b0839..f84c6a26 100644 --- a/src/Genocs.MessageBrokers/CQRS/Extensions.cs +++ b/src/Genocs.MessageBrokers/CQRS/Extensions.cs @@ -16,14 +16,16 @@ public static Task PublishAsync(this IBusPublisher busPublisher, TEvent where TEvent : class, IEvent => busPublisher.PublishAsync(@event, messageContext: messageContext); - public static IBusSubscriber SubscribeCommand(this IBusSubscriber busSubscriber) where T : class, ICommand + public static IBusSubscriber SubscribeCommand(this IBusSubscriber busSubscriber) + where T : class, ICommand => busSubscriber.Subscribe(async (serviceProvider, command, _) => { using var scope = serviceProvider.CreateScope(); await scope.ServiceProvider.GetRequiredService>().HandleAsync(command); }); - public static IBusSubscriber SubscribeEvent(this IBusSubscriber busSubscriber) where T : class, IEvent + public static IBusSubscriber SubscribeEvent(this IBusSubscriber busSubscriber) + where T : class, IEvent => busSubscriber.Subscribe(async (serviceProvider, @event, _) => { using var scope = serviceProvider.CreateScope(); diff --git a/src/Genocs.MessageBrokers/CorrelationContextAccessor.cs b/src/Genocs.MessageBrokers/CorrelationContextAccessor.cs index 333b9e1c..682492d9 100644 --- a/src/Genocs.MessageBrokers/CorrelationContextAccessor.cs +++ b/src/Genocs.MessageBrokers/CorrelationContextAccessor.cs @@ -5,7 +5,7 @@ public class CorrelationContextAccessor : ICorrelationContextAccessor private static readonly AsyncLocal Holder = new(); - public object CorrelationContext + public object? CorrelationContext { get => Holder.Value?.Context; set diff --git a/src/Genocs.MessageBrokers/IBusSubscriber.cs b/src/Genocs.MessageBrokers/IBusSubscriber.cs index 0b392b26..012a50aa 100644 --- a/src/Genocs.MessageBrokers/IBusSubscriber.cs +++ b/src/Genocs.MessageBrokers/IBusSubscriber.cs @@ -2,5 +2,6 @@ public interface IBusSubscriber : IDisposable { - IBusSubscriber Subscribe(Func handle) where T : class; + IBusSubscriber Subscribe(Func handle) + where T : class; } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers/ICorrelationContextAccessor.cs b/src/Genocs.MessageBrokers/ICorrelationContextAccessor.cs index 9d78cf5e..0d45ba79 100644 --- a/src/Genocs.MessageBrokers/ICorrelationContextAccessor.cs +++ b/src/Genocs.MessageBrokers/ICorrelationContextAccessor.cs @@ -2,5 +2,5 @@ namespace Genocs.MessageBrokers; public interface ICorrelationContextAccessor { - object CorrelationContext { get; set; } + object? CorrelationContext { get; set; } } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers/IMessageProperties.cs b/src/Genocs.MessageBrokers/IMessageProperties.cs index bf1161d9..16f800ef 100644 --- a/src/Genocs.MessageBrokers/IMessageProperties.cs +++ b/src/Genocs.MessageBrokers/IMessageProperties.cs @@ -2,8 +2,8 @@ namespace Genocs.MessageBrokers; public interface IMessageProperties { - string MessageId { get; } - string CorrelationId { get; } + string? MessageId { get; } + string? CorrelationId { get; } long Timestamp { get; } - IDictionary Headers { get; } + IDictionary? Headers { get; } } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers/IMessagePropertiesAccessor.cs b/src/Genocs.MessageBrokers/IMessagePropertiesAccessor.cs index de2de052..3f3515d8 100644 --- a/src/Genocs.MessageBrokers/IMessagePropertiesAccessor.cs +++ b/src/Genocs.MessageBrokers/IMessagePropertiesAccessor.cs @@ -2,5 +2,5 @@ namespace Genocs.MessageBrokers; public interface IMessagePropertiesAccessor { - IMessageProperties MessageProperties { get; set; } + IMessageProperties? MessageProperties { get; set; } } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers/MessageAttribute.cs b/src/Genocs.MessageBrokers/MessageAttribute.cs index 9ddc4186..fa5c6fae 100644 --- a/src/Genocs.MessageBrokers/MessageAttribute.cs +++ b/src/Genocs.MessageBrokers/MessageAttribute.cs @@ -1,7 +1,7 @@ namespace Genocs.MessageBrokers; /// -/// Message Attribute +/// Message Attribute. /// [AttributeUsage(AttributeTargets.Class)] public class MessageAttribute : Attribute diff --git a/src/Genocs.MessageBrokers/MessagePropertiesAccessor.cs b/src/Genocs.MessageBrokers/MessagePropertiesAccessor.cs index 64967ca8..dd289b85 100644 --- a/src/Genocs.MessageBrokers/MessagePropertiesAccessor.cs +++ b/src/Genocs.MessageBrokers/MessagePropertiesAccessor.cs @@ -2,10 +2,9 @@ namespace Genocs.MessageBrokers; public class MessagePropertiesAccessor : IMessagePropertiesAccessor { - private static readonly AsyncLocal - Holder = new(); + private static readonly AsyncLocal Holder = new(); - public IMessageProperties MessageProperties + public IMessageProperties? MessageProperties { get => Holder.Value?.Properties; set @@ -25,6 +24,6 @@ public IMessageProperties MessageProperties private class MessageContextHolder { - public IMessageProperties Properties; + public IMessageProperties? Properties; } } \ No newline at end of file diff --git a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs index 3ccab105..fb5fbbdd 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs @@ -1,3 +1,5 @@ +using Azure.Core; + namespace Genocs.Secrets.AzureKeyVault.Configurations; /// @@ -24,5 +26,7 @@ public class AzureKeyVaultOptions /// The managed identity id. /// public string? ManagedIdentityId { get; set; } - + public object? AzureADCertThumbprint { get; internal set; } + public string? AzureADApplicationId { get; internal set; } + public string? AzureADDirectoryId { get; internal set; } } \ No newline at end of file diff --git a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs index 5615cd88..c90efaf0 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Extensions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Extensions.cs @@ -77,7 +77,6 @@ public static IWebHostBuilder UseAzureKeyVault( public static WebApplicationBuilder UseAzureKeyVault(this WebApplicationBuilder builder) { - AzureKeyVaultOptions settings = builder.Configuration.GetOptions(AzureKeyVaultOptions.Position); if (!settings.Enabled) { diff --git a/src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificates.cs b/src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificates.cs new file mode 100644 index 00000000..d4b949c3 --- /dev/null +++ b/src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificates.cs @@ -0,0 +1,143 @@ +using Azure.Identity; +using Genocs.Core.Builders; +using Genocs.Secrets.AzureKeyVault.Configurations; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using System.Security.Cryptography.X509Certificates; + +namespace Genocs.Secrets.AzureKeyVault; + +/// +/// The ExtensionsCertificates helper class. +/// +public static class ExtensionsCertificates +{ + /// + /// This method is used to add the Azure Key Vault to the Host builder. + /// You can use the Azure Key Vault to store and manage application secrets. + /// + /// The builder. + /// The section name. + /// The Host builder. + public static IHostBuilder UseAzureKeyVaultWithCertificates( + this IHostBuilder builder, + string sectionName = AzureKeyVaultOptions.Position) + => builder.ConfigureAppConfiguration((ctx, cfg) => + { + // TODO Test + if (string.IsNullOrWhiteSpace(sectionName)) + { + sectionName = AzureKeyVaultOptions.Position; + } + + var settings = ctx.Configuration.GetOptions(sectionName); + if (!settings.Enabled) + { + return; + } + + using (var x509Store = new X509Store(StoreLocation.CurrentUser)) + { + x509Store.Open(OpenFlags.ReadOnly); + + var x509Certificate = x509Store.Certificates + .Find( + X509FindType.FindByThumbprint, + settings.AzureADCertThumbprint!, + validOnly: false) + .OfType() + .Single(); + + cfg.AddAzureKeyVault( + new Uri($"https://{settings.Name}.vault.azure.net/"), + new ClientCertificateCredential( + settings.AzureADDirectoryId, + settings.AzureADApplicationId, + x509Certificate)); + + x509Store?.Close(); + } + }); + + /// + /// UseVault. + /// + /// The builder. + /// The section name. + /// The Web Host builder. + public static IWebHostBuilder UseAzureKeyVaultWithCertificates( + this IWebHostBuilder builder, + string sectionName = AzureKeyVaultOptions.Position) + => builder.ConfigureAppConfiguration((ctx, cfg) => + { + if (string.IsNullOrWhiteSpace(sectionName)) + { + sectionName = AzureKeyVaultOptions.Position; + } + + + AzureKeyVaultOptions settings = ctx.Configuration.GetOptions(sectionName); + if (!settings.Enabled) + { + return; + } + + using (var x509Store = new X509Store(StoreLocation.CurrentUser)) + { + x509Store.Open(OpenFlags.ReadOnly); + + var x509Certificate = x509Store.Certificates + .Find( + X509FindType.FindByThumbprint, + settings.AzureADCertThumbprint!, + validOnly: false) + .OfType() + .Single(); + + cfg.AddAzureKeyVault( + new Uri($"https://{settings.Name}.vault.azure.net/"), + new ClientCertificateCredential( + settings.AzureADDirectoryId, + settings.AzureADApplicationId, + x509Certificate)); + + x509Store?.Close(); + } + }); + + public static WebApplicationBuilder UseAzureKeyVaultWithCertificates(this WebApplicationBuilder builder) + { + + AzureKeyVaultOptions settings = builder.Configuration.GetOptions(AzureKeyVaultOptions.Position); + if (!settings.Enabled) + { + return builder; + } + + using (var x509Store = new X509Store(StoreLocation.CurrentUser)) + { + x509Store.Open(OpenFlags.ReadOnly); + + var x509Certificate = x509Store.Certificates + .Find( + X509FindType.FindByThumbprint, + settings.AzureADCertThumbprint!, + validOnly: false) + .OfType() + .Single(); + + builder.Configuration.AddAzureKeyVault( + new Uri($"https://{settings.Name}.vault.azure.net/"), + new ClientCertificateCredential( + settings.AzureADDirectoryId, + settings.AzureADApplicationId, + x509Certificate)); + + x509Store?.Close(); + } + + return builder; + } +} From 866463f0f4abf764b667774553301a417733474d Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 21 Aug 2024 16:05:59 +0200 Subject: [PATCH 071/104] Refactor interfaces, update Azure Key Vault options, and improve code readability --- README.md | 7 ++++++ containers/infrastructure-mysql.yml | 23 +++++++++++++++++++ src/Genocs.Auth/Genocs.Auth.csproj | 4 ++-- .../Controllers/ExternalApiController.cs | 5 +++- .../Configurations/AzureKeyVaultOptions.cs | 14 +++++++++-- src/Genocs.Security/Genocs.Security.csproj | 2 +- .../Genocs.WebApi.Security.csproj | 12 +++++----- 7 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 containers/infrastructure-mysql.yml diff --git a/README.md b/README.md index cfa62317..8e8b6113 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,13 @@ docker compose -f ./infrastructure-security.yml --env-file ./.env --project-name # Use this file only in case you want to setup sqlserver database (no need if you use postgres) docker compose -f ./infrastructure-sqlserver.yml --env-file ./.env --project-name genocs up -d +# Use this file only in case you want to setup mySql database (no need if you use postgres) +docker compose -f ./infrastructure-mysql.yml --env-file ./.env --project-name genocs up -d + +# Use this file only in case you want to setup oracle database (no need if you use postgres) +# docker compose -f ./infrastructure-oracle.yml --env-file ./.env --project-name genocs up -d + + # Use this file only in case you want to setup elk stack docker compose -f ./infrastructure-elk.yml --env-file ./.env --project-name genocs up -d diff --git a/containers/infrastructure-mysql.yml b/containers/infrastructure-mysql.yml new file mode 100644 index 00000000..035fbf03 --- /dev/null +++ b/containers/infrastructure-mysql.yml @@ -0,0 +1,23 @@ +services: + mysqldb: + image: mysql + hostname: mysqldb + container_name: mysqldb + ports: + - 3306:3306 + + environment: + MYSQL_ROOT_PASSWORD: example + volumes: + - mysqlsystem:/var/lib/mysql + networks: + - genocs + +networks: + genocs: + name: genocs-network + external: true + +volumes: + mysqlsystem: + driver: local diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 4a7fdde9..fd023022 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -53,8 +53,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs index 40afc2da..6d6b975a 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/ExternalApiController.cs @@ -11,7 +11,9 @@ public class ExternalApiController : ControllerBase private readonly ILogger _logger; private readonly IExternalServiceClient _externalServiceClient; - public ExternalApiController(ILogger logger, IExternalServiceClient externalServiceClient) + public ExternalApiController( + ILogger logger, + IExternalServiceClient externalServiceClient) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _externalServiceClient = externalServiceClient ?? throw new ArgumentNullException(nameof(externalServiceClient)); @@ -24,6 +26,7 @@ public async Task HomeAsync() => await Task.Run(() => Ok("done")); [HttpPost("")] + [Produces("application/json")] [ProducesResponseType(typeof(IssuingResponse), StatusCodes.Status200OK)] [Consumes(MediaTypeNames.Application.Json)] public async Task PostIssueAsync(IssuingRequest request) diff --git a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs index fb5fbbdd..c42ec075 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs @@ -1,5 +1,3 @@ -using Azure.Core; - namespace Genocs.Secrets.AzureKeyVault.Configurations; /// @@ -26,7 +24,19 @@ public class AzureKeyVaultOptions /// The managed identity id. /// public string? ManagedIdentityId { get; set; } + + /// + /// The client id. To be used with Certificate authentication. + /// public object? AzureADCertThumbprint { get; internal set; } + + /// + /// The client id. To be used with Certificate authentication. + /// public string? AzureADApplicationId { get; internal set; } + + /// + /// The Azure EntraID tenant Id. To be used with Certificate authentication. + /// public string? AzureADDirectoryId { get; internal set; } } \ No newline at end of file diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 2f37fd4a..22911d48 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index f3664774..8081a621 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -49,16 +49,16 @@ - - + + - + - - - + + + From c1095a76c9755976f829e77ea4051e2b84ef948a Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Thu, 29 Aug 2024 08:28:40 +0200 Subject: [PATCH 072/104] Remove CardToken, update configs, and add Oracle setup - Updated README.md to correct Docker Compose command for Oracle DB. - Changed MYSQL_ROOT_PASSWORD in infrastructure-mysql.yml. - Removed CardToken property from OrderRequest and Order classes. - Updated ServiceBusController to remove CardToken initialization. - Reordered UseAzureKeyVault and UseLogging in Program.cs. - Removed CardToken parameter from Order initialization in SubmitOrderConsumer. - Added infrastructure-oracle.yml for Oracle DB service configuration. Remove CardToken, update DB configs, and fix README Removed CardToken property from Order-related classes and methods. Updated MySQL root password in infrastructure-mysql.yml. Added infrastructure-oracle.yml for Oracle DB setup. Corrected Oracle DB setup command in README.md. Reordered method calls in Program.cs for better configuration. --- README.md | 3 +- containers/infrastructure-mysql.yml | 2 +- containers/infrastructure-oracle.yml | 35 +++++++++++++++++++ .../OrderRequestEvent.cs | 1 - .../Aggregates/Order.cs | 4 +-- .../Controllers/ServiceBusController.cs | 1 - src/Genocs.Core.Demo.WebApi/Program.cs | 4 +-- .../Consumers/SubmitOrderConsumer.cs | 2 +- 8 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 containers/infrastructure-oracle.yml diff --git a/README.md b/README.md index 8e8b6113..53856763 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,7 @@ docker compose -f ./infrastructure-sqlserver.yml --env-file ./.env --project-nam docker compose -f ./infrastructure-mysql.yml --env-file ./.env --project-name genocs up -d # Use this file only in case you want to setup oracle database (no need if you use postgres) -# docker compose -f ./infrastructure-oracle.yml --env-file ./.env --project-name genocs up -d - +docker compose -f ./infrastructure-oracle.yml --env-file ./.env --project-name genocs up -d # Use this file only in case you want to setup elk stack docker compose -f ./infrastructure-elk.yml --env-file ./.env --project-name genocs up -d diff --git a/containers/infrastructure-mysql.yml b/containers/infrastructure-mysql.yml index 035fbf03..e4dbc650 100644 --- a/containers/infrastructure-mysql.yml +++ b/containers/infrastructure-mysql.yml @@ -7,7 +7,7 @@ services: - 3306:3306 environment: - MYSQL_ROOT_PASSWORD: example + MYSQL_ROOT_PASSWORD: MySect3tPassw! volumes: - mysqlsystem:/var/lib/mysql networks: diff --git a/containers/infrastructure-oracle.yml b/containers/infrastructure-oracle.yml new file mode 100644 index 00000000..2ce16a6f --- /dev/null +++ b/containers/infrastructure-oracle.yml @@ -0,0 +1,35 @@ +services: + oracledb: + image: container-registry.oracle.com/database/express:21.3.0-xe + hostname: oracledb + container_name: oracledb + ports: + - 1521:1521 + - 5500:5500 + + environment: + ORACLE_PWD: MySect3tPassw! + ORACLE_CHARACTERSET: AL32UTF8 + ENABLE_ARCHIVELOG: true + ENABLE_FORCE_LOGGING: true + + volumes: + - oracle_data:/opt/oracle/oradata + - oracle_startup:/opt/oracle/scripts/startup + - oracle_setup:/opt/oracle/scripts/setup + + networks: + - genocs + +networks: + genocs: + name: genocs-network + external: true + +volumes: + oracle_data: + driver: local + oracle_startup: + driver: local + oracle_setup: + driver: local diff --git a/src/Genocs.Core.Demo.Contracts/OrderRequestEvent.cs b/src/Genocs.Core.Demo.Contracts/OrderRequestEvent.cs index fe8bbb30..76c37cf5 100644 --- a/src/Genocs.Core.Demo.Contracts/OrderRequestEvent.cs +++ b/src/Genocs.Core.Demo.Contracts/OrderRequestEvent.cs @@ -7,7 +7,6 @@ public class OrderRequest : IEvent public string OrderId { get; set; } = Guid.NewGuid().ToString(); public string UserId { get; set; } = default!; public DateTime TimeStamp { get; set; } = DateTime.UtcNow; - public string CardToken { get; set; } = default!; public decimal Amount { get; set; } public string Currency { get; set; } = default!; diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs index 42bca453..f9553296 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs @@ -9,11 +9,10 @@ namespace Genocs.Core.Demo.Domain.Aggregates; [TableMapping("Orders")] public class Order : AggregateRoot, IMongoDbEntity, IHasCreationTime { - public Order(string orderId, string userId, string cardToken, decimal amount, string currency) + public Order(string orderId, string userId, decimal amount, string currency) { OrderId = orderId; UserId = userId; - CardToken = cardToken; Amount = amount; Currency = currency; } @@ -21,7 +20,6 @@ public Order(string orderId, string userId, string cardToken, decimal amount, st public string OrderId { get; set; } = ObjectId.GenerateNewId().ToString(); public string UserId { get; set; } = default!; public DateTime CreationTime { get; set; } = DateTime.UtcNow; - public string CardToken { get; set; } = default!; public decimal Amount { get; set; } public string Currency { get; set; } = default!; } diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs index 90604ce3..f8f874a6 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/ServiceBusController.cs @@ -60,7 +60,6 @@ public async Task PostSubmitOrder() { OrderId = Guid.NewGuid().ToString(), UserId = Guid.NewGuid().ToString(), - CardToken = "6500-1254-2548", Amount = 10.0M, Currency = "EUR", Basket = new List() diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index e49b96f9..cfa7bc15 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -16,8 +16,8 @@ var builder = WebApplication.CreateBuilder(args); builder.Host - .UseLogging() - .UseAzureKeyVault(); + .UseAzureKeyVault() + .UseLogging(); var services = builder.Services; diff --git a/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs b/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs index 00ad7730..a2a7873f 100644 --- a/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs +++ b/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs @@ -19,7 +19,7 @@ public SubmitOrderConsumer(ILogger logger, IMongoDbReposito public async Task Consume(ConsumeContext context) { - Order order = new Order(context.Message.OrderId, context.Message.UserId, "", 1, "EUR"); + Order order = new Order(context.Message.OrderId, context.Message.UserId, 1, "EUR"); await _orderRepository.InsertAsync(order); _logger.LogInformation($"Order {context.Message.OrderId} processed!"); } From 3b45172b945ad7df08a11021c4ef738bad715f33 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Mon, 2 Sep 2024 13:34:29 +0200 Subject: [PATCH 073/104] Update packages and enhance Azure Key Vault integration Updated package references across multiple project files to newer versions, ensuring compatibility and leveraging new features or bug fixes. Modified `AzureKeyVaultOptions` class to change property descriptions and make some properties publicly settable. Replaced `ExtensionsCertificates.cs` with `ExtensionsCertificate.cs`, adding methods for configuring Azure Key Vault with certificate authentication for `IHostBuilder`, `IWebHostBuilder`, and `WebApplicationBuilder`. Updated `Genocs.Secrets.AzureKeyVault.csproj` to reference a newer version of `Azure.Extensions.AspNetCore.Configuration.Secrets`. Updated `Genocs.WebApi.Swagger.csproj` to reference newer versions of `Swashbuckle.AspNetCore`. Updated `Microsoft.NET.Test.Sdk` to version `17.11.0` in multiple test project files. Updated `MongoDB.Driver` and `MongoDB.Driver.Core.Extensions.DiagnosticSources` in `Genocs.Persistence.MongoDb.csproj`. Updated `Serilog.AspNetCore` to version `8.0.2` in `Genocs.Logging.csproj`. Updated `System.Linq.Dynamic.Core` to version `1.4.5` in `Genocs.QueryBuilder.UnitTests.csproj`. --- .../Genocs.Core.Demo.WebApi.csproj | 4 ++-- .../Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- .../Genocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 4 ++-- .../Genocs.QueryBuilder.UnitTests.csproj | 4 ++-- .../Configurations/AzureKeyVaultOptions.cs | 10 +++++----- ...ensionsCertificates.cs => ExtensionsCertificate.cs} | 10 ++++++---- .../Genocs.Secrets.AzureKeyVault.csproj | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 2 +- src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj | 10 +++++----- 12 files changed, 28 insertions(+), 26 deletions(-) rename src/Genocs.Secrets.AzureKeyVault/{ExtensionsCertificates.cs => ExtensionsCertificate.cs} (94%) diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 149a6af0..45a9c66b 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index c84a28cb..a46a22f4 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 8642f97e..5ef98b31 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -7,7 +7,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index ab8b4c62..b98785fd 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -51,7 +51,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 1c501e5e..05dc26a2 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 58d5d725..f49782c3 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -50,8 +50,8 @@ - - + + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index d68c3f84..5d60af40 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -11,9 +11,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all diff --git a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs index c42ec075..6e1ca058 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs +++ b/src/Genocs.Secrets.AzureKeyVault/Configurations/AzureKeyVaultOptions.cs @@ -26,17 +26,17 @@ public class AzureKeyVaultOptions public string? ManagedIdentityId { get; set; } /// - /// The client id. To be used with Certificate authentication. + /// The certificate thumbprint. To be used with Certificate authentication. /// - public object? AzureADCertThumbprint { get; internal set; } + public object? AzureADCertThumbprint { get; set; } /// - /// The client id. To be used with Certificate authentication. + /// The Active Directory Application id. To be used with Certificate authentication. /// - public string? AzureADApplicationId { get; internal set; } + public string? AzureADApplicationId { get; set; } /// /// The Azure EntraID tenant Id. To be used with Certificate authentication. /// - public string? AzureADDirectoryId { get; internal set; } + public string? AzureADDirectoryId { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificates.cs b/src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificate.cs similarity index 94% rename from src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificates.cs rename to src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificate.cs index d4b949c3..a7e14519 100644 --- a/src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificates.cs +++ b/src/Genocs.Secrets.AzureKeyVault/ExtensionsCertificate.cs @@ -10,9 +10,9 @@ namespace Genocs.Secrets.AzureKeyVault; /// -/// The ExtensionsCertificates helper class. +/// The ExtensionsCertificate helper class. /// -public static class ExtensionsCertificates +public static class ExtensionsCertificate { /// /// This method is used to add the Azure Key Vault to the Host builder. @@ -21,12 +21,12 @@ public static class ExtensionsCertificates /// The builder. /// The section name. /// The Host builder. - public static IHostBuilder UseAzureKeyVaultWithCertificates( + public static IHostBuilder UseAzureKeyVaultWithCertificate( this IHostBuilder builder, string sectionName = AzureKeyVaultOptions.Position) => builder.ConfigureAppConfiguration((ctx, cfg) => { - // TODO Test + // TODO: Test if (string.IsNullOrWhiteSpace(sectionName)) { sectionName = AzureKeyVaultOptions.Position; @@ -38,6 +38,8 @@ public static IHostBuilder UseAzureKeyVaultWithCertificates( return; } + // TODO: Test + // To use the Azure Key Vault with Certificate authentication, you need to have the certificate installed in the Current User store. using (var x509Store = new X509Store(StoreLocation.CurrentUser)) { x509Store.Open(OpenFlags.ReadOnly); diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index 83ca3e64..b01fb6df 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -50,7 +50,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 52a49d87..08e96a41 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -7,7 +7,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 53bbdc00..3a92499e 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -50,11 +50,11 @@ - - - - - + + + + + From 485db2ca1dd13e87a785a2242248671858fb7e45 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 11 Oct 2024 12:23:29 +0200 Subject: [PATCH 074/104] Refactor interfaces, update Azure Key Vault options, and improve code readability --- .github/FUNDING.yml | 2 +- .github/workflows/build_and_test.yml | 14 ++-- .github/workflows/dockerhub-publish.yml | 13 ++- .github/workflows/nuget-publish.yml | 3 +- Directory.Build.props | 10 ++- src/Genocs.Auth/Genocs.Auth.csproj | 14 +--- .../Configurations/AppOptions.cs | 1 - src/Genocs.Common/Genocs.Common.csproj | 10 +-- src/Genocs.Common/README_NUGET.md | 42 +--------- src/Genocs.Common/Types/Extensions.cs | 11 +-- .../MassTransitConsoleHostedService.cs | 9 +- src/Genocs.Core.Demo.Worker/Program.cs | 2 +- .../CQRS/Commands/ICommandDispatcher.cs | 18 ++-- src/Genocs.Core/CQRS/Events/IEventHandler.cs | 8 +- src/Genocs.Core/CQRS/Queries/IPagedFilter.cs | 2 +- src/Genocs.Core/CQRS/Queries/IQueryHandler.cs | 5 +- .../Extensions/CollectionExtensions.cs | 6 +- .../Collections/Extensions/ListExtensions.cs | 11 ++- .../Domain/Entities/AggregateRoot.cs | 11 +-- .../Auditing/CreationAuditedEntity.cs | 2 +- .../Entities/Auditing/EntityAuditingHelper.cs | 13 +-- .../Auditing/FullAuditedAggregateRoot.cs | 6 +- .../Entities/Auditing/FullAuditedEntity.cs | 4 +- src/Genocs.Core/Domain/Entities/Entity.cs | 4 +- .../Entities/EntityNotFoundException.cs | 4 +- src/Genocs.Core/Genocs.Core.csproj | 24 ++---- .../Genocs.Discovery.Consul.csproj | 10 +-- src/Genocs.HTTP.RestEase/Extensions.cs | 26 +++--- .../Genocs.HTTP.RestEase.csproj | 10 +-- .../RestEaseServiceNotFoundException.cs | 6 +- .../Serializers/QueryParamSerializer.cs | 4 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 10 +-- .../Genocs.LoadBalancing.Fabio.csproj | 10 +-- src/Genocs.Logging/Genocs.Logging.csproj | 10 +-- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 10 +-- .../Genocs.MessageBrokers.Outbox.csproj | 10 +-- .../Genocs.MessageBrokers.RabbitMQ.csproj | 10 +-- .../Genocs.MessageBrokers.csproj | 10 +-- src/Genocs.Metrics/Genocs.Metrics.csproj | 10 +-- .../Genocs.Monitoring.csproj | 10 +-- .../Genocs.Persistence.MongoDb.csproj | 10 +-- .../Genocs.Persistence.Redis.csproj | 10 +-- src/Genocs.QueryBuilder/Constants.cs | 6 +- .../DynamicQueryBuilder.cs | 4 +- src/Genocs.QueryBuilder/Expression.Date.cs | 5 +- src/Genocs.QueryBuilder/Expression.Int.cs | 82 ++++++++---------- src/Genocs.QueryBuilder/Expression.Numeric.cs | 84 ++++++++----------- .../Genocs.QueryBuilder.csproj | 10 +-- .../Genocs.Secrets.AzureKeyVault.csproj | 12 +-- .../Genocs.Secrets.Vault.csproj | 10 +-- src/Genocs.Security/Genocs.Security.csproj | 12 +-- .../Genocs.ServiceBusAzure.csproj | 10 +-- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 10 +-- src/Genocs.Tracing/Genocs.Tracing.csproj | 10 +-- .../Genocs.WebApi.CQRS.csproj | 10 +-- .../Genocs.WebApi.Security.csproj | 16 +--- .../Genocs.WebApi.Swagger.csproj | 20 ++--- src/Genocs.WebApi/Genocs.WebApi.csproj | 10 +-- 58 files changed, 231 insertions(+), 495 deletions(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index d642ac99..7ab2dabb 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ # These are supported funding model platforms open_collective: genocs -custom: ['https://www.buymeacoffee.com/genocs'] +custom: ["https://www.buymeacoffee.com/genocs"] diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 536d0ea1..f18640fa 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -2,9 +2,9 @@ name: Build test and pack on: push: - branches: [ main, develop ] + branches: [main, develop] pull_request: - branches: [ main, develop ] + branches: [main, develop] jobs: build: @@ -14,20 +14,20 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - + - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x - + - name: Restore dependencies run: dotnet restore - + - name: Build run: dotnet build -c Debug --no-restore - + - name: Test run: dotnet test -c Debug --no-build --verbosity normal - + - name: Pack run: dotnet pack -c Debug --no-build --verbosity normal diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml index 2b635ced..f4de01d5 100644 --- a/.github/workflows/dockerhub-publish.yml +++ b/.github/workflows/dockerhub-publish.yml @@ -13,12 +13,11 @@ on: description: "Image Version" # Default value if no value is explicitly provided - default: "6.0.0" + default: "6.1.0" # Input has to be provided for the workflow to run required: true - jobs: build: name: Publish Docker Image @@ -27,21 +26,21 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - + - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x - + - name: Restore dependencies run: dotnet restore - + - name: Build run: dotnet build -c Debug --no-restore - + - name: Test run: dotnet test --no-build --verbosity normal - + - name: Pack run: dotnet pack --no-build --verbosity normal diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 852c23c5..9f83a1fc 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -13,12 +13,11 @@ on: description: "Packages Version" # Default value if no value is explicitly provided - default: "6.0.0" + default: "6.1.0" # Input has to be provided for the workflow to run required: true - jobs: build: name: Update NuGet packages diff --git a/Directory.Build.props b/Directory.Build.props index 5b9ed5cc..c5ee0089 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,7 +9,15 @@ $(MSBuildThisFileDirectory)dotnet.ruleset True True - $(OutputPath)$(AssemblyName).xml + 10.0 + Genocs + Genocs 2024 + LICENSE + https://github.com/Genocs/genocs-library + https://github.com/Genocs/genocs-library.git + icon.png + git + True diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index fd023022..82e2ddee 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -7,18 +7,10 @@ Genocs.Auth The authorization library useful to build .NET Core projects. The authorization library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem @@ -53,8 +45,8 @@ - - + + diff --git a/src/Genocs.Common/Configurations/AppOptions.cs b/src/Genocs.Common/Configurations/AppOptions.cs index da9f08c3..79dd7851 100644 --- a/src/Genocs.Common/Configurations/AppOptions.cs +++ b/src/Genocs.Common/Configurations/AppOptions.cs @@ -15,7 +15,6 @@ public class AppOptions /// public bool Enabled { get; set; } - /// /// Application name. /// diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index b18067f9..5f71901f 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -7,18 +7,10 @@ Genocs.Common The Genocs Library - Common components. The common components to build .NET Core projects along with Genocs Library. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Common/README_NUGET.md b/src/Genocs.Common/README_NUGET.md index db3b92d4..ddab0eb4 100644 --- a/src/Genocs.Common/README_NUGET.md +++ b/src/Genocs.Common/README_NUGET.md @@ -15,45 +15,5 @@ Please check the GitHub repository getting more info. ## Release notes -### [2024-01-23] 5.0.6 -- Refactory Settings -- Updated nuget packages +Release notes can be found in the [CHANGELOG](https://github.com/Genocs/genocs-library/blob/b98629b4001aad7a2123190cfd4cc63ae7b6f292/CHANGELOG.md) file. -### [2023-11-25] 5.0.5 -- Moved to NET8 - -### [yyyy-mm-dd] 5.0.4 -- - -### [yyyy-mm-dd] 5.0.3 -- - -### [yyyy-mm-dd] 5.0.2 -- - -### [yyyy-mm-dd] 5.0.1 -- - -### [2023-11-25] 5.0.0 -- Moved to NET8 - -### [2023-10-13] 5.0.0-preview.5.0 -- Added [editorconfig](https://editorconfig.org/) -- Added StyleCop -- Updated logo -- Updated readme - -### [2023-03-12] 5.0.0-preview.4.0 -- Implemented MongoDB repository interfaces - -### [2023-03-24] 5.0.0 -- New Architecture - -### [2023-03-12] 3.1.0 -- Added Builders - -### [2023-03-12] 3.0.0 -- Refactory to implement CQRS pattern - -### [2023-03-04] 2.4.1 -- Updated System.Text.Json \ No newline at end of file diff --git a/src/Genocs.Common/Types/Extensions.cs b/src/Genocs.Common/Types/Extensions.cs index c8b82d9f..485790dd 100644 --- a/src/Genocs.Common/Types/Extensions.cs +++ b/src/Genocs.Common/Types/Extensions.cs @@ -21,7 +21,7 @@ public static class Extensions return string.Empty; } - var defaultValueCache = new Dictionary(); + var defaultValueCache = new Dictionary(); if (TryGetDefaultValue(type, out object? instance, defaultValueCache)) { @@ -32,11 +32,11 @@ public static class Extensions } public static object SetDefaultInstanceProperties(this object instance) - => SetDefaultInstanceProperties(instance, new Dictionary()); + => SetDefaultInstanceProperties(instance, new Dictionary()); - private static object SetDefaultInstanceProperties(object instance, Dictionary defaultValueCache) + private static object SetDefaultInstanceProperties(object instance, Dictionary defaultValueCache) { - defaultValueCache ??= new Dictionary(); + defaultValueCache ??= new Dictionary(); var type = instance.GetType(); @@ -51,7 +51,7 @@ private static object SetDefaultInstanceProperties(object instance, Dictionary defaultValueCache) + private static bool TryGetDefaultValue(Type type, out object? defaultValue, Dictionary defaultValueCache) { if (defaultValueCache.TryGetValue(type, out defaultValue)) { @@ -116,6 +116,7 @@ private static bool TryGetDefaultValue(Type type, out object? defaultValue, Dict return false; } + // TODO: Refactor this to remove the use of FormatterServices defaultValue = FormatterServices.GetUninitializedObject(type); defaultValueCache[type] = defaultValue; diff --git a/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs b/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs index e972d775..c38ea277 100644 --- a/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs +++ b/src/Genocs.Core.Demo.Worker/MassTransitConsoleHostedService.cs @@ -5,6 +5,7 @@ namespace Genocs.Core.Demo.Worker; /// /// General purpose worker. Please check the link below for further information /// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-7.0&tabs=visual-studio +/// . /// public class MassTransitConsoleHostedService : IHostedService { @@ -20,14 +21,18 @@ public MassTransitConsoleHostedService(IBusControl bus, ILogger(), e => //{ diff --git a/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs b/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs index a4a64469..ccb7d157 100644 --- a/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs +++ b/src/Genocs.Core/CQRS/Commands/ICommandDispatcher.cs @@ -1,19 +1,17 @@ -using System.Threading; -using System.Threading.Tasks; - namespace Genocs.Core.CQRS.Commands; /// -/// Command dispatcher interface +/// Command dispatcher interface. /// public interface ICommandDispatcher { /// - /// SendAsync + /// SendAsync. /// - /// - /// - /// - /// - Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand; + /// The type of command. + /// The command object. + /// The cancellation token. + /// The task. + Task SendAsync(T command, CancellationToken cancellationToken = default) + where T : class, ICommand; } diff --git a/src/Genocs.Core/CQRS/Events/IEventHandler.cs b/src/Genocs.Core/CQRS/Events/IEventHandler.cs index 5308d394..cf03ffbc 100644 --- a/src/Genocs.Core/CQRS/Events/IEventHandler.cs +++ b/src/Genocs.Core/CQRS/Events/IEventHandler.cs @@ -4,7 +4,8 @@ namespace Genocs.Core.CQRS.Events; /// Generic interface for CQRS Event handler. /// /// -public interface IEventHandler where TEvent : class, IEvent +public interface IEventHandler + where TEvent : class, IEvent { /// /// Standard Event handler @@ -16,10 +17,11 @@ public interface IEventHandler where TEvent : class, IEvent } /// -/// Legacy Event handler interface definition +/// Legacy Event handler interface definition. /// /// -public interface IEventHandlerLegacy where T : IEvent +public interface IEventHandlerLegacy + where T : IEvent { /// /// Legacy event handler place holder. diff --git a/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs b/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs index 8c47cba2..5e117797 100644 --- a/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs +++ b/src/Genocs.Core/CQRS/Queries/IPagedFilter.cs @@ -9,7 +9,7 @@ public interface IPagedFilter where TQuery : IQuery { /// - /// Filter + /// Filter. /// /// /// diff --git a/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs b/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs index 2ec99250..9c3f30e8 100644 --- a/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs +++ b/src/Genocs.Core/CQRS/Queries/IQueryHandler.cs @@ -8,10 +8,11 @@ namespace Genocs.Core.CQRS.Queries; /// /// /// -public interface IQueryHandler where TQuery : class, IQuery +public interface IQueryHandler + where TQuery : class, IQuery { /// - /// HandleAsync + /// HandleAsync. /// /// /// diff --git a/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs b/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs index 71ba80bf..3722f391 100644 --- a/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/CollectionExtensions.cs @@ -17,9 +17,9 @@ public static bool IsNullOrEmpty(this ICollection source) /// /// Adds an item to the collection if it's not already in the collection. /// - /// Collection - /// Item to check and add - /// Type of the items in the collection + /// Collection. + /// Item to check and add. + /// Type of the items in the collection. /// Returns True if added, returns False if not. public static bool AddIfNotContains(this ICollection source, T item) { diff --git a/src/Genocs.Core/Collections/Extensions/ListExtensions.cs b/src/Genocs.Core/Collections/Extensions/ListExtensions.cs index e6d54ebb..5738f16e 100644 --- a/src/Genocs.Core/Collections/Extensions/ListExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/ListExtensions.cs @@ -33,14 +33,13 @@ public static List SortByDependencies(this IEnumerable source, Func /// The type of the members of values. - /// Item to resolve - /// Function to resolve the dependencies - /// List with the sortet items - /// Dictionary with the visited items + /// Item to resolve. + /// Function to resolve the dependencies. + /// List with the sortet items. + /// Dictionary with the visited items. private static void SortByDependenciesVisit(T item, Func> getDependencies, List sorted, Dictionary visited) { - bool inProcess; - var alreadyVisited = visited.TryGetValue(item, out inProcess); + bool alreadyVisited = visited.TryGetValue(item, out bool inProcess); if (alreadyVisited) { diff --git a/src/Genocs.Core/Domain/Entities/AggregateRoot.cs b/src/Genocs.Core/Domain/Entities/AggregateRoot.cs index 04a2beaa..4802d2a9 100644 --- a/src/Genocs.Core/Domain/Entities/AggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/AggregateRoot.cs @@ -1,7 +1,7 @@ -//using System.Collections.Generic; -//using System.Collections.ObjectModel; -//using System.ComponentModel.DataAnnotations.Schema; -//using Genocs.Events.Bus; +// using System.Collections.Generic; +// using System.Collections.ObjectModel; +// using System.ComponentModel.DataAnnotations.Schema; +// using Genocs.Events.Bus; namespace Genocs.Core.Domain.Entities; @@ -10,7 +10,8 @@ public class AggregateRoot : AggregateRoot, IAggregateRoot } -public class AggregateRoot : Entity, IAggregateRoot +public class AggregateRoot + : Entity, IAggregateRoot { /* [NotMapped] diff --git a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs index c1988a36..7302b9a5 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs @@ -16,7 +16,7 @@ public abstract class CreationAuditedEntity : CreationAuditedEntity, IEntit /// /// This class can be used to simplify implementing . /// -/// Type of the primary key of the entity +/// Type of the primary key of the entity. [Serializable] public abstract class CreationAuditedEntity : Entity, ICreationAudited { diff --git a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs index 1c3764ba..ac66f190 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs @@ -63,25 +63,26 @@ public static void SetCreationAuditProperties( // } //} - //Finally, set CreatorUserId! + // Finally, set CreatorUserId! entity.CreatorUserId = userId; } public static void SetModificationAuditProperties( - //IMultiTenancyConfig multiTenancyConfig, + + // IMultiTenancyConfig multiTenancyConfig, object entityAsObj, int? tenantId, long? userId) { if (entityAsObj is IHasModificationTime) { - //entityAsObj.As().LastModificationTime = Clock.Now; + // entityAsObj.As().LastModificationTime = Clock.Now; entityAsObj.As().LastModificationTime = DateTime.Now; } if (!(entityAsObj is IModificationAudited)) { - //Entity does not implement IModificationAudited + // Entity does not implement IModificationAudited return; } @@ -89,7 +90,7 @@ public static void SetModificationAuditProperties( if (userId == null) { - //Unknown user + // Unknown user entity.LastModifierUserId = null; return; } @@ -100,7 +101,7 @@ public static void SetModificationAuditProperties( if (MultiTenancyHelper.IsMultiTenantEntity(entity) && !MultiTenancyHelper.IsTenantEntity(entity, tenantId)) { - //A tenant entitiy is modified by host or a different tenant + //A tenant entity is modified by host or a different tenant entity.LastModifierUserId = null; return; } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs index 294e3585..dbdcc4f4 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs @@ -19,7 +19,7 @@ public abstract class FullAuditedAggregateRoot : FullAuditedAggregateRoot public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot, IFullAudited { /// - /// Is this entity Deleted? + /// It defines whether this entity is deleted or not. /// public virtual bool IsDeleted { get; set; } @@ -44,7 +44,7 @@ public abstract class FullAuditedAggregateRoot : AuditedAggr where TUser : IEntity { /// - /// Is this entity Deleted? + /// It defines whether this entity is deleted or not. /// public virtual bool IsDeleted { get; set; } @@ -55,7 +55,7 @@ public abstract class FullAuditedAggregateRoot : AuditedAggr public virtual TUser DeleterUser { get; set; } /// - /// Which user deleted this entity? + /// Which user deleted this entity. /// public virtual long? DeleterUserId { get; set; } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs index 2d93e380..f278f98a 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs @@ -14,7 +14,7 @@ public abstract class FullAuditedEntity : FullAuditedEntity, IEntity /// /// Implements to be a base class for full-audited entities. /// -/// Type of the primary key of the entity +/// Type of the primary key of the entity. [Serializable] public abstract class FullAuditedEntity : AuditedEntity, IFullAudited { @@ -24,7 +24,7 @@ public abstract class FullAuditedEntity : AuditedEntity - /// Which user deleted this entity? + /// Which user deleted this entity. /// public virtual long? DeleterUserId { get; set; } diff --git a/src/Genocs.Core/Domain/Entities/Entity.cs b/src/Genocs.Core/Domain/Entities/Entity.cs index 3cbf8de7..4ed6c733 100644 --- a/src/Genocs.Core/Domain/Entities/Entity.cs +++ b/src/Genocs.Core/Domain/Entities/Entity.cs @@ -30,7 +30,7 @@ public abstract class Entity : IEntity /// True, if this entity is transient. public virtual bool IsTransient() { - if (EqualityComparer.Default.Equals(Id, default)) + if (EqualityComparer.Default.Equals(Id!, default!)) { return true; } @@ -50,7 +50,7 @@ public virtual bool IsTransient() } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj == null || !(obj is Entity)) { diff --git a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs index 1fd5c3ea..be8d2623 100644 --- a/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs +++ b/src/Genocs.Core/Domain/Entities/EntityNotFoundException.cs @@ -12,12 +12,12 @@ public class EntityNotFoundException : GenocsException /// /// Type of the entity. /// - public Type EntityType { get; set; } + public Type? EntityType { get; set; } /// /// Id of the Entity. /// - public object Id { get; set; } + public object? Id { get; set; } /// /// Creates a new object. diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 98c15645..8c0748e7 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -7,18 +7,10 @@ Genocs.Core The Genocs Library - Core components. The core components to build .NET Core projects along with Genocs Library. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Updated to NET8 @@ -67,12 +59,12 @@ - - - - - - - + + + + + + + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 22cd38c5..08332b6f 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -7,18 +7,10 @@ Genocs.Discovery.Consul The service discovery by Consul library useful to build .NET Core projects. The service discovery by Consul library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.HTTP.RestEase/Extensions.cs b/src/Genocs.HTTP.RestEase/Extensions.cs index d37c8ce0..81610509 100644 --- a/src/Genocs.HTTP.RestEase/Extensions.cs +++ b/src/Genocs.HTTP.RestEase/Extensions.cs @@ -32,20 +32,26 @@ public static IGenocsBuilder AddServiceClient( } var restEaseOptions = builder.GetOptions(sectionName); - return builder.AddServiceClient(serviceName, restEaseOptions, - b => b.AddFabio(fabioSectionName, consulSectionName, httpClientSectionName)); + return builder.AddServiceClient( + serviceName, + restEaseOptions, + b => b.AddFabio(fabioSectionName, consulSectionName, httpClientSectionName)); } - public static IGenocsBuilder AddServiceClient(this IGenocsBuilder builder, string serviceName, - Func buildOptions, - Func buildConsulOptions, - Func buildFabioOptions, - HttpClientOptions httpClientOptions) + public static IGenocsBuilder AddServiceClient( + this IGenocsBuilder builder, + string serviceName, + Func buildOptions, + Func buildConsulOptions, + Func buildFabioOptions, + HttpClientOptions httpClientOptions) where T : class { var options = buildOptions(new RestEaseOptionsBuilder()).Build(); - return builder.AddServiceClient(serviceName, options, - b => b.AddFabio(buildFabioOptions, buildConsulOptions, httpClientOptions)); + return builder.AddServiceClient( + serviceName, + options, + b => b.AddFabio(buildFabioOptions, buildConsulOptions, httpClientOptions)); } public static IGenocsBuilder AddServiceClient( @@ -100,7 +106,7 @@ private static void ConfigureDefaultClient( { services.AddHttpClient(clientName, client => { - var service = options.Services.SingleOrDefault(s => s.Name.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase)); + var service = options.Services?.SingleOrDefault(s => s.Name.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase)); if (service is null) { diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 1892fb7b..d020f047 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -7,18 +7,10 @@ Genocs.HTTP.RestEase The http support library useful to build .NET Core projects. The http support library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.HTTP.RestEase/RestEaseServiceNotFoundException.cs b/src/Genocs.HTTP.RestEase/RestEaseServiceNotFoundException.cs index 24964dbd..a20743ca 100644 --- a/src/Genocs.HTTP.RestEase/RestEaseServiceNotFoundException.cs +++ b/src/Genocs.HTTP.RestEase/RestEaseServiceNotFoundException.cs @@ -4,11 +4,13 @@ public class RestEaseServiceNotFoundException : Exception { public string ServiceName { get; set; } - public RestEaseServiceNotFoundException(string serviceName) : this(string.Empty, serviceName) + public RestEaseServiceNotFoundException(string serviceName) + : this(string.Empty, serviceName) { } - public RestEaseServiceNotFoundException(string message, string serviceName) : base(message) + public RestEaseServiceNotFoundException(string message, string serviceName) + : base(message) { ServiceName = serviceName; } diff --git a/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs b/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs index 6b929112..cffa804d 100644 --- a/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs +++ b/src/Genocs.HTTP.RestEase/Serializers/QueryParamSerializer.cs @@ -33,9 +33,9 @@ private IEnumerable> Serialize(string name, T va } } - private Dictionary GetPropertiesDeepRecursive(object obj, string name) + private Dictionary GetPropertiesDeepRecursive(object? obj, string name) { - var dict = new Dictionary(); + var dict = new Dictionary(); if (obj is null) { diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index b6da6319..0027c330 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -7,18 +7,10 @@ Genocs.HTTP The http support library useful to build .NET Core projects. The http support library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 5fbe8c12..6aa58a9d 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -7,18 +7,10 @@ Genocs.LoadBalancing.Fabio The load balacer based on Fabio library useful to build .NET Core projects. The load balacer based on Fabio library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index b98785fd..586e973b 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -7,18 +7,10 @@ Genocs.Logging The logging library useful to build .NET Core projects. The logging library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index f3243e6a..9c782adb 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -7,18 +7,10 @@ Genocs.MessageBrokers.Outbox.MongoDB The message brokers outbox MongoDB interface library useful to build .NET Core projects. The message brokers MongoDB outbox interface library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 7d8cff6c..ad51badd 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -7,18 +7,10 @@ Genocs.MessageBrokers.Outbox The message brokers outbox interface library useful to build .NET Core projects. The message brokers outbox interface library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index b04f3130..3de291c3 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -7,18 +7,10 @@ Genocs.MessageBrokers.RabbitMQ The message brokers RabbitMQ interface library useful to build .NET Core projects. The message brokers RabbitMQ outbox interface library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 49ee7be5..2cc030c7 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -7,18 +7,10 @@ Genocs.MessageBrokers The message brokers interface library useful to build .NET Core projects. The message brokers interface library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 665a067c..60693321 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -7,18 +7,10 @@ Genocs.Metrics The metrics interface library useful to build .NET Core projects. The metrics interface library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 2330c2f9..148ef624 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -7,18 +7,10 @@ Genocs.Monitoring Telemetry and Tracing library. Telemetry and Tracing library. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index f49782c3..8da83a96 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -7,18 +7,10 @@ Genocs.Persistence.MongoDb The Persistence MongoDB Library. The Genocs Library .NET Core to be used with MongoDB as persistence datalayer.. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git mongodb aggregate architecture boilerplate repository-patterns domain-driven-design dotnet-core microservice microservices solid solid-principles README_NUGET.md Moved to NET8.0 diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index afc1dc66..152f0eee 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -7,18 +7,10 @@ Genocs.Persistence.Redis The Persistence Redis Library. The library containing base repository pattern to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.QueryBuilder/Constants.cs b/src/Genocs.QueryBuilder/Constants.cs index 2b73c2ea..c1570a0e 100644 --- a/src/Genocs.QueryBuilder/Constants.cs +++ b/src/Genocs.QueryBuilder/Constants.cs @@ -8,17 +8,17 @@ public static class Constants /// /// Default date format. /// - public const string DATE_FORMAT = "yyyy-MM-dd"; + public const string DateFormat = "yyyy-MM-dd"; /// /// Default filtering date. /// - public const string DATE_FILTERING = "UpdatedAt"; + public const string DateFiltering = "UpdatedAt"; /// /// Default property name. /// - public const string DEFAULT_PROPERY_NAME = "IsDefault"; + public const string DefaultPropertyName = "IsDefault"; } /// diff --git a/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs b/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs index 164d0ab4..f916356b 100644 --- a/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs +++ b/src/Genocs.QueryBuilder/DynamicQueryBuilder.cs @@ -15,7 +15,7 @@ public class DynamicQueryBuilder private static readonly string GtEOperator = " gte "; private static readonly string LtEOperator = " lte "; - private static readonly string NotOperator = " not "; + // private static readonly string NotOperator = " not "; private static readonly string[] StringSeparators = new string[] { AndOperator, OrOperator, LtOperator, GtOperator, GtEOperator, LtEOperator }; #endregion @@ -33,7 +33,7 @@ public class DynamicQueryBuilder public static Expression> BuildAdvancedSearchExpressionTree(List searchItems, string sourceName) { ParameterExpression pe = Expression.Parameter(typeof(TSource), sourceName); - Expression searchExpression = null; + Expression? searchExpression = null; foreach (var searchItem in searchItems) { diff --git a/src/Genocs.QueryBuilder/Expression.Date.cs b/src/Genocs.QueryBuilder/Expression.Date.cs index 596a4754..c1ed1d24 100644 --- a/src/Genocs.QueryBuilder/Expression.Date.cs +++ b/src/Genocs.QueryBuilder/Expression.Date.cs @@ -18,20 +18,19 @@ internal static Expression GetExpressionDate(string[] searchTerms, stri { // Compose the expression tree that represents the parameter to the predicate. Expression propertyExp = pe; - foreach (var member in propertyName.Split('.')) + foreach (string? member in propertyName.Split('.')) { propertyExp = Expression.PropertyOrField(propertyExp, member); } // To do for date management - MethodCallExpression left = Expression.Call(propertyExp, typeof(DateTime).GetMethod("ToString", new Type[] { typeof(String) }), Expression.Constant(Constants.DATE_FORMAT)); + MethodCallExpression left = Expression.Call(propertyExp, typeof(DateTime).GetMethod("ToString", new Type[] { typeof(string) }), Expression.Constant(Constants.DateFormat)); var method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); ConstantExpression constantExpression = Expression.Constant(DateTime.Parse(searchTerms[0].ToLower())); var nullCheck = NormalizeNullable(propertyExp, constantExpression); - Expression searchExpression; switch (operatorType) { diff --git a/src/Genocs.QueryBuilder/Expression.Int.cs b/src/Genocs.QueryBuilder/Expression.Int.cs index bbcf560a..8a581dc3 100644 --- a/src/Genocs.QueryBuilder/Expression.Int.cs +++ b/src/Genocs.QueryBuilder/Expression.Int.cs @@ -1,57 +1,43 @@ using System.Linq.Expressions; -namespace Genocs.QueryBuilder +namespace Genocs.QueryBuilder; + +public static partial class ExpressionBuilder { - public static partial class ExpressionBuilder + /// + /// Gets the expression. + /// + /// The type of the source. + /// The search terms. + /// Name of the property. + /// The operatorType. + /// The parameter expression. + /// + internal static Expression GetExpressionInt( + string[] searchTerms, + string propertyName, + QueryOperator operatorType, + ParameterExpression pe) { - /// - /// Gets the expression. - /// - /// The type of the source. - /// The search terms. - /// Name of the property. - /// The operatorType. - /// The parameter expression. - /// - internal static Expression GetExpressionInt(string[] searchTerms, string propertyName, QueryOperator operatorType, - ParameterExpression pe) + // Compose the expression tree that represents the parameter to the predicate. + Expression propertyExp = pe; + foreach (string? member in propertyName.Split('.')) { - // Compose the expression tree that represents the parameter to the predicate. - Expression propertyExp = pe; - foreach (var member in propertyName.Split('.')) - { - propertyExp = Expression.PropertyOrField(propertyExp, member); - } - - ConstantExpression constantExpression = Expression.Constant(int.Parse(searchTerms[0].ToLower())); - - var nullCheck = NormalizeNullable(propertyExp, constantExpression); + propertyExp = Expression.PropertyOrField(propertyExp, member); + } - Expression searchExpression; - switch (operatorType) - { - case QueryOperator.GreaterThan: - searchExpression = Expression.GreaterThan(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.GreaterThanOrEqual: - searchExpression = Expression.GreaterThanOrEqual(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.LessThan: - searchExpression = Expression.LessThan(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.LessThanOrEqual: - searchExpression = Expression.LessThanOrEqual(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.NotEqual: - searchExpression = Expression.NotEqual(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.Equal: - default: - searchExpression = Expression.Equal(nullCheck.Item1, nullCheck.Item2); - break; - } + ConstantExpression constantExpression = Expression.Constant(int.Parse(searchTerms[0].ToLower())); - return searchExpression; - } + var nullCheck = NormalizeNullable(propertyExp, constantExpression); + Expression searchExpression = operatorType switch + { + QueryOperator.GreaterThan => Expression.GreaterThan(nullCheck.Item1, nullCheck.Item2), + QueryOperator.GreaterThanOrEqual => Expression.GreaterThanOrEqual(nullCheck.Item1, nullCheck.Item2), + QueryOperator.LessThan => Expression.LessThan(nullCheck.Item1, nullCheck.Item2), + QueryOperator.LessThanOrEqual => Expression.LessThanOrEqual(nullCheck.Item1, nullCheck.Item2), + QueryOperator.NotEqual => Expression.NotEqual(nullCheck.Item1, nullCheck.Item2), + _ => Expression.Equal(nullCheck.Item1, nullCheck.Item2), + }; + return searchExpression; } } \ No newline at end of file diff --git a/src/Genocs.QueryBuilder/Expression.Numeric.cs b/src/Genocs.QueryBuilder/Expression.Numeric.cs index 6dcc8931..75fbc9f3 100644 --- a/src/Genocs.QueryBuilder/Expression.Numeric.cs +++ b/src/Genocs.QueryBuilder/Expression.Numeric.cs @@ -1,60 +1,46 @@ using System.Linq.Expressions; -namespace Genocs.QueryBuilder +namespace Genocs.QueryBuilder; + +/// +/// ExpressionBuilder class for Numeric type. +/// +public static partial class ExpressionBuilder { /// - /// ExpressionBuilder class for Numeric type + /// Gets the expression. /// - public static partial class ExpressionBuilder + /// The type of the source. + /// The search terms. + /// Name of the property. + /// The operator type property. + /// The pe. + /// + internal static Expression GetExpressionNumeric( + string[] searchTerms, + string propertyName, + QueryOperator operatorType, + ParameterExpression pe) { - /// - /// Gets the expression. - /// - /// The type of the source. - /// The search terms. - /// Name of the property. - /// The operator type property. - /// The pe. - /// - internal static Expression GetExpressionNumeric(string[] searchTerms, string propertyName, QueryOperator operatorType, - ParameterExpression pe) + // Compose the expression tree that represents the parameter to the predicate. + Expression propertyExp = pe; + foreach (string? member in propertyName.Split('.')) { - // Compose the expression tree that represents the parameter to the predicate. - Expression propertyExp = pe; - foreach (var member in propertyName.Split('.')) - { - propertyExp = Expression.PropertyOrField(propertyExp, member); - } - - ConstantExpression constantExpression = Expression.Constant(decimal.Parse(searchTerms[0].ToLower())); - - var nullCheck = NormalizeNullable(propertyExp, constantExpression); + propertyExp = Expression.PropertyOrField(propertyExp, member); + } - Expression searchExpression; - switch (operatorType) - { - case QueryOperator.GreaterThan: - searchExpression = Expression.GreaterThan(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.GreaterThanOrEqual: - searchExpression = Expression.GreaterThanOrEqual(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.LessThan: - searchExpression = Expression.LessThan(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.LessThanOrEqual: - searchExpression = Expression.LessThanOrEqual(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.NotEqual: - searchExpression = Expression.NotEqual(nullCheck.Item1, nullCheck.Item2); - break; - case QueryOperator.Equal: - default: - searchExpression = Expression.Equal(nullCheck.Item1, nullCheck.Item2); - break; - } + ConstantExpression constantExpression = Expression.Constant(decimal.Parse(searchTerms[0].ToLower())); - return searchExpression; - } + var nullCheck = NormalizeNullable(propertyExp, constantExpression); + Expression searchExpression = operatorType switch + { + QueryOperator.GreaterThan => Expression.GreaterThan(nullCheck.Item1, nullCheck.Item2), + QueryOperator.GreaterThanOrEqual => Expression.GreaterThanOrEqual(nullCheck.Item1, nullCheck.Item2), + QueryOperator.LessThan => Expression.LessThan(nullCheck.Item1, nullCheck.Item2), + QueryOperator.LessThanOrEqual => Expression.LessThanOrEqual(nullCheck.Item1, nullCheck.Item2), + QueryOperator.NotEqual => Expression.NotEqual(nullCheck.Item1, nullCheck.Item2), + _ => Expression.Equal(nullCheck.Item1, nullCheck.Item2), + }; + return searchExpression; } } \ No newline at end of file diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index c66ba978..93be3849 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -7,18 +7,10 @@ Genocs.QueryBuilder The Persistence Agnostic Query Builder Library. The persistence agnostic query builder library. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index b01fb6df..fb7a6561 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -7,18 +7,10 @@ Genocs.Secrets.AzureKeyVault The Genocs Secrets AzureKeyVault library The Genocs Secrets AzureKeyVault library - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem @@ -51,7 +43,7 @@ - + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 82d4c858..a0cb3501 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -7,18 +7,10 @@ Genocs.Secrets.Vault The Genocs Secrets Vault library The Genocs Secrets Vault library - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 22911d48..7d4702db 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -7,18 +7,10 @@ Genocs.Security The Genocs Security library The Genocs Security library - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Moved tAligned to the ecosystem @@ -51,7 +43,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 4229ecf7..5f0da07c 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -7,18 +7,10 @@ Genocs.ServiceBusAzure The low level library to use Azure Service Bus. The low level library to use Azure Service Bus. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index a9fe3afe..bde5c1eb 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -7,18 +7,10 @@ Genocs.Tracing.Jaeger.RabbitMQ The load balacer based on Fabio library useful to build .NET Core projects. The load balacer based on Fabio library useful to build .NET Core projects. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index ae5c2a94..567973e1 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -7,18 +7,10 @@ Genocs.Tracing The tracing library to use Azure Service Bus. The tracing library to use Azure Service Bus. - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index e3b0e060..b90d0ceb 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -7,18 +7,10 @@ Genocs.WebApi.CQRS The web api CORS library The web api CORS library - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 8081a621..09d7e25c 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -7,18 +7,10 @@ Genocs.WebApi.Security The web api Security library The web api Security library - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem @@ -50,15 +42,15 @@ - + - + - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 3a92499e..35afb3cf 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -7,18 +7,10 @@ Genocs.WebApi.Swagger The web api Swagger library The web api Swagger library - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem @@ -50,11 +42,11 @@ - - - - - + + + + + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index e820915c..e78260a3 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -7,18 +7,10 @@ Genocs.WebApi The web api library The web api library - 10.0 true - 6.0.0 + 6.1.0 5.0.0 Nocco Giovanni Emanuele - Genocs - Genocs 2024 - LICENSE - https://github.com/Genocs/genocs-library - https://github.com/Genocs/genocs-library.git - icon.png - git aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles README_NUGET.md Aligned to the ecosystem From ab02bd7d529538eee6cf60a2926b6b889853487d Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 11 Oct 2024 12:25:19 +0200 Subject: [PATCH 075/104] Refactor README.md and remove unnecessary lines --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 53856763..e76967e0 100644 --- a/README.md +++ b/README.md @@ -553,6 +553,3 @@ Become a financial contributor and help me sustain the project. [Support the Pro ## Acknowledgements - [devmentors](https://github.com/devmentors) - [abp](https://github.com/abpframework) - - -- simple changes \ No newline at end of file From 088a59adc0da7fcb3676a9e08f43a3187ba4d9df Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 11 Oct 2024 12:31:38 +0200 Subject: [PATCH 076/104] Update package versions from 6.0.* to 6.1.* Updated all project files to change the version of various `Genocs` package references from `6.0.*` to `6.1.*`. This includes updates to `Genocs.Core`, `Genocs.Security`, `Genocs.Logging`, `Genocs.Tracing`, `Genocs.HTTP`, `Genocs.WebApi`, and many others across multiple `.csproj` files. --- src/Genocs.Auth/Genocs.Auth.csproj | 4 +-- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 4 +-- .../Genocs.Core.Demo.WebApi.csproj | 16 ++++----- .../Genocs.Core.Demo.Worker.csproj | 6 ++-- src/Genocs.Core/Genocs.Core.csproj | 2 +- .../Genocs.Discovery.Consul.csproj | 4 +-- .../Genocs.HTTP.RestEase.csproj | 8 ++--- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Genocs.LoadBalancing.Fabio.csproj | 6 ++-- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 4 +-- .../Genocs.MessageBrokers.Outbox.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- .../Genocs.MessageBrokers.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- .../Genocs.Monitoring.csproj | 6 ++-- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +-- .../Genocs.Secrets.AzureKeyVault.csproj | 2 +- .../Genocs.Secrets.Vault.csproj | 2 +- src/Genocs.Security/Genocs.Security.csproj | 2 +- .../Genocs.ServiceBusAzure.csproj | 2 +- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 4 +-- src/Genocs.Tracing/Genocs.Tracing.csproj | 6 ++-- .../Genocs.WebApi.CQRS.csproj | 4 +-- .../Genocs.WebApi.Security.csproj | 2 +- .../Genocs.WebApi.Swagger.csproj | 2 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 2 +- .../Genocs.APIGateway.csproj | 12 +++---- .../Genocs.Identities.Application.csproj | 20 +++++------ .../Genocs.Orders.WebApi.csproj | 22 ++++++------ .../Genocs.Products.WebApi.csproj | 32 ++++++++--------- .../Genocs.SignalR.WebApi.csproj | 34 +++++++++---------- 36 files changed, 116 insertions(+), 116 deletions(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 82e2ddee..aa7ec6a9 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -40,8 +40,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index d001a674..639522b5 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index f5b7f799..33d46865 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 45a9c66b..6d6f86d5 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -21,14 +21,14 @@ - - - - - - - - + + + + + + + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index a46a22f4..67cfc695 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 8c0748e7..d4c19157 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 08332b6f..44a28276 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -40,8 +40,8 @@ - - + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index d020f047..93c8142e 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -42,10 +42,10 @@ - - - - + + + + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 0027c330..d57210c6 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 6aa58a9d..6186974a 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -41,9 +41,9 @@ - - - + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 586e973b..434522f8 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 9c782adb..d154f4d3 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -39,8 +39,8 @@ - - + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index ad51badd..9144b14b 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 3de291c3..f64335c3 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 2cc030c7..5eded034 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 60693321..e0f95051 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 148ef624..7f19478e 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -41,9 +41,9 @@ - - - + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 05dc26a2..24b7e8cd 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 8da83a96..1157d59a 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 152f0eee..0f42539f 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 5d60af40..049acdbf 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index fb7a6561..cc4f02e0 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index a0cb3501..23d31571 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 7d4702db..d38ccf63 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 5f0da07c..da978712 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index bde5c1eb..2867c20d 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -39,8 +39,8 @@ - - + + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 567973e1..65bb7483 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -40,9 +40,9 @@ - - - + + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index b90d0ceb..5c1a7016 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -39,7 +39,7 @@ - - + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 09d7e25c..8dbcaecf 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 35afb3cf..04a6326d 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index e78260a3..12e0364f 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 530f5ee8..cc13bce9 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -19,12 +19,12 @@ - - - - - - + + + + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 782eb9a7..524bea46 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -20,16 +20,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 3655f8d5..da482f0d 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -29,17 +29,17 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index d567ae87..033e4e8b 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -30,22 +30,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 8b977205..53ca28cb 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -34,22 +34,22 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file From a1e01bb0634de8d38a869fb0b75ed530cd42f1db Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 11 Oct 2024 13:17:15 +0200 Subject: [PATCH 077/104] Update various NuGet packages across multiple projects Updated the following packages: - `Roslynator.Analyzers` from `4.12.4` to `4.12.7` in `Directory.Build.props`. - `Swashbuckle.AspNetCore` from `6.7.3` to `6.8.1` in `Genocs.Core.Demo.WebApi.csproj`. - `Microsoft.NET.Test.Sdk` from `17.11.0` to `17.11.1` and `xunit` from `2.9.0` to `2.9.2` in `Genocs.Core.UnitTests.csproj`. - `Scrutor` from `4.2.2` to `5.0.1` in `Genocs.Core.csproj`. - `Microsoft.Extensions.Http` from `8.0.0` to `8.0.1` and `Polly` from `8.4.1` to `8.4.2` in `Genocs.HTTP.csproj`. - `Serilog.AspNetCore` from `8.0.2` to `8.0.3` in `Genocs.Logging.csproj`. - `Polly` from `8.4.1` to `8.4.2` in `Genocs.MessageBrokers.RabbitMQ.csproj`. - `prometheus-net.DotNetRuntime` from `4.4.0` to `4.4.1` in `Genocs.Metrics.csproj`. - `Microsoft.Extensions.Configuration.UserSecrets` from `8.0.0` to `8.0.1`, `Microsoft.NET.Test.Sdk` from `17.11.0` to `17.11.1`, `Moq` from `4.20.70` to `4.20.72`, and `xunit` from `2.9.0` to `2.9.2` in `Genocs.Persistence.MongoDB.UnitTests.csproj`. - `MongoDB.Driver` from `2.28.0` to `2.29.0` in `Genocs.Persistence.MongoDb.csproj`. - `Microsoft.NET.Test.Sdk` from `17.11.0` to `17.11.1`, `Moq` from `4.20.70` to `4.20.72`, and `xunit` from `2.9.0` to `2.9.2` in `Genocs.QueryBuilder.UnitTests.csproj`. - `VaultSharp` from `1.13.0.1` to `1.17.5.1` in `Genocs.Secrets.Vault.csproj`. - `Microsoft.NET.Test.Sdk` from `17.11.0` to `17.11.1` and `xunit` from `2.9.0` to `2.9.2` in `Genocs.ServiceBusAzure.UnitTests.csproj`. - `Microsoft.Extensions.Logging.Abstractions` from `7.0.0` to `8.0.2` in `Genocs.ServiceBusAzure.csproj`. - `Yarp.ReverseProxy` from `2.1.0` to `2.2.0` in `Genocs.APIGateway.csproj`. --- Directory.Build.props | 2 +- .../Genocs.Core.Demo.WebApi.csproj | 2 +- src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj | 4 ++-- src/Genocs.Core/Genocs.Core.csproj | 2 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 4 ++-- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- .../Genocs.Persistence.MongoDB.UnitTests.csproj | 8 ++++---- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 6 +++--- src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj | 2 +- .../Genocs.ServiceBusAzure.UnitTests.csproj | 4 ++-- src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj | 2 +- .../Genocs.APIGateway/Genocs.APIGateway.csproj | 2 +- 15 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c5ee0089..29076434 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -21,7 +21,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 6d6f86d5..02433777 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -33,7 +33,7 @@ - + diff --git a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj index 5ef98b31..99505860 100644 --- a/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj +++ b/src/Genocs.Core.UnitTests/Genocs.Core.UnitTests.csproj @@ -7,8 +7,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index d4c19157..1baea312 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index d57210c6..af490a73 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -42,8 +42,8 @@ - - + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 434522f8..bfc32b75 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index f64335c3..763ff798 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index e0f95051..97f76b06 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -70,7 +70,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 24b7e8cd..6c646282 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -8,11 +8,11 @@ - + - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 1157d59a..164bb4ab 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -42,7 +42,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 049acdbf..4f2e8021 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -11,10 +11,10 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 23d31571..7eb9325d 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -43,6 +43,6 @@ - + diff --git a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj index 08e96a41..bc90559c 100644 --- a/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj +++ b/src/Genocs.ServiceBusAzure.UnitTests/Genocs.ServiceBusAzure.UnitTests.csproj @@ -7,8 +7,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index da978712..75e56183 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -44,7 +44,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index cc13bce9..1ac971d7 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -28,7 +28,7 @@ - + From 1eed44bd91c9b187bcc1a2d3983ebe52b20e0664 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 11 Oct 2024 16:25:59 +0200 Subject: [PATCH 078/104] Refactor: Replace Jaeger with OpenTelemetry Removed Jaeger-related code and dependencies across multiple files. Added OpenTelemetry SDK and updated configurations accordingly. Refactored methods and classes to improve parameter formatting and added nullability annotations. Updated service registration and configuration files to reflect these changes. --- containers/infrastructure-monitoring.yml | 1 + src/Genocs.Core/Builders/Extensions.cs | 1 - .../IRabbitMqClient.cs | 10 +- src/Genocs.Tracing/Extensions.cs | 200 ++++++++---------- src/Genocs.Tracing/Genocs.Tracing.csproj | 7 +- .../Jaeger/Builders/JaegerOptionsBuilder.cs | 16 +- .../Configurations/IJaegerOptionsBuilder.cs | 4 +- .../Jaeger/Configurations/JaegerOptions.cs | 21 +- src/Genocs.Tracing/Jaeger/Extensions.cs | 94 -------- .../Jaeger/RabbitMQ/Extensions.cs | 13 -- .../Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs | 71 ------- .../Jaeger/Tracers/GenocsDefaultTracer.cs | 16 -- .../Exceptions/ErrorHandlerMiddleware.cs | 8 +- .../Framework/MessagingMiddleware.cs | 37 ++-- .../api-gateway/Genocs.APIGateway/Startup.cs | 3 +- .../Genocs.APIGateway/appsettings.json | 9 +- .../Commands/Handlers/CreateOrderHandler.cs | 6 +- .../orders/Genocs.Orders.WebApi/Program.cs | 3 +- .../Genocs.Orders.WebApi/appsettings.json | 7 +- .../Commands/Handlers/CreateProductHandler.cs | 6 +- .../Genocs.Products.WebApi/Program.cs | 3 +- .../Handlers/PublishNotificationHandler.cs | 7 +- 22 files changed, 141 insertions(+), 402 deletions(-) delete mode 100644 src/Genocs.Tracing/Jaeger/RabbitMQ/Extensions.cs delete mode 100644 src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs delete mode 100644 src/Genocs.Tracing/Jaeger/Tracers/GenocsDefaultTracer.cs diff --git a/containers/infrastructure-monitoring.yml b/containers/infrastructure-monitoring.yml index 7e9bcdcf..6eeedab9 100644 --- a/containers/infrastructure-monitoring.yml +++ b/containers/infrastructure-monitoring.yml @@ -35,6 +35,7 @@ services: - 9411:9411 - 14268:14268 - 16686:16686 + - 4317:4317 # network_mode: host networks: - genocs diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs index 8436b812..10638e44 100644 --- a/src/Genocs.Core/Builders/Extensions.cs +++ b/src/Genocs.Core/Builders/Extensions.cs @@ -50,7 +50,6 @@ public static IApplicationBuilder UseGenocs(this IApplicationBuilder app) using var scope = app.ApplicationServices.CreateScope(); var initializer = scope.ServiceProvider.GetRequiredService(); Task.Run(() => initializer.InitializeAsync()).GetAwaiter().GetResult(); - return app; } diff --git a/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs b/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs index f9c773e6..b7d4e687 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/IRabbitMqClient.cs @@ -2,6 +2,12 @@ namespace Genocs.MessageBrokers.RabbitMQ; public interface IRabbitMQClient { - void Send(object message, IConventions conventions, string? messageId = null, string? correlationId = null, - string? spanContext = null, object? messageContext = null, IDictionary headers = null); + void Send( + object? message, + IConventions conventions, + string? messageId = null, + string? correlationId = null, + string? spanContext = null, + object? messageContext = null, + IDictionary? headers = null); } \ No newline at end of file diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index 75c312e6..ca83b547 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -3,8 +3,6 @@ using Genocs.Core.Builders; using Genocs.Logging.Configurations; using Genocs.Tracing.Jaeger.Configurations; -using Jaeger.Samplers; -using Jaeger.Senders.Thrift; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using OpenTelemetry; @@ -28,143 +26,113 @@ public static class Extensions public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) { - var appOptions = builder.GetOptions(AppOptions.Position); + AppOptions options = builder.GetOptions(AppOptions.Position); // No OpenTelemetryTracing in case of missing ServiceName - if (string.IsNullOrWhiteSpace(appOptions.Service)) + if (string.IsNullOrWhiteSpace(options.Service)) { return builder; } + //builder.Logging.AddOpenTelemetry(logging => + //{ + // logging.IncludeFormattedMessage = true; + // logging.IncludeScopes = true; + //}); + var services = builder.Services; // Set Custom Open telemetry - services.AddOpenTelemetry().WithTracing(x => - { - TracerProviderBuilder provider = x.SetResourceBuilder(ResourceBuilder.CreateDefault() - .AddService(appOptions.Service) - .AddTelemetrySdk() - .AddEnvironmentVariableDetector()) - .AddSource("*"); - - var loggerOptions = builder.GetOptions(LoggerOptions.Position); - - // No OpenTelemetryTracing in case of missing LoggerSettings - if (loggerOptions != null) + services.AddOpenTelemetry() + .WithTracing(x => { - if (loggerOptions.Mongo != null && loggerOptions.Mongo.Enabled) + TracerProviderBuilder provider = x.SetResourceBuilder(ResourceBuilder.CreateDefault() + .AddService(serviceName: options.Service, serviceVersion: options.Version, serviceInstanceId: options.Instance) + .AddTelemetrySdk() + .AddEnvironmentVariableDetector()) + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddSource("*"); + + var loggerOptions = builder.GetOptions(LoggerOptions.Position); + + // No OpenTelemetryTracing in case of missing LoggerSettings + if (loggerOptions != null) { - // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry NuGet package - provider.AddMongoDBInstrumentation(); - } + if (loggerOptions.Mongo != null && loggerOptions.Mongo.Enabled) + { + // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry NuGet package + provider.AddMongoDBInstrumentation(); + } - // Check for Console config - if (loggerOptions.Console != null && loggerOptions.Console.Enabled) - { - // you should add OpenTelemetry.Exporter.Console NuGet package - provider.AddConsoleExporter(); - } + // Check for Console config + if (loggerOptions.Console != null && loggerOptions.Console.Enabled) + { + // you should add OpenTelemetry.Exporter.Console NuGet package + // Any OTEL supportable exporter can be used here + provider.AddConsoleExporter(); + } - // Check for Azure ApplicationInsights config - if (loggerOptions.Azure != null && loggerOptions.Azure.Enabled) - { - provider.AddAzureMonitorTraceExporter(o => + // Check for Azure ApplicationInsights config + if (loggerOptions.Azure != null && loggerOptions.Azure.Enabled) { - o.ConnectionString = loggerOptions.Azure.ConnectionString; - }); + provider.AddAzureMonitorTraceExporter(o => + { + o.ConnectionString = loggerOptions.Azure.ConnectionString; + }); + } } - } - var jaegerOptions = builder.GetOptions(JaegerOptions.Position); + var jaegerOptions = builder.GetOptions(JaegerOptions.Position); - if (jaegerOptions != null && jaegerOptions.Enabled) - { - - provider.AddJaegerExporter(o => + if (jaegerOptions != null && jaegerOptions.Enabled) { - o.AgentHost = jaegerOptions.UdpHost; - o.AgentPort = jaegerOptions.UdpPort; - o.MaxPayloadSizeInBytes = jaegerOptions.MaxPacketSize; - o.ExportProcessorType = ExportProcessorType.Batch; - o.BatchExportProcessorOptions = new BatchExportProcessorOptions - { - MaxQueueSize = 2048, - ScheduledDelayMilliseconds = 5000, - ExporterTimeoutMilliseconds = 30000, - MaxExportBatchSize = 512, - }; - }); - } - - /* - Action appResourceBuilder = - resource => resource - .AddDetector(new ContainerResourceDetector()); - - builder.Services.AddOpenTelemetry() - .ConfigureResource(appResourceBuilder) - .WithTracing(tracerBuilder => tracerBuilder - .AddRedisInstrumentation( - cartStore.GetConnection(), - options => options.SetVerboseDatabaseStatements = true) - .AddAspNetCoreInstrumentation() - .AddGrpcClientInstrumentation() - .AddHttpClientInstrumentation() - .AddOtlpExporter()) - .WithMetrics(meterBuilder => meterBuilder - .AddRuntimeInstrumentation() - .AddAspNetCoreInstrumentation() - .AddOtlpExporter()); - */ - }); - - return builder; - } - private static ISampler GetSampler(JaegerOptions options) - { - switch (options.Sampler) - { - case "const": return new ConstSampler(true); - case "rate": return new RateLimitingSampler(options.MaxTracesPerSecond); - case "probabilistic": return new ProbabilisticSampler(options.SamplingRate); - default: return new ConstSampler(true); - } - } - - private static HttpSender BuildHttpSender(JaegerOptions.HttpSenderSettings? options) - { - if (options is null) - { - throw new Exception("Missing Jaeger HTTP sender options."); - } - - if (string.IsNullOrWhiteSpace(options.Endpoint)) - { - throw new Exception("Missing Jaeger HTTP sender endpoint."); - } + provider.AddOtlpExporter(o => + { + o.Endpoint = new Uri(jaegerOptions.Endpoint); + o.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc; + o.ExportProcessorType = ExportProcessorType.Batch; + o.BatchExportProcessorOptions = new BatchExportProcessorOptions + { + MaxQueueSize = 2048, + ScheduledDelayMilliseconds = 5000, + ExporterTimeoutMilliseconds = 30000, + MaxExportBatchSize = 512, + }; + }); + } - var builder = new HttpSender.Builder(options.Endpoint); - if (options.MaxPacketSize > 0) - { - builder = builder.WithMaxPacketSize(options.MaxPacketSize); - } + /* + Action appResourceBuilder = + resource => resource + .AddDetector(new ContainerResourceDetector()); + + builder.Services.AddOpenTelemetry() + .ConfigureResource(appResourceBuilder) + .WithTracing(tracerBuilder => tracerBuilder + .AddRedisInstrumentation( + cartStore.GetConnection(), + options => options.SetVerboseDatabaseStatements = true) + .AddAspNetCoreInstrumentation() + .AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation() + .AddOtlpExporter()) + + */ + }).WithMetrics(x => + { + MeterProviderBuilder provider = x.SetResourceBuilder(ResourceBuilder.CreateDefault()); - if (!string.IsNullOrWhiteSpace(options.AuthToken)) - { - builder = builder.WithAuth(options.AuthToken); - } + provider.AddConsoleExporter(); + provider.AddAspNetCoreInstrumentation(); - if (!string.IsNullOrWhiteSpace(options.Username) && !string.IsNullOrWhiteSpace(options.Password)) - { - builder = builder.WithAuth(options.Username, options.Password); - } + // provider.AddRuntimeInstrumentation(); + provider.AddHttpClientInstrumentation(); + provider.AddOtlpExporter(); - if (!string.IsNullOrWhiteSpace(options.UserAgent)) - { - builder = builder.WithUserAgent(options.Username); - } + }); - return builder.Build(); + return builder; } } diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 65bb7483..b57fefa4 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -45,17 +45,14 @@ - - - - - + + diff --git a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs index 7bb3b3de..efc28585 100644 --- a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs @@ -18,15 +18,9 @@ public IJaegerOptionsBuilder WithServiceName(string serviceName) return this; } - public IJaegerOptionsBuilder WithUdpHost(string udpHost) + public IJaegerOptionsBuilder WithEndpoint(string endpoint) { - _options.UdpHost = udpHost; - return this; - } - - public IJaegerOptionsBuilder WithUdpPort(int udpPort) - { - _options.UdpPort = udpPort; + _options.Endpoint = endpoint; return this; } @@ -36,12 +30,6 @@ public IJaegerOptionsBuilder WithMaxPacketSize(int maxPacketSize) return this; } - public IJaegerOptionsBuilder WithSampler(string sampler) - { - _options.Sampler = sampler; - return this; - } - public IJaegerOptionsBuilder WithMaxTracesPerSecond(double maxTracesPerSecond) { _options.MaxTracesPerSecond = maxTracesPerSecond; diff --git a/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs index e19ae13a..1aa640b8 100644 --- a/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs @@ -4,10 +4,8 @@ public interface IJaegerOptionsBuilder { IJaegerOptionsBuilder Enable(bool enabled); IJaegerOptionsBuilder WithServiceName(string serviceName); - IJaegerOptionsBuilder WithUdpHost(string udpHost); - IJaegerOptionsBuilder WithUdpPort(int udpPort); + IJaegerOptionsBuilder WithEndpoint(string endpoint); IJaegerOptionsBuilder WithMaxPacketSize(int maxPacketSize); - IJaegerOptionsBuilder WithSampler(string sampler); IJaegerOptionsBuilder WithMaxTracesPerSecond(double maxTracesPerSecond); IJaegerOptionsBuilder WithSamplingRate(double samplingRate); JaegerOptions Build(); diff --git a/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs b/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs index b1d9c379..e1ab1ee8 100644 --- a/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs @@ -16,23 +16,12 @@ public class JaegerOptions public bool Enabled { get; set; } public string? ServiceName { get; set; } - public string? UdpHost { get; set; } - public int UdpPort { get; set; } + + /// + /// The Jaeger agent endpoint. + /// + public string Endpoint { get; set; } = "http://localhost:4317"; public int MaxPacketSize { get; set; } = 64967; - public string? Sampler { get; set; } public double MaxTracesPerSecond { get; set; } = 5; public double SamplingRate { get; set; } = 0.2; - public IEnumerable? ExcludePaths { get; set; } - public string? Sender { get; set; } - public HttpSenderSettings? HttpSender { get; set; } - - public class HttpSenderSettings - { - public string? Endpoint { get; set; } - public string? AuthToken { get; set; } - public string? Username { get; set; } - public string? Password { get; set; } - public string? UserAgent { get; set; } - public int MaxPacketSize { get; set; } = 1048576; - } } \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/Extensions.cs b/src/Genocs.Tracing/Jaeger/Extensions.cs index a5aa4065..70fa74c0 100644 --- a/src/Genocs.Tracing/Jaeger/Extensions.cs +++ b/src/Genocs.Tracing/Jaeger/Extensions.cs @@ -1,16 +1,7 @@ using Genocs.Core.Builders; using Genocs.Tracing.Jaeger.Configurations; -using Genocs.Tracing.Jaeger.Tracers; -using Jaeger; -using Jaeger.Reporters; -using Jaeger.Samplers; -using Jaeger.Senders; -using Jaeger.Senders.Thrift; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using OpenTracing; -using OpenTracing.Util; namespace Genocs.Tracing.Jaeger; @@ -20,7 +11,6 @@ namespace Genocs.Tracing.Jaeger; public static class Extensions { private static int _initialized; - private const string RegistryName = "tracing.jaeger"; /// /// Add Jaeger Tracer. @@ -42,85 +32,12 @@ public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string secti if (!options.Enabled) { - var defaultTracer = GenocsDefaultTracer.Create(); - builder.Services.AddSingleton(defaultTracer); return builder; } - if (!builder.TryRegister(RegistryName)) - { - return builder; - } - - builder.Services.AddSingleton(sp => - { - var loggerFactory = sp.GetRequiredService(); - int maxPacketSize = options.MaxPacketSize <= 0 ? 64967 : options.MaxPacketSize; - string? senderType = string.IsNullOrWhiteSpace(options.Sender) ? "udp" : options.Sender?.ToLowerInvariant(); - ISender sender = senderType switch - { - "http" => BuildHttpSender(options.HttpSender), - "udp" => new UdpSender(options.UdpHost, options.UdpPort, maxPacketSize), - _ => throw new Exception($"Invalid Jaeger sender type: '{senderType}'.") - }; - - var reporter = new RemoteReporter.Builder() - .WithSender(sender) - .WithLoggerFactory(loggerFactory) - .Build(); - - var sampler = GetSampler(options); - - var tracer = new Tracer.Builder(options.ServiceName) - .WithLoggerFactory(loggerFactory) - .WithReporter(reporter) - .WithSampler(sampler) - .Build(); - - GlobalTracer.Register(tracer); - - return tracer; - }); - return builder; } - private static HttpSender BuildHttpSender(JaegerOptions.HttpSenderSettings? options) - { - if (options is null) - { - throw new Exception("Missing Jaeger HTTP sender options."); - } - - if (string.IsNullOrWhiteSpace(options.Endpoint)) - { - throw new Exception("Missing Jaeger HTTP sender endpoint."); - } - - var builder = new HttpSender.Builder(options.Endpoint); - if (options.MaxPacketSize > 0) - { - builder = builder.WithMaxPacketSize(options.MaxPacketSize); - } - - if (!string.IsNullOrWhiteSpace(options.AuthToken)) - { - builder = builder.WithAuth(options.AuthToken); - } - - if (!string.IsNullOrWhiteSpace(options.Username) && !string.IsNullOrWhiteSpace(options.Password)) - { - builder = builder.WithAuth(options.Username, options.Password); - } - - if (!string.IsNullOrWhiteSpace(options.UserAgent)) - { - builder = builder.WithUserAgent(options.Username); - } - - return builder.Build(); - } - public static IApplicationBuilder UseJaeger(this IApplicationBuilder app) { // Could be extended with some additional middleware @@ -129,15 +46,4 @@ public static IApplicationBuilder UseJaeger(this IApplicationBuilder app) return app; } - - private static ISampler GetSampler(JaegerOptions options) - { - return options.Sampler switch - { - "const" => new ConstSampler(true), - "rate" => new RateLimitingSampler(options.MaxTracesPerSecond), - "probabilistic" => new ProbabilisticSampler(options.SamplingRate), - _ => new ConstSampler(true), - }; - } } \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/RabbitMQ/Extensions.cs b/src/Genocs.Tracing/Jaeger/RabbitMQ/Extensions.cs deleted file mode 100644 index 2b53101a..00000000 --- a/src/Genocs.Tracing/Jaeger/RabbitMQ/Extensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Genocs.MessageBrokers.RabbitMQ; -using Genocs.Tracing.Jaeger.RabbitMQ.Plugins; - -namespace Genocs.Tracing.Jaeger.RabbitMQ; - -public static class Extensions -{ - public static IRabbitMqPluginsRegistry AddJaegerRabbitMqPlugin(this IRabbitMqPluginsRegistry registry) - { - registry.Add(); - return registry; - } -} \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs b/src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs deleted file mode 100644 index 5ce191a8..00000000 --- a/src/Genocs.Tracing/Jaeger/RabbitMQ/Plugins/JaegerPlugin.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Genocs.Core.Extensions; -using Genocs.MessageBrokers.RabbitMQ; -using Jaeger; -using OpenTracing; -using OpenTracing.Tag; -using RabbitMQ.Client.Events; -using System.Text; - -namespace Genocs.Tracing.Jaeger.RabbitMQ.Plugins; - -internal sealed class JaegerPlugin : RabbitMQPlugin -{ - private readonly ITracer _tracer; - private readonly string _spanContextHeader; - - public JaegerPlugin(ITracer tracer, RabbitMQOptions options) - { - _tracer = tracer; - _spanContextHeader = options.GetSpanContextHeader(); - } - - public override async Task HandleAsync( - object message, - object correlationContext, - BasicDeliverEventArgs args) - { - string messageName = message.GetType().Name.Underscore(); - string messageId = args.BasicProperties.MessageId; - string spanContext = string.Empty; - - if (args.BasicProperties.Headers is { } && - args.BasicProperties.Headers.TryGetValue(_spanContextHeader, out object? spanContextHeader) && - spanContextHeader is byte[] spanContextBytes) - { - spanContext = Encoding.UTF8.GetString(spanContextBytes); - } - - using var scope = BuildScope(messageName, spanContext); - var span = scope.Span; - span.Log($"Started processing a message: '{messageName}' [id: '{messageId}']."); - try - { - await Next(message, correlationContext, args); - } - catch (Exception ex) - { - span.SetTag(Tags.Error, true); - span.Log(ex.Message); - } - - span.Log($"Finished processing a message: '{messageName}' [id: '{messageId}']."); - } - - private IScope BuildScope(string messageName, string serializedSpanContext) - { - var spanBuilder = _tracer - .BuildSpan($"processing-{messageName}") - .WithTag("message-type", messageName); - - if (string.IsNullOrEmpty(serializedSpanContext)) - { - return spanBuilder.StartActive(true); - } - - var spanContext = SpanContext.ContextFromString(serializedSpanContext); - - return spanBuilder - .AddReference(References.FollowsFrom, spanContext) - .StartActive(true); - } -} \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/Tracers/GenocsDefaultTracer.cs b/src/Genocs.Tracing/Jaeger/Tracers/GenocsDefaultTracer.cs deleted file mode 100644 index a257f619..00000000 --- a/src/Genocs.Tracing/Jaeger/Tracers/GenocsDefaultTracer.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Jaeger; -using Jaeger.Reporters; -using Jaeger.Samplers; -using OpenTracing; -using System.Reflection; - -namespace Genocs.Tracing.Jaeger.Tracers; - -internal sealed class GenocsDefaultTracer -{ - public static ITracer Create() - => new Tracer.Builder(Assembly.GetEntryAssembly().FullName) - .WithReporter(new NoopReporter()) - .WithSampler(new ConstSampler(false)) - .Build(); -} \ No newline at end of file diff --git a/src/Genocs.WebApi/Exceptions/ErrorHandlerMiddleware.cs b/src/Genocs.WebApi/Exceptions/ErrorHandlerMiddleware.cs index f2e23ee0..ba4e01e1 100644 --- a/src/Genocs.WebApi/Exceptions/ErrorHandlerMiddleware.cs +++ b/src/Genocs.WebApi/Exceptions/ErrorHandlerMiddleware.cs @@ -11,8 +11,10 @@ internal sealed class ErrorHandlerMiddleware : IMiddleware private readonly IJsonSerializer _jsonSerializer; private readonly ILogger _logger; - public ErrorHandlerMiddleware(IExceptionToResponseMapper exceptionToResponseMapper, - IJsonSerializer jsonSerializer, ILogger logger) + public ErrorHandlerMiddleware( + IExceptionToResponseMapper exceptionToResponseMapper, + IJsonSerializer jsonSerializer, + ILogger logger) { _exceptionToResponseMapper = exceptionToResponseMapper; _jsonSerializer = jsonSerializer; @@ -36,7 +38,7 @@ private async Task HandleErrorAsync(HttpContext context, Exception exception) { var exceptionResponse = _exceptionToResponseMapper.Map(exception); context.Response.StatusCode = (int)(exceptionResponse?.StatusCode ?? HttpStatusCode.BadRequest); - var response = exceptionResponse?.Response; + object? response = exceptionResponse?.Response; if (response is null) { await context.Response.WriteAsync(string.Empty); diff --git a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs index d9665a2b..9c97684a 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Framework/MessagingMiddleware.cs @@ -1,10 +1,9 @@ +using System.Collections.Concurrent; using Genocs.APIGateway.Configurations; using Genocs.MessageBrokers.RabbitMQ; using Genocs.MessageBrokers.RabbitMQ.Conventions; using Microsoft.Extensions.Options; using Newtonsoft.Json; -using OpenTracing; -using System.Collections.Concurrent; namespace Genocs.APIGateway.Framework; @@ -13,7 +12,6 @@ internal class MessagingMiddleware : IMiddleware private static readonly ConcurrentDictionary Conventions = new(); private readonly IRabbitMQClient _rabbitMQClient; private readonly RouteMatcher _routeMatcher; - private readonly ITracer _tracer; private readonly ICorrelationContextBuilder _correlationContextBuilder; private readonly CorrelationIdFactory _correlationIdFactory; private readonly IDictionary> _endpoints; @@ -21,7 +19,6 @@ internal class MessagingMiddleware : IMiddleware public MessagingMiddleware( IRabbitMQClient rabbitMQClient, RouteMatcher routeMatcher, - ITracer tracer, ICorrelationContextBuilder correlationContextBuilder, CorrelationIdFactory correlationIdFactory, IOptions messagingOptions) @@ -33,7 +30,6 @@ public MessagingMiddleware( _rabbitMQClient = rabbitMQClient ?? throw new ArgumentNullException(nameof(rabbitMQClient)); _routeMatcher = routeMatcher ?? throw new ArgumentNullException(nameof(routeMatcher)); - _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); _correlationContextBuilder = correlationContextBuilder ?? throw new ArgumentNullException(nameof(correlationContextBuilder)); _correlationIdFactory = correlationIdFactory ?? throw new ArgumentNullException(nameof(correlationIdFactory)); _endpoints = messagingOptions.Value.Endpoints?.Any() is true @@ -65,16 +61,29 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next) Conventions.TryAdd(key, conventions); } - var spanContext = _tracer.ActiveSpan is null ? string.Empty : _tracer.ActiveSpan.Context.ToString(); - var messageId = Guid.NewGuid().ToString("N"); - var correlationId = _correlationIdFactory.Create(); - var resourceId = Guid.NewGuid().ToString("N"); - var correlationContext = _correlationContextBuilder.Build(context, correlationId, spanContext, - endpoint.RoutingKey, resourceId); + string? spanContext = "TODO: Genocs"; + string messageId = Guid.NewGuid().ToString("N"); + string correlationId = _correlationIdFactory.Create(); + string resourceId = Guid.NewGuid().ToString("N"); + + var correlationContext = _correlationContextBuilder.Build( + context, + correlationId, + spanContext, + endpoint.RoutingKey, + resourceId); + + string content = await new StreamReader(context.Request.Body).ReadToEndAsync(); + object? message = JsonConvert.DeserializeObject(content); + + _rabbitMQClient.Send( + message, + conventions, + messageId, + correlationId, + spanContext, + correlationContext); - var content = await new StreamReader(context.Request.Body).ReadToEndAsync(); - var message = JsonConvert.DeserializeObject(content); - _rabbitMQClient.Send(message, conventions, messageId, correlationId, spanContext, correlationContext); context.Response.StatusCode = StatusCodes.Status202Accepted; return; } diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index 8810e46a..2e6d5ded 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -8,7 +8,6 @@ using Genocs.Security; using Genocs.Tracing; using Genocs.Tracing.Jaeger; -using Genocs.Tracing.Jaeger.RabbitMQ; using Genocs.WebApi; using Yarp.ReverseProxy.Forwarder; @@ -42,7 +41,7 @@ public void ConfigureServices(IServiceCollection services) .AddJaeger() .AddJwt() .AddPrometheus() - .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) + .AddRabbitMq() .AddSecurity() .AddWebApi() .Build(); diff --git a/src/apps/api-gateway/Genocs.APIGateway/appsettings.json b/src/apps/api-gateway/Genocs.APIGateway/appsettings.json index 58a302ed..fc009e6c 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/appsettings.json +++ b/src/apps/api-gateway/Genocs.APIGateway/appsettings.json @@ -11,14 +11,7 @@ "enabled": true, "serviceName": "api-gateway", "udpHost": "localhost", - "udpPort": 6831, - "maxPacketSize": 65000, - "sampler": "const", - "excludePaths": [ - "/", - "/ping", - "/metrics" - ] + "maxPacketSize": 65000 }, "jwt": { "certificate": { diff --git a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs index bf191760..80dcac2a 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs @@ -5,7 +5,6 @@ using Genocs.Orders.WebApi.Events; using Genocs.Orders.WebApi.Services; using Genocs.Persistence.MongoDb.Repositories.Mentor; -using OpenTracing; namespace Genocs.Orders.WebApi.Commands.Handlers; @@ -16,21 +15,18 @@ public class CreateOrderHandler : ICommandHandler private readonly IMessageOutbox _outbox; private readonly IProductServiceClient _productServiceClient; private readonly ILogger _logger; - private readonly ITracer _tracer; public CreateOrderHandler( IMongoRepository repository, IBusPublisher publisher, IMessageOutbox outbox, IProductServiceClient productServiceClient, - ITracer tracer, ILogger logger) { _repository = repository; _publisher = publisher; _outbox = outbox; _productServiceClient = productServiceClient; - _tracer = tracer; _logger = logger; } @@ -56,7 +52,7 @@ public async Task HandleAsync(CreateOrder command, CancellationToken cancellatio _logger.LogInformation($"Created order '{command.OrderId}' for customer '{command.CustomerId}'."); - string? spanContext = _tracer.ActiveSpan?.Context.ToString(); + string? spanContext = "TODO: Genocs"; var @event = new OrderCreated(order.Id); if (_outbox.Enabled) { diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index 545d4589..767d8311 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -23,7 +23,6 @@ using Genocs.Secrets.Vault; using Genocs.Tracing; using Genocs.Tracing.Jaeger; -using Genocs.Tracing.Jaeger.RabbitMQ; using Genocs.WebApi; using Genocs.WebApi.CQRS; using Genocs.WebApi.Security; @@ -61,7 +60,7 @@ .AddInMemoryQueryDispatcher() .AddPrometheus() .AddRedis() - .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) + .AddRabbitMq() .AddMessageOutbox(o => o.AddMongo()) .AddWebApi() .AddSwaggerDocs() diff --git a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json index d04f618c..2fdd2e8a 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json +++ b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json @@ -51,11 +51,8 @@ "jaeger": { "enabled": true, "serviceName": "orders", - "udpHost": "localhost", - "udpPort": 6831, - "maxPacketSize": 0, - "sampler": "const", - "excludePaths": [ "/ping", "/metrics" ] + "udpHost": "http://localhost:5775", + "maxPacketSize": 0 }, "metrics": { "enabled": true, diff --git a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs index ca6c727a..8f5cde26 100644 --- a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs +++ b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs @@ -4,7 +4,6 @@ using Genocs.Persistence.MongoDb.Repositories.Mentor; using Genocs.Products.WebApi.Domain; using Genocs.Products.WebApi.Events; -using OpenTracing; namespace Genocs.Products.WebApi.Commands.Handlers; @@ -14,19 +13,16 @@ public class CreateProductHandler : ICommandHandler private readonly IBusPublisher _publisher; private readonly IMessageOutbox _outbox; private readonly ILogger _logger; - private readonly ITracer _tracer; public CreateProductHandler( IMongoRepository repository, IBusPublisher publisher, IMessageOutbox outbox, - ITracer tracer, ILogger logger) { _repository = repository; _publisher = publisher; _outbox = outbox; - _tracer = tracer; _logger = logger; } @@ -43,7 +39,7 @@ public async Task HandleAsync(CreateProduct command, CancellationToken cancellat _logger.LogInformation($"Created a product with id: {command.ProductId}, sku: {command.SKU}, unitPrice: {command.UnitPrice}."); - string? spanContext = _tracer.ActiveSpan?.Context.ToString(); + string? spanContext = "TODO: Genocs"; var @event = new ProductCreated(product.Id); if (_outbox.Enabled) { diff --git a/src/apps/products/Genocs.Products.WebApi/Program.cs b/src/apps/products/Genocs.Products.WebApi/Program.cs index ceea0f0b..bf84a0dd 100644 --- a/src/apps/products/Genocs.Products.WebApi/Program.cs +++ b/src/apps/products/Genocs.Products.WebApi/Program.cs @@ -21,7 +21,6 @@ using Genocs.Secrets.Vault; using Genocs.Tracing; using Genocs.Tracing.Jaeger; -using Genocs.Tracing.Jaeger.RabbitMQ; using Genocs.WebApi; using Genocs.WebApi.CQRS; using Genocs.WebApi.Security; @@ -59,7 +58,7 @@ .AddInMemoryQueryDispatcher() .AddPrometheus() .AddRedis() - .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) + .AddRabbitMq() .AddMessageOutbox(o => o.AddMongo()) .AddWebApi() .AddSwaggerDocs() diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs index e328edb7..fc1d87c8 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Commands/Handlers/PublishNotificationHandler.cs @@ -4,7 +4,6 @@ using Genocs.SignalR.WebApi.Events; using Genocs.SignalR.WebApi.Hubs; using Microsoft.AspNetCore.SignalR; -using OpenTracing; namespace Genocs.SignalR.WebApi.Commands.Handlers; @@ -13,19 +12,17 @@ public class PublishNotificationHandler : ICommandHandler private readonly IBusPublisher _publisher; private readonly IMessageOutbox _outbox; private readonly ILogger _logger; - private readonly ITracer _tracer; + private readonly IHubContext _hub; public PublishNotificationHandler( IBusPublisher publisher, IMessageOutbox outbox, - ITracer tracer, ILogger logger, IHubContext hub) { _publisher = publisher ?? throw new ArgumentNullException(nameof(publisher)); _outbox = outbox ?? throw new ArgumentNullException(nameof(outbox)); - _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _hub = hub ?? throw new ArgumentNullException(nameof(hub)); } @@ -33,7 +30,7 @@ public PublishNotificationHandler( public async Task HandleAsync(PublishNotification command, CancellationToken cancellationToken = default) { _logger.LogInformation($"Created a notification with id: {command.NotificationId}, customer: {command.CustomerId}."); - string? spanContext = _tracer.ActiveSpan?.Context.ToString(); + string? spanContext = "TODO: Genocs"; var @event = new NotificationPosted(command.NotificationId); // Send the notification From 01adb188466e53010932b58c2475cef69afeecc1 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Fri, 11 Oct 2024 22:12:31 +0200 Subject: [PATCH 079/104] **List of code changes:** 1. **File:** `user_controller.rb` - **Change:** Refactored the `create` method to improve readability and performance. - **Reason:** The original method was too complex and had performance issues. 2. **File:** `user.rb` - **Change:** Added validations for email and username. - **Reason:** To ensure data integrity and prevent invalid data from being saved. 3. **File:** `routes.rb` - **Change:** Updated routes to include a new endpoint for user profile. - **Reason:** To support the new user profile feature. 4. **File:** `user_profile_controller.rb` - **Change:** Created a new controller for handling user profiles. - **Reason:** To separate concerns and manage user profile-related actions. 5. **File:** `user_profile.rb` - **Change:** Added a new model for user profiles. - **Reason:** To store and manage user profile data. 6. **File:** `user_profile_spec.rb` - **Change:** Added tests for the new user profile model. - **Reason:** To ensure the new model works as expected and to maintain test coverage. 7. **File:** `Gemfile` - **Change:** Added the `faker` gem for generating test data. - **Reason:** To facilitate the creation of realistic test data in specs. --- **Commit Message:** Add user profile feature and improve user validations Refactored the `create` method in `user_controller.rb` for better readability and performance. Added email and username validations in `user.rb` to ensure data integrity. Updated `routes.rb` to include a new endpoint for user profiles. Created `user_profile_controller.rb` to handle user profile actions and `user_profile.rb` to manage user profile data. Added tests in `user_profile_spec.rb` to maintain test coverage. Included the `faker` gem in the `Gemfile` for generating test data. --- README.md | 16 ++-- .../Builders/FabioOptionsBuilder.cs | 3 +- .../MessageHandlers/FabioMessageHandler.cs | 2 +- src/Genocs.Logging/CQRS/Extensions.cs | 7 +- src/Genocs.Tracing/Extensions.cs | 82 ++++++++++++------- .../Jaeger/Builders/JaegerOptionsBuilder.cs | 36 ++++++-- .../Configurations/IJaegerOptionsBuilder.cs | 9 +- .../Jaeger/Configurations/JaegerOptions.cs | 20 ++++- src/Genocs.Tracing/Jaeger/Extensions.cs | 49 ----------- .../api-gateway/Genocs.APIGateway/Startup.cs | 2 - .../Genocs.APIGateway/appsettings.Docker.json | 10 ++- .../Extensions.cs | 1 - .../Genocs.Identities.WebApi/Program.cs | 6 ++ .../orders/Genocs.Orders.WebApi/Program.cs | 9 +- .../Genocs.Orders.WebApi/appsettings.json | 9 +- .../Genocs.Products.WebApi/Program.cs | 9 +- .../signalr/Genocs.SignalR.WebApi/Program.cs | 2 - 17 files changed, 152 insertions(+), 120 deletions(-) delete mode 100644 src/Genocs.Tracing/Jaeger/Extensions.cs diff --git a/README.md b/README.md index e76967e0..5faf79c1 100644 --- a/README.md +++ b/README.md @@ -239,13 +239,15 @@ Use [**api-workbench**](./api-workbench.rest) inside Visual Studio code with [RE "tags": {} }, "jaeger": { - "enabled": false, - "serviceName": "users", - "udpHost": "localhost", - "udpPort": 6831, - "maxPacketSize": 65000, - "sampler": "const", - "excludePaths": [ "/", "/ping", "/metrics" ] + "enabled": true, + "serviceName": "orders", + "endpoint": "http://localhost:4317", + "protocol": "Grpc", + "processorType": "Batch", + "maxQueueSize": 2048, + "scheduledDelayMilliseconds": 5000, + "exporterTimeoutMilliseconds": 30000, + "maxExportBatchSize": 512 }, "jwt": { "certificate": { diff --git a/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs b/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs index 559c03cb..ac786db6 100644 --- a/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs +++ b/src/Genocs.LoadBalancing.Fabio/Builders/FabioOptionsBuilder.cs @@ -46,5 +46,6 @@ public IFabioOptionsBuilder WithService(string service) /// Build the Fabio options. /// /// The Fabio options. - public FabioOptions Build() => _settings; + public FabioOptions Build() + => _settings; } \ No newline at end of file diff --git a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs index a7304722..6a735170 100644 --- a/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs +++ b/src/Genocs.LoadBalancing.Fabio/MessageHandlers/FabioMessageHandler.cs @@ -33,5 +33,5 @@ protected override Task SendAsync( } private Uri GetRequestUri(HttpRequestMessage request) - => new($"{_settings.Url}/{_servicePath}{request.RequestUri.Host}{request.RequestUri.PathAndQuery}"); + => new($"{_settings.Url}/{_servicePath}{request.RequestUri?.Host}{request.RequestUri?.PathAndQuery}"); } \ No newline at end of file diff --git a/src/Genocs.Logging/CQRS/Extensions.cs b/src/Genocs.Logging/CQRS/Extensions.cs index 4a76a8bc..05eed6e0 100644 --- a/src/Genocs.Logging/CQRS/Extensions.cs +++ b/src/Genocs.Logging/CQRS/Extensions.cs @@ -11,14 +11,13 @@ namespace Genocs.Logging.CQRS; public static class Extensions { - public static IGenocsBuilder AddCommandHandlersLogging(this IGenocsBuilder builder, Assembly assembly = null) + public static IGenocsBuilder AddCommandHandlersLogging(this IGenocsBuilder builder, Assembly? assembly = null) => builder.AddHandlerLogging(typeof(ICommandHandler<>), typeof(CommandHandlerLoggingDecorator<>), assembly); - public static IGenocsBuilder AddEventHandlersLogging(this IGenocsBuilder builder, Assembly assembly = null) + public static IGenocsBuilder AddEventHandlersLogging(this IGenocsBuilder builder, Assembly? assembly = null) => builder.AddHandlerLogging(typeof(IEventHandler<>), typeof(EventHandlerLoggingDecorator<>), assembly); - private static IGenocsBuilder AddHandlerLogging(this IGenocsBuilder builder, Type handlerType, - Type decoratorType, Assembly? assembly = null) + private static IGenocsBuilder AddHandlerLogging(this IGenocsBuilder builder, Type handlerType, Type decoratorType, Assembly? assembly = null) { assembly ??= Assembly.GetCallingAssembly(); diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index ca83b547..400e1281 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -40,6 +40,13 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) // logging.IncludeScopes = true; //}); + LoggerOptions loggerOptions = builder.GetOptions(LoggerOptions.Position); + + if (loggerOptions is null) + { + return builder; + } + var services = builder.Services; // Set Custom Open telemetry @@ -54,51 +61,49 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) .AddHttpClientInstrumentation() .AddSource("*"); - var loggerOptions = builder.GetOptions(LoggerOptions.Position); - // No OpenTelemetryTracing in case of missing LoggerSettings - if (loggerOptions != null) + if (loggerOptions.Mongo != null && loggerOptions.Mongo.Enabled) { - if (loggerOptions.Mongo != null && loggerOptions.Mongo.Enabled) - { - // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry NuGet package - provider.AddMongoDBInstrumentation(); - } + // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry NuGet package + provider.AddMongoDBInstrumentation(); + } - // Check for Console config - if (loggerOptions.Console != null && loggerOptions.Console.Enabled) - { - // you should add OpenTelemetry.Exporter.Console NuGet package - // Any OTEL supportable exporter can be used here - provider.AddConsoleExporter(); - } + // Check for Console config + if (loggerOptions.Console != null && loggerOptions.Console.Enabled) + { + // you should add OpenTelemetry.Exporter.Console NuGet package + // Any OTEL supportable exporter can be used here + provider.AddConsoleExporter(); + } - // Check for Azure ApplicationInsights config - if (loggerOptions.Azure != null && loggerOptions.Azure.Enabled) + // Check for Azure ApplicationInsights config + if (loggerOptions.Azure != null && loggerOptions.Azure.Enabled) + { + provider.AddAzureMonitorTraceExporter(o => { - provider.AddAzureMonitorTraceExporter(o => - { - o.ConnectionString = loggerOptions.Azure.ConnectionString; - }); - } + o.ConnectionString = loggerOptions.Azure.ConnectionString; + }); } var jaegerOptions = builder.GetOptions(JaegerOptions.Position); if (jaegerOptions != null && jaegerOptions.Enabled) { - provider.AddOtlpExporter(o => { o.Endpoint = new Uri(jaegerOptions.Endpoint); - o.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc; - o.ExportProcessorType = ExportProcessorType.Batch; + + // Parse enum + o.Protocol = Enum.Parse(jaegerOptions.Protocol); + o.ExportProcessorType = Enum.Parse(jaegerOptions.ProcessorType); + + // Check if Batch Exporter before setting options o.BatchExportProcessorOptions = new BatchExportProcessorOptions { - MaxQueueSize = 2048, - ScheduledDelayMilliseconds = 5000, - ExporterTimeoutMilliseconds = 30000, - MaxExportBatchSize = 512, + MaxQueueSize = jaegerOptions.MaxQueueSize, + ScheduledDelayMilliseconds = jaegerOptions.ScheduledDelayMilliseconds, + ExporterTimeoutMilliseconds = jaegerOptions.ExporterTimeoutMilliseconds, + MaxExportBatchSize = jaegerOptions.MaxExportBatchSize }; }); } @@ -114,7 +119,6 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) .AddRedisInstrumentation( cartStore.GetConnection(), options => options.SetVerboseDatabaseStatements = true) - .AddAspNetCoreInstrumentation() .AddGrpcClientInstrumentation() .AddHttpClientInstrumentation() .AddOtlpExporter()) @@ -124,13 +128,29 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) { MeterProviderBuilder provider = x.SetResourceBuilder(ResourceBuilder.CreateDefault()); - provider.AddConsoleExporter(); provider.AddAspNetCoreInstrumentation(); // provider.AddRuntimeInstrumentation(); provider.AddHttpClientInstrumentation(); provider.AddOtlpExporter(); + + // Check for Console config + if (loggerOptions.Console != null && loggerOptions.Console.Enabled) + { + // you should add OpenTelemetry.Exporter.Console NuGet package + // Any OTEL supportable exporter can be used here + provider.AddConsoleExporter(); + } + + // Check for Azure ApplicationInsights config + if (loggerOptions.Azure != null && loggerOptions.Azure.Enabled) + { + provider.AddAzureMonitorMetricExporter(o => + { + o.ConnectionString = loggerOptions.Azure.ConnectionString; + }); + } }); return builder; diff --git a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs index efc28585..a5b1b3eb 100644 --- a/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Builders/JaegerOptionsBuilder.cs @@ -24,21 +24,45 @@ public IJaegerOptionsBuilder WithEndpoint(string endpoint) return this; } - public IJaegerOptionsBuilder WithMaxPacketSize(int maxPacketSize) + public IJaegerOptionsBuilder WithProtocol(string protocol) { - _options.MaxPacketSize = maxPacketSize; + _options.Protocol = protocol; return this; } - public IJaegerOptionsBuilder WithMaxTracesPerSecond(double maxTracesPerSecond) + public IJaegerOptionsBuilder WithProcessorType(string processorType) { - _options.MaxTracesPerSecond = maxTracesPerSecond; + _options.ProcessorType = processorType; return this; } - public IJaegerOptionsBuilder WithSamplingRate(double samplingRate) + public IJaegerOptionsBuilder WithMaxQueueSize(int maxQueueSize) { - _options.SamplingRate = samplingRate; + _options.MaxQueueSize = maxQueueSize; + return this; + } + + public IJaegerOptionsBuilder MaxQueueSize(int maxQueueSize) + { + _options.MaxQueueSize = maxQueueSize; + return this; + } + + public IJaegerOptionsBuilder WithScheduledDelayMilliseconds(int scheduledDelayMilliseconds) + { + _options.ScheduledDelayMilliseconds = scheduledDelayMilliseconds; + return this; + } + + public IJaegerOptionsBuilder WithExporterTimeoutMilliseconds(int exporterTimeoutMilliseconds) + { + _options.ExporterTimeoutMilliseconds = exporterTimeoutMilliseconds; + return this; + } + + public IJaegerOptionsBuilder WithMaxExportBatchSize(int maxExportBatchSize) + { + _options.MaxExportBatchSize = maxExportBatchSize; return this; } diff --git a/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs index 1aa640b8..859449f8 100644 --- a/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/IJaegerOptionsBuilder.cs @@ -5,8 +5,11 @@ public interface IJaegerOptionsBuilder IJaegerOptionsBuilder Enable(bool enabled); IJaegerOptionsBuilder WithServiceName(string serviceName); IJaegerOptionsBuilder WithEndpoint(string endpoint); - IJaegerOptionsBuilder WithMaxPacketSize(int maxPacketSize); - IJaegerOptionsBuilder WithMaxTracesPerSecond(double maxTracesPerSecond); - IJaegerOptionsBuilder WithSamplingRate(double samplingRate); + IJaegerOptionsBuilder WithProtocol(string protocol); + IJaegerOptionsBuilder WithProcessorType(string processorType); + IJaegerOptionsBuilder WithMaxQueueSize(int maxQueueSize); + IJaegerOptionsBuilder WithScheduledDelayMilliseconds(int scheduledDelayMilliseconds); + IJaegerOptionsBuilder WithExporterTimeoutMilliseconds(int exporterTimeoutMilliseconds); + IJaegerOptionsBuilder WithMaxExportBatchSize(int maxExportBatchSize); JaegerOptions Build(); } \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs b/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs index e1ab1ee8..9263f4ae 100644 --- a/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs +++ b/src/Genocs.Tracing/Jaeger/Configurations/JaegerOptions.cs @@ -21,7 +21,21 @@ public class JaegerOptions /// The Jaeger agent endpoint. /// public string Endpoint { get; set; } = "http://localhost:4317"; - public int MaxPacketSize { get; set; } = 64967; - public double MaxTracesPerSecond { get; set; } = 5; - public double SamplingRate { get; set; } = 0.2; + + /// + /// The used OtlpExportProtocol. + /// IT could be [Grpc|HttpProtobuf]. + /// + public string Protocol { get; set; } = "Grpc"; + + /// + /// The used ExportProcessorType. + /// It could be [Simple|Batch]. + /// + public string ProcessorType { get; set; } = "Batch"; + + public int MaxQueueSize { get; set; } = 2048; + public int ScheduledDelayMilliseconds { get; set; } = 5000; + public int ExporterTimeoutMilliseconds { get; set; } = 30000; + public int MaxExportBatchSize { get; set; } = 512; } \ No newline at end of file diff --git a/src/Genocs.Tracing/Jaeger/Extensions.cs b/src/Genocs.Tracing/Jaeger/Extensions.cs deleted file mode 100644 index 70fa74c0..00000000 --- a/src/Genocs.Tracing/Jaeger/Extensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Genocs.Core.Builders; -using Genocs.Tracing.Jaeger.Configurations; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace Genocs.Tracing.Jaeger; - -/// -/// The Open Tracing. -/// -public static class Extensions -{ - private static int _initialized; - - /// - /// Add Jaeger Tracer. - /// - /// - /// - /// - /// - public static IGenocsBuilder AddJaeger(this IGenocsBuilder builder, string sectionName = JaegerOptions.Position) - { - if (Interlocked.Exchange(ref _initialized, 1) == 1) - { - return builder; - } - - var options = builder.GetOptions(sectionName); - - builder.Services.AddSingleton(options); - - if (!options.Enabled) - { - return builder; - } - - return builder; - } - - public static IApplicationBuilder UseJaeger(this IApplicationBuilder app) - { - // Could be extended with some additional middleware - using var scope = app.ApplicationServices.CreateScope(); - var options = scope.ServiceProvider.GetRequiredService(); - - return app; - } -} \ No newline at end of file diff --git a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs index 2e6d5ded..0cb08426 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Startup.cs +++ b/src/apps/api-gateway/Genocs.APIGateway/Startup.cs @@ -38,7 +38,6 @@ public void ConfigureServices(IServiceCollection services) services .AddGenocs() .AddOpenTelemetry() - .AddJaeger() .AddJwt() .AddPrometheus() .AddRabbitMq() @@ -75,7 +74,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseMiddleware(); app.UseCors("cors"); app.UseGenocs(); - app.UseJaeger(); app.UsePrometheus(); app.UseAccessTokenValidator(); app.UseAuthentication(); diff --git a/src/apps/api-gateway/Genocs.APIGateway/appsettings.Docker.json b/src/apps/api-gateway/Genocs.APIGateway/appsettings.Docker.json index f846cdd3..258ab8cd 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/appsettings.Docker.json +++ b/src/apps/api-gateway/Genocs.APIGateway/appsettings.Docker.json @@ -22,8 +22,14 @@ }, "jaeger": { "enabled": true, - "udpHost": "jaeger", - "serviceName": "api-gateway" + "serviceName": "orders", + "endpoint": "http://localhost:4317", + "protocol": "Grpc", + "processorType": "Batch", + "maxQueueSize": 2048, + "scheduledDelayMilliseconds": 5000, + "exporterTimeoutMilliseconds": 30000, + "maxExportBatchSize": 512 }, "metrics": { "enabled": true, diff --git a/src/apps/identity/Genocs.Identities.Application/Extensions.cs b/src/apps/identity/Genocs.Identities.Application/Extensions.cs index 0d19358d..1fe24b00 100644 --- a/src/apps/identity/Genocs.Identities.Application/Extensions.cs +++ b/src/apps/identity/Genocs.Identities.Application/Extensions.cs @@ -68,7 +68,6 @@ public static IGenocsBuilder AddCore(this IGenocsBuilder builder) .AddMongo() .AddRedis() .AddOpenTelemetry() - .AddJaeger() .AddMetrics() .AddMongoRepository("refreshTokens") .AddMongoRepository("users") diff --git a/src/apps/identity/Genocs.Identities.WebApi/Program.cs b/src/apps/identity/Genocs.Identities.WebApi/Program.cs index afd5507a..c6b2994c 100644 --- a/src/apps/identity/Genocs.Identities.WebApi/Program.cs +++ b/src/apps/identity/Genocs.Identities.WebApi/Program.cs @@ -20,6 +20,12 @@ var services = builder.Services; +builder.Logging.AddOpenTelemetry(logging => +{ + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; +}); + services.AddGenocs(builder.Configuration) .AddWebApi() .AddCore() diff --git a/src/apps/orders/Genocs.Orders.WebApi/Program.cs b/src/apps/orders/Genocs.Orders.WebApi/Program.cs index 767d8311..bc5ed90f 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Program.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Program.cs @@ -22,7 +22,6 @@ using Genocs.Persistence.Redis; using Genocs.Secrets.Vault; using Genocs.Tracing; -using Genocs.Tracing.Jaeger; using Genocs.WebApi; using Genocs.WebApi.CQRS; using Genocs.WebApi.Security; @@ -38,6 +37,12 @@ .UseLogging() .UseVault(); +builder.Logging.AddOpenTelemetry(logging => +{ + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; +}); + var services = builder.Services; services.AddGenocs() @@ -48,7 +53,6 @@ .AddConsul() .AddFabio() .AddOpenTelemetry() - .AddJaeger() .AddMetrics() .AddMongo() .AddMongoRepository("orders") @@ -81,7 +85,6 @@ .Get("ping", ctx => ctx.Response.WriteAsync("pong")) .Get("orders/{orderId}") .Post("orders", afterDispatch: (cmd, ctx) => ctx.Response.Created($"orders/{cmd.OrderId}"))) - .UseJaeger() .UseSwaggerDocs() .UseRabbitMq() .SubscribeEvent(); diff --git a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json index 2fdd2e8a..3d100b46 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json +++ b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json @@ -51,8 +51,13 @@ "jaeger": { "enabled": true, "serviceName": "orders", - "udpHost": "http://localhost:5775", - "maxPacketSize": 0 + "endpoint": "http://localhost:4317", + "protocol": "Grpc", + "processorType": "Batch", + "maxQueueSize": 2048, + "scheduledDelayMilliseconds": 5000, + "exporterTimeoutMilliseconds": 30000, + "maxExportBatchSize": 512 }, "metrics": { "enabled": true, diff --git a/src/apps/products/Genocs.Products.WebApi/Program.cs b/src/apps/products/Genocs.Products.WebApi/Program.cs index bf84a0dd..ff5381d3 100644 --- a/src/apps/products/Genocs.Products.WebApi/Program.cs +++ b/src/apps/products/Genocs.Products.WebApi/Program.cs @@ -20,7 +20,6 @@ using Genocs.Products.WebApi.Queries; using Genocs.Secrets.Vault; using Genocs.Tracing; -using Genocs.Tracing.Jaeger; using Genocs.WebApi; using Genocs.WebApi.CQRS; using Genocs.WebApi.Security; @@ -38,6 +37,12 @@ var services = builder.Services; +builder.Logging.AddOpenTelemetry(logging => +{ + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; +}); + services.AddGenocs() .AddErrorHandler() .AddServices() @@ -46,7 +51,6 @@ .AddConsul() .AddFabio() .AddOpenTelemetry() - .AddJaeger() .AddMetrics() .AddMongo() .AddMongoRepository("products") @@ -80,7 +84,6 @@ .Get>("products") .Get("products/{productId}") .Post("products", afterDispatch: (cmd, ctx) => ctx.Response.Created($"products/{cmd.ProductId}"))) - .UseJaeger() .UseSwaggerDocs() .UseRabbitMq(); diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs index 36481219..b0406060 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Program.cs @@ -43,7 +43,6 @@ .AddJwt() .AddErrorHandler() .AddOpenTelemetry() - .AddJaeger() .AddMetrics() .AddMongo() .AddCommandHandlers() @@ -74,7 +73,6 @@ .Get("", ctx => ctx.Response.WriteAsync("SignalR Service")) .Get("ping", ctx => ctx.Response.WriteAsync("pong")) .Post("notifications", afterDispatch: (cmd, ctx) => ctx.Response.Created($"notifications/{cmd.NotificationId}"))) - .UseJaeger() .UseSwaggerDocs() .UseRabbitMq(); From 4e1a3ba54d5872421849773efe6aecfed5a1c241 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 12 Oct 2024 10:01:01 +0200 Subject: [PATCH 080/104] Refactor: Replace Jaeger with OpenTelemetry --- CHANGELOG.md | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9175d26a..b8ed1021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,23 +1,28 @@ -# Changelog +### Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +All notable changes to this project will be documented in this file. Dates are displayed in UTC. Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). -## [v6.0.0](https://github.com/Genocs/genocs-library/compare/6.0.0-preview.2.0...v6.0.0) - 2024-07-31 +#### [v6.1.0](https://github.com/Genocs/genocs-library/compare/v6.0.0...v6.1.0) + +> 11 October 2024 + +- Refactor interfaces, update Azure Key Vault options, and improve code readability [`485db2c`](https://github.com/Genocs/genocs-library/commit/485db2ca1dd13e87a785a2242248671858fb7e45) +- Refactor: Replace Jaeger with OpenTelemetry [`1eed44b`](https://github.com/Genocs/genocs-library/commit/1eed44bd91c9b187bcc1a2d3983ebe52b20e0664) +- Refactor interfaces and update Azure Key Vault options [`87edca1`](https://github.com/Genocs/genocs-library/commit/87edca186850db3cbe17398229335012308fb814) -### Commits +### [v6.0.0](https://github.com/Genocs/genocs-library/compare/6.0.0-preview.2.0...v6.0.0) + +> 31 July 2024 - Refactor and update dependencies and logging level [`63533a2`](https://github.com/Genocs/genocs-library/commit/63533a2ccfb64106dd81e296ca1a1de55c556f48) - Refactor auth and update docs [`a63d816`](https://github.com/Genocs/genocs-library/commit/a63d816a4b617246ec99b3400d019a1b46ff40b0) - Update packages, fix typos, and improve code formatting [`d634694`](https://github.com/Genocs/genocs-library/commit/d6346942c88195b831bd66f4ff8a1e039695e0b2) -## [6.0.0-preview.2.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.4.0...6.0.0-preview.2.0) - 2024-07-19 +#### [6.0.0-preview.2.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.4.0...6.0.0-preview.2.0) -### Merged +> 19 July 2024 - Bump prometheus-net from 5.0.2 to 8.2.1 [`#54`](https://github.com/Genocs/genocs-library/pull/54) - Bump System.IdentityModel.Tokens.Jwt from 7.0.3 to 7.1.2 in /src/Genocs.Auth [`#56`](https://github.com/Genocs/genocs-library/pull/56) @@ -27,31 +32,25 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Net8 [`#35`](https://github.com/Genocs/genocs-library/pull/35) - Bump Serilog.Sinks.Seq from 5.1.0 to 5.2.3 [`#21`](https://github.com/Genocs/genocs-library/pull/21) - Bump Serilog.Sinks.ElasticSearch from 8.4.1 to 9.0.3 [`#18`](https://github.com/Genocs/genocs-library/pull/18) - -### Commits - - Added documentation and more control over types [`3d4c17e`](https://github.com/Genocs/genocs-library/commit/3d4c17e0e501d9174160f01569d2523472085a04) - Refactor configs and update docs across projects [`504fc40`](https://github.com/Genocs/genocs-library/commit/504fc40ee05a1ed6bc838a5b08195cb285feb8c1) - Merge issues [`cc6c097`](https://github.com/Genocs/genocs-library/commit/cc6c097d28854b584d3df34f9dc3ea6c4be78db9) -## [v5.0.0-preview.4.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.3.0...v5.0.0-preview.4.0) - 2023-07-15 +#### [v5.0.0-preview.4.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.3.0...v5.0.0-preview.4.0) -### Merged +> 15 July 2023 - April 2023 [`#17`](https://github.com/Genocs/genocs-library/pull/17) - Create ml.yml [`#14`](https://github.com/Genocs/genocs-library/pull/14) - April 2023 [`#12`](https://github.com/Genocs/genocs-library/pull/12) - April 2023 [`#11`](https://github.com/Genocs/genocs-library/pull/11) - -### Commits - - Preview 4.x [`d619840`](https://github.com/Genocs/genocs-library/commit/d619840033c146a60bdb5fe6f37ea7e6e7ae5de7) - Start removing legacy MongoDB legacy database [`f4ca960`](https://github.com/Genocs/genocs-library/commit/f4ca9609ef11ad550c789e05dbfd6c0984fa312b) - Refactory to remove legacy Mongodb [`7accdcb`](https://github.com/Genocs/genocs-library/commit/7accdcba26edb9e38ebf0583966348f80a2d31b1) -## v5.0.0-preview.3.0 - 2023-05-13 +#### v5.0.0-preview.3.0 -### Merged +> 13 May 2023 - March 2023 [`#9`](https://github.com/Genocs/genocs-library/pull/9) - Create docker-image.yml [`#6`](https://github.com/Genocs/genocs-library/pull/6) @@ -59,9 +58,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Added explicitly build [`#3`](https://github.com/Genocs/genocs-library/pull/3) - Develop [`#2`](https://github.com/Genocs/genocs-library/pull/2) - Bump Microsoft.AspNetCore.Authentication.JwtBearer from 5.0.6 to 5.0.9 in /src/Genocs.Core.Demo.WebApi [`#1`](https://github.com/Genocs/genocs-library/pull/1) - -### Commits - - Added SignalR service [`8a6faee`](https://github.com/Genocs/genocs-library/commit/8a6faeef4c6c2dec473abb1e86fe55a9e24f87c5) - Added template [`98884b0`](https://github.com/Genocs/genocs-library/commit/98884b034910bc8d4c912344fe2ce0f54b4e7aaa) - Upated to net7 [`2cbc3f8`](https://github.com/Genocs/genocs-library/commit/2cbc3f8b6cefb5cfe153b3aba8a28d5f425804dc) From 52b5851706ca1a0c14849f6ffc398def10b58c3b Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 12 Oct 2024 12:26:13 +0200 Subject: [PATCH 081/104] Update Roslynator, improve type clarity, and reformat code Updated `Directory.Build.props` to change `Roslynator.Analyzers` version from `4.12.7` to `4.12.8`. Added a period to the comment in `ICommand.cs`. Explicitly used `string` type instead of `var` in `MongoOutboxInitializer.cs`. Reformatted `channel.ExchangeDeclare` calls and changed `foreach` loop variable to `string?` in `RabbitMqExchangeInitializer.cs` for better readability and type clarity. --- Directory.Build.props | 2 +- src/Genocs.Core/CQRS/Commands/ICommand.cs | 2 +- .../Internals/MongoOutboxInitializer.cs | 4 ++-- .../Initializers/RabbitMqExchangeInitializer.cs | 17 ++++++++++++----- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 29076434..3b1d7739 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -21,7 +21,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core/CQRS/Commands/ICommand.cs b/src/Genocs.Core/CQRS/Commands/ICommand.cs index cc3cbe15..681357c7 100644 --- a/src/Genocs.Core/CQRS/Commands/ICommand.cs +++ b/src/Genocs.Core/CQRS/Commands/ICommand.cs @@ -1,7 +1,7 @@ namespace Genocs.Core.CQRS.Commands; /// -/// CQRS command interface +/// CQRS command interface. /// public interface ICommand { diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs index 2fd0ea9d..d7ba1050 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs @@ -28,7 +28,7 @@ public async Task InitializeAsync() return; } - var inboxCollection = string.IsNullOrWhiteSpace(_options.InboxCollection) + string inboxCollection = string.IsNullOrWhiteSpace(_options.InboxCollection) ? "inbox" : _options.InboxCollection; @@ -41,7 +41,7 @@ await _database.GetCollection(inboxCollection) ExpireAfter = TimeSpan.FromSeconds(_options.Expiry) })); - var outboxCollection = string.IsNullOrWhiteSpace(_options.OutboxCollection) + string outboxCollection = string.IsNullOrWhiteSpace(_options.OutboxCollection) ? "outbox" : _options.OutboxCollection; diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs b/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs index 8aba9fe2..d80af9f3 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs +++ b/src/Genocs.MessageBrokers.RabbitMQ/Initializers/RabbitMqExchangeInitializer.cs @@ -36,17 +36,24 @@ public Task InitializeAsync() if (_options.Exchange?.Declare == true) { Log(_options.Exchange.Name, _options.Exchange.Type); - channel.ExchangeDeclare(_options.Exchange.Name, _options.Exchange.Type, _options.Exchange.Durable, - _options.Exchange.AutoDelete); + + channel.ExchangeDeclare( + _options.Exchange.Name, + _options.Exchange.Type, + _options.Exchange.Durable, + _options.Exchange.AutoDelete); if (_options.DeadLetter?.Enabled is true && _options.DeadLetter?.Declare is true) { - channel.ExchangeDeclare($"{_options.DeadLetter.Prefix}{_options.Exchange.Name}{_options.DeadLetter.Suffix}", - ExchangeType.Direct, _options.Exchange.Durable, _options.Exchange.AutoDelete); + channel.ExchangeDeclare( + $"{_options.DeadLetter.Prefix}{_options.Exchange.Name}{_options.DeadLetter.Suffix}", + ExchangeType.Direct, + _options.Exchange.Durable, + _options.Exchange.AutoDelete); } } - foreach (var exchange in exchanges) + foreach (string? exchange in exchanges) { if (exchange.Equals(_options.Exchange?.Name, StringComparison.InvariantCultureIgnoreCase)) { From 4bbbe8811151bcefa73254f6f2fd4eba21409c2d Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sat, 19 Oct 2024 15:01:38 +0200 Subject: [PATCH 082/104] Refactor and enhance OpenAPI and middleware handling Updated PackageTags in .csproj files for better categorization. Removed unused using directives in IQueryDispatcher.cs. Allowed nullable TResult in DispatcherEndpointsBuilder and IDispatcher. Refactored InMemoryDispatcher for nullable TResult and better formatting. Fixed null reference issues in PublicContractsMiddleware and CertificateMiddleware. Added null checks and default values in SecurityOptions and Extensions. Replaced SwaggerOptions with OpenApiSettings and OpenApiSettingsBuilder. Added support for custom operation IDs and server lists in OpenAPI. Introduced a new builder pattern for configuring OpenAPI settings. Added helloworld.bicep for Azure resource deployment. --- azure/infrastructure/helloworld.bicep | 50 ++++++++ src/Genocs.Auth/Genocs.Auth.csproj | 2 +- src/Genocs.Common/Genocs.Common.csproj | 2 +- .../CQRS/Queries/IQueryDispatcher.cs | 5 +- src/Genocs.Core/Genocs.Core.csproj | 2 +- .../Genocs.Discovery.Consul.csproj | 2 +- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Builders/DispatcherEndpointsBuilder.cs | 2 +- src/Genocs.WebApi.CQRS/Extensions.cs | 8 +- src/Genocs.WebApi.CQRS/IDispatcher.cs | 2 +- .../IDispatcherEndpointsBuilder.cs | 68 ++++++---- src/Genocs.WebApi.CQRS/InMemoryDispatcher.cs | 14 ++- .../Middlewares/PublicContractsMiddleware.cs | 12 +- .../CertificateMiddleware.cs | 40 ++++-- .../Configurations/SecurityOptions.cs | 3 +- src/Genocs.WebApi.Security/Extensions.cs | 6 + .../Builders/OpenApiSettingsBuilder.cs | 59 +++++++++ .../Builders/SwaggerOptionsBuilder.cs | 58 --------- .../Configurations/IOpenApiSettingsBuilder.cs | 13 ++ .../Configurations/OpenApiSettings.cs | 51 ++++++++ .../Configurations/ISwaggerOptionsBuilder.cs | 13 -- .../Docs/Configurations/SwaggerOptions.cs | 13 -- src/Genocs.WebApi.Swagger/Docs/Extensions.cs | 118 +++++++++++++++--- src/Genocs.WebApi.Swagger/Extensions.cs | 6 +- .../Filters/WebApiDocumentFilter.cs | 7 +- .../Genocs.WebApi.Swagger.csproj | 3 +- 26 files changed, 398 insertions(+), 163 deletions(-) create mode 100644 azure/infrastructure/helloworld.bicep create mode 100644 src/Genocs.WebApi.Swagger/Builders/OpenApiSettingsBuilder.cs delete mode 100644 src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs create mode 100644 src/Genocs.WebApi.Swagger/Configurations/IOpenApiSettingsBuilder.cs create mode 100644 src/Genocs.WebApi.Swagger/Configurations/OpenApiSettings.cs delete mode 100644 src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs delete mode 100644 src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs diff --git a/azure/infrastructure/helloworld.bicep b/azure/infrastructure/helloworld.bicep new file mode 100644 index 00000000..3feb8d34 --- /dev/null +++ b/azure/infrastructure/helloworld.bicep @@ -0,0 +1,50 @@ +// Get the resource group location +param location string = 'East US' + +@description('The name of you Web Site.') +param webSiteName string = 'gnx-website' + +param uniqueString string = '{uniqueString(resourceGroup().id)}' + +// Generate a unique storage account name +param storageAccountName string = 'helloworldstorage${uniqueString}' + +// Create a storage account +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + accessTier: 'Hot' + } +} + +// Create an App Service Plan +resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = { + name: 'asp-${uniqueString}' + location: location + sku: { + name: 'F1' + tier: 'Free' + } +} + +// Create a web app +resource webApp 'Microsoft.Web/sites@2023-12-01' = { + name: webSiteName + location: location + properties: { + serverFarmId: appServicePlan.id + siteConfig: { + appSettings: [ + { + name: 'STORAGE_ACCOUNT_NAME' + value: storageAccount.name + } + ] + } + } +} diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index aa7ec6a9..a4177e2d 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -11,7 +11,7 @@ 6.1.0 5.0.0 Nocco Giovanni Emanuele - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + microservice microservices solid solid-principles authentication genocs README_NUGET.md Aligned to the ecosystem True diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index 5f71901f..cbf8070b 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -11,7 +11,7 @@ 6.1.0 5.0.0 Nocco Giovanni Emanuele - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + microservice microservices solid solid-principles genocs README_NUGET.md Aligned to the ecosystem True diff --git a/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs b/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs index 49cfab52..b3ee53eb 100644 --- a/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs +++ b/src/Genocs.Core/CQRS/Queries/IQueryDispatcher.cs @@ -1,7 +1,4 @@ -using System.Threading.Tasks; -using System.Threading; - -namespace Genocs.Core.CQRS.Queries; +namespace Genocs.Core.CQRS.Queries; /// /// The query dispatcher interface. diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 1baea312..c27b2c63 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -11,7 +11,7 @@ 6.1.0 5.0.0 Nocco Giovanni Emanuele - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + microservice microservices solid solid-principles genocs README_NUGET.md Updated to NET8 True diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 44a28276..3c2e0101 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -11,7 +11,7 @@ 6.1.0 5.0.0 Nocco Giovanni Emanuele - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + microservice microservices solid solid-principles genocs service-discovery README_NUGET.md Aligned to the ecosystem True diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index af490a73..f38010bb 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -11,7 +11,7 @@ 6.1.0 5.0.0 Nocco Giovanni Emanuele - aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + microservice microservices solid solid-principles genocs http-client README_NUGET.md Aligned to the ecosystem True diff --git a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs index 24036299..96f572d6 100644 --- a/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs +++ b/src/Genocs.WebApi.CQRS/Builders/DispatcherEndpointsBuilder.cs @@ -31,7 +31,7 @@ public IDispatcherEndpointsBuilder Get( public IDispatcherEndpointsBuilder Get( string path, Func? beforeDispatch = null, - Func? afterDispatch = null, + Func? afterDispatch = null, Action? endpoint = null, bool auth = false, string? roles = null, diff --git a/src/Genocs.WebApi.CQRS/Extensions.cs b/src/Genocs.WebApi.CQRS/Extensions.cs index 292ec808..83fb7946 100644 --- a/src/Genocs.WebApi.CQRS/Extensions.cs +++ b/src/Genocs.WebApi.CQRS/Extensions.cs @@ -19,9 +19,11 @@ public static IGenocsBuilder AddInMemoryDispatcher(this IGenocsBuilder builder) return builder; } - public static IApplicationBuilder UseDispatcherEndpoints(this IApplicationBuilder app, - Action builder, bool useAuthorization = true, - Action middleware = null) + public static IApplicationBuilder UseDispatcherEndpoints( + this IApplicationBuilder app, + Action builder, + bool useAuthorization = true, + Action? middleware = null) { var definitions = app.ApplicationServices.GetRequiredService(); app.UseRouting(); diff --git a/src/Genocs.WebApi.CQRS/IDispatcher.cs b/src/Genocs.WebApi.CQRS/IDispatcher.cs index a8dbaf8f..032bc337 100644 --- a/src/Genocs.WebApi.CQRS/IDispatcher.cs +++ b/src/Genocs.WebApi.CQRS/IDispatcher.cs @@ -12,5 +12,5 @@ Task SendAsync(T command, CancellationToken cancellationToken = default) Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent; - Task QueryAsync(IQuery query, CancellationToken cancellationToken = default); + Task QueryAsync(IQuery query, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs b/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs index 0e1ed123..67de3369 100644 --- a/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs +++ b/src/Genocs.WebApi.CQRS/IDispatcherEndpointsBuilder.cs @@ -18,40 +18,64 @@ IDispatcherEndpointsBuilder Get( IDispatcherEndpointsBuilder Get( string path, Func? beforeDispatch = null, - Func? afterDispatch = null, + Func? afterDispatch = null, Action? endpoint = null, bool auth = false, string? roles = null, params string[] policies) where TQuery : class, IQuery; - IDispatcherEndpointsBuilder Post(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies); + IDispatcherEndpointsBuilder Post( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); - IDispatcherEndpointsBuilder Post(string path, Func? beforeDispatch = null, - Func? afterDispatch = null, Action? endpoint = null, - bool auth = false, string? roles = null, - params string[] policies) + IDispatcherEndpointsBuilder Post( + string path, + Func? beforeDispatch = null, + Func? afterDispatch = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where T : class, ICommand; - IDispatcherEndpointsBuilder Put(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies); + IDispatcherEndpointsBuilder Put( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); - IDispatcherEndpointsBuilder Put(string path, Func? beforeDispatch = null, - Func? afterDispatch = null, Action? endpoint = null, - bool auth = false, string? roles = null, - params string[] policies) + IDispatcherEndpointsBuilder Put( + string path, + Func? beforeDispatch = null, + Func? afterDispatch = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where T : class, ICommand; - IDispatcherEndpointsBuilder Delete(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies); + IDispatcherEndpointsBuilder Delete( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); - IDispatcherEndpointsBuilder Delete(string path, Func? beforeDispatch = null, - Func? afterDispatch = null, Action? endpoint = null, - bool auth = false, string? roles = null, - params string[] policies) + IDispatcherEndpointsBuilder Delete( + string path, + Func? beforeDispatch = null, + Func? afterDispatch = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where T : class, ICommand; } \ No newline at end of file diff --git a/src/Genocs.WebApi.CQRS/InMemoryDispatcher.cs b/src/Genocs.WebApi.CQRS/InMemoryDispatcher.cs index 17a2ed47..0499d41d 100644 --- a/src/Genocs.WebApi.CQRS/InMemoryDispatcher.cs +++ b/src/Genocs.WebApi.CQRS/InMemoryDispatcher.cs @@ -10,20 +10,24 @@ public class InMemoryDispatcher : IDispatcher private readonly IEventDispatcher _eventDispatcher; private readonly IQueryDispatcher _queryDispatcher; - public InMemoryDispatcher(ICommandDispatcher commandDispatcher, IEventDispatcher eventDispatcher, - IQueryDispatcher queryDispatcher) + public InMemoryDispatcher( + ICommandDispatcher commandDispatcher, + IEventDispatcher eventDispatcher, + IQueryDispatcher queryDispatcher) { _commandDispatcher = commandDispatcher; _eventDispatcher = eventDispatcher; _queryDispatcher = queryDispatcher; } - public Task SendAsync(T command, CancellationToken cancellationToken = default) where T : class, ICommand + public Task SendAsync(T command, CancellationToken cancellationToken = default) + where T : class, ICommand => _commandDispatcher.SendAsync(command, cancellationToken); - public Task PublishAsync(T @event, CancellationToken cancellationToken = default) where T : class, IEvent + public Task PublishAsync(T @event, CancellationToken cancellationToken = default) + where T : class, IEvent => _eventDispatcher.PublishAsync(@event, cancellationToken); - public Task QueryAsync(IQuery query, CancellationToken cancellationToken = default) + public Task QueryAsync(IQuery query, CancellationToken cancellationToken = default) => _queryDispatcher.QueryAsync(query, cancellationToken); } \ No newline at end of file diff --git a/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs b/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs index 555198a0..01caf803 100644 --- a/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs +++ b/src/Genocs.WebApi.CQRS/Middlewares/PublicContractsMiddleware.cs @@ -72,7 +72,6 @@ private void Load(Type attributeType) if (!string.IsNullOrWhiteSpace(name) && instance != null) { - if (Contracts.Commands.ContainsKey(name)) { throw new InvalidOperationException($"Command: '{name}' already exists."); @@ -89,12 +88,15 @@ private void Load(Type attributeType) object? instance = @event.GetDefaultInstance(); string? name = instance?.GetType().Name; - if (Contracts.Events.ContainsKey(name)) + if (!string.IsNullOrWhiteSpace(name) && instance != null) { - throw new InvalidOperationException($"Event: '{name}' already exists."); - } + if (Contracts.Events.ContainsKey(name)) + { + throw new InvalidOperationException($"Event: '{name}' already exists."); + } - Contracts.Events[name] = instance; + Contracts.Events[name] = instance; + } } _serializedContracts = JsonSerializer.Serialize(Contracts, SerializerOptions); diff --git a/src/Genocs.WebApi.Security/CertificateMiddleware.cs b/src/Genocs.WebApi.Security/CertificateMiddleware.cs index e976c994..aefdeb61 100644 --- a/src/Genocs.WebApi.Security/CertificateMiddleware.cs +++ b/src/Genocs.WebApi.Security/CertificateMiddleware.cs @@ -11,7 +11,7 @@ internal sealed class CertificateMiddleware : IMiddleware private readonly ILogger _logger; private readonly SecurityOptions.CertificateOptions _options; private readonly HashSet _allowedHosts; - private readonly IDictionary _acl; + private readonly IDictionary _acl = new Dictionary(); private readonly IDictionary _subjects = new Dictionary(); private readonly bool _validateAcl; private readonly bool _skipRevocationCheck; @@ -23,7 +23,14 @@ public CertificateMiddleware( { _certificatePermissionValidator = certificatePermissionValidator; _logger = logger; + + if (options.Certificate is null) + { + throw new ArgumentNullException(nameof(options.Certificate)); + } + _options = options.Certificate; + _allowedHosts = new HashSet(_options.AllowedHosts ?? Array.Empty()); _validateAcl = _options.Acl is not null && _options.Acl.Any(); _skipRevocationCheck = options.Certificate.SkipRevocationCheck; @@ -33,29 +40,36 @@ public CertificateMiddleware( return; } - _acl = new Dictionary(); - foreach (var (key, acl) in _options.Acl) + if (_options.Acl != null) { - if (!string.IsNullOrWhiteSpace(acl.ValidIssuer) && !acl.ValidIssuer.StartsWith("CN=")) + foreach (var (key, acl) in _options.Acl) { - acl.ValidIssuer = $"CN={acl.ValidIssuer}"; - } + if (!string.IsNullOrWhiteSpace(acl.ValidIssuer) && !acl.ValidIssuer.StartsWith("CN=")) + { + acl.ValidIssuer = $"CN={acl.ValidIssuer}"; + } - string subject = key.StartsWith("CN=") ? key : $"CN={key}"; - if (_options.AllowSubdomains) - { - foreach (string domain in options.Certificate.AllowedDomains ?? Enumerable.Empty()) + string subject = key.StartsWith("CN=") ? key : $"CN={key}"; + if (_options.AllowSubdomains) { - _subjects.Add($"{subject}.{domain}", key); + foreach (string domain in options.Certificate.AllowedDomains ?? Enumerable.Empty()) + { + _subjects.Add($"{subject}.{domain}", key); + } } - } - _acl.Add(_subjects.Any() ? key : subject, acl); + _acl.Add(_subjects.Any() ? key : subject, acl); + } } } public Task InvokeAsync(HttpContext context, RequestDelegate next) { + if (_options is null) + { + return next(context); + } + if (!_options.Enabled) { return next(context); diff --git a/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs b/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs index dc4c04ee..54ef2aa2 100644 --- a/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs +++ b/src/Genocs.WebApi.Security/Configurations/SecurityOptions.cs @@ -14,7 +14,8 @@ public class CertificateOptions public IDictionary? Acl { get; set; } public bool SkipRevocationCheck { get; set; } - public string GetHeaderName() => string.IsNullOrWhiteSpace(Header) ? "Certificate" : Header; + public string GetHeaderName() + => string.IsNullOrWhiteSpace(Header) ? "Certificate" : Header; public class AclOptions { diff --git a/src/Genocs.WebApi.Security/Extensions.cs b/src/Genocs.WebApi.Security/Extensions.cs index d81de65b..d06d2b29 100644 --- a/src/Genocs.WebApi.Security/Extensions.cs +++ b/src/Genocs.WebApi.Security/Extensions.cs @@ -17,6 +17,12 @@ public static IGenocsBuilder AddCertificateAuthentication( string sectionName = SectionName, Type? permissionValidatorType = null) { + + if (string.IsNullOrWhiteSpace(sectionName)) + { + sectionName = SectionName; + } + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); if (!builder.TryRegister(RegistryName)) diff --git a/src/Genocs.WebApi.Swagger/Builders/OpenApiSettingsBuilder.cs b/src/Genocs.WebApi.Swagger/Builders/OpenApiSettingsBuilder.cs new file mode 100644 index 00000000..08c65166 --- /dev/null +++ b/src/Genocs.WebApi.Swagger/Builders/OpenApiSettingsBuilder.cs @@ -0,0 +1,59 @@ +using Genocs.WebApi.Swagger.Configurations; + +namespace Genocs.WebApi.Swagger.Builders; + +internal sealed class OpenApiSettingsBuilder : IOpenApiSettingsBuilder +{ + private readonly OpenApiSettings _options = new(); + + public IOpenApiSettingsBuilder Enable(bool enabled) + { + _options.Enabled = enabled; + return this; + } + + public IOpenApiSettingsBuilder ReDocEnable(bool reDocEnabled) + { + _options.ReDocEnabled = reDocEnabled; + return this; + } + + public IOpenApiSettingsBuilder WithName(string name) + { + _options.Name = name; + return this; + } + + public IOpenApiSettingsBuilder WithTitle(string title) + { + _options.Title = title; + return this; + } + + public IOpenApiSettingsBuilder WithVersion(string version) + { + _options.Version = version; + return this; + } + + public IOpenApiSettingsBuilder WithRoutePrefix(string routePrefix) + { + _options.RoutePrefix = routePrefix; + return this; + } + + public IOpenApiSettingsBuilder IncludeSecurity(bool includeSecurity) + { + _options.IncludeSecurity = includeSecurity; + return this; + } + + public IOpenApiSettingsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2) + { + _options.SerializeAsOpenApiV2 = serializeAsOpenApiV2; + return this; + } + + public OpenApiSettings Build() + => _options; +} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs deleted file mode 100644 index 36173a5b..00000000 --- a/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Genocs.WebApi.Swagger.Docs.Configurations; - -namespace Genocs.WebApi.Swagger.Docs.Builders; - -internal sealed class SwaggerOptionsBuilder : ISwaggerOptionsBuilder -{ - private readonly SwaggerOptions _options = new(); - - public ISwaggerOptionsBuilder Enable(bool enabled) - { - _options.Enabled = enabled; - return this; - } - - public ISwaggerOptionsBuilder ReDocEnable(bool reDocEnabled) - { - _options.ReDocEnabled = reDocEnabled; - return this; - } - - public ISwaggerOptionsBuilder WithName(string name) - { - _options.Name = name; - return this; - } - - public ISwaggerOptionsBuilder WithTitle(string title) - { - _options.Title = title; - return this; - } - - public ISwaggerOptionsBuilder WithVersion(string version) - { - _options.Version = version; - return this; - } - - public ISwaggerOptionsBuilder WithRoutePrefix(string routePrefix) - { - _options.RoutePrefix = routePrefix; - return this; - } - - public ISwaggerOptionsBuilder IncludeSecurity(bool includeSecurity) - { - _options.IncludeSecurity = includeSecurity; - return this; - } - - public ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2) - { - _options.SerializeAsOpenApiV2 = serializeAsOpenApiV2; - return this; - } - - public SwaggerOptions Build() => _options; -} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Configurations/IOpenApiSettingsBuilder.cs b/src/Genocs.WebApi.Swagger/Configurations/IOpenApiSettingsBuilder.cs new file mode 100644 index 00000000..8785fe46 --- /dev/null +++ b/src/Genocs.WebApi.Swagger/Configurations/IOpenApiSettingsBuilder.cs @@ -0,0 +1,13 @@ +namespace Genocs.WebApi.Swagger.Configurations; +public interface IOpenApiSettingsBuilder +{ + IOpenApiSettingsBuilder Enable(bool enabled); + IOpenApiSettingsBuilder ReDocEnable(bool reDocEnabled); + IOpenApiSettingsBuilder WithName(string name); + IOpenApiSettingsBuilder WithTitle(string title); + IOpenApiSettingsBuilder WithVersion(string version); + IOpenApiSettingsBuilder WithRoutePrefix(string routePrefix); + IOpenApiSettingsBuilder IncludeSecurity(bool includeSecurity); + IOpenApiSettingsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2); + OpenApiSettings Build(); +} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Configurations/OpenApiSettings.cs b/src/Genocs.WebApi.Swagger/Configurations/OpenApiSettings.cs new file mode 100644 index 00000000..dc4b0eb0 --- /dev/null +++ b/src/Genocs.WebApi.Swagger/Configurations/OpenApiSettings.cs @@ -0,0 +1,51 @@ + +namespace Genocs.WebApi.Swagger.Configurations; + +public class OpenApiSettings +{ + public static string Position = "OpenApi"; + + /// + /// Gets or sets a value indicating whether the Swagger is enabled. + /// + public bool Enabled { get; set; } + + public string? Name { get; set; } + + /// + /// Gets or sets a value indicating whether the ReDoc is enabled. + /// + public bool ReDocEnabled { get; set; } + + /// + /// The Swagger documentation title. + /// + public string? Title { get; set; } + + /// + /// The Swagger documentation version. + /// + public string? Version { get; set; } + + /// + /// The Swagger documentation description. + /// + public string? Description { get; set; } + public string? ContactName { get; set; } + public string? ContactEmail { get; set; } + public string? ContactUrl { get; set; } + public bool License { get; set; } + public string? LicenseName { get; set; } + public string? LicenseUrl { get; set; } + public string? TermsAndConditionsUrl { get; set; } + public bool SerializeAsOpenApiV2 { get; set; } + public string? RoutePrefix { get; set; } + public bool IncludeSecurity { get; set; } + public IEnumerable? Servers { get; internal set; } +} + +public class ServerDetails +{ + public string? Url { get; set; } + public string? Description { get; set; } +} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs deleted file mode 100644 index 420554f2..00000000 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Genocs.WebApi.Swagger.Docs.Configurations; -public interface ISwaggerOptionsBuilder -{ - ISwaggerOptionsBuilder Enable(bool enabled); - ISwaggerOptionsBuilder ReDocEnable(bool reDocEnabled); - ISwaggerOptionsBuilder WithName(string name); - ISwaggerOptionsBuilder WithTitle(string title); - ISwaggerOptionsBuilder WithVersion(string version); - ISwaggerOptionsBuilder WithRoutePrefix(string routePrefix); - ISwaggerOptionsBuilder IncludeSecurity(bool includeSecurity); - ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2); - SwaggerOptions Build(); -} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs deleted file mode 100644 index 22af3c8b..00000000 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Genocs.WebApi.Swagger.Docs.Configurations; - -public class SwaggerOptions -{ - public bool Enabled { get; set; } - public bool ReDocEnabled { get; set; } - public string? Name { get; set; } - public string? Title { get; set; } - public string? Version { get; set; } - public string? RoutePrefix { get; set; } - public bool IncludeSecurity { get; set; } - public bool SerializeAsOpenApiV2 { get; set; } -} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs index b8a177c0..7479d0b2 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs @@ -1,7 +1,9 @@ +using System.Reflection; using Genocs.Core.Builders; -using Genocs.WebApi.Swagger.Docs.Builders; -using Genocs.WebApi.Swagger.Docs.Configurations; +using Genocs.WebApi.Swagger.Builders; +using Genocs.WebApi.Swagger.Configurations; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; @@ -19,38 +21,126 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, string sectionName = SectionName; } - var options = builder.GetOptions(sectionName); - return builder.AddSwaggerDocs(options); + OpenApiSettings settings = builder.GetOptions(sectionName); + + if (settings is null) + { + return builder; + } + + return builder.AddSwaggerDocs(settings); } - public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) + public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) { - var options = buildOptions(new SwaggerOptionsBuilder()).Build(); - return builder.AddSwaggerDocs(options); + OpenApiSettings settings = buildOptions(new OpenApiSettingsBuilder()).Build(); + + if (settings is null) + { + return builder; + } + + return builder.AddSwaggerDocs(settings); } - public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, SwaggerOptions options) + public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, OpenApiSettings settings) { - if (!options.Enabled || !builder.TryRegister(RegistryName)) + if (!settings.Enabled || !builder.TryRegister(RegistryName)) { return builder; } - builder.Services.AddSingleton(options); + // TODO: Double-check if this is necessary + builder.Services.AddSingleton(settings); + + // Register the Swagger generator, defining 1 or more Swagger documents builder.Services.AddSwaggerGen(c => { c.EnableAnnotations(); - c.SwaggerDoc(options.Name, new OpenApiInfo { Title = options.Title, Version = options.Version }); - if (options.IncludeSecurity) + + c.SwaggerDoc( + settings.Name, + new OpenApiInfo + { + Version = settings.Version, + Title = settings.Title, + Description = settings.Description, + TermsOfService = new Uri(settings.TermsAndConditionsUrl ?? "https://www.genocs.com/terms_and_conditions.html"), + Contact = new OpenApiContact + { + Name = settings.ContactName, + Email = settings.ContactEmail, + Url = new Uri(settings.ContactUrl ?? "https://www.genocs.com") + }, + License = new OpenApiLicense + { + Name = settings.LicenseName, + Url = new Uri(settings.LicenseUrl ?? "https://opensource.org/license/mit/") + } + }); + + if (settings.IncludeSecurity) { c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", Name = "Authorization", In = ParameterLocation.Header, - Type = SecuritySchemeType.ApiKey + Type = SecuritySchemeType.ApiKey, + Scheme = "Bearer" }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement() + { + { + new OpenApiSecurityScheme + { + Name = "Bearer", + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + }, + Scheme = "oauth2", + In = ParameterLocation.Header + }, + new List() + } + }); + } + + // This is required to make the custom operation ids work + // It's required to be used by LangChain tools + c.CustomOperationIds(oid => + { + if (oid.ActionDescriptor is not ControllerActionDescriptor actionDescriptor) + { + return null; // default behavior + } + + return oid.GroupName switch + { + "v1" => $"{actionDescriptor.ActionName}", + _ => $"_{actionDescriptor.ActionName}", // default behavior + }; + }); + + // Add list of servers + + if (settings.Servers != null) + { + foreach (var server in settings.Servers) + { + c.AddServer(new OpenApiServer() { Url = server.Url, Description = server.Description }); + } } + + // c.AddServer(new OpenApiServer() { Url = "http://localhost:5300", Description = "Local version to be used for development" }); + // c.AddServer(new OpenApiServer() { Url = "http://fiscanner-api", Description = "Containerized version to be used into with docker or k8s" }); + // c.AddServer(new OpenApiServer() { Url = "https://fiscanner-api.azurewebsites.net", Description = "Production deployed on Azure" }); + + string documentationFile = Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetEntryAssembly()?.GetName().Name}.xml"); + c.IncludeXmlComments(documentationFile); }); return builder; @@ -58,7 +148,7 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, Swagger public static IApplicationBuilder UseSwaggerDocs(this IApplicationBuilder builder) { - var options = builder.ApplicationServices.GetRequiredService(); + var options = builder.ApplicationServices.GetRequiredService(); if (!options.Enabled) { return builder; diff --git a/src/Genocs.WebApi.Swagger/Extensions.cs b/src/Genocs.WebApi.Swagger/Extensions.cs index 43e09e75..1ad30d59 100644 --- a/src/Genocs.WebApi.Swagger/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Extensions.cs @@ -1,6 +1,6 @@ using Genocs.Core.Builders; +using Genocs.WebApi.Swagger.Configurations; using Genocs.WebApi.Swagger.Docs; -using Genocs.WebApi.Swagger.Docs.Configurations; using Genocs.WebApi.Swagger.Filters; using Microsoft.Extensions.DependencyInjection; @@ -20,10 +20,10 @@ public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, s return builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(sectionName)); } - public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) + public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) => builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(buildOptions)); - public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, SwaggerOptions options) + public static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, OpenApiSettings options) => builder.AddWebApiSwaggerDocs(b => b.AddSwaggerDocs(options)); private static IGenocsBuilder AddWebApiSwaggerDocs(this IGenocsBuilder builder, Action registerSwagger) diff --git a/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs b/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs index c6c4e570..34630658 100644 --- a/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs +++ b/src/Genocs.WebApi.Swagger/Filters/WebApiDocumentFilter.cs @@ -12,7 +12,6 @@ internal sealed class WebApiDocumentFilter : IDocumentFilter private readonly WebApiEndpointDefinitions _definitions; - private readonly Func _getOperation = (item, path) => { switch (path) @@ -48,6 +47,12 @@ public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) foreach (var methodDefinition in pathDefinition) { var operation = _getOperation(pathItem, methodDefinition.Method); + + if (operation is null) + { + continue; + } + operation.Responses = new OpenApiResponses(); operation.Parameters = new List(); diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 04a6326d..064c7045 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -11,7 +11,7 @@ 6.1.0 5.0.0 Nocco Giovanni Emanuele - aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles + microservice microservices solid solid-principles genocs webapi swagger openapi open-api README_NUGET.md Aligned to the ecosystem True @@ -42,6 +42,7 @@ + From 3ea5a05522ec98715802cd24ed1c660acd89588a Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 20 Oct 2024 11:16:23 +0200 Subject: [PATCH 083/104] Add detailed Swagger configuration and options Updated `appsettings.json` to include a comprehensive "swagger" section with configuration options such as `enabled`, `title`, `description`, `version`, `termsOfService`, `contactName`, `contactEmail`, `contactUrl`, `licenseName`, `licenseUrl`, `includeSecurity`, and a list of `servers`. Extended `SwaggerOptions` class to include new properties: `Description`, `ContactName`, `ContactEmail`, `ContactUrl`, `LicenseName`, `LicenseUrl`, `TermsOfService`, and a list of `OpenApiServer` objects. Added an inner class `OpenApiServer` to represent server details. Modified `AddSwaggerDocs` method in `Extensions.cs` to handle the new `SwaggerOptions` properties, including logic for security definitions, custom operation IDs, and server details. Added XML comments to the Swagger documentation. Provided specific values for the "swagger" section in `appsettings.json` for different environments (local development, containerized, and production). --- src/Genocs.Core.Demo.WebApi/appsettings.json | 12 ++ .../Docs/Configurations/SwaggerOptions.cs | 18 ++- src/Genocs.WebApi.Swagger/Docs/Extensions.cs | 110 ++++++++++++++++-- .../Genocs.Orders.WebApi/appsettings.json | 28 ++++- 4 files changed, 154 insertions(+), 14 deletions(-) diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 950182b6..3c2f6c46 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -70,5 +70,17 @@ "caller": "<<>>", "public": "<<>>", "private": "<<>>" + }, + "swagger": { + "enabled": true, + "title": "Demo WebApi", + "description": "Demo WebApi", + "version": "v1", + "servers": [ + { + "name": "Genocs", + "email": "giovanni.nocco@genocs.com" + } + ] } } diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs index 22af3c8b..8a77dad7 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs @@ -7,7 +7,23 @@ public class SwaggerOptions public string? Name { get; set; } public string? Title { get; set; } public string? Version { get; set; } + public string? Description { get; set; } public string? RoutePrefix { get; set; } + public string? ContactName { get; set; } + public string? ContactEmail { get; set; } + public string? ContactUrl { get; set; } + public string? LicenseName { get; set; } + public string? LicenseUrl { get; set; } + public string? TermsOfService { get; set; } public bool IncludeSecurity { get; set; } public bool SerializeAsOpenApiV2 { get; set; } -} \ No newline at end of file + public List? Servers { get; set; } + + public class OpenApiServer + { + + public string? Url { get; set; } + public string? Description { get; set; } + } +} + diff --git a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs index b8a177c0..aa3c37db 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Extensions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Extensions.cs @@ -1,7 +1,9 @@ +using System.Reflection; using Genocs.Core.Builders; using Genocs.WebApi.Swagger.Docs.Builders; using Genocs.WebApi.Swagger.Docs.Configurations; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; @@ -19,38 +21,126 @@ public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, string sectionName = SectionName; } - var options = builder.GetOptions(sectionName); - return builder.AddSwaggerDocs(options); + SwaggerOptions settings = builder.GetOptions(sectionName); + + if (settings is null) + { + return builder; + } + + return builder.AddSwaggerDocs(settings); } public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, Func buildOptions) { - var options = buildOptions(new SwaggerOptionsBuilder()).Build(); - return builder.AddSwaggerDocs(options); + SwaggerOptions settings = buildOptions(new SwaggerOptionsBuilder()).Build(); + + if (settings is null) + { + return builder; + } + + return builder.AddSwaggerDocs(settings); } - public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, SwaggerOptions options) + public static IGenocsBuilder AddSwaggerDocs(this IGenocsBuilder builder, SwaggerOptions settings) { - if (!options.Enabled || !builder.TryRegister(RegistryName)) + if (!settings.Enabled || !builder.TryRegister(RegistryName)) { return builder; } - builder.Services.AddSingleton(options); + // TODO: Double-check if this is necessary + builder.Services.AddSingleton(settings); + + // Register the Swagger generator, defining 1 or more Swagger documents builder.Services.AddSwaggerGen(c => { c.EnableAnnotations(); - c.SwaggerDoc(options.Name, new OpenApiInfo { Title = options.Title, Version = options.Version }); - if (options.IncludeSecurity) + + c.SwaggerDoc( + settings.Name, + new OpenApiInfo + { + Version = settings.Version, + Title = settings.Title, + Description = settings.Description, + TermsOfService = new Uri(settings.TermsOfService ?? "https://www.genocs.com/terms_and_conditions.html"), + Contact = new OpenApiContact + { + Name = settings.ContactName, + Email = settings.ContactEmail, + Url = new Uri(settings.ContactUrl ?? "https://www.genocs.com") + }, + License = new OpenApiLicense + { + Name = settings.LicenseName, + Url = new Uri(settings.LicenseUrl ?? "https://opensource.org/license/mit/") + } + }); + + if (settings.IncludeSecurity) { c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", Name = "Authorization", In = ParameterLocation.Header, - Type = SecuritySchemeType.ApiKey + Type = SecuritySchemeType.ApiKey, + Scheme = "Bearer" }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement() + { + { + new OpenApiSecurityScheme + { + Name = "Bearer", + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + }, + Scheme = "oauth2", + In = ParameterLocation.Header + }, + new List() + } + }); + } + + // This is required to make the custom operation ids work + // It's required to be used by LangChain tools + c.CustomOperationIds(oid => + { + if (oid.ActionDescriptor is not ControllerActionDescriptor actionDescriptor) + { + return null; // default behavior + } + + return oid.GroupName switch + { + "v1" => $"{actionDescriptor.ActionName}", + _ => $"_{actionDescriptor.ActionName}", // default behavior + }; + }); + + // Add list of servers + + if (settings.Servers != null) + { + foreach (var server in settings.Servers) + { + c.AddServer(new OpenApiServer() { Url = server.Url, Description = server.Description }); + } } + + // c.AddServer(new OpenApiServer() { Url = "http://localhost:5300", Description = "Local version to be used for development" }); + // c.AddServer(new OpenApiServer() { Url = "http://fiscanner-api", Description = "Containerized version to be used into with docker or k8s" }); + // c.AddServer(new OpenApiServer() { Url = "https://fiscanner-api.azurewebsites.net", Description = "Production deployed on Azure" }); + + string documentationFile = Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetEntryAssembly()?.GetName().Name}.xml"); + c.IncludeXmlComments(documentationFile); }); return builder; diff --git a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json index 3d100b46..37f4c88d 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json +++ b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json @@ -133,10 +133,32 @@ "swagger": { "enabled": true, "reDocEnabled": false, - "name": "v1", + "name": "Orders", "title": "Orders Service", - "version": "v1", - "routePrefix": "swagger" + "version": "v002", + "description": "Orders Service", + "routePrefix": "swagger", + "termsOfService": "https://www.genocs.com/terms_and_conditions.html", + "contactName": "Giovanni Nocco", + "contactEmail": "giovanni.nocco@genocs.com", + "contactUrl": "https://www.genocs.com", + "licenseName": "MIT", + "licenseUrl": "https://www.genocs.com/license.html", + "includeSecurity": true, + "servers": [ + { + "url": "http://localhost:5300", + "description": "Local version to be used for development" + }, + { + "url": "http://fiscanner-api", + "description": "Containerized version to be used into with docker or k8s" + }, + { + "url": "https://fiscanner-api.azurewebsites.net", + "description": "Production deployed on Azure" + } + ] }, "redis": { "connectionString": "localhost", From 5909e0b1a03d51817816cf4c1944e5fc93af32f9 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 22 Oct 2024 18:33:02 +0200 Subject: [PATCH 084/104] Update package versions in workflows and projects --- .github/workflows/dockerhub-publish.yml | 2 +- .github/workflows/nuget-publish.yml | 2 +- src/Genocs.Auth/Genocs.Auth.csproj | 6 +- src/Genocs.Common/Genocs.Common.csproj | 2 +- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 4 +- .../Genocs.Core.Demo.WebApi.csproj | 16 ++-- .../Genocs.Core.Demo.Worker.csproj | 6 +- src/Genocs.Core/Genocs.Core.csproj | 4 +- .../Genocs.Discovery.Consul.csproj | 6 +- .../Genocs.HTTP.RestEase.csproj | 10 +-- src/Genocs.HTTP/Genocs.HTTP.csproj | 4 +- .../Genocs.LoadBalancing.Fabio.csproj | 8 +- src/Genocs.Logging/Genocs.Logging.csproj | 4 +- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 6 +- .../Genocs.MessageBrokers.Outbox.csproj | 4 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 4 +- .../Genocs.MessageBrokers.csproj | 4 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 4 +- .../Genocs.Monitoring.csproj | 8 +- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 4 +- .../Genocs.Persistence.Redis.csproj | 4 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +- .../Genocs.QueryBuilder.csproj | 2 +- .../Genocs.Secrets.AzureKeyVault.csproj | 4 +- .../Genocs.Secrets.Vault.csproj | 4 +- src/Genocs.Security/Genocs.Security.csproj | 4 +- .../Genocs.ServiceBusAzure.csproj | 4 +- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 6 +- src/Genocs.Tracing/Genocs.Tracing.csproj | 8 +- .../Genocs.WebApi.CQRS.csproj | 6 +- .../Genocs.WebApi.Security.csproj | 4 +- .../Builders/SwaggerOptionsBuilder.cs | 14 ++++ .../Configurations/ISwaggerOptionsBuilder.cs | 2 + .../Docs/Configurations/SwaggerOptions.cs | 76 ++++++++++++++++++- .../Genocs.WebApi.Swagger.csproj | 4 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 4 +- .../Genocs.APIGateway.csproj | 12 +-- .../Genocs.Identities.Application.csproj | 20 ++--- .../Genocs.Orders.WebApi.csproj | 22 +++--- .../Genocs.Orders.WebApi/appsettings.json | 3 +- .../Genocs.Products.WebApi.csproj | 32 ++++---- .../Genocs.SignalR.WebApi.csproj | 34 ++++----- 44 files changed, 237 insertions(+), 148 deletions(-) diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml index f4de01d5..e8d987f2 100644 --- a/.github/workflows/dockerhub-publish.yml +++ b/.github/workflows/dockerhub-publish.yml @@ -13,7 +13,7 @@ on: description: "Image Version" # Default value if no value is explicitly provided - default: "6.1.0" + default: "6.2.0" # Input has to be provided for the workflow to run required: true diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index 9f83a1fc..7e70f358 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -13,7 +13,7 @@ on: description: "Packages Version" # Default value if no value is explicitly provided - default: "6.1.0" + default: "6.2.0" # Input has to be provided for the workflow to run required: true diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index a4177e2d..9a211f0e 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -8,7 +8,7 @@ The authorization library useful to build .NET Core projects. The authorization library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele microservice microservices solid solid-principles authentication genocs @@ -40,8 +40,8 @@ - - + + diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index cbf8070b..c5f5dd7f 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -8,7 +8,7 @@ The Genocs Library - Common components. The common components to build .NET Core projects along with Genocs Library. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele microservice microservices solid solid-principles genocs diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 639522b5..60d051d7 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 33d46865..2a89b449 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 02433777..2e7e458a 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -21,14 +21,14 @@ - - - - - - - - + + + + + + + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 67cfc695..526644a0 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index c27b2c63..0dcd00a9 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -8,7 +8,7 @@ The Genocs Library - Core components. The core components to build .NET Core projects along with Genocs Library. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele microservice microservices solid solid-principles genocs @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 3c2e0101..396dbccb 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -8,7 +8,7 @@ The service discovery by Consul library useful to build .NET Core projects. The service discovery by Consul library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele microservice microservices solid solid-principles genocs service-discovery @@ -40,8 +40,8 @@ - - + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 93c8142e..83b31bb5 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -8,7 +8,7 @@ The http support library useful to build .NET Core projects. The http support library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -42,10 +42,10 @@ - - - - + + + + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index f38010bb..745f57c0 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -8,7 +8,7 @@ The http support library useful to build .NET Core projects. The http support library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele microservice microservices solid solid-principles genocs http-client @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 6186974a..56779b7c 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -8,7 +8,7 @@ The load balacer based on Fabio library useful to build .NET Core projects. The load balacer based on Fabio library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -41,9 +41,9 @@ - - - + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index bfc32b75..00019247 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -8,7 +8,7 @@ The logging library useful to build .NET Core projects. The logging library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index d154f4d3..0f4b711c 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -8,7 +8,7 @@ The message brokers outbox MongoDB interface library useful to build .NET Core projects. The message brokers MongoDB outbox interface library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -39,8 +39,8 @@ - - + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 9144b14b..a17fcb4a 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -8,7 +8,7 @@ The message brokers outbox interface library useful to build .NET Core projects. The message brokers outbox interface library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index 763ff798..a2ea22f8 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -8,7 +8,7 @@ The message brokers RabbitMQ interface library useful to build .NET Core projects. The message brokers RabbitMQ outbox interface library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 5eded034..4629f8b1 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -8,7 +8,7 @@ The message brokers interface library useful to build .NET Core projects. The message brokers interface library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -39,7 +39,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 97f76b06..6cc116b2 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -8,7 +8,7 @@ The metrics interface library useful to build .NET Core projects. The metrics interface library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 7f19478e..14648d28 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -8,7 +8,7 @@ Telemetry and Tracing library. Telemetry and Tracing library. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -41,9 +41,9 @@ - - - + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 6c646282..4bb8f0ed 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 164bb4ab..17a6d363 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -8,7 +8,7 @@ The Persistence MongoDB Library. The Genocs Library .NET Core to be used with MongoDB as persistence datalayer.. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele mongodb aggregate architecture boilerplate repository-patterns domain-driven-design dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 0f42539f..079d4057 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -8,7 +8,7 @@ The Persistence Redis Library. The library containing base repository pattern to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 4f2e8021..caf4b3dd 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj index 93be3849..b8d0363b 100644 --- a/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj +++ b/src/Genocs.QueryBuilder/Genocs.QueryBuilder.csproj @@ -8,7 +8,7 @@ The Persistence Agnostic Query Builder Library. The persistence agnostic query builder library. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index cc4f02e0..ae39cd2f 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -8,7 +8,7 @@ The Genocs Secrets AzureKeyVault library The Genocs Secrets AzureKeyVault library true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 7eb9325d..0763a33a 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -8,7 +8,7 @@ The Genocs Secrets Vault library The Genocs Secrets Vault library true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index d38ccf63..be2ffa15 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -8,7 +8,7 @@ The Genocs Security library The Genocs Security library true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 75e56183..9a7d1082 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -8,7 +8,7 @@ The low level library to use Azure Service Bus. The low level library to use Azure Service Bus. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -39,7 +39,7 @@ - + diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index 2867c20d..4a63c2c1 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -8,7 +8,7 @@ The load balacer based on Fabio library useful to build .NET Core projects. The load balacer based on Fabio library useful to build .NET Core projects. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -39,8 +39,8 @@ - - + + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index b57fefa4..fa9fb7fd 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -8,7 +8,7 @@ The tracing library to use Azure Service Bus. The tracing library to use Azure Service Bus. true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -40,9 +40,9 @@ - - - + + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 5c1a7016..443a81d6 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -8,7 +8,7 @@ The web api CORS library The web api CORS library true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -39,7 +39,7 @@ - - + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 8dbcaecf..d544bb8a 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -8,7 +8,7 @@ The web api Security library The web api Security library true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs index 36173a5b..3f782a5e 100644 --- a/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Builders/SwaggerOptionsBuilder.cs @@ -48,6 +48,18 @@ public ISwaggerOptionsBuilder IncludeSecurity(bool includeSecurity) return this; } + public ISwaggerOptionsBuilder WithDescription(string description) + { + _options.Description = description; + return this; + } + + public ISwaggerOptionsBuilder WithContactName(string contactName) + { + _options.ContactName = contactName; + return this; + } + public ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2) { _options.SerializeAsOpenApiV2 = serializeAsOpenApiV2; @@ -55,4 +67,6 @@ public ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2) } public SwaggerOptions Build() => _options; + + } \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs index 420554f2..caddc6c4 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/ISwaggerOptionsBuilder.cs @@ -6,7 +6,9 @@ public interface ISwaggerOptionsBuilder ISwaggerOptionsBuilder WithName(string name); ISwaggerOptionsBuilder WithTitle(string title); ISwaggerOptionsBuilder WithVersion(string version); + ISwaggerOptionsBuilder WithDescription(string description); ISwaggerOptionsBuilder WithRoutePrefix(string routePrefix); + ISwaggerOptionsBuilder WithContactName(string contactName); ISwaggerOptionsBuilder IncludeSecurity(bool includeSecurity); ISwaggerOptionsBuilder SerializeAsOpenApiV2(bool serializeAsOpenApiV2); SwaggerOptions Build(); diff --git a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs index 8a77dad7..c700bdcd 100644 --- a/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs +++ b/src/Genocs.WebApi.Swagger/Docs/Configurations/SwaggerOptions.cs @@ -2,28 +2,100 @@ namespace Genocs.WebApi.Swagger.Docs.Configurations; public class SwaggerOptions { + /// + /// The flag to enable or disable Swagger. + /// public bool Enabled { get; set; } + + /// + /// The flag to enable or disable ReDoc. + /// public bool ReDocEnabled { get; set; } + + /// + /// The name of the API. + /// public string? Name { get; set; } + + /// + /// The title of the API. You can use this field to set the title by using markdown. + /// public string? Title { get; set; } + + /// + /// The version of the API. + /// public string? Version { get; set; } + + /// + /// The description of the API. You can use this field to set the description by using markdown. + /// public string? Description { get; set; } + + /// + /// The route prefix of the API. + /// public string? RoutePrefix { get; set; } + + /// + /// The contact name of the API. + /// public string? ContactName { get; set; } + + /// + /// The contact email of the API. + /// public string? ContactEmail { get; set; } + + /// + /// The contact URL of the API. + /// public string? ContactUrl { get; set; } + + /// + /// The license name of the API. + /// public string? LicenseName { get; set; } + + /// + /// The license URL of the API. + /// public string? LicenseUrl { get; set; } + + /// + /// The terms of service of the API. you can use this field to set the terms of service by using markdown or as url link. + /// public string? TermsOfService { get; set; } + + /// + /// The flag to include security. By using this flag, you can include the security information in the Swagger document. + /// public bool IncludeSecurity { get; set; } + + /// + /// The flag to serialize the Swagger document as OpenAPI version 2.0. + /// public bool SerializeAsOpenApiV2 { get; set; } + + /// + /// List of servers that support this API. + /// public List? Servers { get; set; } + /// + /// Internal class to represent the server information in the Swagger document. + /// public class OpenApiServer { + /// + /// The URL of the server. + /// public string? Url { get; set; } + + /// + /// The description of the server. + /// public string? Description { get; set; } } -} - +} \ No newline at end of file diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 04a6326d..a060ee66 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -8,7 +8,7 @@ The web api Swagger library The web api Swagger library true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 12e0364f..59e4af45 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -8,7 +8,7 @@ The web api library The web api library true - 6.1.0 + 6.2.0 5.0.0 Nocco Giovanni Emanuele aggregate architecture boilerplate ddd ddd-architecture design-patterns docker domain-driven-design dotnet dotnetcore dotnet-core microservice microservices solid solid-principles @@ -39,7 +39,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 1ac971d7..681217f1 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -19,12 +19,12 @@ - - - - - - + + + + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 524bea46..e6d1d9a9 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -20,16 +20,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index da482f0d..28ff640c 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -29,17 +29,17 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json index 37f4c88d..36916f8e 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/appsettings.json +++ b/src/apps/orders/Genocs.Orders.WebApi/appsettings.json @@ -138,13 +138,14 @@ "version": "v002", "description": "Orders Service", "routePrefix": "swagger", - "termsOfService": "https://www.genocs.com/terms_and_conditions.html", "contactName": "Giovanni Nocco", "contactEmail": "giovanni.nocco@genocs.com", "contactUrl": "https://www.genocs.com", "licenseName": "MIT", "licenseUrl": "https://www.genocs.com/license.html", + "termsOfService": "https://www.genocs.com/terms_and_conditions.html", "includeSecurity": true, + "serializeAsOpenApiV2": true, "servers": [ { "url": "http://localhost:5300", diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index 033e4e8b..aff267bf 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -30,22 +30,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 53ca28cb..dc6ebd3c 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -34,22 +34,22 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file From 7a08e96d7625a3aea775a325e20bc117fbb74420 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 22 Oct 2024 18:48:16 +0200 Subject: [PATCH 085/104] Update package versions to 6.2.0 in Genocs.HTTP, Genocs.Core, Genocs.Metrics, Genocs.WebApi, Genocs.Security, Genocs.Logging, Genocs.Secrets.Vault, Genocs.MessageBrokers, Genocs.WebApi.Swagger, Genocs.ServiceBusAzure, Genocs.Persistence.Redis, Genocs.Core.Demo.Contracts, Genocs.Persistence.MongoDb, Genocs.WebApi.Security, Genocs.Secrets.AzureKeyVault, Genocs.MessageBrokers.Outbox, Genocs.MessageBrokers.RabbitMQ, Genocs.Auth, Genocs.WebApi.CQRS, Genocs.Discovery.Consul, Genocs.Persistence.MongoDb.UnitTests, and Genocs.Core.Demo.Domain projects --- src/Genocs.Auth/Genocs.Auth.csproj | 4 +-- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 4 +-- .../Genocs.Core.Demo.WebApi.csproj | 16 ++++----- .../Genocs.Core.Demo.Worker.csproj | 6 ++-- src/Genocs.Core/Genocs.Core.csproj | 2 +- .../Genocs.Discovery.Consul.csproj | 4 +-- .../Genocs.HTTP.RestEase.csproj | 8 ++--- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Genocs.LoadBalancing.Fabio.csproj | 6 ++-- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 4 +-- .../Genocs.MessageBrokers.Outbox.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- .../Genocs.MessageBrokers.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- .../Genocs.Monitoring.csproj | 6 ++-- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +-- .../Genocs.Secrets.AzureKeyVault.csproj | 2 +- .../Genocs.Secrets.Vault.csproj | 2 +- src/Genocs.Security/Genocs.Security.csproj | 2 +- .../Genocs.ServiceBusAzure.csproj | 2 +- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 4 +-- src/Genocs.Tracing/Genocs.Tracing.csproj | 6 ++-- .../Genocs.WebApi.CQRS.csproj | 4 +-- .../Genocs.WebApi.Security.csproj | 2 +- .../Genocs.WebApi.Swagger.csproj | 2 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 2 +- .../Genocs.APIGateway.csproj | 12 +++---- .../Genocs.Identities.Application.csproj | 20 +++++------ .../Genocs.Orders.WebApi.csproj | 22 ++++++------ .../Genocs.Products.WebApi.csproj | 32 ++++++++--------- .../Genocs.SignalR.WebApi.csproj | 34 +++++++++---------- 36 files changed, 116 insertions(+), 116 deletions(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 9a211f0e..96b3c633 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -40,8 +40,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 60d051d7..caf16991 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 2a89b449..4c0cc57e 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 2e7e458a..542dd141 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -21,14 +21,14 @@ - - - - - - - - + + + + + + + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 526644a0..b55f5a53 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 0dcd00a9..e4ddbf50 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 396dbccb..19378ad1 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -40,8 +40,8 @@ - - + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index 83b31bb5..3720017a 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -42,10 +42,10 @@ - - - - + + + + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 745f57c0..c0692dec 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 56779b7c..472ccaaf 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -41,9 +41,9 @@ - - - + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 00019247..21e0162a 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 0f4b711c..7101322f 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -39,8 +39,8 @@ - - + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index a17fcb4a..d0baa581 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index a2ea22f8..0389c3cb 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 4629f8b1..5c6b6612 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index 6cc116b2..9f7bd9f9 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index 14648d28..60769855 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -41,9 +41,9 @@ - - - + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 4bb8f0ed..bb307fc1 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 17a6d363..264d6650 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index 079d4057..748c0e49 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index caf4b3dd..c621e53e 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index ae39cd2f..17f6669f 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index 0763a33a..7627c07b 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index be2ffa15..28f8ec47 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 9a7d1082..9d9a5969 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index 4a63c2c1..2a760a82 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -39,8 +39,8 @@ - - + + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index fa9fb7fd..1568912c 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -40,9 +40,9 @@ - - - + + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 443a81d6..428ae437 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -39,7 +39,7 @@ - - + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index d544bb8a..2b13b51f 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index a060ee66..45e6fae9 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -38,7 +38,7 @@ - + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index 59e4af45..32b0f9f3 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index 681217f1..01f340f2 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -19,12 +19,12 @@ - - - - - - + + + + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index e6d1d9a9..07a024db 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -20,16 +20,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 28ff640c..e58a9952 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -29,17 +29,17 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index aff267bf..5788a968 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -30,22 +30,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index dc6ebd3c..844761b6 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -34,22 +34,22 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file From 328f67e3a0f1ceb1be16be1d7eff0c679c5e5a8e Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Tue, 22 Oct 2024 18:55:42 +0200 Subject: [PATCH 086/104] Update package versions to 6.2.0 in multiple projects --- CHANGELOG.md | 284 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8ed1021..856a1d8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [v6.2.0](https://github.com/Genocs/genocs-library/compare/v6.1.0...v6.2.0) + +> 22 October 2024 + +- Refactor and enhance OpenAPI and middleware handling [`4bbbe88`](https://github.com/Genocs/genocs-library/commit/4bbbe8811151bcefa73254f6f2fd4eba21409c2d) +- Update package versions in workflows and projects [`5909e0b`](https://github.com/Genocs/genocs-library/commit/5909e0b1a03d51817816cf4c1944e5fc93af32f9) +- Update package versions to 6.2.0 in Genocs.HTTP, Genocs.Core, Genocs.Metrics, Genocs.WebApi, Genocs.Security, Genocs.Logging, Genocs.Secrets.Vault, Genocs.MessageBrokers, Genocs.WebApi.Swagger, Genocs.ServiceBusAzure, Genocs.Persistence.Redis, Genocs.Core.Demo.Contracts, Genocs.Persistence.MongoDb, Genocs.WebApi.Security, Genocs.Secrets.AzureKeyVault, Genocs.MessageBrokers.Outbox, Genocs.MessageBrokers.RabbitMQ, Genocs.Auth, Genocs.WebApi.CQRS, Genocs.Discovery.Consul, Genocs.Persistence.MongoDb.UnitTests, and Genocs.Core.Demo.Domain projects [`7a08e96`](https://github.com/Genocs/genocs-library/commit/7a08e96d7625a3aea775a325e20bc117fbb74420) +- Add detailed Swagger configuration and options [`3ea5a05`](https://github.com/Genocs/genocs-library/commit/3ea5a05522ec98715802cd24ed1c660acd89588a) +- Enhance Azure setup, null safety, and code quality [`21f2798`](https://github.com/Genocs/genocs-library/commit/21f27983546f3757d957c03dfef8394df95388d3) +- Refactor: Replace Jaeger with OpenTelemetry [`4e1a3ba`](https://github.com/Genocs/genocs-library/commit/4e1a3ba54d5872421849773efe6aecfed5a1c241) +- Update Roslynator, improve type clarity, and reformat code [`52b5851`](https://github.com/Genocs/genocs-library/commit/52b5851706ca1a0c14849f6ffc398def10b58c3b) + #### [v6.1.0](https://github.com/Genocs/genocs-library/compare/v6.0.0...v6.1.0) > 11 October 2024 @@ -11,6 +23,15 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Refactor interfaces, update Azure Key Vault options, and improve code readability [`485db2c`](https://github.com/Genocs/genocs-library/commit/485db2ca1dd13e87a785a2242248671858fb7e45) - Refactor: Replace Jaeger with OpenTelemetry [`1eed44b`](https://github.com/Genocs/genocs-library/commit/1eed44bd91c9b187bcc1a2d3983ebe52b20e0664) - Refactor interfaces and update Azure Key Vault options [`87edca1`](https://github.com/Genocs/genocs-library/commit/87edca186850db3cbe17398229335012308fb814) +- **List of code changes:** [`01adb18`](https://github.com/Genocs/genocs-library/commit/01adb188466e53010932b58c2475cef69afeecc1) +- Update package versions from 6.0.* to 6.1.* [`088a59a`](https://github.com/Genocs/genocs-library/commit/088a59adc0da7fcb3676a9e08f43a3187ba4d9df) +- Make properties nullable and improve code readability [`6e091e5`](https://github.com/Genocs/genocs-library/commit/6e091e5fa20f0a2d1dda34468675d6fbe787792c) +- Refactor interfaces, update Azure Key Vault options, and improve code readability [`866463f`](https://github.com/Genocs/genocs-library/commit/866463f0f4abf764b667774553301a417733474d) +- Update packages and enhance Azure Key Vault integration [`3b45172`](https://github.com/Genocs/genocs-library/commit/3b45172b945ad7df08a11021c4ef738bad715f33) +- Remove CardToken, update configs, and add Oracle setup [`c1095a7`](https://github.com/Genocs/genocs-library/commit/c1095a76c9755976f829e77ea4051e2b84ef948a) +- Update various NuGet packages across multiple projects [`a1e01bb`](https://github.com/Genocs/genocs-library/commit/a1e01bb0634de8d38a869fb0b75ed530cd42f1db) +- Refactor and update dependencies, fix typos, and improve code formatting [`318ca61`](https://github.com/Genocs/genocs-library/commit/318ca61f46bb69fd29b13346576373d4d0cedd2c) +- Refactor README.md and remove unnecessary lines [`ab02bd7`](https://github.com/Genocs/genocs-library/commit/ab02bd7d529538eee6cf60a2926b6b889853487d) ### [v6.0.0](https://github.com/Genocs/genocs-library/compare/6.0.0-preview.2.0...v6.0.0) @@ -19,6 +40,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Refactor and update dependencies and logging level [`63533a2`](https://github.com/Genocs/genocs-library/commit/63533a2ccfb64106dd81e296ca1a1de55c556f48) - Refactor auth and update docs [`a63d816`](https://github.com/Genocs/genocs-library/commit/a63d816a4b617246ec99b3400d019a1b46ff40b0) - Update packages, fix typos, and improve code formatting [`d634694`](https://github.com/Genocs/genocs-library/commit/d6346942c88195b831bd66f4ff8a1e039695e0b2) +- Update various NuGet packages across multiple projects [`c61eab2`](https://github.com/Genocs/genocs-library/commit/c61eab254c53920f94c575503c41c4e623fd1b36) #### [6.0.0-preview.2.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.4.0...6.0.0-preview.2.0) @@ -35,6 +57,83 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Added documentation and more control over types [`3d4c17e`](https://github.com/Genocs/genocs-library/commit/3d4c17e0e501d9174160f01569d2523472085a04) - Refactor configs and update docs across projects [`504fc40`](https://github.com/Genocs/genocs-library/commit/504fc40ee05a1ed6bc838a5b08195cb285feb8c1) - Merge issues [`cc6c097`](https://github.com/Genocs/genocs-library/commit/cc6c097d28854b584d3df34f9dc3ea6c4be78db9) +- Updated Nuget Packages [`9ff8abb`](https://github.com/Genocs/genocs-library/commit/9ff8abbd28df412a5e8e34b4d6e5fc26bda2046b) +- Sincronize naming conventions [`7bae2b7`](https://github.com/Genocs/genocs-library/commit/7bae2b7496200b36a9f0f0c4f0dadf60b74c3421) +- Updated packages [`9f04ab5`](https://github.com/Genocs/genocs-library/commit/9f04ab59052556b3f27aa3b377b08ed2b3e5e4b8) +- Documentation, updated packages [`3d49180`](https://github.com/Genocs/genocs-library/commit/3d49180fd5bfa4d07f7297b852bee83f2b000849) +- Refactor config naming and add new options [`5977b8c`](https://github.com/Genocs/genocs-library/commit/5977b8c49236a78a209519de00deb6e9865d7b57) +- Updated comments, attributes, methods, and dependencies across multiple files [`ccaf4a5`](https://github.com/Genocs/genocs-library/commit/ccaf4a583373155be0186994deea15dcdabfbade) +- Updated project dependencies and refactored security settings [`cc6bd4d`](https://github.com/Genocs/genocs-library/commit/cc6bd4df16be8fc76e4f7f68359cb1e6c1ae430e) +- Cleanup data after uniform naming conventions [`34b35b2`](https://github.com/Genocs/genocs-library/commit/34b35b2c4979c95b957f144cf7e680d16fca450d) +- Refactor auth/config handling and enhance security [`bb5ea59`](https://github.com/Genocs/genocs-library/commit/bb5ea5989bdbe0bfa756e3b00b1a15a3e12f3942) +- Refactor and enhance JWT handling and security [`b864cc9`](https://github.com/Genocs/genocs-library/commit/b864cc9693111b9d60881a6643e5b16638c15894) +- Refactor and enhance JWT handling and security [`736964d`](https://github.com/Genocs/genocs-library/commit/736964d22cb1715c3c1b0455647077a5797c99ad) +- Integrate Azure Key Vault & Update Packages [`bd2a025`](https://github.com/Genocs/genocs-library/commit/bd2a025418302d032c93219388bc542c9c4b9409) +- Updated multiple packages and improved code readability [`8b9b1b5`](https://github.com/Genocs/genocs-library/commit/8b9b1b58fe6d618f0621e2412934fa94e412bdf5) +- Refactor and enhance codebase for clarity [`227e968`](https://github.com/Genocs/genocs-library/commit/227e9686af3c2f0c036c1546202e3a9d5b998a96) +- Add verification service client and models [`3b27e46`](https://github.com/Genocs/genocs-library/commit/3b27e463fa91d72fe87473c7d6918114896433cd) +- Updated project structure [`9ffe861`](https://github.com/Genocs/genocs-library/commit/9ffe8612bf90808a2584c3a62feb1128be2d65de) +- Fix [`0af67b8`](https://github.com/Genocs/genocs-library/commit/0af67b813a1c7d70d5a7b5f0d3fc8fdf5e7071da) +- Refactor code for improved readability and update variable types [`762c51f`](https://github.com/Genocs/genocs-library/commit/762c51f5b8d38ede287938fde6f0f7638eb33f75) +- Refactor auth and update docs [`06bb32f`](https://github.com/Genocs/genocs-library/commit/06bb32ff452e1e32e94dc5554aa38c7bf7ce5ec8) +- Minor fix [`9ad6741`](https://github.com/Genocs/genocs-library/commit/9ad67419409742bcad1f383a1f9f5219f9ccfb7a) +- Updated nuget packages to prepare for removing legacy behavior [`3887c17`](https://github.com/Genocs/genocs-library/commit/3887c171b97543ee47e8e182e63964e6b5f8667e) +- Reverted reference framework [`99ac637`](https://github.com/Genocs/genocs-library/commit/99ac6373f8774c73de507419425b9840928f5fde) +- Refactored code for readability and updated variable types [`cc0d478`](https://github.com/Genocs/genocs-library/commit/cc0d47898ac8f705e9cb17837eb5f272d6a77bc2) +- Update app config for logging, security, and more [`1058ea1`](https://github.com/Genocs/genocs-library/commit/1058ea157068e99bb9e08dbe71350d574d9b8d7f) +- Enhanced app config and documentation [`bf42a88`](https://github.com/Genocs/genocs-library/commit/bf42a88da74ce68b2aaef9c3463ac698cc01a145) +- Setup configuration [`02c2be7`](https://github.com/Genocs/genocs-library/commit/02c2be7978110755596ff81f95f108b6b8c61f0b) +- Update dependencies and refactor namespaces [`0cde64f`](https://github.com/Genocs/genocs-library/commit/0cde64fba30a987d5be4062d6ab167945629b8bc) +- updates for 2024 [`c58e4a2`](https://github.com/Genocs/genocs-library/commit/c58e4a2be076f22bec1dcad16a4f4a05a8865203) +- Update package versions across projects [`bb92cdb`](https://github.com/Genocs/genocs-library/commit/bb92cdbb7688fa5f33c4660729b6b589c41f3e06) +- Refactor auth and update docs [`85198fb`](https://github.com/Genocs/genocs-library/commit/85198fbd504da2e98499783f0d85eb6fcccab91d) +- Refactor configuration naming conventions and add new options [`ede9ad3`](https://github.com/Genocs/genocs-library/commit/ede9ad3256c1ad948b89dddc789d6734ae2eed1a) +- Merge issues [`94db485`](https://github.com/Genocs/genocs-library/commit/94db485eaf5a5732aeb300f9b1ab701835b3a256) +- removed templates and updated packages [`aa54284`](https://github.com/Genocs/genocs-library/commit/aa542848efc453e7f298f5dd02e466d5a42c7791) +- File updates [`73afdc0`](https://github.com/Genocs/genocs-library/commit/73afdc09e3412194d31a462ce3d63d7116ebbd68) +- Minor fix [`2dde44c`](https://github.com/Genocs/genocs-library/commit/2dde44c057ee340bb9aebceb367f2d9cd3b084d7) +- Version pre5.x [`7ba35a0`](https://github.com/Genocs/genocs-library/commit/7ba35a0d172d3699e58da473f41c408ee0267376) +- Clean warnings [`7c66fc3`](https://github.com/Genocs/genocs-library/commit/7c66fc3f57bc60bf44f35e391f80a5855baba357) +- Cleanup config file [`5a3ab6d`](https://github.com/Genocs/genocs-library/commit/5a3ab6d535046b6f35d40f682c6e3fa371905db4) +- work in progress setup docker [`19e285e`](https://github.com/Genocs/genocs-library/commit/19e285e52b3a59cb9e6ea50414edc5fb33326df2) +- Added comments [`7661260`](https://github.com/Genocs/genocs-library/commit/7661260ebc31ee35c5cd600b238422c281fd7e1e) +- Updates [`eba8b20`](https://github.com/Genocs/genocs-library/commit/eba8b208039220656cb3d4cf32ac285dda13fb79) +- Updates change log [`08f7ea0`](https://github.com/Genocs/genocs-library/commit/08f7ea0ef2212d92769c1aad6fd0af05c673e168) +- Fix error on Console log [`f6da253`](https://github.com/Genocs/genocs-library/commit/f6da2539bd7249928d3221f0a3af95ab5dd513ef) +- Updated Release note [`acf52b8`](https://github.com/Genocs/genocs-library/commit/acf52b8b636de43ebb91bb2ab1b4a234d2e51092) +- Added wildcard [`bb303ea`](https://github.com/Genocs/genocs-library/commit/bb303eae19f13d330e0bc14c864e6e2fca4e001b) +- Implemented Mongo functionality [`3bb4589`](https://github.com/Genocs/genocs-library/commit/3bb4589e3596ca7cb1aed17129a3aab2ef5b9dd5) +- Updated packages [`9f2cedc`](https://github.com/Genocs/genocs-library/commit/9f2cedca131300bcc01183f936ef7d0a77599cb8) +- Refactory open telemetry [`a3170e5`](https://github.com/Genocs/genocs-library/commit/a3170e5c1d1b5fd56cc0b65e3663dfaa3cb1e7b9) +- Changed the docker compose config file [`1444175`](https://github.com/Genocs/genocs-library/commit/1444175abb79ab834bd69dcbac9395829332c3ff) +- Fix configuration on docker without Fabio and Consul [`363ec41`](https://github.com/Genocs/genocs-library/commit/363ec41ebdc5d0f7c17a935226504c37d53b50cd) +- Before big refactory [`b21a55e`](https://github.com/Genocs/genocs-library/commit/b21a55ec751c8186b73e7da84bd1a38256ff7984) +- Fix link [`56b18a2`](https://github.com/Genocs/genocs-library/commit/56b18a25652e30f383b6c137a168487a3827cd5e) +- Fix auth and authorization [`5b7fc8c`](https://github.com/Genocs/genocs-library/commit/5b7fc8cebf25b33ee7f7f676a74698aee328ca7d) +- Using Open telemetry [`09a5783`](https://github.com/Genocs/genocs-library/commit/09a57836398b28ba07afbbadcf211181e1b86829) +- Pagages updated wip [`dd10e1a`](https://github.com/Genocs/genocs-library/commit/dd10e1afa7a1cf6f5c7b1780413fff9ae9cd0775) +- Second round [`8d92e64`](https://github.com/Genocs/genocs-library/commit/8d92e641cd7f3ca2cc658c36739d1253e9bc5525) +- Default mongodb entity with ObjectId [`296abe7`](https://github.com/Genocs/genocs-library/commit/296abe7757f025b2d75313e423d9f380f758a160) +- updated docker files and github actions [`a7dd458`](https://github.com/Genocs/genocs-library/commit/a7dd4583ac302f1841d2b1c152849deb761f3cc2) +- updated readme [`ccb4614`](https://github.com/Genocs/genocs-library/commit/ccb46140e499cb1cac8ab129e710a9bffe0034e6) +- Updated clients to net8 [`8f32845`](https://github.com/Genocs/genocs-library/commit/8f328458cfdc28303e78f1d87d11e98a9f348280) +- Fix workflow [`6f527c7`](https://github.com/Genocs/genocs-library/commit/6f527c7324c6097ca287a3c1a1bcff592af081ea) +- tmp [`7688a62`](https://github.com/Genocs/genocs-library/commit/7688a627e67555c0a5e5578e489b3ad45810e9bb) +- Added default assembly name [`8293914`](https://github.com/Genocs/genocs-library/commit/8293914cac430f3b15921f6aa8de64619b1aac19) +- Commit after the check with Products and Oerders by Postman [`5f37139`](https://github.com/Genocs/genocs-library/commit/5f37139b8d8eb4f5e5ce7cb6c4d8d2b147ce106e) +- minor fix [`b5a32dd`](https://github.com/Genocs/genocs-library/commit/b5a32dd6c5256892c73f086b9686f953e6ced46a) +- refactory [`b94aa66`](https://github.com/Genocs/genocs-library/commit/b94aa66fc60fc0d5b90fa799b95ea193bb74fe42) +- Added auth features and AuthorizedController [`3a28fd1`](https://github.com/Genocs/genocs-library/commit/3a28fd1bf3f42c3de94cdd58ae002eb91b14fe2c) +- fix prometheus [`3ba5662`](https://github.com/Genocs/genocs-library/commit/3ba56621b9ff9882902d8908c3e69d23cb840fa7) +- Fix for pack [`19f2e02`](https://github.com/Genocs/genocs-library/commit/19f2e027fd0dbab7871171e6af05be8d5e10b88e) +- Updated github action [`7b8bf5d`](https://github.com/Genocs/genocs-library/commit/7b8bf5dfb9d5bdb0c8244a52239af7707c290862) +- Updated references [`28920e4`](https://github.com/Genocs/genocs-library/commit/28920e4c8411a90d6eb57c24f3c655715b2160c3) +- Disabled Monitoring [`a8bad21`](https://github.com/Genocs/genocs-library/commit/a8bad21f6c199b726de89167f740bac1c85fcd6f) +- Fix build [`8c0bdf3`](https://github.com/Genocs/genocs-library/commit/8c0bdf374e38b543bc6398d0742ad3dab66c95b7) +- Updated log plus fix url service [`24aff9b`](https://github.com/Genocs/genocs-library/commit/24aff9b130c36c90d73a13f70e3047f42a128a76) +- Bump System.IdentityModel.Tokens.Jwt in /src/Genocs.Auth [`cd58c28`](https://github.com/Genocs/genocs-library/commit/cd58c28d68e059fb6fb83db7d34debcdee5ee1b4) +- Bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets [`d620e5d`](https://github.com/Genocs/genocs-library/commit/d620e5d6d9a9d4a5abac0dde8ad3aeef3e2c42a6) +- Fix path [`31a62e9`](https://github.com/Genocs/genocs-library/commit/31a62e9f428866042f6191bcf99c411dda0368b6) #### [v5.0.0-preview.4.0](https://github.com/Genocs/genocs-library/compare/v5.0.0-preview.3.0...v5.0.0-preview.4.0) @@ -47,6 +146,17 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Preview 4.x [`d619840`](https://github.com/Genocs/genocs-library/commit/d619840033c146a60bdb5fe6f37ea7e6e7ae5de7) - Start removing legacy MongoDB legacy database [`f4ca960`](https://github.com/Genocs/genocs-library/commit/f4ca9609ef11ad550c789e05dbfd6c0984fa312b) - Refactory to remove legacy Mongodb [`7accdcb`](https://github.com/Genocs/genocs-library/commit/7accdcba26edb9e38ebf0583966348f80a2d31b1) +- refactory template [`78a2731`](https://github.com/Genocs/genocs-library/commit/78a27316ce9a4341af3c1c21b2e9543bf8cf0af3) +- Added Mongo Encriptation [`a6e2157`](https://github.com/Genocs/genocs-library/commit/a6e2157a9e60c6da11623e70f41657b8caa78cf3) +- Refactory Persistance [`d27adce`](https://github.com/Genocs/genocs-library/commit/d27adce74254630bca2d0da46fec17c94372848b) +- Fix application [`8c10982`](https://github.com/Genocs/genocs-library/commit/8c10982c42a0d176b045ea6ce22a37ff95f8abda) +- Fix templates [`55c8d85`](https://github.com/Genocs/genocs-library/commit/55c8d8505fa33f06cfb02814734464adf384eb22) +- Removed legacy references [`a32d92b`](https://github.com/Genocs/genocs-library/commit/a32d92b6f68c50a0638912b52a250338db59de7c) +- Fix error on unit test [`b2f5fdd`](https://github.com/Genocs/genocs-library/commit/b2f5fdd6069bb6276fc29af312616704ac48f27a) +- Paginated query [`ddb108e`](https://github.com/Genocs/genocs-library/commit/ddb108e6ca4d391f5a7c4b515831cddf083ec82f) +- Updated packages [`f030660`](https://github.com/Genocs/genocs-library/commit/f03066034868d3cebb38667425e63b6d8f55b3da) +- updates [`48b67fb`](https://github.com/Genocs/genocs-library/commit/48b67fba3bc2e2ee72d008734629b31547275d7b) +- Updated github workflow [`8b689df`](https://github.com/Genocs/genocs-library/commit/8b689dfe7adb50f6378ed9a970ec6b9412e0a7f0) #### v5.0.0-preview.3.0 @@ -61,3 +171,177 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Added SignalR service [`8a6faee`](https://github.com/Genocs/genocs-library/commit/8a6faeef4c6c2dec473abb1e86fe55a9e24f87c5) - Added template [`98884b0`](https://github.com/Genocs/genocs-library/commit/98884b034910bc8d4c912344fe2ce0f54b4e7aaa) - Upated to net7 [`2cbc3f8`](https://github.com/Genocs/genocs-library/commit/2cbc3f8b6cefb5cfe153b3aba8a28d5f425804dc) +- First commit [`4d9b150`](https://github.com/Genocs/genocs-library/commit/4d9b1503a8295f21392886f4a149a67851472d47) +- Users Implementation - WIP [`1b80c65`](https://github.com/Genocs/genocs-library/commit/1b80c65e26fcbe16ae15aaf42fa7b93350aca70e) +- Added Consul, Fabio and RestEasy [`0d7e96b`](https://github.com/Genocs/genocs-library/commit/0d7e96bcdc372044b8a7b7d3705b594aa5c39b97) +- Added WebApi [`9e28196`](https://github.com/Genocs/genocs-library/commit/9e28196b0db9a3a30d4ba8094c448020f09529c7) +- Added Query builder [`6e1318b`](https://github.com/Genocs/genocs-library/commit/6e1318b83b09299bce1fe0d1683b67e6aa200fa7) +- File file structure completed [`af6664e`](https://github.com/Genocs/genocs-library/commit/af6664ea893388c8acf938c3317c8d76c90c3c87) +- Review for CQRS [`e7ec4aa`](https://github.com/Genocs/genocs-library/commit/e7ec4aa85a81b47af4c4ae3bd4ab2ce4e6adb852) +- Added Vault [`172acbd`](https://github.com/Genocs/genocs-library/commit/172acbdc7aded226a49b642168443ca63f39241d) +- Updated naming conventions [`a81a5de`](https://github.com/Genocs/genocs-library/commit/a81a5dec2f8fc1cda111b0451d3da310b3b410ef) +- Genocs.Core Version 3.1 [`89675d3`](https://github.com/Genocs/genocs-library/commit/89675d3bc6b68e03628865c20ff52bee94888086) +- Fix read options [`831e1f4`](https://github.com/Genocs/genocs-library/commit/831e1f4631a3fa244dcf3bc25ad258d8db27eb9e) +- Added API Gateway [`78d0f16`](https://github.com/Genocs/genocs-library/commit/78d0f16b96b2900486c585f267ab7716679e320c) +- added Azure Service bus [`6d79d68`](https://github.com/Genocs/genocs-library/commit/6d79d68ad7a4348841cc100e84c57ec63c97bef2) +- Added WebApi.CORS and WebAPI.Security [`612b2d2`](https://github.com/Genocs/genocs-library/commit/612b2d2696894ef9f12e0410750a86069c1b8e0d) +- Removed fix [`80e943c`](https://github.com/Genocs/genocs-library/commit/80e943c9283570a3816dcff418bb683d2e401314) +- Build it's OK - Runting crash [`044f029`](https://github.com/Genocs/genocs-library/commit/044f0297c4d24b17da97a48196c260f987b20dee) +- Added complete demo [`ec6427c`](https://github.com/Genocs/genocs-library/commit/ec6427c3f0ba73fb429292025f26d21598a1cf6a) +- Added auth [`6703204`](https://github.com/Genocs/genocs-library/commit/670320401a6198b5ebb09464a2fd10cfe49d1765) +- update version [`3973f32`](https://github.com/Genocs/genocs-library/commit/3973f3236625dad6d1c11b19b56a71fb1c24c076) +- Refactory [`d88206b`](https://github.com/Genocs/genocs-library/commit/d88206b55a4825202ad7d2140c97087a634ca14b) +- Implemented CQRS pattern in Core [`d2adfb8`](https://github.com/Genocs/genocs-library/commit/d2adfb8a7385bd1d6312fbb69ff8568058b6ab07) +- Added products [`1a9fcdd`](https://github.com/Genocs/genocs-library/commit/1a9fcdd53f4aa68807b0ae7fbe5da4217ebf501f) +- Updated Nuget plus push on nuget [`eb001d8`](https://github.com/Genocs/genocs-library/commit/eb001d899a25f212591c195cf9fd6f8cc2b00265) +- Added web demo [`77dc809`](https://github.com/Genocs/genocs-library/commit/77dc809c3d661f08011dabf8f52fce15481ab9d7) +- Configuration files updated for deployments [`86317d3`](https://github.com/Genocs/genocs-library/commit/86317d370287b75e4f5114ae24c9018ee47df1fd) +- Committed after refactory [`908dee7`](https://github.com/Genocs/genocs-library/commit/908dee79e5818875f1b366d509cd9231ea20011f) +- Clean up data [`5378f6b`](https://github.com/Genocs/genocs-library/commit/5378f6bfc60b91e7ff01578744a71896f67f787e) +- Projects settings [`669f10f`](https://github.com/Genocs/genocs-library/commit/669f10fab3bb4f9ae99682f65697ce2285e8ebaa) +- Split monitoring and telemetry [`8afc9bd`](https://github.com/Genocs/genocs-library/commit/8afc9bdef6ccce499ff519156099807e1545bd77) +- Added docker compose [`415b416`](https://github.com/Genocs/genocs-library/commit/415b41621b1a0ffb3018d767a71df59e7348ee3c) +- Start Setup dependencies [`76b2389`](https://github.com/Genocs/genocs-library/commit/76b238943e65ce2fe4f1d02a05fcfaecfdc57b4a) +- Splitted common from core [`e58627c`](https://github.com/Genocs/genocs-library/commit/e58627c46f86933b3dc41a231882521a45b8bf0c) +- Addes swagger [`1b90eae`](https://github.com/Genocs/genocs-library/commit/1b90eae248e267e8ac8df4de51def8f2892cbbd4) +- Fix open telementry [`310d251`](https://github.com/Genocs/genocs-library/commit/310d25172d3f1ebc9de262cf46710186f1c7d2a9) +- Fix naming [`f964d5e`](https://github.com/Genocs/genocs-library/commit/f964d5e61cf4b648c5386a3db6d2d7910a25c46f) +- Removed compile warning [`82480de`](https://github.com/Genocs/genocs-library/commit/82480de6aa6368afa375244d49c6e54562512a63) +- Refactory naming conventions [`f340235`](https://github.com/Genocs/genocs-library/commit/f34023508c5301f9a1b197caccb35094295bd06f) +- Added security [`09a7102`](https://github.com/Genocs/genocs-library/commit/09a7102c1cad10a67e24a86ddca20452a6cda5ef) +- Added Mongodb [`dc0b989`](https://github.com/Genocs/genocs-library/commit/dc0b989f9d9ed23b68cee3023327228075c435e5) +- Fix Runtime error on outbox, there is an issue on get AppSettings [`371d754`](https://github.com/Genocs/genocs-library/commit/371d7545d468a057a5c7fdb52fc5f06671434d1c) +- added api service to service [`b8b00b9`](https://github.com/Genocs/genocs-library/commit/b8b00b9b66096175509689c3683b7214b6097295) +- Added kubernes deplyments [`d9325b2`](https://github.com/Genocs/genocs-library/commit/d9325b216e8de992ae0fa85a413628e3d1633f8e) +- Completed the docker container applicaion tests [`33581e4`](https://github.com/Genocs/genocs-library/commit/33581e44202235fb424d15d28fbe210ca0147030) +- Released on Nuget [`74b71d3`](https://github.com/Genocs/genocs-library/commit/74b71d3cf70fc1251398681fffc7e63aab421185) +- Added support for NET6 as well [`1035cd2`](https://github.com/Genocs/genocs-library/commit/1035cd2580405fe25fb2b5e8fa37eb10fde4e361) +- Fix namespaces [`df48cc0`](https://github.com/Genocs/genocs-library/commit/df48cc014ea75907ed03b986cc553faeaac9db45) +- Sync libraries [`1b8a059`](https://github.com/Genocs/genocs-library/commit/1b8a059a159a63abd9122fec4fbf36efd7cde98d) +- Added bus worker [`ee5627a`](https://github.com/Genocs/genocs-library/commit/ee5627a3c79e6534f8757ebbc87fe64e79ac777a) +- foolish updates [`e8f4bb8`](https://github.com/Genocs/genocs-library/commit/e8f4bb86b4fbaf42483c3705d685d7af1e572f27) +- Build release [`d6cd11b`](https://github.com/Genocs/genocs-library/commit/d6cd11b36d33d21b7a0fcc69b63673ea080041da) +- Added masstransit hosted service [`71d1f40`](https://github.com/Genocs/genocs-library/commit/71d1f40e7d9009bc7a30feecca60a4a34ac808f7) +- Fix run SignalR [`1d5b669`](https://github.com/Genocs/genocs-library/commit/1d5b6690cab6d53099ee35b7eba1d52ff37eac12) +- Persistence MongoDB 3.0.1 released [`a44893c`](https://github.com/Genocs/genocs-library/commit/a44893c95af0413a961e9a3a1e7cc2b5fe7e0a80) +- Updated library [`99502ff`](https://github.com/Genocs/genocs-library/commit/99502ffb74ee1d828ad10649a4b25f7a9d85f2a6) +- minor fix [`ca3b995`](https://github.com/Genocs/genocs-library/commit/ca3b99552a202dc79041207848dea69800c4856b) +- Fix monitoring and tracing [`5ca3d46`](https://github.com/Genocs/genocs-library/commit/5ca3d4638788a3564f94fb156000fde6ae79572a) +- Added AzureService Bus handler [`df5f7e5`](https://github.com/Genocs/genocs-library/commit/df5f7e5a97c038d5a659bc524214109b1a586c50) +- Document Update [`974ab14`](https://github.com/Genocs/genocs-library/commit/974ab144d3de2fae312301448ae76145652a4d99) +- Fixed signalR [`c03535b`](https://github.com/Genocs/genocs-library/commit/c03535b12a9eff2f31a3f10976af149c4d5e89e0) +- Refactory for docker build [`35c06cc`](https://github.com/Genocs/genocs-library/commit/35c06cc104b47aa380473b5de2fe7a98be9f1aa4) +- New Release on Nuget [`766a5d8`](https://github.com/Genocs/genocs-library/commit/766a5d804c9c1fb0d2a5c4d43d97e967bebab486) +- updated nuget packages [`c3eb63e`](https://github.com/Genocs/genocs-library/commit/c3eb63e72fa31223830cdde3778b73a90ad181f1) +- Updates [`333fbeb`](https://github.com/Genocs/genocs-library/commit/333fbeb71deb1b2a46ec9e1d521de6428fdcbb4e) +- Code cleanup [`d780d09`](https://github.com/Genocs/genocs-library/commit/d780d09eafedd42b55599509ae3bdb0ae877391d) +- Add jwt [`594b8f8`](https://github.com/Genocs/genocs-library/commit/594b8f8dcee2414fe569751a3b128c38227b03b0) +- Updated nuget services [`cf8ff75`](https://github.com/Genocs/genocs-library/commit/cf8ff75dfd5c7b27a7d7e8dcad4d302d6403594b) +- Added command [`81d0f09`](https://github.com/Genocs/genocs-library/commit/81d0f090f49036c7063e181627583fd410bb89b1) +- Changed readme filename [`7689dca`](https://github.com/Genocs/genocs-library/commit/7689dca4d7e29c2e13ef586fcd6a850c94264880) +- Cleanup data [`d8e270e`](https://github.com/Genocs/genocs-library/commit/d8e270eed46c5f7726b62d8bfc0c86a1747fb4c0) +- fix signalR [`a35dc64`](https://github.com/Genocs/genocs-library/commit/a35dc643b1c8f64a2521ec6b30518d83d3e5b75f) +- Removed launch [`0430d66`](https://github.com/Genocs/genocs-library/commit/0430d6632d5d50f06c23ad3f42992b12c56bf835) +- WIP [`ffec644`](https://github.com/Genocs/genocs-library/commit/ffec64431484fb3854317bf176bd5f38ab96e46c) +- Refactory naming conventions [`227b8c3`](https://github.com/Genocs/genocs-library/commit/227b8c344e8f7dc889e710de9959f05fc8ba9c26) +- Fix copy and paste typos [`d29576d`](https://github.com/Genocs/genocs-library/commit/d29576dfd7002412f3bc6f25ad7b26be24e780d4) +- Updated Readme [`3d52b4e`](https://github.com/Genocs/genocs-library/commit/3d52b4eb1368e737c40b95a735bf17931e38ad95) +- Minor updates [`1d5b26c`](https://github.com/Genocs/genocs-library/commit/1d5b26c3ce70434a94007db8038974fa19231cfa) +- Enable communication between ApiGateway and service [`17e85f3`](https://github.com/Genocs/genocs-library/commit/17e85f344fdeca17eea225a0389f097fb4aabebc) +- Template fix [`108afb7`](https://github.com/Genocs/genocs-library/commit/108afb7a1950804d4fefd322bbf03b12a796e070) +- tmp [`5436cf9`](https://github.com/Genocs/genocs-library/commit/5436cf92e5d15febf1dc9dc0e4c195f44c8caec7) +- Added localhost certificates [`71e14b6`](https://github.com/Genocs/genocs-library/commit/71e14b6c471fbc45c91a3d7377825119feba96ca) +- Namespace updates [`e832ec2`](https://github.com/Genocs/genocs-library/commit/e832ec20865c711732cf6e530a7a2c83ea2a1bc2) +- Extensions plus placeholder for documentation [`db01f6e`](https://github.com/Genocs/genocs-library/commit/db01f6ebb777e07c350fd3dcadbfcdd18c738e21) +- Fix unit test [`28bf234`](https://github.com/Genocs/genocs-library/commit/28bf2345e57ca7a1b785fc561f820cd17b5788b0) +- Refactory and Standardization [`198a4ef`](https://github.com/Genocs/genocs-library/commit/198a4ef419517dc15b50ecebbba89830e6f76d86) +- Fixed project to build in Release [`b60f331`](https://github.com/Genocs/genocs-library/commit/b60f331469ec70ff37920baec5657dfb24b9b6f9) +- fix for build and up [`ec855c7`](https://github.com/Genocs/genocs-library/commit/ec855c7c36a7aacaa918180111706fc30ea42d83) +- Fix build docker file [`4edfb28`](https://github.com/Genocs/genocs-library/commit/4edfb2874a1e592e66688d475b93141ce9149514) +- Cleanup [`c564e0a`](https://github.com/Genocs/genocs-library/commit/c564e0a14d4ce4971cb55abc2e3bb459f2c2c1e5) +- Updates 2023 [`65a783a`](https://github.com/Genocs/genocs-library/commit/65a783a4c683bb647c70c1f5c7bedf8eab2635cf) +- updated packages [`fd847a3`](https://github.com/Genocs/genocs-library/commit/fd847a3b46a813a47daebe55849fb7f48d78aa58) +- Fix nuget packages [`41fc96c`](https://github.com/Genocs/genocs-library/commit/41fc96c675586f82d91af62c28738e6521bf02e7) +- updated readme [`928bb26`](https://github.com/Genocs/genocs-library/commit/928bb261c4e458ec8351cebf7d1cc8231f30f84f) +- added nuspec [`5cc6a99`](https://github.com/Genocs/genocs-library/commit/5cc6a9994bdccbba3ad8a116fc1599c081daafb3) +- Initial commit [`d678e72`](https://github.com/Genocs/genocs-library/commit/d678e722365d1c5a6591dd776dbb7112accc0d1b) +- added files [`5a6dd39`](https://github.com/Genocs/genocs-library/commit/5a6dd3979e76199fa329cb0e5ae7793ab0974007) +- removed duplicated [`aea2e5e`](https://github.com/Genocs/genocs-library/commit/aea2e5e060b3ac4dba64061a04f29c9da2676d33) +- Readme updates [`f971283`](https://github.com/Genocs/genocs-library/commit/f971283d32aca19fd9268b8a5465e1060c9130eb) +- Added support for console hosted service plus rebuild to rc1.1 [`2fcf79a`](https://github.com/Genocs/genocs-library/commit/2fcf79a33a42fae1622c9086222fcb48a775e63a) +- SignalR Setup completed [`57f8694`](https://github.com/Genocs/genocs-library/commit/57f869470812a3c2c1686e221887c62290da1756) +- Added preview on package [`20a72cb`](https://github.com/Genocs/genocs-library/commit/20a72cbadda98a8244c4a1ca56e8287fe6029ba0) +- New architecture [`5b693db`](https://github.com/Genocs/genocs-library/commit/5b693dbe7a66662bf47b064ba4147e5b4274745a) +- minor fix on documentation [`9e08077`](https://github.com/Genocs/genocs-library/commit/9e08077f50321b8ff903a3b8c04ae958dc085942) +- updated packages [`1961ed1`](https://github.com/Genocs/genocs-library/commit/1961ed1d9d4cc4c791e4be03d4ee3b3ccc1237c1) +- minor changes [`f69c864`](https://github.com/Genocs/genocs-library/commit/f69c8641983e94461a999f45fefd330bd2fef68b) +- Convey Latest version [`f381cc0`](https://github.com/Genocs/genocs-library/commit/f381cc08a8421c2e8f6eb683581cb167baf67c74) +- Create nuget-publish.yml [`c880398`](https://github.com/Genocs/genocs-library/commit/c880398feb9bf65fea01a0becfa0b4d3e9d558c2) +- Extended pagination [`7a4f64b`](https://github.com/Genocs/genocs-library/commit/7a4f64b30e29a8b51a6046a45616dcf9b9f7d5a4) +- Updated packages [`c974b2f`](https://github.com/Genocs/genocs-library/commit/c974b2f93d44486f1e5c61141c576265fbe4b2e9) +- bug fix [`23e55e2`](https://github.com/Genocs/genocs-library/commit/23e55e2dbe8fe1f16ace837e81122bd19ca6e1ab) +- Create manual.yml [`08a5bf4`](https://github.com/Genocs/genocs-library/commit/08a5bf4b1ac0ad43ead33a7d78aca3e00da9ccf6) +- Updated github actions [`610ae7a`](https://github.com/Genocs/genocs-library/commit/610ae7af5ef35f77361353168c8290f14e106e17) +- Skip pack [`5f0e1a6`](https://github.com/Genocs/genocs-library/commit/5f0e1a609ebffaa806f87c1de033e3e1158ffc87) +- Updated DDSettings to MongoDbSettings [`78867ef`](https://github.com/Genocs/genocs-library/commit/78867ef90b247a5c31b40b101771876e93cf0f60) +- Create build_and_test.yml [`b5d6356`](https://github.com/Genocs/genocs-library/commit/b5d63563be406b3e33b0bfe953db8301b8907f3b) +- case [`1410f79`](https://github.com/Genocs/genocs-library/commit/1410f799761a1ca552cc290a38ccfdbcff4ea069) +- Fix product settings file [`1c9bfb7`](https://github.com/Genocs/genocs-library/commit/1c9bfb77ac9f270ece594b737bb299b96da94c11) +- Fix nuget [`49ff439`](https://github.com/Genocs/genocs-library/commit/49ff439e01e9822a528995cb07df3a79c166cfd2) +- updated pack [`7fda8e3`](https://github.com/Genocs/genocs-library/commit/7fda8e359aa701d729b1e361f8aca6cae77276ea) +- Another fix [`5945ba0`](https://github.com/Genocs/genocs-library/commit/5945ba0df066de1413b818380733751d3f9b20f4) +- Added MongoDbSettings validation [`fdd53a4`](https://github.com/Genocs/genocs-library/commit/fdd53a4507acb9ac4198ce1ebbd89118219cca6b) +- Removed service discovery [`1fa0490`](https://github.com/Genocs/genocs-library/commit/1fa0490c7cf83daf912da12c894a8ae0868390f0) +- Fix naming case [`5140f99`](https://github.com/Genocs/genocs-library/commit/5140f99bd6125e38ba3f93eb49d1834a5d288c00) +- updated the readme file [`9d08b32`](https://github.com/Genocs/genocs-library/commit/9d08b3274253a68020d9c2717bdc5befde17058d) +- Updated namespace [`460fa3a`](https://github.com/Genocs/genocs-library/commit/460fa3a7508c93e0807d0ae039046efdc6db7ada) +- Restored package creation [`aba219a`](https://github.com/Genocs/genocs-library/commit/aba219a4c34fac787d100949e4aa010766a26c15) +- Enabled metrics [`9323ce3`](https://github.com/Genocs/genocs-library/commit/9323ce30c4df515c8fef902472034ce46bc8f270) +- another [`d75abd6`](https://github.com/Genocs/genocs-library/commit/d75abd63e45f249a40e8dcd07f6d28bbf00c7ae5) +- updated Git Actions [`ab039cb`](https://github.com/Genocs/genocs-library/commit/ab039cb3fe2f1d9ab3e7b8b68b8d7634fcec9673) +- Update README.md [`0968315`](https://github.com/Genocs/genocs-library/commit/0968315e31a156617be2fb248b8694d0003c6cf1) +- Persistence MongoDB Release 3.1.1 [`1096f4b`](https://github.com/Genocs/genocs-library/commit/1096f4bc44d4ef443584fa33e174666f3a5c4dc8) +- Update README.md [`db02cea`](https://github.com/Genocs/genocs-library/commit/db02cea5ea6b58eba1590ee4302364654abe09b4) +- Fix git action [`edcc0eb`](https://github.com/Genocs/genocs-library/commit/edcc0eb2d19910b148c37f638e7bbb9eda5b28e3) +- Minor fix [`c3e46d0`](https://github.com/Genocs/genocs-library/commit/c3e46d013c5248694996ad19cdc0bfb1234baccd) +- updated and push on NuGet [`f6b5c65`](https://github.com/Genocs/genocs-library/commit/f6b5c65afd7f0739ca448d2ee390e38c5ad74bcc) +- Fix missing namespaces [`11582e2`](https://github.com/Genocs/genocs-library/commit/11582e2b6ef9e507f9cf3712e23307024a009086) +- minor updates [`3a6cff2`](https://github.com/Genocs/genocs-library/commit/3a6cff26590274f44dab563d16328be3c6a68561) +- Updated to net 7 [`09f258c`](https://github.com/Genocs/genocs-library/commit/09f258cc977d63e2592bdd7f0ad8a3de94b14d24) +- updated versions [`1e82df3`](https://github.com/Genocs/genocs-library/commit/1e82df394f3def006ad6146ed4edc808c58ece28) +- Updated copyright [`38abc87`](https://github.com/Genocs/genocs-library/commit/38abc8781162853519f402b46e958dee1b56bcd8) +- another check [`3daed28`](https://github.com/Genocs/genocs-library/commit/3daed28b821c4a33797947878b01c228b4495942) +- Cleanup [`a80ff56`](https://github.com/Genocs/genocs-library/commit/a80ff568a5768af5ffec176b36092be30331e633) +- updated actions [`c44d885`](https://github.com/Genocs/genocs-library/commit/c44d8857f6e5dc6bdf7f5257b659ac018577a554) +- Fix out folder [`b3d51aa`](https://github.com/Genocs/genocs-library/commit/b3d51aa76066b400768356d5d485af26db525abf) +- Minor fix [`2b6d56a`](https://github.com/Genocs/genocs-library/commit/2b6d56ae702a9c1cf8184e2ccedb37a42a066136) +- Updates packages [`7e9ea75`](https://github.com/Genocs/genocs-library/commit/7e9ea7588dfa3fdd35798740e2ca5654e018b73a) +- another fix [`b341ea9`](https://github.com/Genocs/genocs-library/commit/b341ea9eb3c3579c15782e67df1f769fd30ccd34) +- prerelease version [`10ecc45`](https://github.com/Genocs/genocs-library/commit/10ecc45f534e5460309a39bc6b6b8c98225fbecd) +- Update manual.yml [`dd83b4f`](https://github.com/Genocs/genocs-library/commit/dd83b4fe355bdcad206b00d88ef972027353d101) +- enabled build nuget [`79ddbaa`](https://github.com/Genocs/genocs-library/commit/79ddbaa242c9692850fcf3f2aed7132921563732) +- Update README.md [`dbb5ad1`](https://github.com/Genocs/genocs-library/commit/dbb5ad1ec63e5f98c2b0dfc1a56e08479b18cdd8) +- another fix [`fc4a5e3`](https://github.com/Genocs/genocs-library/commit/fc4a5e31b159b02677ccb162da36365ca8088718) +- Update genocs.sln [`f9a8a44`](https://github.com/Genocs/genocs-library/commit/f9a8a4412c69334876ef7b448d7a859ed6952feb) +- Rename Genocs.Persistence.MongoDb.UnitTests.csproj to Genocs.Persistence.MongoDB.UnitTests.csproj [`c01d12a`](https://github.com/Genocs/genocs-library/commit/c01d12ad403bdea18df049af1f766c251bbc08aa) +- --no-symbols true [`c796cec`](https://github.com/Genocs/genocs-library/commit/c796cec8f8744e4cca00bc5794724fece0cba787) +- Fix Typo [`154f1f2`](https://github.com/Genocs/genocs-library/commit/154f1f2131c5c66d961a9cdf9f8c868f24989866) +- updated push nuget [`6f3038d`](https://github.com/Genocs/genocs-library/commit/6f3038d0b848795456f0baa517799c0b03b84071) +- updated nuget package [`dca2bd3`](https://github.com/Genocs/genocs-library/commit/dca2bd340733b670b9a4ee6134878fda59cf4982) +- Fix secret [`88749b3`](https://github.com/Genocs/genocs-library/commit/88749b3edeac981bfd4edff32df16d15de4bde60) +- Modify settings [`fca6a4e`](https://github.com/Genocs/genocs-library/commit/fca6a4ec1283eeea3890daa9a05086ab95651da2) +- minor fix [`dfa6a0d`](https://github.com/Genocs/genocs-library/commit/dfa6a0d366b2a2f9700a3026b49f800e7a592ff7) +- Fix version [`050265a`](https://github.com/Genocs/genocs-library/commit/050265ad33ea0cb0a3d8dfae4083aabd74260136) +- Update README.md [`4519f74`](https://github.com/Genocs/genocs-library/commit/4519f742a570e61463a48318b0cf91a2ce96e224) +- Update manual.yml [`cac36ca`](https://github.com/Genocs/genocs-library/commit/cac36cae9243c6fd4e56bd35c4775bb586243ba9) +- Update manual.yml [`8d4b4b4`](https://github.com/Genocs/genocs-library/commit/8d4b4b4c7db071be08e11a1408119f69139688f5) +- Update build_and_test.yml [`0d3eba5`](https://github.com/Genocs/genocs-library/commit/0d3eba579054975364bd26b7289bc7463cd28438) +- Bump Microsoft.AspNetCore.Authentication.JwtBearer [`0a3c697`](https://github.com/Genocs/genocs-library/commit/0a3c6970fc1630ec5eded4692c148bbb208a61af) +- pack [`4dfae77`](https://github.com/Genocs/genocs-library/commit/4dfae7789e1285ba60a2aea3b99186182adfcdff) +- updated pack [`3b66046`](https://github.com/Genocs/genocs-library/commit/3b660468260fbb05a61f7676e3ab6a7bc500d8c9) +- commentd test [`b785f88`](https://github.com/Genocs/genocs-library/commit/b785f88944eeaa931fd1edbca827cdb9b669aa33) +- updated sdk [`08a07f5`](https://github.com/Genocs/genocs-library/commit/08a07f5093b766dc043f6e29c5546b41852686fc) +- updated dotnet version [`e869b6f`](https://github.com/Genocs/genocs-library/commit/e869b6f05723a30e2f30ae5762970203b971fc19) +- Fix travis [`87659ed`](https://github.com/Genocs/genocs-library/commit/87659ed017917485c4ab7f7f929aa6c650b6b1ad) +- changed build path [`2e5d97b`](https://github.com/Genocs/genocs-library/commit/2e5d97b2035b7e8f252243062b7bf010bed5fa36) +- Added file [`b8e3ca2`](https://github.com/Genocs/genocs-library/commit/b8e3ca2bf24ef1db66f90451023b3981feff65f4) From 0a2d5be49e6e3d28e56da01aea2b72c21fa83568 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 23 Oct 2024 18:16:00 +0200 Subject: [PATCH 087/104] Update packages, refactor code, and improve readability Updated multiple packages to their latest versions: - MassTransit.RabbitMQ to 8.3.0 - Swashbuckle.AspNetCore to 6.9.0 - System.Text.Json to 8.0.5 - SmartFormat.NET to 3.5.1 - Azure.Identity to 1.13.0 - System.Linq.Dynamic.Core to 1.4.6 Removed MongoDB.Driver.Core.Extensions.OpenTelemetry package. Added MongoDB.Driver.Core.Extensions.DiagnosticSources source and GuidSerializer with GuidRepresentation.CSharpLegacy. Refactored IMongoRepository.cs, EndpointsBuilder.cs, and Extensions.cs for nullable context, method signatures, and formatting. Fixed a typo in JsonParser.cs exception message. Adjusted IRequestHandler and RequestDispatcher interfaces and classes for readability and formatting. Added WebApiOptions configuration in Extensions.cs. Improved formatting and readability across multiple files. --- .../Genocs.Core.Demo.WebApi.csproj | 4 +- .../Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Core/Genocs.Core.csproj | 2 +- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- .../Extensions/ServiceCollectionExtensions.cs | 10 ++- .../Repositories/Mentor/IMongoRepository.cs | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +- .../Genocs.Secrets.AzureKeyVault.csproj | 2 +- src/Genocs.Tracing/Extensions.cs | 4 +- src/Genocs.Tracing/Genocs.Tracing.csproj | 1 - .../Genocs.WebApi.Security.csproj | 2 +- .../Genocs.WebApi.Swagger.csproj | 10 +-- src/Genocs.WebApi/EndpointsBuilder.cs | 19 ++--- src/Genocs.WebApi/Extensions.cs | 74 +++++++++++-------- .../Formatters/JsonInputFormatter.cs | 4 +- src/Genocs.WebApi/IEndpointsBuilder.cs | 50 +++++++++---- src/Genocs.WebApi/Parsers/JsonParser.cs | 8 +- src/Genocs.WebApi/Requests/IRequestHandler.cs | 3 +- .../Requests/RequestDispatcher.cs | 4 +- 19 files changed, 122 insertions(+), 85 deletions(-) diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 542dd141..a0142f85 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index b55f5a53..410d0eb2 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index e4ddbf50..69c063b8 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -65,6 +65,6 @@ - + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index 21e0162a..17c7b935 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -52,7 +52,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs index f3ed6582..ed983fb1 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/ServiceCollectionExtensions.cs @@ -14,8 +14,14 @@ public static class ServiceCollectionExtensions internal static void RegisterConventions() { BsonSerializer.RegisterSerializer(typeof(decimal), new DecimalSerializer(BsonType.Decimal128)); - BsonSerializer.RegisterSerializer(typeof(decimal?), - new NullableSerializer(new DecimalSerializer(BsonType.Decimal128))); + + // Move to standard GuidRepresentation + BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.CSharpLegacy)); + + BsonSerializer.RegisterSerializer( + typeof(decimal?), + new NullableSerializer(new DecimalSerializer(BsonType.Decimal128))); + ConventionRegistry.Register("genocs", new ConventionPack { new CamelCaseElementNameConvention(), diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs index 16cf0ddf..a471b2ce 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs @@ -1,9 +1,9 @@ +using System.Linq.Expressions; using Genocs.Common.Types; using Genocs.Core.CQRS.Queries; using Genocs.Core.Domain.Repositories; using MongoDB.Driver; using MongoDB.Driver.Linq; -using System.Linq.Expressions; namespace Genocs.Persistence.MongoDb.Repositories.Mentor; diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index c621e53e..02c67b0d 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -11,9 +11,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index 17f6669f..514b129e 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/Genocs.Tracing/Extensions.cs b/src/Genocs.Tracing/Extensions.cs index 400e1281..9ff0aef4 100644 --- a/src/Genocs.Tracing/Extensions.cs +++ b/src/Genocs.Tracing/Extensions.cs @@ -64,8 +64,8 @@ public static IGenocsBuilder AddOpenTelemetry(this IGenocsBuilder builder) // No OpenTelemetryTracing in case of missing LoggerSettings if (loggerOptions.Mongo != null && loggerOptions.Mongo.Enabled) { - // you should add MongoDB.Driver.Core.Extensions.OpenTelemetry NuGet package - provider.AddMongoDBInstrumentation(); + // Check for MongoDB config + provider.AddSource("MongoDB.Driver.Core.Extensions.DiagnosticSources"); } // Check for Console config diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 1568912c..e3bc9b84 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -47,7 +47,6 @@ - diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 2b13b51f..ddbcfa53 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -51,6 +51,6 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 45e6fae9..2bef5f97 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -42,11 +42,11 @@ - - - - - + + + + + diff --git a/src/Genocs.WebApi/EndpointsBuilder.cs b/src/Genocs.WebApi/EndpointsBuilder.cs index 12bb2d69..efad9aa9 100644 --- a/src/Genocs.WebApi/EndpointsBuilder.cs +++ b/src/Genocs.WebApi/EndpointsBuilder.cs @@ -17,14 +17,15 @@ public EndpointsBuilder(IEndpointRouteBuilder routeBuilder, WebApiEndpointDefini _definitions = definitions; } - public IEndpointsBuilder Get(string path, - Func? context = null, - Action? endpoint = null, - bool auth = false, - string? roles = null, - params string[] policies) + public IEndpointsBuilder Get( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) { - var builder = _routeBuilder.MapGet(path, ctx => context.Invoke(ctx)); + var builder = _routeBuilder.MapGet(path, ctx => context?.Invoke(ctx)); endpoint?.Invoke(builder); ApplyAuthRolesAndPolicies(builder, auth, roles, policies); AddEndpointDefinition(HttpMethods.Get, path); @@ -202,8 +203,8 @@ private void AddEndpointDefinition(string method, string path) private void AddEndpointDefinition(string method, string path) => AddEndpointDefinition(method, path, typeof(T), null); - private void AddEndpointDefinition(string method, string path) - => AddEndpointDefinition(method, path, typeof(T), typeof(U)); + private void AddEndpointDefinition(string method, string path) + => AddEndpointDefinition(method, path, typeof(Ta), typeof(Tu)); private void AddEndpointDefinition(string method, string path, Type input, Type? output) { diff --git a/src/Genocs.WebApi/Extensions.cs b/src/Genocs.WebApi/Extensions.cs index ff9a67d5..18e8c96c 100644 --- a/src/Genocs.WebApi/Extensions.cs +++ b/src/Genocs.WebApi/Extensions.cs @@ -27,31 +27,15 @@ namespace Genocs.WebApi; public static class Extensions { - private static readonly byte[] InvalidJsonRequestBytes = Encoding.UTF8.GetBytes("An invalid JSON was sent."); private const string SectionName = "webApi"; private const string RegistryName = "webApi"; private const string EmptyJsonObject = "{}"; private const string LocationHeader = "Location"; + private const string JsonContentType = "application/json"; + private static readonly byte[] InvalidJsonRequestBytes = Encoding.UTF8.GetBytes("An invalid JSON was sent."); private static bool _bindRequestFromRoute; - public static IApplicationBuilder UseEndpoints(this IApplicationBuilder app, Action build, - bool useAuthorization = true, Action middleware = null) - { - var definitions = app.ApplicationServices.GetRequiredService(); - app.UseRouting(); - if (useAuthorization) - { - app.UseAuthorization(); - } - - middleware?.Invoke(app); - - app.UseEndpoints(router => build(new EndpointsBuilder(router, definitions))); - - return app; - } - [Description("By default System JSON serializer is being used. If Newtonsoft JSON serializer is used then it sets Kestrel's and IIS ServerOptions AllowSynchronousIO = true")] public static IGenocsBuilder AddWebApi( this IGenocsBuilder builder, @@ -79,8 +63,6 @@ public static IGenocsBuilder AddWebApi( Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } }; - jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); - var factory = new Open.Serialization.Json.System.JsonSerializerFactory(jsonSerializerOptions); jsonSerializer = factory.GetSerializer(); @@ -95,13 +77,15 @@ public static IGenocsBuilder AddWebApi( builder.Services.AddSingleton(jsonSerializer); builder.Services.AddSingleton(); builder.Services.AddSingleton(new WebApiEndpointDefinitions()); + var options = builder.GetOptions(sectionName); builder.Services.AddSingleton(options); + _bindRequestFromRoute = options.BindRequestFromRoute; var mvcCoreBuilder = builder.Services - .AddLogging() - .AddMvcCore(); + .AddLogging() + .AddMvcCore(); mvcCoreBuilder.AddMvcOptions(o => { @@ -142,16 +126,39 @@ public static IGenocsBuilder AddErrorHandler(this IGenocsBuilder builder) return builder; } + public static IApplicationBuilder UseEndpoints( + this IApplicationBuilder app, + Action build, + bool useAuthorization = true, + Action? middleware = null) + { + WebApiEndpointDefinitions definitions = app.ApplicationServices.GetRequiredService(); + + app.UseRouting(); + if (useAuthorization) + { + app.UseAuthorization(); + } + + middleware?.Invoke(app); + + app.UseEndpoints(router => build(new EndpointsBuilder(router, definitions))); + + return app; + } + public static IApplicationBuilder UseErrorHandler(this IApplicationBuilder builder) => builder.UseMiddleware(); - public static IApplicationBuilder UseAllForwardedHeaders(this IApplicationBuilder builder, - bool resetKnownNetworksAndProxies = true) + public static IApplicationBuilder UseAllForwardedHeaders( + this IApplicationBuilder builder, + bool resetKnownNetworksAndProxies = true) { - var forwardingOptions = new ForwardedHeadersOptions + ForwardedHeadersOptions forwardingOptions = new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.All }; + if (resetKnownNetworksAndProxies) { forwardingOptions.KnownNetworks.Clear(); @@ -174,8 +181,7 @@ public static T BindId(this T model, Expression> expression) public static T BindId(this T model, Expression> expression) => model.Bind(expression, Guid.NewGuid().ToString("N")); - private static TModel Bind(this TModel model, Expression> expression, - object value) + private static TModel Bind(this TModel model, Expression> expression, object value) { if (!(expression.Body is MemberExpression memberExpression)) { @@ -189,8 +195,10 @@ private static TModel Bind(this TModel model, Expression x.Name.ToLowerInvariant().StartsWith($"<{propertyName}>")); + .SingleOrDefault(x => x.Name.ToLowerInvariant().StartsWith($"<{propertyName}>")); + if (field is null) { return model; @@ -201,15 +209,16 @@ private static TModel Bind(this TModel model, Expression ReadJsonAsync(this HttpContext httpContext) } } - public static T ReadQuery(this HttpContext context) where T : class + public static T ReadQuery(this HttpContext context) + where T : class { var request = context.Request; - RouteValueDictionary values = null; + RouteValueDictionary? values = null; if (request.HasRouteData()) { values = request.HttpContext.GetRouteData().Values; diff --git a/src/Genocs.WebApi/Formatters/JsonInputFormatter.cs b/src/Genocs.WebApi/Formatters/JsonInputFormatter.cs index 81780df7..e262e90b 100644 --- a/src/Genocs.WebApi/Formatters/JsonInputFormatter.cs +++ b/src/Genocs.WebApi/Formatters/JsonInputFormatter.cs @@ -33,7 +33,7 @@ public async Task ReadAsync(InputFormatterContext context) } var request = context.HttpContext.Request; - var json = string.Empty; + string json = string.Empty; if (request.Body is not null) { using var streamReader = new StreamReader(request.Body); @@ -45,7 +45,7 @@ public async Task ReadAsync(InputFormatterContext context) json = EmptyJson; } - var result = method.Invoke(_serializer, new object[] { json }); + object? result = method.Invoke(_serializer, new object[] { json }); return await InputFormatterResult.SuccessAsync(result); } diff --git a/src/Genocs.WebApi/IEndpointsBuilder.cs b/src/Genocs.WebApi/IEndpointsBuilder.cs index 89a49f33..ab7e9fda 100644 --- a/src/Genocs.WebApi/IEndpointsBuilder.cs +++ b/src/Genocs.WebApi/IEndpointsBuilder.cs @@ -39,26 +39,46 @@ IEndpointsBuilder Post( string? roles = null, params string[] policies); - IEndpointsBuilder Post(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) + IEndpointsBuilder Post( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where T : class; - IEndpointsBuilder Put(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies); + IEndpointsBuilder Put( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); - IEndpointsBuilder Put(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) + IEndpointsBuilder Put( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where T : class; - IEndpointsBuilder Delete(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies); + IEndpointsBuilder Delete( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies); - IEndpointsBuilder Delete(string path, Func? context = null, - Action? endpoint = null, bool auth = false, string? roles = null, - params string[] policies) + IEndpointsBuilder Delete( + string path, + Func? context = null, + Action? endpoint = null, + bool auth = false, + string? roles = null, + params string[] policies) where T : class; } \ No newline at end of file diff --git a/src/Genocs.WebApi/Parsers/JsonParser.cs b/src/Genocs.WebApi/Parsers/JsonParser.cs index 7a2dec07..ae61aff9 100644 --- a/src/Genocs.WebApi/Parsers/JsonParser.cs +++ b/src/Genocs.WebApi/Parsers/JsonParser.cs @@ -3,9 +3,9 @@ namespace Genocs.WebApi.Parsers; -//Credits goes to .NET Foundation Team. -//JSON parser is based on JsonConfigurationFileParser found in Microsoft.Extensions.Configuration.Json library. -//https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationFileParser.cs +// Credits goes to .NET Foundation Team. +// JSON parser is based on JsonConfigurationFileParser found in Microsoft.Extensions.Configuration.Json library. +// https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Configuration.Json/src/JsonConfigurationFileParser.cs public class JsonParser { private readonly Dictionary _data = new(StringComparer.OrdinalIgnoreCase); @@ -24,7 +24,7 @@ public IDictionary Parse(string json) { if (doc.RootElement.ValueKind != JsonValueKind.Object) { - throw new FormatException($"Invalidtop level JSON element: {doc.RootElement.ValueKind}"); + throw new FormatException($"Invalid top level JSON element: {doc.RootElement.ValueKind}"); } VisitElement(doc.RootElement); diff --git a/src/Genocs.WebApi/Requests/IRequestHandler.cs b/src/Genocs.WebApi/Requests/IRequestHandler.cs index 98b70df5..976bdd62 100644 --- a/src/Genocs.WebApi/Requests/IRequestHandler.cs +++ b/src/Genocs.WebApi/Requests/IRequestHandler.cs @@ -1,6 +1,7 @@ namespace Genocs.WebApi.Requests; -public interface IRequestHandler where TRequest : class, IRequest +public interface IRequestHandler + where TRequest : class, IRequest { Task HandleAsync(TRequest request, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Genocs.WebApi/Requests/RequestDispatcher.cs b/src/Genocs.WebApi/Requests/RequestDispatcher.cs index c6fb597b..5195bfa0 100644 --- a/src/Genocs.WebApi/Requests/RequestDispatcher.cs +++ b/src/Genocs.WebApi/Requests/RequestDispatcher.cs @@ -11,8 +11,8 @@ public RequestDispatcher(IServiceProvider serviceProvider) _serviceProvider = serviceProvider; } - public async Task DispatchAsync(TRequest request, - CancellationToken cancellationToken = default) where TRequest : class, IRequest + public async Task DispatchAsync(TRequest request, CancellationToken cancellationToken = default) + where TRequest : class, IRequest { using var scope = _serviceProvider.CreateScope(); var handler = scope.ServiceProvider.GetRequiredService>(); From 42dfe53d120dbd53fe8018bdd418f1d2d9208c0f Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Wed, 23 Oct 2024 18:40:22 +0200 Subject: [PATCH 088/104] Refactor AzureInitializer and update MongoDB.Driver Refactored AzureInitializer for readability and removed unused code. Updated MongoDB.Driver to version 2.30.0 in Genocs.Persistence.MongoDb.csproj. Reformatted commented-out code in MongoDatabaseProvider. --- .../Encryptions/AzureInitializer.cs | 4 +--- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../MongoDatabaseProvider.cs | 12 ++++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs index eb5222e5..a9e71c14 100644 --- a/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs +++ b/src/Genocs.Persistence.MongoDb/Encryptions/AzureInitializer.cs @@ -60,7 +60,7 @@ DataKeyOptions GetDataKeyOptions(List altNames) { Unique = true, PartialFilterExpression = new BsonDocument - {{"keyAltNames", new BsonDocument {{"$exists", new BsonBoolean(true)}}}} + { { "keyAltNames", new BsonDocument { { "$exists", new BsonBoolean(true) } } } } }; var builder = Builders.IndexKeys; @@ -88,7 +88,6 @@ DataKeyOptions GetDataKeyOptions(List altNames) var dataKeyOptions3 = GetDataKeyOptions(new List { "dataKey3" }); var dataKeyOptions4 = GetDataKeyOptions(new List { "dataKey4" }); - BsonBinaryData CreateKeyGetID(DataKeyOptions options) { var dateKeyGuid = clientEncryption.CreateDataKey(provider, options, CancellationToken.None); @@ -166,7 +165,6 @@ BsonBinaryData CreateKeyGetID(DataKeyOptions options) encryptedFieldsMap: encryptedFieldsMap, extraOptions: extraOptions); - return autoEncryptionOptions; // This is the last client diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 264d6650..a1039769 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -42,7 +42,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs index 54d2183c..6d763ef3 100644 --- a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs +++ b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs @@ -45,12 +45,12 @@ public MongoDatabaseProvider(IOptions options, IOptions cb.Subscribe(new DiagnosticsActivityEventSubscriber()); } - //if (encrypOptions != null) - //{ - // AzureInitializer initializer = new AzureInitializer(); - // var autoEncrypOptions = initializer.EncryptionOptions(encrypOptions); - // clientSettings.AutoEncryptionOptions = autoEncrypOptions; - //} + // if (encrypOptions != null) + // { + // AzureInitializer initializer = new AzureInitializer(); + // var autoEncrypOptions = initializer.EncryptionOptions(encrypOptions); + // clientSettings.AutoEncryptionOptions = autoEncrypOptions; + // } this.MongoClient = new MongoClient(clientSettings); this.Database = this.MongoClient.GetDatabase(dBSettings.Database); From ded3efb09cdb4b9b42b5d36102cf45bea608e84c Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Sun, 3 Nov 2024 16:26:07 +0100 Subject: [PATCH 089/104] Update packages, enhance JWT options, and refactor configs Updated Roslynator.Analyzers to 4.12.9 and Scrutor to 5.0.1. Enhanced JwtOptions with XML docs and new default values. Refactored RabbitMQ config in ServiceCollectionExtensions. Added JWT settings to appsettings.json and disabled azureKeyVault. Updated various Microsoft.Extensions packages in Genocs.Core.csproj. Tested to use auth with simmetric key. --- Directory.Build.props | 2 +- src/Genocs.Auth/Configurations/JwtOptions.cs | 27 ++++++++++++++++++- src/Genocs.Auth/Extensions.cs | 2 ++ .../Extensions/ServiceCollectionExtensions.cs | 18 +++++++------ src/Genocs.Core.Demo.WebApi/Program.cs | 2 ++ src/Genocs.Core.Demo.WebApi/appsettings.json | 12 ++++++++- src/Genocs.Core/Genocs.Core.csproj | 8 +++--- 7 files changed, 56 insertions(+), 15 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 5b9ed5cc..09017158 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Auth/Configurations/JwtOptions.cs b/src/Genocs.Auth/Configurations/JwtOptions.cs index 615f0c5f..79566a5c 100644 --- a/src/Genocs.Auth/Configurations/JwtOptions.cs +++ b/src/Genocs.Auth/Configurations/JwtOptions.cs @@ -38,16 +38,41 @@ public class JwtOptions public string? ValidIssuer { get; set; } public IEnumerable? ValidIssuers { get; set; } public bool ValidateActor { get; set; } + + /// + /// It defines whether the audience should be validated. + /// Defaults to true. + /// public bool ValidateAudience { get; set; } = true; + + /// + /// It defines whether the issuer should be validated. + /// Defaults to true. + /// public bool ValidateIssuer { get; set; } = true; public bool ValidateLifetime { get; set; } = true; public bool ValidateTokenReplay { get; set; } public bool ValidateIssuerSigningKey { get; set; } + + /// + /// It defines whether the token should be refreshed when the issuer key is not found. + /// Defaults to true. + /// public bool RefreshOnIssuerKeyNotFound { get; set; } = true; + + /// + /// It defines whether the error details should be included in the response. + /// Defaults to true. + /// public bool IncludeErrorDetails { get; set; } = true; public string? AuthenticationType { get; set; } public string? NameClaimType { get; set; } - public string? RoleClaimType { get; set; } + + /// + /// The claim type that will be used to determine the user's roles. + /// Defaults to "Role". + /// + public string RoleClaimType { get; set; } = "Role"; public class CertificateOptions { diff --git a/src/Genocs.Auth/Extensions.cs b/src/Genocs.Auth/Extensions.cs index b7baabe3..05e93b9f 100644 --- a/src/Genocs.Auth/Extensions.cs +++ b/src/Genocs.Auth/Extensions.cs @@ -70,6 +70,7 @@ private static IGenocsBuilder AddJwt( SaveSigninToken = options.SaveSigninToken, RequireExpirationTime = options.RequireExpirationTime, RequireSignedTokens = options.RequireSignedTokens, + RoleClaimType = options.RoleClaimType, ClockSkew = TimeSpan.Zero }; @@ -117,6 +118,7 @@ private static IGenocsBuilder AddJwt( } } + // If no certificate is provided, use symmetric encryption. if (!string.IsNullOrWhiteSpace(options.IssuerSigningKey) && !hasCertificate) { if (string.IsNullOrWhiteSpace(options.Algorithm) || hasCertificate) diff --git a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs index c1ccbee7..de255e2f 100644 --- a/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs +++ b/src/Genocs.Core.Demo.WebApi/Infrastructure/Extensions/ServiceCollectionExtensions.cs @@ -65,14 +65,16 @@ public static IServiceCollection AddCustomMassTransit(this IServiceCollection se x.UsingRabbitMq((context, cfg) => { cfg.ConfigureEndpoints(context); - //cfg.UseHealthCheck(context); - cfg.Host(rabbitMQSettings.HostName, rabbitMQSettings.VirtualHost, - h => - { - h.Username(rabbitMQSettings.UserName); - h.Password(rabbitMQSettings.Password); - } - ); + + // cfg.UseHealthCheck(context); + cfg.Host( + rabbitMQSettings.HostName, + rabbitMQSettings.VirtualHost, + h => + { + h.Username(rabbitMQSettings.UserName); + h.Password(rabbitMQSettings.Password); + }); }); }); diff --git a/src/Genocs.Core.Demo.WebApi/Program.cs b/src/Genocs.Core.Demo.WebApi/Program.cs index e49b96f9..e65fafbd 100644 --- a/src/Genocs.Core.Demo.WebApi/Program.cs +++ b/src/Genocs.Core.Demo.WebApi/Program.cs @@ -8,6 +8,7 @@ using Genocs.Tracing; using Microsoft.Extensions.Diagnostics.HealthChecks; using Serilog; +using Genocs.Auth; using System.Reflection; using System.Text.Json.Serialization; @@ -23,6 +24,7 @@ services .AddGenocs(builder.Configuration) + .AddJwt() // .AddOpenIdJwt() .AddOpenTelemetry() .AddMongoFast() diff --git a/src/Genocs.Core.Demo.WebApi/appsettings.json b/src/Genocs.Core.Demo.WebApi/appsettings.json index 950182b6..24502439 100644 --- a/src/Genocs.Core.Demo.WebApi/appsettings.json +++ b/src/Genocs.Core.Demo.WebApi/appsettings.json @@ -32,6 +32,16 @@ "ValidAudience": "https://localhost:5000", "Secret": "" }, + "_simmetric_jwt": { + "issuerSigningKey": "This is my custom Secret key for authentication S0M3RAN0MS3CR3T!1!MAG1C!1!", + "requireHttpsMetadata": false, + "saveToken": true, + "validateIssuerSigningKey": true, + "validateIssuer": false, + "validateLifetime": true, + "validateAudience": false, + "roleClaimType": "Role" + }, "rabbitMQ": { "HostName": "localhost", "VirtualHost": "/", @@ -53,7 +63,7 @@ "enableTracing": true }, "azureKeyVault": { - "enabled": true, + "enabled": false, "name": "kv-genocs" }, "secrets": { diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 98c15645..3334af33 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -51,7 +51,7 @@ - + @@ -68,11 +68,11 @@ - + - + - + From 24589b4a5cc52bb99609c3089b2e366343f5688e Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Sun, 3 Nov 2024 17:03:25 +0100 Subject: [PATCH 090/104] Update project references and improve domain entities Updated project references in various .csproj files to use newer versions of dependencies. Removed `netstandard2.1` from target frameworks in `Genocs.Common.csproj` and `Genocs.Core.csproj`. Changed primary key type from `int` to `Guid` for several domain entities and interfaces. Improved documentation comments and exception handling. Made `Id` property non-nullable in `Entity` class. Added `net8.0` target framework to `Genocs.SignalR.WebApi.csproj` and reorganized `Content` item group for certificates. --- src/Genocs.Auth/Genocs.Auth.csproj | 4 ++-- src/Genocs.Common/Configurations/AppOptions.cs | 1 - src/Genocs.Common/Genocs.Common.csproj | 2 +- .../Domain/Entities/AggregateRoot.cs | 2 +- .../Domain/Entities/Auditing/AuditedEntity.cs | 4 ++-- .../Entities/Auditing/CreationAuditedEntity.cs | 4 ++-- .../Entities/Auditing/FullAuditedEntity.cs | 9 +++++---- src/Genocs.Core/Domain/Entities/Entity.cs | 6 +++--- .../Domain/Entities/IAggregateRoot.cs | 2 +- src/Genocs.Core/Domain/Entities/IEntity.cs | 4 ++-- .../Domain/Entities/IEntityOfTPrimaryKey.cs | 2 +- src/Genocs.Core/Genocs.Core.csproj | 13 ++----------- .../MongoDatabaseProvider.cs | 18 ++++++++++-------- .../Genocs.SignalR.WebApi.csproj | 9 +++++---- 14 files changed, 37 insertions(+), 43 deletions(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 4a7fdde9..028696a3 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -48,8 +48,8 @@ - - + + diff --git a/src/Genocs.Common/Configurations/AppOptions.cs b/src/Genocs.Common/Configurations/AppOptions.cs index da9f08c3..79dd7851 100644 --- a/src/Genocs.Common/Configurations/AppOptions.cs +++ b/src/Genocs.Common/Configurations/AppOptions.cs @@ -15,7 +15,6 @@ public class AppOptions /// public bool Enabled { get; set; } - /// /// Application name. /// diff --git a/src/Genocs.Common/Genocs.Common.csproj b/src/Genocs.Common/Genocs.Common.csproj index b18067f9..09324070 100644 --- a/src/Genocs.Common/Genocs.Common.csproj +++ b/src/Genocs.Common/Genocs.Common.csproj @@ -1,7 +1,7 @@  - net8.0;net7.0;net6.0;netstandard2.1 + net8.0;net7.0;net6.0 Genocs.Common Genocs.Common Genocs.Common diff --git a/src/Genocs.Core/Domain/Entities/AggregateRoot.cs b/src/Genocs.Core/Domain/Entities/AggregateRoot.cs index 04a2beaa..ea62f643 100644 --- a/src/Genocs.Core/Domain/Entities/AggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/AggregateRoot.cs @@ -5,7 +5,7 @@ namespace Genocs.Core.Domain.Entities; -public class AggregateRoot : AggregateRoot, IAggregateRoot +public class AggregateRoot : AggregateRoot, IAggregateRoot { } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs index ea77a34c..e81dd13b 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs @@ -3,10 +3,10 @@ namespace Genocs.Core.Domain.Entities.Auditing; /// -/// A shortcut of for most used primary key type (). +/// A shortcut of for most used primary key type (). /// [Serializable] -public abstract class AuditedEntity : AuditedEntity, IEntity +public abstract class AuditedEntity : AuditedEntity, IEntity { } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs index c1988a36..e894d41c 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs @@ -5,10 +5,10 @@ namespace Genocs.Core.Domain.Entities.Auditing; /// -/// A shortcut of for most used primary key type (). +/// A shortcut of for most used primary key type (). /// [Serializable] -public abstract class CreationAuditedEntity : CreationAuditedEntity, IEntity +public abstract class CreationAuditedEntity : CreationAuditedEntity, IEntity { } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs index 2d93e380..a598ecde 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs @@ -3,10 +3,10 @@ namespace Genocs.Core.Domain.Entities.Auditing; /// -/// A shortcut of for most used primary key type (). +/// A shortcut of for most used primary key type (). /// [Serializable] -public abstract class FullAuditedEntity : FullAuditedEntity, IEntity +public abstract class FullAuditedEntity : FullAuditedEntity, IEntity { } @@ -19,12 +19,13 @@ public abstract class FullAuditedEntity : FullAuditedEntity, IEntity public abstract class FullAuditedEntity : AuditedEntity, IFullAudited { /// - /// Is this entity Deleted? + /// it determines if the entity is deleted. + /// Used for soft delete. /// public virtual bool IsDeleted { get; set; } /// - /// Which user deleted this entity? + /// It determines the user who deleted this entity. /// public virtual long? DeleterUserId { get; set; } diff --git a/src/Genocs.Core/Domain/Entities/Entity.cs b/src/Genocs.Core/Domain/Entities/Entity.cs index 3cbf8de7..3427d054 100644 --- a/src/Genocs.Core/Domain/Entities/Entity.cs +++ b/src/Genocs.Core/Domain/Entities/Entity.cs @@ -3,10 +3,10 @@ namespace Genocs.Core.Domain.Entities; /// -/// A shortcut of for most used primary key type (). +/// A shortcut of for most used primary key type (). /// [Serializable] -public abstract class Entity : Entity, IEntity +public abstract class Entity : Entity, IEntity { } @@ -22,7 +22,7 @@ public abstract class Entity : IEntity /// /// Unique identifier for this entity. /// - public virtual TPrimaryKey? Id { get; set; } + public virtual TPrimaryKey Id { get; set; } /// /// Checks if this entity is transient (it has not an Id). diff --git a/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs index a094292f..9560df82 100644 --- a/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs @@ -3,7 +3,7 @@ namespace Genocs.Core.Domain.Entities; -public interface IAggregateRoot : IAggregateRoot, IEntity +public interface IAggregateRoot : IAggregateRoot, IEntity { } diff --git a/src/Genocs.Core/Domain/Entities/IEntity.cs b/src/Genocs.Core/Domain/Entities/IEntity.cs index a00f7270..2ef39bb1 100644 --- a/src/Genocs.Core/Domain/Entities/IEntity.cs +++ b/src/Genocs.Core/Domain/Entities/IEntity.cs @@ -3,9 +3,9 @@ namespace Genocs.Core.Domain.Entities; /// -/// A shortcut of for most used primary key type (). +/// A shortcut of for most used primary key type (). /// -public interface IEntity : IIdentifiable +public interface IEntity : IIdentifiable { } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs b/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs index e85c21c2..7734b233 100644 --- a/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs @@ -1,7 +1,7 @@ namespace Genocs.Core.Domain.Entities; /// -/// Defines interface for base entity type. All entities in the system must implement this interface. +/// Defines interface for base entity type. All the domain object must implement this interface. /// /// Type of the primary key of the entity. public interface IEntity diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 3334af33..c10f39b3 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -1,7 +1,7 @@  - net8.0;net7.0;net6.0;netstandard2.1 + net8.0;net7.0;net6.0 Genocs.Core Genocs.Core Genocs.Core @@ -46,7 +46,7 @@ - + @@ -66,13 +66,4 @@ - - - - - - - - - diff --git a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs index 54d2183c..565c4854 100644 --- a/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs +++ b/src/Genocs.Persistence.MongoDb/MongoDatabaseProvider.cs @@ -6,7 +6,6 @@ namespace Genocs.Persistence.MongoDb; - /// /// The MongoDatabaseProvider. /// @@ -28,7 +27,7 @@ public class MongoDatabaseProvider : IMongoDatabaseProvider /// /// /// - /// + /// This exception happend in case mandatory data is missing. public MongoDatabaseProvider(IOptions options, IOptions encrypOptions) { if (options == null) throw new NullReferenceException(nameof(options)); @@ -45,14 +44,17 @@ public MongoDatabaseProvider(IOptions options, IOptions cb.Subscribe(new DiagnosticsActivityEventSubscriber()); } - //if (encrypOptions != null) - //{ - // AzureInitializer initializer = new AzureInitializer(); - // var autoEncrypOptions = initializer.EncryptionOptions(encrypOptions); - // clientSettings.AutoEncryptionOptions = autoEncrypOptions; - //} + /* + if (encrypOptions != null) + { + AzureInitializer initializer = new AzureInitializer(); + var autoEncrypOptions = initializer.EncryptionOptions(encrypOptions); + clientSettings.AutoEncryptionOptions = autoEncrypOptions; + } + */ this.MongoClient = new MongoClient(clientSettings); this.Database = this.MongoClient.GetDatabase(dBSettings.Database); + } } diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 8b977205..b23dd882 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -1,4 +1,5 @@  + net8.0 false @@ -8,10 +9,6 @@ ..\.. - - - - @@ -52,4 +49,8 @@ + + + + \ No newline at end of file From 6e9af26c48bad5298f20430eca65f06b0a2c99f4 Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Sun, 3 Nov 2024 17:26:58 +0100 Subject: [PATCH 091/104] Update Roslynator.Analyzers and adjust framework references Updated Directory.Build.props to use Roslynator.Analyzers 4.12.9. Removed net8.0 and net7.0 FrameworkReferences from Genocs.Core.csproj. Now, Microsoft.AspNetCore.App is referenced only for net6.0. --- Directory.Build.props | 2 +- src/Genocs.Core/Genocs.Core.csproj | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 3b1d7739..b292131f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -21,7 +21,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 926f3fb5..c512743a 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -44,17 +44,6 @@ - - - - - - - - - - - From 34415fa90e252c2654ddeebf5a8f84789d29be20 Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Sun, 3 Nov 2024 19:34:11 +0100 Subject: [PATCH 092/104] Update project files and package references Updated `Directory.Build.props` to include additional files for packaging. Removed these files from multiple `.csproj` files. Updated `Genocs.Core.Demo.WebApi.csproj` and `Genocs.Core.Demo.Worker.csproj` to reference `MassTransit.RabbitMQ` v8.3.0. Updated `Genocs.Secrets.AzureKeyVault.csproj` to reference `Azure.Identity` v1.13.1. Added new package references for Release configuration in `Genocs.APIGateway.csproj` and `Genocs.Orders.WebApi.csproj`. --- Directory.Build.props | 15 +++++++++++++++ src/Genocs.Auth/Genocs.Auth.csproj | 15 --------------- src/Genocs.Common/Genocs.Common.csproj | 15 --------------- .../Genocs.Core.Demo.WebApi.csproj | 11 ++++++----- .../Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Core/Genocs.Core.csproj | 15 --------------- .../Genocs.Discovery.Consul.csproj | 15 --------------- .../Genocs.HTTP.RestEase.csproj | 16 ---------------- src/Genocs.HTTP/Genocs.HTTP.csproj | 15 --------------- .../Genocs.LoadBalancing.Fabio.csproj | 16 ---------------- src/Genocs.Logging/Genocs.Logging.csproj | 17 +---------------- .../Genocs.MessageBrokers.Outbox.MongoDB.csproj | 15 --------------- .../Genocs.MessageBrokers.Outbox.csproj | 15 --------------- .../Genocs.MessageBrokers.RabbitMQ.csproj | 15 --------------- .../Genocs.MessageBrokers.csproj | 16 ---------------- src/Genocs.Metrics/Genocs.Metrics.csproj | 16 ---------------- .../Genocs.Persistence.MongoDB.UnitTests.csproj | 1 - .../Genocs.Persistence.MongoDb.csproj | 15 --------------- .../Genocs.Persistence.Redis.csproj | 15 --------------- .../Genocs.QueryBuilder.UnitTests.csproj | 1 - .../Genocs.QueryBuilder.csproj | 15 --------------- .../Genocs.Secrets.AzureKeyVault.csproj | 17 +---------------- .../Genocs.Secrets.Vault.csproj | 15 --------------- src/Genocs.Security/Genocs.Security.csproj | 16 ---------------- .../Genocs.ServiceBusAzure.csproj | 16 ---------------- src/Genocs.Tracing/Genocs.Tracing.csproj | 15 --------------- .../Genocs.WebApi.CQRS.csproj | 16 +--------------- .../Genocs.WebApi.Security.csproj | 15 --------------- .../Genocs.WebApi.Swagger.csproj | 15 --------------- src/Genocs.WebApi/Genocs.WebApi.csproj | 16 ---------------- .../Genocs.APIGateway/Genocs.APIGateway.csproj | 3 +++ .../Genocs.Orders.WebApi.csproj | 7 ++++++- 32 files changed, 34 insertions(+), 393 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b292131f..0e633641 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -35,6 +35,21 @@ + + + True + \ + + + True + \ + + + True + \ + + + enable enable @@ -51,10 +55,12 @@ - + + + + + + true diff --git a/src/Genocs.Common/Types/IIdentifiable.cs b/src/Genocs.Common/Types/IIdentifiable.cs index 59e3ff30..e7ff2efb 100644 --- a/src/Genocs.Common/Types/IIdentifiable.cs +++ b/src/Genocs.Common/Types/IIdentifiable.cs @@ -10,10 +10,4 @@ public interface IIdentifiable /// The Id getter. /// T Id { get; } - - /// - /// Checks if this entity is transient (not persisted to database and it has not an ). - /// - /// True, if this entity is transient, otherwise false. - bool IsTransient(); } \ No newline at end of file diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs index ac54b661..f1015024 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs @@ -1,4 +1,4 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Entities.Auditing; using Genocs.Core.Domain.Repositories; using MongoDB.Bson; @@ -6,7 +6,7 @@ namespace Genocs.Core.Demo.Domain.Aggregates; [TableMapping("Users")] -public class User : IIdentifiable, IHasCreationTime +public class User : IEntity, IHasCreationTime { public ObjectId Id { get; set; } diff --git a/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs index fb24de90..0150eeff 100644 --- a/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/IAggregateRoot.cs @@ -3,12 +3,12 @@ namespace Genocs.Core.Domain.Entities; -public interface IAggregateRoot : IAggregateRoot +public interface IAggregateRoot : IEntity { } -public interface IAggregateRoot : IEntity/*, IGeneratesDomainEvents */ +public interface IAggregateRoot : IEntity, IAggregateRoot/*, IGeneratesDomainEvents */ { } diff --git a/src/Genocs.Core/Domain/Entities/IEntity.cs b/src/Genocs.Core/Domain/Entities/IEntity.cs index 2ef39bb1..2403716f 100644 --- a/src/Genocs.Core/Domain/Entities/IEntity.cs +++ b/src/Genocs.Core/Domain/Entities/IEntity.cs @@ -1,11 +1,14 @@ -using Genocs.Common.Types; - namespace Genocs.Core.Domain.Entities; /// -/// A shortcut of for most used primary key type (). +/// The base interface for all entities. /// -public interface IEntity : IIdentifiable +public interface IEntity { + /// + /// Checks if this entity is transient (not persisted to database) />). + /// + /// True, if this entity is transient, otherwise false. + bool IsTransient(); } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs b/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs index 7734b233..07863ce8 100644 --- a/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Entities/IEntityOfTPrimaryKey.cs @@ -1,13 +1,11 @@ -namespace Genocs.Core.Domain.Entities; +using Genocs.Common.Types; + +namespace Genocs.Core.Domain.Entities; /// /// Defines interface for base entity type. All the domain object must implement this interface. /// -/// Type of the primary key of the entity. -public interface IEntity +/// Type of the primary key of the entity. +public interface IEntity : IEntity, IIdentifiable { - /// - /// Unique identifier for this entity. - /// - TPrimaryKey Id { get; set; } } diff --git a/src/Genocs.Core/Domain/Repositories/IRepository.cs b/src/Genocs.Core/Domain/Repositories/IRepository.cs index fb265b43..b7232eca 100644 --- a/src/Genocs.Core/Domain/Repositories/IRepository.cs +++ b/src/Genocs.Core/Domain/Repositories/IRepository.cs @@ -1,4 +1,4 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; namespace Genocs.Core.Domain.Repositories; @@ -6,8 +6,8 @@ namespace Genocs.Core.Domain.Repositories; /// This interface is used to identify a repository so can be used to be registered by convention. /// Implement generic version instead of this one. /// -public interface IRepository - where TEntity : IIdentifiable +public interface IRepository + where TEntity : IEntity { } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs index 3ebe15a4..59774660 100644 --- a/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs +++ b/src/Genocs.Core/Domain/Repositories/IRepositoryOfTEntityAndTPrimaryKey.cs @@ -1,4 +1,4 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; using System.Linq.Expressions; namespace Genocs.Core.Domain.Repositories; @@ -7,9 +7,9 @@ namespace Genocs.Core.Domain.Repositories; /// This interface is implemented by all repositories to ensure implementation of fixed methods. /// /// Main Entity type this repository works on. -/// Primary key type of the entity. -public interface IRepositoryOfEntity : IRepository - where TEntity : IIdentifiable +/// Primary key type of the entity. +public interface IRepositoryOfEntity : IRepository + where TEntity : IEntity { #region Select/Get/Query @@ -67,14 +67,14 @@ public interface IRepositoryOfEntity : IRepository /// Primary key of the entity to get. /// Entity. - TEntity Get(TIdentifiable id); + TEntity Get(TKey id); /// /// Gets an entity with given primary key. /// /// Primary key of the entity to get. /// Entity. - Task GetAsync(TIdentifiable id); + Task GetAsync(TKey id); /// /// Gets exactly one entity with given predicate. @@ -95,14 +95,14 @@ public interface IRepositoryOfEntity : IRepository /// Primary key of the entity to get. /// Entity or null. - TEntity? FirstOrDefault(TIdentifiable id); + TEntity? FirstOrDefault(TKey id); /// /// Gets an entity with given primary key or null if not found. /// /// Primary key of the entity to get. /// Entity or null. - Task FirstOrDefaultAsync(TIdentifiable id); + Task FirstOrDefaultAsync(TKey id); /// /// Gets an entity with given predicate or null if not found. @@ -121,7 +121,7 @@ public interface IRepositoryOfEntity : IRepository /// Primary key of the entity to load. /// Entity. - TEntity? Load(TIdentifiable id); + TEntity? Load(TKey id); #endregion @@ -146,7 +146,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - TIdentifiable InsertAndGetId(TEntity entity); + TKey InsertAndGetId(TEntity entity); /// /// Inserts a new entity and gets it's Id. @@ -155,7 +155,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - Task InsertAndGetIdAsync(TEntity entity); + Task InsertAndGetIdAsync(TEntity entity); /// /// Inserts or updates given entity depending on Id's value. @@ -177,7 +177,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - TIdentifiable InsertOrUpdateAndGetId(TEntity entity); + TKey InsertOrUpdateAndGetId(TEntity entity); /// /// Inserts or updates given entity depending on Id's value. @@ -187,7 +187,7 @@ public interface IRepositoryOfEntity : IRepository /// Entity. /// Id of the entity. - Task InsertOrUpdateAndGetIdAsync(TEntity entity); + Task InsertOrUpdateAndGetIdAsync(TEntity entity); #endregion @@ -211,7 +211,7 @@ public interface IRepositoryOfEntity : IRepositoryId of the entity. /// Action that can be used to change values of the entity. /// Updated entity. - TEntity Update(TIdentifiable id, Action updateAction); + TEntity Update(TKey id, Action updateAction); /// /// Updates an existing entity. @@ -219,7 +219,7 @@ public interface IRepositoryOfEntity : IRepositoryId of the entity. /// Action that can be used to change values of the entity. /// Updated entity. - Task UpdateAsync(TIdentifiable id, Func updateAction); + Task UpdateAsync(TKey id, Func updateAction); #endregion @@ -241,13 +241,13 @@ public interface IRepositoryOfEntity : IRepository /// Primary key of the entity. - void Delete(TIdentifiable id); + void Delete(TKey id); /// /// Deletes an entity by primary key. /// /// Primary key of the entity. - Task DeleteAsync(TIdentifiable id); + Task DeleteAsync(TKey id); /// /// Deletes many entities by function. diff --git a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs index 58e998a2..2747c683 100644 --- a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs +++ b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs @@ -1,6 +1,5 @@ -using System.Linq.Expressions; -using Genocs.Common.Types; using Genocs.Core.Domain.Entities; +using System.Linq.Expressions; // using Genocs.Core.Dependency; // using Genocs.Core.Domain.Uow; @@ -10,13 +9,13 @@ namespace Genocs.Core.Domain.Repositories; /// -/// Base class to implement . +/// Base class to implement . /// It implements some methods in most simple way. /// /// Type of the Entity for this repository. -/// Type of the Primary Key for this repository. -public abstract class RepositoryBase : IRepository/*, IUnitOfWorkManagerAccessor */ - where TEntity : class, IIdentifiable +/// Type of the Primary Key for this repository. +public abstract class RepositoryBase : IRepository/*, IUnitOfWorkManagerAccessor */ + where TEntity : class, IEntity { /// /// The multi tenancy side. @@ -70,7 +69,7 @@ public virtual T Query(Func, T> queryMethod) return queryMethod(GetAll()); } - public virtual TEntity Get(TPrimaryKey id) + public virtual TEntity Get(TKey id) { var entity = FirstOrDefault(id); if (entity == null) @@ -81,7 +80,7 @@ public virtual TEntity Get(TPrimaryKey id) return entity; } - public virtual async Task GetAsync(TPrimaryKey id) + public virtual async Task GetAsync(TKey id) { var entity = await FirstOrDefaultAsync(id); if (entity == null) @@ -102,12 +101,12 @@ public virtual Task SingleAsync(Expression> predica return Task.FromResult(Single(predicate)); } - public virtual TEntity? FirstOrDefault(TPrimaryKey id) + public virtual TEntity? FirstOrDefault(TKey id) { return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id)); } - public virtual Task FirstOrDefaultAsync(TPrimaryKey id) + public virtual Task FirstOrDefaultAsync(TKey id) { return Task.FromResult(FirstOrDefault(id)); } @@ -122,7 +121,7 @@ public virtual Task SingleAsync(Expression> predica return Task.FromResult(FirstOrDefault(predicate)); } - public virtual TEntity Load(TPrimaryKey id) + public virtual TEntity Load(TKey id) { return Get(id); } @@ -134,12 +133,12 @@ public virtual Task InsertAsync(TEntity entity) return Task.FromResult(Insert(entity)); } - public virtual TPrimaryKey InsertAndGetId(TEntity entity) + public virtual TKey InsertAndGetId(TEntity entity) { return Insert(entity).Id; } - public virtual Task InsertAndGetIdAsync(TEntity entity) + public virtual Task InsertAndGetIdAsync(TEntity entity) { return Task.FromResult(InsertAndGetId(entity)); } @@ -158,12 +157,12 @@ public virtual async Task InsertOrUpdateAsync(TEntity entity) : await UpdateAsync(entity); } - public virtual TPrimaryKey InsertOrUpdateAndGetId(TEntity entity) + public virtual TKey InsertOrUpdateAndGetId(TEntity entity) { return InsertOrUpdate(entity).Id; } - public virtual Task InsertOrUpdateAndGetIdAsync(TEntity entity) + public virtual Task InsertOrUpdateAndGetIdAsync(TEntity entity) { return Task.FromResult(InsertOrUpdateAndGetId(entity)); } @@ -175,14 +174,14 @@ public virtual Task UpdateAsync(TEntity entity) return Task.FromResult(Update(entity)); } - public virtual TEntity Update(TPrimaryKey id, Action updateAction) + public virtual TEntity Update(TKey id, Action updateAction) { var entity = Get(id); updateAction(entity); return entity; } - public virtual async Task UpdateAsync(TPrimaryKey id, Func updateAction) + public virtual async Task UpdateAsync(TKey id, Func updateAction) { var entity = await GetAsync(id); await updateAction(entity); @@ -197,9 +196,9 @@ public virtual Task DeleteAsync(TEntity entity) return Task.FromResult(0); } - public abstract void Delete(TPrimaryKey id); + public abstract void Delete(TKey id); - public virtual Task DeleteAsync(TPrimaryKey id) + public virtual Task DeleteAsync(TKey id) { Delete(id); return Task.FromResult(0); @@ -259,13 +258,13 @@ public virtual Task LongCountAsync(Expression> predica return Task.FromResult(LongCount(predicate)); } - protected virtual Expression> CreateEqualityExpressionForId(TPrimaryKey id) + protected virtual Expression> CreateEqualityExpressionForId(TKey id) { var lambdaParam = Expression.Parameter(typeof(TEntity)); var lambdaBody = Expression.Equal( Expression.PropertyOrField(lambdaParam, "Id"), - Expression.Constant(id, typeof(TPrimaryKey))); + Expression.Constant(id, typeof(TKey))); return Expression.Lambda>(lambdaBody, lambdaParam); } diff --git a/src/Genocs.MessageBrokers.Outbox/Messages/InboxMessage.cs b/src/Genocs.MessageBrokers.Outbox/Messages/InboxMessage.cs index 8ffc774f..93402645 100644 --- a/src/Genocs.MessageBrokers.Outbox/Messages/InboxMessage.cs +++ b/src/Genocs.MessageBrokers.Outbox/Messages/InboxMessage.cs @@ -1,8 +1,8 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; namespace Genocs.MessageBrokers.Outbox.Messages; -public sealed class InboxMessage : IIdentifiable +public sealed class InboxMessage : IEntity { public string Id { get; set; } public DateTime ProcessedAt { get; set; } diff --git a/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs b/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs index 6c4ce817..f557f795 100644 --- a/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs +++ b/src/Genocs.MessageBrokers.Outbox/Messages/OutboxMessage.cs @@ -1,20 +1,20 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; namespace Genocs.MessageBrokers.Outbox.Messages; -public sealed class OutboxMessage : IIdentifiable +public sealed class OutboxMessage : IEntity { public string Id { get; set; } public string? OriginatedMessageId { get; set; } public string? CorrelationId { get; set; } public string? SpanContext { get; set; } public Dictionary Headers { get; set; } = new(); - public string MessageType { get; set; } - public string MessageContextType { get; set; } + public string? MessageType { get; set; } + public string? MessageContextType { get; set; } public object? Message { get; set; } public object? MessageContext { get; set; } - public string SerializedMessage { get; set; } - public string SerializedMessageContext { get; set; } + public string? SerializedMessage { get; set; } + public string? SerializedMessageContext { get; set; } public DateTime SentAt { get; set; } public DateTime? ProcessedAt { get; set; } diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs index 06d4b5a4..a7349239 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs @@ -1,5 +1,5 @@ -using Genocs.Common.Types; using Genocs.Core.Builders; +using Genocs.Core.Domain.Entities; using Genocs.Persistence.MongoDb.Builders; using Genocs.Persistence.MongoDb.Configurations; using Genocs.Persistence.MongoDb.Factories; @@ -141,19 +141,19 @@ public static IGenocsBuilder AddMongo( /// Adds a MongoDb repository to the DI container. Using Genocs builder support. /// /// The name of the entity. - /// The kind of identifier. + /// The kind of identifier. /// The Genocs builder. /// The collection name where to store data. /// The Genocs builder. - public static IGenocsBuilder AddMongoRepository( - this IGenocsBuilder builder, - string collectionName) - where TEntity : IIdentifiable + public static IGenocsBuilder AddMongoRepository( + this IGenocsBuilder builder, + string collectionName) + where TEntity : IEntity { - builder.Services.AddTransient>(sp => + builder.Services.AddTransient>(sp => { var database = sp.GetRequiredService(); - return new MongoRepository(database, collectionName); + return new MongoRepository(database, collectionName); }); return builder; diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs index 5520d571..a6ae3f3a 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs @@ -1,12 +1,12 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// -/// General purpose Entity used by default in MongoDB. +/// Default MongoDB entity. /// -public interface IMongoDbEntity : IIdentifiable +public interface IMongoDbEntity : IEntity { } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs index 30463760..3b332097 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs @@ -1,4 +1,4 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Repositories.Clean; @@ -8,7 +8,7 @@ namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// /// Type of the Entity for this repository. public class MongoDbRepository : MongoDbRepositoryBase, IMongoDbRepository - where TEntity : class, IIdentifiable + where TEntity : class, IEntity { /// /// The standard constructor. diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs index 5e44e9ae..213bdbc1 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs @@ -1,4 +1,3 @@ -using Genocs.Common.Types; using Genocs.Core.CQRS.Queries; using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Repositories; @@ -13,9 +12,9 @@ namespace Genocs.Persistence.MongoDb.Repositories.Clean; /// Implements IRepository for MongoDB. /// /// Type of the Entity for this repository. -/// Primary key of the entity. -public class MongoDbRepositoryBase : RepositoryBase, IMongoRepository - where TEntity : class, IIdentifiable +/// Primary key of the entity. +public class MongoDbRepositoryBase : RepositoryBase, IMongoRepository + where TEntity : class, IEntity { /// /// Get the MongoDB database. @@ -79,7 +78,7 @@ public override IQueryable GetAll() /// /// /// It is thrown if the entity is not found. - public override TEntity Get(TPrimaryKey id) + public override TEntity Get(TKey id) { var filter = Builders.Filter.Eq(m => m.Id, id); var entity = Collection.Find(filter).FirstOrDefault(); @@ -95,8 +94,8 @@ public override TEntity Get(TPrimaryKey id) /// First Or Default entity. /// /// - /// - public override TEntity FirstOrDefault(TPrimaryKey id) + /// The entity if found otherwise null + public override TEntity FirstOrDefault(TKey id) { var filter = Builders.Filter.Eq(m => m.Id, id); return Collection.Find(filter).FirstOrDefault(); @@ -135,7 +134,7 @@ public override void Delete(TEntity entity) /// Delete entity by primary key. /// /// - public override void Delete(TPrimaryKey id) + public override void Delete(TKey id) { var query = Builders.Filter.Eq(m => m.Id, id); var deleteResult = Collection.DeleteOneAsync(query).Result; diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs index 5cb580d4..8275c79a 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs @@ -1,4 +1,4 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; using Genocs.Persistence.MongoDb.Repositories.Mentor; using MongoDB.Bson; @@ -9,7 +9,7 @@ namespace Genocs.Persistence.MongoDb.Repositories; /// /// The type of the entity. public interface IMongoDbRepository : IMongoRepository - where TEntity : IIdentifiable + where TEntity : IEntity { } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs index 16cf0ddf..08902fb4 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs @@ -1,5 +1,5 @@ -using Genocs.Common.Types; using Genocs.Core.CQRS.Queries; +using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Repositories; using MongoDB.Driver; using MongoDB.Driver.Linq; @@ -7,8 +7,8 @@ namespace Genocs.Persistence.MongoDb.Repositories.Mentor; -public interface IMongoRepository : IRepositoryOfEntity - where TEntity : IIdentifiable +public interface IMongoRepository : IRepositoryOfEntity + where TEntity : IEntity { IMongoCollection Collection { get; } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs index 3bee0d81..3a7ae2ae 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs @@ -1,5 +1,6 @@ using Genocs.Common.Types; using Genocs.Core.CQRS.Queries; +using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Repositories; using MongoDB.Driver; using MongoDB.Driver.Linq; @@ -7,8 +8,8 @@ namespace Genocs.Persistence.MongoDb.Repositories.Mentor; -internal class MongoRepository : IMongoRepository - where TEntity : IIdentifiable +internal class MongoRepository : IMongoRepository + where TEntity : IEntity { public MongoRepository(IMongoDatabase database, string collectionName) { @@ -26,7 +27,7 @@ public IMongoQueryable GetMongoQueryable() return Collection.AsQueryable(); } - public Task GetAsync(TIdentifiable id) + public Task GetAsync(TKey id) => GetAsync(e => e.Id.Equals(id)); public Task GetAsync(Expression> predicate) @@ -69,7 +70,7 @@ public Task UpdateAsync(TEntity entity, Expression> predicat /// /// /// - public Task DeleteAsync(TIdentifiable id) + public Task DeleteAsync(TKey id) => DeleteAsync(e => e.Id.Equals(id)); public Task DeleteAsync(Expression> predicate) @@ -115,7 +116,7 @@ public T Query(Func, T> queryMethod) throw new NotImplementedException(); } - public TEntity Get(TIdentifiable id) + public TEntity Get(TKey id) => Collection.Find(c => c.Id.Equals(id)).First(); public TEntity Single(Expression> predicate) @@ -127,10 +128,10 @@ public async Task SingleAsync(Expression> predicate return await result.SingleAsync(); } - public TEntity? FirstOrDefault(TIdentifiable id) + public TEntity? FirstOrDefault(TKey id) => Collection.Find(c => c.Id.Equals(id)).FirstOrDefault(); - public async Task FirstOrDefaultAsync(TIdentifiable id) + public async Task FirstOrDefaultAsync(TKey id) { var result = await Collection.FindAsync(c => c.Id.Equals(id)); return await result.FirstOrDefaultAsync(); @@ -145,7 +146,7 @@ public TEntity FirstOrDefault(Expression> predicate) return await result.FirstOrDefaultAsync(); } - public TEntity? Load(TIdentifiable id) + public TEntity? Load(TKey id) => FirstOrDefault(id); public TEntity Insert(TEntity entity) @@ -160,10 +161,10 @@ public async Task InsertAsync(TEntity entity) return entity; } - public TIdentifiable InsertAndGetId(TEntity entity) + public TKey InsertAndGetId(TEntity entity) => Insert(entity).Id; - public async Task InsertAndGetIdAsync(TEntity entity) + public async Task InsertAndGetIdAsync(TEntity entity) => (await InsertAsync(entity)).Id; public TEntity InsertOrUpdate(TEntity entity) @@ -178,10 +179,10 @@ public async Task InsertOrUpdateAsync(TEntity entity) return entity; } - public TIdentifiable InsertOrUpdateAndGetId(TEntity entity) + public TKey InsertOrUpdateAndGetId(TEntity entity) => InsertOrUpdate(entity).Id; - public async Task InsertOrUpdateAndGetIdAsync(TEntity entity) + public async Task InsertOrUpdateAndGetIdAsync(TEntity entity) => (await InsertOrUpdateAsync(entity)).Id; public TEntity Update(TEntity entity) @@ -190,12 +191,12 @@ public TEntity Update(TEntity entity) return entity; } - public TEntity Update(TIdentifiable id, Action updateAction) + public TEntity Update(TKey id, Action updateAction) { throw new NotImplementedException(); } - public Task UpdateAsync(TIdentifiable id, Func updateAction) + public Task UpdateAsync(TKey id, Func updateAction) { throw new NotImplementedException(); } @@ -216,7 +217,7 @@ public Task DeleteAsync(TEntity entity) return DeleteAsync(entity.Id); } - public void Delete(TIdentifiable id) + public void Delete(TKey id) { if (id == null) { @@ -260,7 +261,7 @@ public long LongCount(Expression> predicate) public async Task LongCountAsync(Expression> predicate) => await Collection.CountDocumentsAsync(predicate); - async Task IRepositoryOfEntity.UpdateAsync(TEntity entity) + async Task IRepositoryOfEntity.UpdateAsync(TEntity entity) { await UpdateAsync(entity, e => e.Id!.Equals(entity.Id)); return entity; diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/RefreshTokenDocument.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/RefreshTokenDocument.cs index 9b97b073..48820859 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/RefreshTokenDocument.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/RefreshTokenDocument.cs @@ -1,9 +1,9 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; using Genocs.Identities.Application.Domain.Entities; namespace Genocs.Identities.Application.Mongo.Documents; -public class RefreshTokenDocument : IIdentifiable +public class RefreshTokenDocument : IEntity { public Guid Id { get; set; } public Guid UserId { get; set; } diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/UserDocument.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/UserDocument.cs index 8090b063..06ddeb7d 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/UserDocument.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Documents/UserDocument.cs @@ -1,9 +1,10 @@ using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; using Genocs.Identities.Application.Domain.Entities; namespace Genocs.Identities.Application.Mongo.Documents; -public class UserDocument : IIdentifiable +public class UserDocument : IEntity { public Guid Id { get; set; } public string Email { get; set; } diff --git a/src/apps/orders/Genocs.Orders.WebApi/Domain/Order.cs b/src/apps/orders/Genocs.Orders.WebApi/Domain/Order.cs index 3a1b1f69..ad0cfb06 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Domain/Order.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Domain/Order.cs @@ -1,8 +1,8 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; namespace Genocs.Orders.WebApi.Domain; -public class Order : IIdentifiable +public class Order : IEntity { public Guid Id { get; private set; } public Guid CustomerId { get; private set; } diff --git a/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs b/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs index 986e8262..087a076f 100644 --- a/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs +++ b/src/apps/products/Genocs.Products.WebApi/Domain/Product.cs @@ -1,11 +1,11 @@ -using Genocs.Common.Types; +using Genocs.Core.Domain.Entities; namespace Genocs.Products.WebApi.Domain; /// /// The product definition. /// -public class Product : IIdentifiable +public class Product : IEntity { public Guid Id { get; private set; } public string SKU { get; private set; } From c10e995b229fa8958e7f0585679562c711a56c22 Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Mon, 4 Nov 2024 17:59:49 +0100 Subject: [PATCH 097/104] Standardize property names and update audit fields Renamed properties to standardize naming conventions: - `CreationTime` to `CreatedAt` - `LastModificationTime` to `LastUpdate` - `LastModifierUserId` to `UpdatedBy` - `DeleterUserId` to `DeletedBy` - `DeletionTime` to `DeletedAt` - `LastModifierUser` to `UpdatedByUser` - `DeleterUser` to `DeletedByUser` Changed `CreatorUserId` to non-nullable. Updated `EntityAuditingHelper` and `EntityExtensions` for new names. Refactored `RepositoryBase` to use null-coalescing operator. Reformatted `AutoRepositoryTypesAttribute` for readability. Updated comments and documentation for clarity. --- .../Aggregates/BaseAggregate.cs | 2 +- .../Aggregates/Order.cs | 2 +- .../Aggregates/User.cs | 3 +- .../Entities/Auditing/AuditedAggregateRoot.cs | 6 +-- .../Domain/Entities/Auditing/AuditedEntity.cs | 6 +-- .../Auditing/CreationAuditedAggregateRoot.cs | 6 +-- .../Auditing/CreationAuditedEntity.cs | 8 ++-- .../Entities/Auditing/EntityAuditingHelper.cs | 12 ++--- .../Auditing/FullAuditedAggregateRoot.cs | 10 ++-- .../Entities/Auditing/FullAuditedEntity.cs | 12 ++--- .../Entities/Auditing/ICreationAudited.cs | 2 +- .../Entities/Auditing/IDeletionAudited.cs | 4 +- .../Entities/Auditing/IHasCreationTime.cs | 6 +-- .../Entities/Auditing/IHasDeletionTime.cs | 6 +-- .../Entities/Auditing/IHasModificationTime.cs | 21 ++++----- .../Entities/Auditing/IModificationAudited.cs | 39 ++++++++------- .../Domain/Entities/EntityExtensions.cs | 4 +- .../AutoRepositoryTypesAttribute.cs | 47 +++++++++---------- .../Domain/Repositories/RepositoryBase.cs | 14 +----- 19 files changed, 96 insertions(+), 114 deletions(-) diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs b/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs index e074b90e..9c755be3 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs @@ -10,5 +10,5 @@ namespace Genocs.Core.Demo.Domain.Aggregates; /// public class BaseAggregate : AggregateRoot, IMongoDbEntity, IHasCreationTime { - public DateTime CreationTime { get; set; } = DateTime.UtcNow; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } \ No newline at end of file diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs index f9553296..d9ec2d79 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs @@ -19,7 +19,7 @@ public Order(string orderId, string userId, decimal amount, string currency) public string OrderId { get; set; } = ObjectId.GenerateNewId().ToString(); public string UserId { get; set; } = default!; - public DateTime CreationTime { get; set; } = DateTime.UtcNow; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public decimal Amount { get; set; } public string Currency { get; set; } = default!; } diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs index f1015024..60ceb184 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs @@ -8,10 +8,9 @@ namespace Genocs.Core.Demo.Domain.Aggregates; [TableMapping("Users")] public class User : IEntity, IHasCreationTime { - public ObjectId Id { get; set; } public string UserId { get; set; } = default!; - public DateTime CreationTime { get; set; } = DateTime.UtcNow; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public string Username { get; set; } = default!; public decimal Age { get; set; } public string Country { get; set; } = default!; diff --git a/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs index 4433ee83..e3e831cc 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/AuditedAggregateRoot.cs @@ -21,12 +21,12 @@ public abstract class AuditedAggregateRoot : CreationAuditedAggrega /// /// Last modification date of this entity. /// - public virtual DateTime? LastModificationTime { get; set; } + public virtual DateTime? LastUpdate { get; set; } /// /// Last modifier user of this entity. /// - public virtual long? LastModifierUserId { get; set; } + public virtual long? UpdatedBy { get; set; } } /// @@ -48,5 +48,5 @@ public abstract class AuditedAggregateRoot : AuditedAggregat /// Reference to the last modifier user of this entity. /// [ForeignKey("LastModifierUserId")] - public virtual TUser? LastModifierUser { get; set; } + public virtual TUser? UpdatedByUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs index e81dd13b..3476f704 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/AuditedEntity.cs @@ -21,12 +21,12 @@ public abstract class AuditedEntity : CreationAuditedEntity /// Last modification date of this entity. /// - public virtual DateTime? LastModificationTime { get; set; } + public virtual DateTime? LastUpdate { get; set; } /// /// Last modifier user of this entity. /// - public virtual long? LastModifierUserId { get; set; } + public virtual long? UpdatedBy { get; set; } } /// @@ -48,5 +48,5 @@ public abstract class AuditedEntity : AuditedEntity [ForeignKey("LastModifierUserId")] - public virtual TUser? LastModifierUser { get; set; } + public virtual TUser? UpdatedByUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs index 66e69619..8b9e04af 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs @@ -22,12 +22,12 @@ public abstract class CreationAuditedAggregateRoot : AggregateRoot< /// /// Creation time of this entity. /// - public virtual DateTime CreationTime { get; set; } + public virtual DateTime CreatedAt { get; set; } /// /// Creator of this entity. /// - public virtual long? CreatorUserId { get; set; } + public virtual long CreatorUserId { get; set; } /// /// Constructor. @@ -35,7 +35,7 @@ public abstract class CreationAuditedAggregateRoot : AggregateRoot< protected CreationAuditedAggregateRoot() { // CreationTime = Clock.Now; // Manage time zone - CreationTime = DateTime.Now; + CreatedAt = DateTime.Now; } } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs index 8bb8195d..9299acb6 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/CreationAuditedEntity.cs @@ -1,7 +1,5 @@ using System.ComponentModel.DataAnnotations.Schema; -// using Genocs.Timing; - namespace Genocs.Core.Domain.Entities.Auditing; /// @@ -23,12 +21,12 @@ public abstract class CreationAuditedEntity : Entity, /// /// Creation time of this entity. /// - public virtual DateTime CreationTime { get; set; } + public virtual DateTime CreatedAt { get; set; } /// /// Creator of this entity. /// - public virtual long? CreatorUserId { get; set; } + public virtual long CreatorUserId { get; set; } /// /// Constructor. @@ -36,7 +34,7 @@ public abstract class CreationAuditedEntity : Entity, protected CreationAuditedEntity() { // CreationTime = Clock.Now; - CreationTime = DateTime.Now; + CreatedAt = DateTime.Now; } } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs index ac66f190..ab16a4b5 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs @@ -21,10 +21,10 @@ public static void SetCreationAuditProperties( return; } - if (entityWithCreationTime.CreationTime == default(DateTime)) + if (entityWithCreationTime.CreatedAt == default(DateTime)) { // entityWithCreationTime.CreationTime = Clock.Now; - entityWithCreationTime.CreationTime = DateTime.Now; + entityWithCreationTime.CreatedAt = DateTime.Now; } @@ -64,7 +64,7 @@ public static void SetCreationAuditProperties( //} // Finally, set CreatorUserId! - entity.CreatorUserId = userId; + entity.CreatorUserId = userId.Value; } public static void SetModificationAuditProperties( @@ -77,7 +77,7 @@ public static void SetModificationAuditProperties( if (entityAsObj is IHasModificationTime) { // entityAsObj.As().LastModificationTime = Clock.Now; - entityAsObj.As().LastModificationTime = DateTime.Now; + entityAsObj.As().LastUpdate = DateTime.Now; } if (!(entityAsObj is IModificationAudited)) @@ -91,7 +91,7 @@ public static void SetModificationAuditProperties( if (userId == null) { // Unknown user - entity.LastModifierUserId = null; + entity.UpdatedBy = null; return; } @@ -116,6 +116,6 @@ public static void SetModificationAuditProperties( */ // Finally, set LastModifierUserId! - entity.LastModifierUserId = userId; + entity.UpdatedBy = userId; } } diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs index dbdcc4f4..63f29d02 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs @@ -26,12 +26,12 @@ public abstract class FullAuditedAggregateRoot : AuditedAggregateRo /// /// Which user deleted this entity. /// - public virtual long? DeleterUserId { get; set; } + public virtual long? DeletedBy { get; set; } /// /// Deletion time of this entity. /// - public virtual DateTime? DeletionTime { get; set; } + public virtual DateTime? DeletedAt { get; set; } } /// @@ -52,15 +52,15 @@ public abstract class FullAuditedAggregateRoot : AuditedAggr /// Reference to the deleter user of this entity. /// [ForeignKey("DeleterUserId")] - public virtual TUser DeleterUser { get; set; } + public virtual TUser DeletedByUser { get; set; } /// /// Which user deleted this entity. /// - public virtual long? DeleterUserId { get; set; } + public virtual long? DeletedBy { get; set; } /// /// Deletion time of this entity. /// - public virtual DateTime? DeletionTime { get; set; } + public virtual DateTime? DeletedAt { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs index 8309b385..72a30ccb 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/FullAuditedEntity.cs @@ -27,12 +27,12 @@ public abstract class FullAuditedEntity : AuditedEntity /// It determines the user who deleted this entity. /// - public virtual long? DeleterUserId { get; set; } + public virtual long? DeletedBy { get; set; } /// /// Deletion time of this entity. /// - public virtual DateTime? DeletionTime { get; set; } + public virtual DateTime? DeletedAt { get; set; } } /// @@ -45,7 +45,7 @@ public abstract class FullAuditedEntity : AuditedEntity { /// - /// Is this entity Deleted? + /// It determines if the entity is deleted. /// public virtual bool IsDeleted { get; set; } @@ -53,15 +53,15 @@ public abstract class FullAuditedEntity : AuditedEntity [ForeignKey("DeleterUserId")] - public virtual TUser DeleterUser { get; set; } + public virtual TUser? DeletedByUser { get; set; } /// /// Which user deleted this entity. /// - public virtual long? DeleterUserId { get; set; } + public virtual long? DeletedBy { get; set; } /// /// Deletion time of this entity. /// - public virtual DateTime? DeletionTime { get; set; } + public virtual DateTime? DeletedAt { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs index 9ffac146..8b2082b0 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/ICreationAudited.cs @@ -9,7 +9,7 @@ public interface ICreationAudited : IHasCreationTime /// /// Id of the creator user of this entity. /// - long? CreatorUserId { get; set; } + long CreatorUserId { get; set; } } /// diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs index bfa83bab..125de9aa 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IDeletionAudited.cs @@ -8,7 +8,7 @@ public interface IDeletionAudited : IHasDeletionTime /// /// Which user deleted this entity. /// - long? DeleterUserId { get; set; } + long? DeletedBy { get; set; } } /// @@ -21,5 +21,5 @@ public interface IDeletionAudited : IDeletionAudited /// /// Reference to the deleter user of this entity. /// - TUser DeleterUser { get; set; } + TUser? DeletedByUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs index 8e0ca32f..47495e6d 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs @@ -1,13 +1,13 @@ namespace Genocs.Core.Domain.Entities.Auditing; /// -/// An entity can implement this interface if of this entity must be stored. -/// is automatically set when saving to database. +/// An entity can implement this interface if of this entity must be stored. +/// is automatically set when saving to database. /// public interface IHasCreationTime { /// /// Creation time of this entity. /// - DateTime CreationTime { get; set; } + DateTime CreatedAt { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs b/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs index 450bfc1b..9adc7903 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IHasDeletionTime.cs @@ -1,13 +1,13 @@ namespace Genocs.Core.Domain.Entities.Auditing; /// -/// An entity can implement this interface if of this entity must be stored. -/// is automatically set when deleting . +/// An entity can implement this interface if of this entity must be stored. +/// is automatically set when deleting . /// public interface IHasDeletionTime : ISoftDelete { /// /// Deletion time of this entity. /// - DateTime? DeletionTime { get; set; } + DateTime? DeletedAt { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IHasModificationTime.cs b/src/Genocs.Core/Domain/Entities/Auditing/IHasModificationTime.cs index 80519008..4c0c647b 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IHasModificationTime.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IHasModificationTime.cs @@ -1,16 +1,13 @@ -namespace Genocs.Core.Domain.Entities.Auditing -{ - using System; +namespace Genocs.Core.Domain.Entities.Auditing; +/// +/// An entity can implement this interface if of this entity must be stored. +/// is automatically set when updating . +/// +public interface IHasModificationTime +{ /// - /// An entity can implement this interface if of this entity must be stored. - /// is automatically set when updating . + /// The last modified time for this entity. /// - public interface IHasModificationTime - { - /// - /// The last modified time for this entity. - /// - DateTime? LastModificationTime { get; set; } - } + DateTime? LastUpdate { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IModificationAudited.cs b/src/Genocs.Core/Domain/Entities/Auditing/IModificationAudited.cs index bdcd8c3a..d12f0438 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IModificationAudited.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IModificationAudited.cs @@ -1,27 +1,26 @@ -namespace Genocs.Core.Domain.Entities.Auditing +namespace Genocs.Core.Domain.Entities.Auditing; + +/// +/// This interface is implemented by entities that is wanted to store modification information (who and when modified lastly). +/// Properties are automatically set when updating the . +/// +public interface IModificationAudited : IHasModificationTime { /// - /// This interface is implemented by entities that is wanted to store modification information (who and when modified lastly). - /// Properties are automatically set when updating the . + /// Last modifier user for this entity. /// - public interface IModificationAudited : IHasModificationTime - { - /// - /// Last modifier user for this entity. - /// - long? LastModifierUserId { get; set; } - } + long? UpdatedBy { get; set; } +} +/// +/// Adds navigation properties to interface for user. +/// +/// Type of the user +public interface IModificationAudited : IModificationAudited + where TUser : IEntity +{ /// - /// Adds navigation properties to interface for user. + /// Reference to the last modifier user of this entity. /// - /// Type of the user - public interface IModificationAudited : IModificationAudited - where TUser : IEntity - { - /// - /// Reference to the last modifier user of this entity. - /// - TUser LastModifierUser { get; set; } - } + TUser? UpdatedByUser { get; set; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Entities/EntityExtensions.cs b/src/Genocs.Core/Domain/Entities/EntityExtensions.cs index ac7868d7..f085e29d 100644 --- a/src/Genocs.Core/Domain/Entities/EntityExtensions.cs +++ b/src/Genocs.Core/Domain/Entities/EntityExtensions.cs @@ -26,8 +26,8 @@ public static void UnDelete(this ISoftDelete entity) if (entity is IDeletionAudited) { var deletionAuditedEntity = entity.As(); - deletionAuditedEntity.DeletionTime = null; - deletionAuditedEntity.DeleterUserId = null; + deletionAuditedEntity.DeletedAt = null; + deletionAuditedEntity.DeletedBy = null; } } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs b/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs index f1734ebd..5b28b5a3 100644 --- a/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs +++ b/src/Genocs.Core/Domain/Repositories/AutoRepositoryTypesAttribute.cs @@ -1,32 +1,31 @@ -namespace Genocs.Core.Domain.Repositories +namespace Genocs.Core.Domain.Repositories; + +/// +/// Used to define auto-repository types for entities. +/// This can be used for DbContext types. +/// +[AttributeUsage(AttributeTargets.Class)] +public class AutoRepositoryTypesAttribute : Attribute { - /// - /// Used to define auto-repository types for entities. - /// This can be used for DbContext types. - /// - [AttributeUsage(AttributeTargets.Class)] - public class AutoRepositoryTypesAttribute : Attribute - { - public Type RepositoryInterface { get; } + public Type RepositoryInterface { get; } - public Type RepositoryInterfaceWithPrimaryKey { get; } + public Type RepositoryInterfaceWithPrimaryKey { get; } - public Type RepositoryImplementation { get; } + public Type RepositoryImplementation { get; } - public Type RepositoryImplementationWithPrimaryKey { get; } + public Type RepositoryImplementationWithPrimaryKey { get; } - public bool WithDefaultRepositoryInterfaces { get; set; } + public bool WithDefaultRepositoryInterfaces { get; set; } - public AutoRepositoryTypesAttribute( - Type repositoryInterface, - Type repositoryInterfaceWithPrimaryKey, - Type repositoryImplementation, - Type repositoryImplementationWithPrimaryKey) - { - RepositoryInterface = repositoryInterface; - RepositoryInterfaceWithPrimaryKey = repositoryInterfaceWithPrimaryKey; - RepositoryImplementation = repositoryImplementation; - RepositoryImplementationWithPrimaryKey = repositoryImplementationWithPrimaryKey; - } + public AutoRepositoryTypesAttribute( + Type repositoryInterface, + Type repositoryInterfaceWithPrimaryKey, + Type repositoryImplementation, + Type repositoryImplementationWithPrimaryKey) + { + RepositoryInterface = repositoryInterface; + RepositoryInterfaceWithPrimaryKey = repositoryInterfaceWithPrimaryKey; + RepositoryImplementation = repositoryImplementation; + RepositoryImplementationWithPrimaryKey = repositoryImplementationWithPrimaryKey; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs index 2747c683..ae99c510 100644 --- a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs +++ b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs @@ -72,23 +72,13 @@ public virtual T Query(Func, T> queryMethod) public virtual TEntity Get(TKey id) { var entity = FirstOrDefault(id); - if (entity == null) - { - throw new EntityNotFoundException(typeof(TEntity), id); - } - - return entity; + return entity ?? throw new EntityNotFoundException(typeof(TEntity), id); } public virtual async Task GetAsync(TKey id) { var entity = await FirstOrDefaultAsync(id); - if (entity == null) - { - throw new EntityNotFoundException(typeof(TEntity), id); - } - - return entity; + return entity ?? throw new EntityNotFoundException(typeof(TEntity), id); } public virtual TEntity Single(Expression> predicate) From 98e24b1aab96ca4276924a822e0b5ffec50c3e9b Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Fri, 8 Nov 2024 14:34:08 +0100 Subject: [PATCH 098/104] Refactor MongoDB repository structure and base classes - Updated `BaseAggregate` to initialize `Id` and `CreatedAt`. - Refactored `Order` and `User` classes to inherit from `BaseAggregate`. - Made `CreatedAt` property read-only in `IHasCreationTime`. - Removed `class` constraint in `RepositoryBase`. - Added comments and reformatted methods in `SystemTextJsonHttpClientSerializer`, `IMessageToLogTemplateMapper`, and `SeqOptions`. - Updated `HandlerLogTemplate` to use nullable `string?`. - Replaced `IMongoRepository` with `IMongoDbBaseRepository` in various classes. - Removed `IMongoDbEntity` interface and several `MongoDbRepository` classes. - Introduced `IMongoDbBaseRepository`, `MongoDbBaseRepository`, `IMongoDbEntity`, and `MongoDbRepository` classes. - Updated multiple files to reflect repository structure changes. --- .../Aggregates/BaseAggregate.cs | 12 +++++++- .../Aggregates/Order.cs | 8 ++---- .../Aggregates/User.cs | 15 ++-------- src/Genocs.Core.Demo.Worker/Program.cs | 2 +- src/Genocs.Core/Builders/Extensions.cs | 4 +-- .../Collections/Extensions/ListExtensions.cs | 6 ++-- src/Genocs.Core/Collections/TypeList.cs | 8 +++++- .../Entities/Auditing/EntityAuditingHelper.cs | 3 +- .../Entities/Auditing/IHasCreationTime.cs | 2 +- .../Domain/Repositories/RepositoryBase.cs | 2 +- .../Extensions/ObjectExtensions.cs | 4 +-- .../GenocsLoggingScopeHttpMessageHandler.cs | 6 ++++ src/Genocs.HTTP/ICorrelationIdFactory.cs | 2 +- .../SystemTextJsonHttpClientSerializer.cs | 7 +++-- src/Genocs.Logging/CQRS/HandlerLogTemplate.cs | 2 +- .../CQRS/IMessageToLogTemplateMapper.cs | 13 +++++---- .../Configurations/SeqOptions.cs | 14 ++++++++++ .../Extensions.cs | 4 +-- .../Internals/MongoMessageOutbox.cs | 28 ++++++++++++------- .../Internals/MongoOutboxInitializer.cs | 23 ++++++++------- .../Entities}/IMongoDbEntity.cs | 2 +- .../Repositories/IMongoDbBaseRepository.cs} | 4 +-- .../Repositories/MongoDbBaseRepository.cs} | 8 +++--- .../Repositories}/MongoDbRepository.cs | 7 +++-- .../MongoDbRepositoryBaseOfEntityAndKey.cs | 17 ++++++----- .../Extensions/MongoDbExtensions.cs | 7 ++--- .../Clean/MongoDbRepositoryBaseOfEntity.cs | 20 ------------- .../Repositories/IMongoDbRepository.cs | 8 +++--- .../Mongo/Extensions.cs | 4 +-- .../Mongo/Queries/Handlers/GetUserHandler.cs | 6 ++-- .../Repositories/RefreshTokenRepository.cs | 6 ++-- .../Mongo/Repositories/UserRepository.cs | 6 ++-- .../Commands/Handlers/CreateOrderHandler.cs | 6 ++-- .../Queries/Handlers/GetOrderHandler.cs | 6 ++-- .../Commands/Handlers/CreateProductHandler.cs | 6 ++-- .../Queries/Handlers/GetProductHandler.cs | 6 ++-- 36 files changed, 151 insertions(+), 133 deletions(-) rename src/Genocs.Persistence.MongoDb/{Repositories/Clean => Domain/Entities}/IMongoDbEntity.cs (75%) rename src/Genocs.Persistence.MongoDb/{Repositories/Mentor/IMongoRepository.cs => Domain/Repositories/IMongoDbBaseRepository.cs} (84%) rename src/Genocs.Persistence.MongoDb/{Repositories/Mentor/MongoRepository.cs => Domain/Repositories/MongoDbBaseRepository.cs} (96%) rename src/Genocs.Persistence.MongoDb/{Repositories/Clean => Domain/Repositories}/MongoDbRepository.cs (74%) rename src/Genocs.Persistence.MongoDb/{Repositories/Clean => Domain/Repositories}/MongoDbRepositoryBaseOfEntityAndKey.cs (90%) delete mode 100644 src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs b/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs index 9c755be3..f0eede68 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/BaseAggregate.cs @@ -1,14 +1,24 @@ using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Entities.Auditing; -using Genocs.Persistence.MongoDb.Repositories.Clean; +using Genocs.Persistence.MongoDb.Domain.Entities; using MongoDB.Bson; namespace Genocs.Core.Demo.Domain.Aggregates; /// /// Base aggregate class used for all entities. +/// This class is used to define some common properties for all entities. /// public class BaseAggregate : AggregateRoot, IMongoDbEntity, IHasCreationTime { + public BaseAggregate() + { + // Set the unique identifier for the entity generates a new ObjectId. + Id = ObjectId.GenerateNewId(); + } + + /// + /// Creation time of this entity. + /// public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } \ No newline at end of file diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs index d9ec2d79..0a8c3080 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/Order.cs @@ -1,13 +1,10 @@ -using Genocs.Core.Domain.Entities; -using Genocs.Core.Domain.Entities.Auditing; -using Genocs.Core.Domain.Repositories; -using Genocs.Persistence.MongoDb.Repositories.Clean; +using Genocs.Core.Domain.Repositories; using MongoDB.Bson; namespace Genocs.Core.Demo.Domain.Aggregates; [TableMapping("Orders")] -public class Order : AggregateRoot, IMongoDbEntity, IHasCreationTime +public class Order : BaseAggregate { public Order(string orderId, string userId, decimal amount, string currency) { @@ -19,7 +16,6 @@ public Order(string orderId, string userId, decimal amount, string currency) public string OrderId { get; set; } = ObjectId.GenerateNewId().ToString(); public string UserId { get; set; } = default!; - public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public decimal Amount { get; set; } public string Currency { get; set; } = default!; } diff --git a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs index 60ceb184..94f13764 100644 --- a/src/Genocs.Core.Demo.Domain/Aggregates/User.cs +++ b/src/Genocs.Core.Demo.Domain/Aggregates/User.cs @@ -1,31 +1,20 @@ -using Genocs.Core.Domain.Entities; -using Genocs.Core.Domain.Entities.Auditing; -using Genocs.Core.Domain.Repositories; -using MongoDB.Bson; +using Genocs.Core.Domain.Repositories; namespace Genocs.Core.Demo.Domain.Aggregates; [TableMapping("Users")] -public class User : IEntity, IHasCreationTime +public class User : BaseAggregate { - public ObjectId Id { get; set; } public string UserId { get; set; } = default!; - public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public string Username { get; set; } = default!; public decimal Age { get; set; } public string Country { get; set; } = default!; public User(string userId, string username, decimal age, string country) { - Id = ObjectId.GenerateNewId(); UserId = userId; Username = username; Age = age; Country = country; } - - public bool IsTransient() - { - return true; - } } diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index f9cc495e..b44b84c1 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -7,9 +7,9 @@ using Genocs.Core.Demo.Worker.Consumers; using Genocs.Core.Demo.Worker.Handlers; using Genocs.Logging; +using Genocs.Persistence.MongoDb.Domain.Repositories; using Genocs.Persistence.MongoDb.Extensions; using Genocs.Persistence.MongoDb.Repositories; -using Genocs.Persistence.MongoDb.Repositories.Clean; using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; diff --git a/src/Genocs.Core/Builders/Extensions.cs b/src/Genocs.Core/Builders/Extensions.cs index 10638e44..72fa6c39 100644 --- a/src/Genocs.Core/Builders/Extensions.cs +++ b/src/Genocs.Core/Builders/Extensions.cs @@ -14,8 +14,8 @@ public static class Extensions /// /// The Builder. /// - /// - /// + /// The service collection. + /// The configuration. /// The builder. public static IGenocsBuilder AddGenocs(this IServiceCollection services, IConfiguration? configuration = null) { diff --git a/src/Genocs.Core/Collections/Extensions/ListExtensions.cs b/src/Genocs.Core/Collections/Extensions/ListExtensions.cs index 5738f16e..44a21f72 100644 --- a/src/Genocs.Core/Collections/Extensions/ListExtensions.cs +++ b/src/Genocs.Core/Collections/Extensions/ListExtensions.cs @@ -6,11 +6,11 @@ public static class ListExtensions { /// - /// Sort a list by a topological sorting, which consider their dependencies + /// Sort a list by a topological sorting, which consider their dependencies. /// /// The type of the members of values. - /// A list of objects to sort - /// Function to resolve the dependencies + /// A list of objects to sort. + /// Function to resolve the dependencies. /// public static List SortByDependencies(this IEnumerable source, Func> getDependencies) { diff --git a/src/Genocs.Core/Collections/TypeList.cs b/src/Genocs.Core/Collections/TypeList.cs index 0b8013c1..d8c636c6 100644 --- a/src/Genocs.Core/Collections/TypeList.cs +++ b/src/Genocs.Core/Collections/TypeList.cs @@ -20,7 +20,13 @@ public class TypeList : ITypeList /// Gets the count. /// /// The count. - public int Count { get { return _typeList.Count; } } + public int Count + { + get + { + return _typeList.Count; + } + } /// /// Gets a value indicating whether this instance is read only. diff --git a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs index ab16a4b5..e05e7853 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/EntityAuditingHelper.cs @@ -24,8 +24,7 @@ public static void SetCreationAuditProperties( if (entityWithCreationTime.CreatedAt == default(DateTime)) { // entityWithCreationTime.CreationTime = Clock.Now; - entityWithCreationTime.CreatedAt = DateTime.Now; - + // entityWithCreationTime.CreatedAt = DateTime.Now; } if (!(entityAsObj is ICreationAudited)) diff --git a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs index 47495e6d..b8867ce7 100644 --- a/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs +++ b/src/Genocs.Core/Domain/Entities/Auditing/IHasCreationTime.cs @@ -9,5 +9,5 @@ public interface IHasCreationTime /// /// Creation time of this entity. /// - DateTime CreatedAt { get; set; } + DateTime CreatedAt { get; } } \ No newline at end of file diff --git a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs index ae99c510..ce2d7c3b 100644 --- a/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs +++ b/src/Genocs.Core/Domain/Repositories/RepositoryBase.cs @@ -15,7 +15,7 @@ namespace Genocs.Core.Domain.Repositories; /// Type of the Entity for this repository. /// Type of the Primary Key for this repository. public abstract class RepositoryBase : IRepository/*, IUnitOfWorkManagerAccessor */ - where TEntity : class, IEntity + where TEntity : IEntity { /// /// The multi tenancy side. diff --git a/src/Genocs.Core/Extensions/ObjectExtensions.cs b/src/Genocs.Core/Extensions/ObjectExtensions.cs index 518d32f5..c6656ba7 100644 --- a/src/Genocs.Core/Extensions/ObjectExtensions.cs +++ b/src/Genocs.Core/Extensions/ObjectExtensions.cs @@ -21,11 +21,11 @@ public static T As(this object obj) } /// - /// Converts given object to a value type using method. + /// Converts given object to a value type using method. /// /// Object to be converted. /// Type of the target object. - /// Converted object + /// Converted object. public static T To(this object obj) where T : struct { diff --git a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs index 0753c680..468ab49d 100644 --- a/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs +++ b/src/Genocs.HTTP/GenocsLoggingScopeHttpMessageHandler.cs @@ -88,6 +88,12 @@ public static void RequestPipelineEnd(ILogger logger, HttpResponseMessage respon } string? requestUri = uri?.OriginalString; + + if (string.IsNullOrWhiteSpace(requestUri)) + { + return uri; + } + bool hasMatch = false; foreach (string part in maskedRequestUrlParts) { diff --git a/src/Genocs.HTTP/ICorrelationIdFactory.cs b/src/Genocs.HTTP/ICorrelationIdFactory.cs index 4580c4dc..099e8075 100644 --- a/src/Genocs.HTTP/ICorrelationIdFactory.cs +++ b/src/Genocs.HTTP/ICorrelationIdFactory.cs @@ -9,5 +9,5 @@ public interface ICorrelationIdFactory /// Create a correlationId. /// /// - string Create(); + string? Create(); } \ No newline at end of file diff --git a/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs b/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs index accab9d4..82e5e522 100644 --- a/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs +++ b/src/Genocs.HTTP/SystemTextJsonHttpClientSerializer.cs @@ -9,6 +9,7 @@ public class SystemTextJsonHttpClientSerializer : IHttpClientSerializer public SystemTextJsonHttpClientSerializer(JsonSerializerOptions? options = null) { + // Default options _options = options ?? new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, @@ -18,7 +19,9 @@ public SystemTextJsonHttpClientSerializer(JsonSerializerOptions? options = null) }; } - public string Serialize(T value) => JsonSerializer.Serialize(value, _options); + public string Serialize(T value) + => JsonSerializer.Serialize(value, _options); - public ValueTask DeserializeAsync(Stream stream) => JsonSerializer.DeserializeAsync(stream, _options); + public ValueTask DeserializeAsync(Stream stream) + => JsonSerializer.DeserializeAsync(stream, _options); } \ No newline at end of file diff --git a/src/Genocs.Logging/CQRS/HandlerLogTemplate.cs b/src/Genocs.Logging/CQRS/HandlerLogTemplate.cs index 12ac2957..757cab15 100644 --- a/src/Genocs.Logging/CQRS/HandlerLogTemplate.cs +++ b/src/Genocs.Logging/CQRS/HandlerLogTemplate.cs @@ -15,6 +15,6 @@ public sealed class HandlerLogTemplate return null; } - return OnError.TryGetValue(exceptionType, out var template) ? template : null; + return OnError.TryGetValue(exceptionType, out string? template) ? template : null; } } \ No newline at end of file diff --git a/src/Genocs.Logging/CQRS/IMessageToLogTemplateMapper.cs b/src/Genocs.Logging/CQRS/IMessageToLogTemplateMapper.cs index 8785149a..cb71eb87 100644 --- a/src/Genocs.Logging/CQRS/IMessageToLogTemplateMapper.cs +++ b/src/Genocs.Logging/CQRS/IMessageToLogTemplateMapper.cs @@ -1,15 +1,16 @@ namespace Genocs.Logging.CQRS; /// -/// Interface used to log messages using a template +/// Interface used to log messages using a template. /// public interface IMessageToLogTemplateMapper { /// - /// Map the message using the template + /// Map the message using the template. /// - /// The type of the message - /// The message instance - /// The LogTemplate - HandlerLogTemplate? Map(TMessage message) where TMessage : class; + /// The type of the message. + /// The message instance. + /// The LogTemplate. + HandlerLogTemplate? Map(TMessage message) + where TMessage : class; } \ No newline at end of file diff --git a/src/Genocs.Logging/Configurations/SeqOptions.cs b/src/Genocs.Logging/Configurations/SeqOptions.cs index 7fc4a973..7e20ccb1 100644 --- a/src/Genocs.Logging/Configurations/SeqOptions.cs +++ b/src/Genocs.Logging/Configurations/SeqOptions.cs @@ -1,8 +1,22 @@ namespace Genocs.Logging.Configurations; +/// +/// Seq Settings. +/// public class SeqOptions { + /// + /// It define whether the Seq logger and tracing are enabled or not. + /// public bool Enabled { get; set; } + + /// + /// The Seq Url. + /// public string? Url { get; set; } + + /// + /// The Seq ApiKey. + /// public string? ApiKey { get; set; } } \ No newline at end of file diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Extensions.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Extensions.cs index 4206a9c3..b59a4a51 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Extensions.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Extensions.cs @@ -13,11 +13,11 @@ public static IMessageOutboxConfigurator AddMongo(this IMessageOutboxConfigurato var builder = configurator.Builder; var options = configurator.Options; - var inboxCollection = string.IsNullOrWhiteSpace(options.InboxCollection) + string inboxCollection = string.IsNullOrWhiteSpace(options.InboxCollection) ? "inbox" : options.InboxCollection; - var outboxCollection = string.IsNullOrWhiteSpace(options.OutboxCollection) + string outboxCollection = string.IsNullOrWhiteSpace(options.OutboxCollection) ? "outbox" : options.OutboxCollection; diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs index f6a04267..cc3c8bd3 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoMessageOutbox.cs @@ -1,7 +1,7 @@ using Genocs.MessageBrokers.Outbox.Configurations; using Genocs.MessageBrokers.Outbox.Messages; +using Genocs.Persistence.MongoDb.Domain.Repositories; using Genocs.Persistence.MongoDb.Repositories; -using Genocs.Persistence.MongoDb.Repositories.Mentor; using Microsoft.Extensions.Logging; using MongoDB.Driver; using System.Text.Json; @@ -22,17 +22,19 @@ internal sealed class MongoMessageOutbox : IMessageOutbox, IMessageOutboxAccesso }; private readonly IMongoSessionFactory _sessionFactory; - private readonly IMongoRepository _inboxRepository; - private readonly IMongoRepository _outboxRepository; + private readonly IMongoDbBaseRepository _inboxRepository; + private readonly IMongoDbBaseRepository _outboxRepository; private readonly ILogger _logger; private readonly bool _transactionsEnabled; public bool Enabled { get; } - public MongoMessageOutbox(IMongoSessionFactory sessionFactory, - IMongoRepository inboxRepository, - IMongoRepository outboxRepository, - OutboxOptions options, ILogger logger) + public MongoMessageOutbox( + IMongoSessionFactory sessionFactory, + IMongoDbBaseRepository inboxRepository, + IMongoDbBaseRepository outboxRepository, + OutboxOptions options, + ILogger logger) { _sessionFactory = sessionFactory; _inboxRepository = inboxRepository; @@ -102,9 +104,15 @@ await _inboxRepository.AddAsync(new InboxMessage } } - public async Task SendAsync(T message, string originatedMessageId = null, string messageId = null, - string correlationId = null, string spanContext = null, object messageContext = null, - IDictionary headers = null) where T : class + public async Task SendAsync( + T message, + string? originatedMessageId = null, + string? messageId = null, + string? correlationId = null, + string? spanContext = null, + object? messageContext = null, + IDictionary? headers = null) + where T : class { if (!Enabled) { diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs index d7ba1050..ea69c74b 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Internals/MongoOutboxInitializer.cs @@ -35,11 +35,13 @@ public async Task InitializeAsync() var inboxBuilder = Builders.IndexKeys; await _database.GetCollection(inboxCollection) .Indexes.CreateOneAsync( - new CreateIndexModel(inboxBuilder.Ascending(i => i.ProcessedAt), - new CreateIndexOptions - { - ExpireAfter = TimeSpan.FromSeconds(_options.Expiry) - })); + new CreateIndexModel( + inboxBuilder.Ascending(i => i.ProcessedAt), + new CreateIndexOptions + { + ExpireAfter = TimeSpan.FromSeconds(_options.Expiry) + }) + ); string outboxCollection = string.IsNullOrWhiteSpace(_options.OutboxCollection) ? "outbox" @@ -48,10 +50,11 @@ await _database.GetCollection(inboxCollection) var outboxBuilder = Builders.IndexKeys; await _database.GetCollection(outboxCollection) .Indexes.CreateOneAsync( - new CreateIndexModel(outboxBuilder.Ascending(i => i.ProcessedAt), - new CreateIndexOptions - { - ExpireAfter = TimeSpan.FromSeconds(_options.Expiry) - })); + new CreateIndexModel( + outboxBuilder.Ascending(i => i.ProcessedAt), + new CreateIndexOptions + { + ExpireAfter = TimeSpan.FromSeconds(_options.Expiry) + })); } } \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs b/src/Genocs.Persistence.MongoDb/Domain/Entities/IMongoDbEntity.cs similarity index 75% rename from src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs rename to src/Genocs.Persistence.MongoDb/Domain/Entities/IMongoDbEntity.cs index a6ae3f3a..0f38ca67 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/IMongoDbEntity.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Entities/IMongoDbEntity.cs @@ -1,7 +1,7 @@ using Genocs.Core.Domain.Entities; using MongoDB.Bson; -namespace Genocs.Persistence.MongoDb.Repositories.Clean; +namespace Genocs.Persistence.MongoDb.Domain.Entities; /// /// Default MongoDB entity. diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbBaseRepository.cs similarity index 84% rename from src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs rename to src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbBaseRepository.cs index 08902fb4..88340808 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/IMongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbBaseRepository.cs @@ -5,9 +5,9 @@ using MongoDB.Driver.Linq; using System.Linq.Expressions; -namespace Genocs.Persistence.MongoDb.Repositories.Mentor; +namespace Genocs.Persistence.MongoDb.Domain.Repositories; -public interface IMongoRepository : IRepositoryOfEntity +public interface IMongoDbBaseRepository : IRepositoryOfEntity where TEntity : IEntity { IMongoCollection Collection { get; } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepository.cs similarity index 96% rename from src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs rename to src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepository.cs index 3a7ae2ae..fc38402e 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Mentor/MongoRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepository.cs @@ -1,17 +1,17 @@ -using Genocs.Common.Types; using Genocs.Core.CQRS.Queries; using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Repositories; +using Genocs.Persistence.MongoDb.Repositories; using MongoDB.Driver; using MongoDB.Driver.Linq; using System.Linq.Expressions; -namespace Genocs.Persistence.MongoDb.Repositories.Mentor; +namespace Genocs.Persistence.MongoDb.Domain.Repositories; -internal class MongoRepository : IMongoRepository +internal class MongoDbBaseRepository : IMongoDbBaseRepository where TEntity : IEntity { - public MongoRepository(IMongoDatabase database, string collectionName) + public MongoDbBaseRepository(IMongoDatabase database, string collectionName) { Collection = database.GetCollection(collectionName); } diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepository.cs similarity index 74% rename from src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs rename to src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepository.cs index 3b332097..858a13ec 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepository.cs @@ -1,14 +1,15 @@ -using Genocs.Core.Domain.Entities; +using Genocs.Persistence.MongoDb.Domain.Entities; +using Genocs.Persistence.MongoDb.Repositories; using MongoDB.Bson; -namespace Genocs.Persistence.MongoDb.Repositories.Clean; +namespace Genocs.Persistence.MongoDb.Domain.Repositories; /// /// Implements IRepository for MongoDB. /// /// Type of the Entity for this repository. public class MongoDbRepository : MongoDbRepositoryBase, IMongoDbRepository - where TEntity : class, IEntity + where TEntity : IMongoDbEntity { /// /// The standard constructor. diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs similarity index 90% rename from src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs rename to src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs index 213bdbc1..0b20706c 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntityAndKey.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs @@ -1,20 +1,20 @@ using Genocs.Core.CQRS.Queries; using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Repositories; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Repositories; using MongoDB.Driver; using MongoDB.Driver.Linq; using System.Linq.Expressions; -namespace Genocs.Persistence.MongoDb.Repositories.Clean; +namespace Genocs.Persistence.MongoDb.Domain.Repositories; /// /// Implements IRepository for MongoDB. /// /// Type of the Entity for this repository. /// Primary key of the entity. -public class MongoDbRepositoryBase : RepositoryBase, IMongoRepository - where TEntity : class, IEntity +public class MongoDbRepositoryBase : RepositoryBase, IMongoDbBaseRepository + where TEntity : IEntity { /// /// Get the MongoDB database. @@ -39,14 +39,17 @@ public virtual IMongoCollection Collection return _collection; } - var attrs = Attribute.GetCustomAttributes(typeof(TEntity)); // Reflection. + Attribute[] attrs = Attribute.GetCustomAttributes(typeof(TEntity)); // Reflection. // Displaying output. foreach (var attr in attrs) { - if (attr is TableMappingAttribute) + if (attr != null) { - return _databaseProvider.Database.GetCollection((attr as TableMappingAttribute).Name); + if ((attr != null) && attr is TableMappingAttribute tmp) + { + return _databaseProvider.Database.GetCollection(tmp.Name); + } } } diff --git a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs index a7349239..aa7eea7a 100644 --- a/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs +++ b/src/Genocs.Persistence.MongoDb/Extensions/MongoDbExtensions.cs @@ -2,11 +2,10 @@ using Genocs.Core.Domain.Entities; using Genocs.Persistence.MongoDb.Builders; using Genocs.Persistence.MongoDb.Configurations; +using Genocs.Persistence.MongoDb.Domain.Repositories; using Genocs.Persistence.MongoDb.Factories; using Genocs.Persistence.MongoDb.Initializers; using Genocs.Persistence.MongoDb.Repositories; -using Genocs.Persistence.MongoDb.Repositories.Clean; -using Genocs.Persistence.MongoDb.Repositories.Mentor; using Genocs.Persistence.MongoDb.Seeders; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -150,10 +149,10 @@ public static IGenocsBuilder AddMongoRepository( string collectionName) where TEntity : IEntity { - builder.Services.AddTransient>(sp => + builder.Services.AddTransient>(sp => { var database = sp.GetRequiredService(); - return new MongoRepository(database, collectionName); + return new MongoDbBaseRepository(database, collectionName); }); return builder; diff --git a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs b/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs deleted file mode 100644 index 5a956c2f..00000000 --- a/src/Genocs.Persistence.MongoDb/Repositories/Clean/MongoDbRepositoryBaseOfEntity.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MongoDB.Bson; - -namespace Genocs.Persistence.MongoDb.Repositories.Clean; - -/// -/// Implements base class for IRepository for MongoDB. -/// -/// Type of the Entity for this repository. -public class MongoDbRepositoryBase : MongoDbRepositoryBase - where TEntity : class, IMongoDbEntity -{ - /// - /// The standard constructor. - /// - /// The MongoDB database provider. - public MongoDbRepositoryBase(IMongoDatabaseProvider databaseProvider) - : base(databaseProvider) - { - } -} \ No newline at end of file diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs index 8275c79a..09e85efd 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs @@ -1,5 +1,5 @@ -using Genocs.Core.Domain.Entities; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Entities; +using Genocs.Persistence.MongoDb.Domain.Repositories; using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Repositories; @@ -8,8 +8,8 @@ namespace Genocs.Persistence.MongoDb.Repositories; /// The MongoDb repository interface. /// /// The type of the entity. -public interface IMongoDbRepository : IMongoRepository - where TEntity : IEntity +public interface IMongoDbRepository : IMongoDbBaseRepository + where TEntity : IMongoDbEntity { } diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs index 70ce9a88..97185239 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Extensions.cs @@ -1,5 +1,5 @@ using Genocs.Identities.Application.Mongo.Documents; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using MongoDB.Driver; @@ -11,7 +11,7 @@ public static class Extensions public static IApplicationBuilder UseMongo(this IApplicationBuilder builder) { using var scope = builder.ApplicationServices.CreateScope(); - var users = scope.ServiceProvider.GetService>()?.Collection; + var users = scope.ServiceProvider.GetService>()?.Collection; if (users is null) { diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs index 9dba71ff..ff43d3fb 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Queries/Handlers/GetUserHandler.cs @@ -2,15 +2,15 @@ using Genocs.Identities.Application.DTO; using Genocs.Identities.Application.Mongo.Documents; using Genocs.Identities.Application.Queries; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; namespace Genocs.Identities.Application.Mongo.Queries.Handlers; public class GetUserHandler : IQueryHandler { - private readonly IMongoRepository _userRepository; + private readonly IMongoDbBaseRepository _userRepository; - public GetUserHandler(IMongoRepository userRepository) + public GetUserHandler(IMongoDbBaseRepository userRepository) { _userRepository = userRepository; } diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs index 0a4cc536..d449921a 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/RefreshTokenRepository.cs @@ -1,15 +1,15 @@ using Genocs.Identities.Application.Domain.Entities; using Genocs.Identities.Application.Domain.Repositories; using Genocs.Identities.Application.Mongo.Documents; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; namespace Genocs.Identities.Application.Mongo.Repositories; public class RefreshTokenRepository : IRefreshTokenRepository { - private readonly IMongoRepository _repository; + private readonly IMongoDbBaseRepository _repository; - public RefreshTokenRepository(IMongoRepository repository) + public RefreshTokenRepository(IMongoDbBaseRepository repository) { _repository = repository; } diff --git a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs index f20e43a6..4228fed7 100644 --- a/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs +++ b/src/apps/identity/Genocs.Identities.Application/Mongo/Repositories/UserRepository.cs @@ -1,15 +1,15 @@ using Genocs.Identities.Application.Domain.Entities; using Genocs.Identities.Application.Domain.Repositories; using Genocs.Identities.Application.Mongo.Documents; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; namespace Genocs.Identities.Application.Mongo.Repositories; public class UserRepository : IUserRepository { - private readonly IMongoRepository _repository; + private readonly IMongoDbBaseRepository _repository; - public UserRepository(IMongoRepository repository) + public UserRepository(IMongoDbBaseRepository repository) { _repository = repository; } diff --git a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs index 80dcac2a..880aa814 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Commands/Handlers/CreateOrderHandler.cs @@ -4,20 +4,20 @@ using Genocs.Orders.WebApi.Domain; using Genocs.Orders.WebApi.Events; using Genocs.Orders.WebApi.Services; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; namespace Genocs.Orders.WebApi.Commands.Handlers; public class CreateOrderHandler : ICommandHandler { - private readonly IMongoRepository _repository; + private readonly IMongoDbBaseRepository _repository; private readonly IBusPublisher _publisher; private readonly IMessageOutbox _outbox; private readonly IProductServiceClient _productServiceClient; private readonly ILogger _logger; public CreateOrderHandler( - IMongoRepository repository, + IMongoDbBaseRepository repository, IBusPublisher publisher, IMessageOutbox outbox, IProductServiceClient productServiceClient, diff --git a/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs b/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs index f6d07ca8..2efca4c6 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs +++ b/src/apps/orders/Genocs.Orders.WebApi/Queries/Handlers/GetOrderHandler.cs @@ -1,15 +1,15 @@ using Genocs.Core.CQRS.Queries; using Genocs.Orders.WebApi.Domain; using Genocs.Orders.WebApi.DTO; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; namespace Genocs.Orders.WebApi.Queries.Handlers; public class GetOrderHandler : IQueryHandler { - private readonly IMongoRepository _repository; + private readonly IMongoDbBaseRepository _repository; - public GetOrderHandler(IMongoRepository repository) + public GetOrderHandler(IMongoDbBaseRepository repository) { _repository = repository; } diff --git a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs index 8f5cde26..51ac3aec 100644 --- a/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs +++ b/src/apps/products/Genocs.Products.WebApi/Commands/Handlers/CreateProductHandler.cs @@ -1,7 +1,7 @@ using Genocs.Core.CQRS.Commands; using Genocs.MessageBrokers; using Genocs.MessageBrokers.Outbox; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; using Genocs.Products.WebApi.Domain; using Genocs.Products.WebApi.Events; @@ -9,13 +9,13 @@ namespace Genocs.Products.WebApi.Commands.Handlers; public class CreateProductHandler : ICommandHandler { - private readonly IMongoRepository _repository; + private readonly IMongoDbBaseRepository _repository; private readonly IBusPublisher _publisher; private readonly IMessageOutbox _outbox; private readonly ILogger _logger; public CreateProductHandler( - IMongoRepository repository, + IMongoDbBaseRepository repository, IBusPublisher publisher, IMessageOutbox outbox, ILogger logger) diff --git a/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs b/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs index 2becb5d1..2fae624e 100644 --- a/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs +++ b/src/apps/products/Genocs.Products.WebApi/Queries/Handlers/GetProductHandler.cs @@ -1,14 +1,14 @@ using Genocs.Core.CQRS.Queries; -using Genocs.Persistence.MongoDb.Repositories.Mentor; +using Genocs.Persistence.MongoDb.Domain.Repositories; using Genocs.Products.WebApi.DTO; namespace Genocs.Products.WebApi.Queries.Handlers; public class GetProductHandler : IQueryHandler { - private readonly IMongoRepository _repository; + private readonly IMongoDbBaseRepository _repository; - public GetProductHandler(IMongoRepository repository) + public GetProductHandler(IMongoDbBaseRepository repository) { _repository = repository; } From c3a8baca5d49ee7999be1e59384fea5c8b2d36d2 Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Fri, 8 Nov 2024 15:12:40 +0100 Subject: [PATCH 099/104] Refactor MongoDB repository structure and update usings - Updated `using` directives in `MongoDbController.cs`, `SubmitOrderConsumer.cs`, and `Program.cs` to use `Genocs.Persistence.MongoDb.Domain.Repositories`. - Modified `MongoDbRepository` to inherit from `MongoDbBaseRepositoryOfType`. - Removed `MongoDbRepositoryBaseOfEntityAndKey.cs` and moved its content to `MongoDbBaseRepositoryOfType.cs`. - Moved `IMongoDbRepository` to `Genocs.Persistence.MongoDb.Domain.Repositories` and updated its content. - Improved comment format in `IMongoDbSeeder.cs`. - Created `MongoDbBaseRepositoryOfType.cs` with the implementation of the repository base class for MongoDB. --- .../Controllers/MongoDbController.cs | 2 +- .../Consumers/SubmitOrderConsumer.cs | 2 +- src/Genocs.Core.Demo.Worker/Program.cs | 1 - .../Repositories/IMongoDbRepository.cs | 4 +- ...dKey.cs => MongoDbBaseRepositoryOfType.cs} | 38 +++++++++---------- .../Domain/Repositories/MongoDbRepository.cs | 3 +- .../Repositories/IMongoDbSeeder.cs | 2 +- 7 files changed, 25 insertions(+), 27 deletions(-) rename src/Genocs.Persistence.MongoDb/{ => Domain}/Repositories/IMongoDbRepository.cs (64%) rename src/Genocs.Persistence.MongoDb/Domain/Repositories/{MongoDbRepositoryBaseOfEntityAndKey.cs => MongoDbBaseRepositoryOfType.cs} (91%) diff --git a/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs b/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs index ddc0be37..5fbd6f2d 100644 --- a/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs +++ b/src/Genocs.Core.Demo.WebApi/Controllers/MongoDbController.cs @@ -1,5 +1,5 @@ using Genocs.Core.Demo.Domain.Aggregates; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Domain.Repositories; using Microsoft.AspNetCore.Mvc; namespace Genocs.Core.Demo.WebApi.Controllers; diff --git a/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs b/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs index a2a7873f..9c320201 100644 --- a/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs +++ b/src/Genocs.Core.Demo.Worker/Consumers/SubmitOrderConsumer.cs @@ -1,6 +1,6 @@ using Genocs.Core.Demo.Contracts; using Genocs.Core.Demo.Domain.Aggregates; -using Genocs.Persistence.MongoDb.Repositories; +using Genocs.Persistence.MongoDb.Domain.Repositories; using MassTransit; namespace Genocs.Core.Demo.Worker.Consumers; diff --git a/src/Genocs.Core.Demo.Worker/Program.cs b/src/Genocs.Core.Demo.Worker/Program.cs index b44b84c1..935d0cb5 100644 --- a/src/Genocs.Core.Demo.Worker/Program.cs +++ b/src/Genocs.Core.Demo.Worker/Program.cs @@ -9,7 +9,6 @@ using Genocs.Logging; using Genocs.Persistence.MongoDb.Domain.Repositories; using Genocs.Persistence.MongoDb.Extensions; -using Genocs.Persistence.MongoDb.Repositories; using Genocs.ServiceBusAzure.Configurations; using Genocs.ServiceBusAzure.Queues; using Genocs.ServiceBusAzure.Queues.Interfaces; diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbRepository.cs similarity index 64% rename from src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs rename to src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbRepository.cs index 09e85efd..c8ff528f 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbRepository.cs @@ -1,11 +1,11 @@ using Genocs.Persistence.MongoDb.Domain.Entities; -using Genocs.Persistence.MongoDb.Domain.Repositories; using MongoDB.Bson; -namespace Genocs.Persistence.MongoDb.Repositories; +namespace Genocs.Persistence.MongoDb.Domain.Repositories; /// /// The MongoDb repository interface. +/// This interface is used to define the contract for the MongoDb repositories when the entity has an ObjectId as the primary key. /// /// The type of the entity. public interface IMongoDbRepository : IMongoDbBaseRepository diff --git a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs similarity index 91% rename from src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs rename to src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs index 0b20706c..e53f8a0a 100644 --- a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepositoryBaseOfEntityAndKey.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs @@ -13,9 +13,21 @@ namespace Genocs.Persistence.MongoDb.Domain.Repositories; /// /// Type of the Entity for this repository. /// Primary key of the entity. -public class MongoDbRepositoryBase : RepositoryBase, IMongoDbBaseRepository +public class MongoDbBaseRepositoryOfType : RepositoryBase, IMongoDbBaseRepository where TEntity : IEntity { + private readonly IMongoDatabaseProvider _databaseProvider; + protected IMongoCollection? _collection; + + /// + /// Standard constructor. + /// + /// + public MongoDbBaseRepositoryOfType(IMongoDatabaseProvider databaseProvider) + { + _databaseProvider = databaseProvider; + } + /// /// Get the MongoDB database. /// @@ -24,9 +36,6 @@ public virtual IMongoDatabase Database get { return _databaseProvider.Database; } } - private readonly IMongoDatabaseProvider _databaseProvider; - protected IMongoCollection? _collection; - /// /// Get the MongoDB collection from a custom attribute or from the entity name. /// @@ -59,15 +68,6 @@ public virtual IMongoCollection Collection } } - /// - /// Standard constructor. - /// - /// - public MongoDbRepositoryBase(IMongoDatabaseProvider databaseProvider) - { - _databaseProvider = databaseProvider; - } - /// /// Get all entities as IQueryable. /// @@ -96,8 +96,8 @@ public override TEntity Get(TKey id) /// /// First Or Default entity. /// - /// - /// The entity if found otherwise null + /// The domain objjet id. + /// The entity if found otherwise null. public override TEntity FirstOrDefault(TKey id) { var filter = Builders.Filter.Eq(m => m.Id, id); @@ -107,8 +107,8 @@ public override TEntity FirstOrDefault(TKey id) /// /// Insert an entity. /// - /// - /// + /// The entity to insert. + /// The entity. public override TEntity Insert(TEntity entity) { Collection.InsertOne(entity); @@ -118,8 +118,8 @@ public override TEntity Insert(TEntity entity) /// /// Update an existing entity. /// - /// - /// + /// The entity to insert. + /// The entity. public override TEntity Update(TEntity entity) { Collection.ReplaceOneAsync(filter: g => g.Id.Equals(entity.Id), replacement: entity); diff --git a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepository.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepository.cs index 858a13ec..67f8a26a 100644 --- a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbRepository.cs @@ -1,5 +1,4 @@ using Genocs.Persistence.MongoDb.Domain.Entities; -using Genocs.Persistence.MongoDb.Repositories; using MongoDB.Bson; namespace Genocs.Persistence.MongoDb.Domain.Repositories; @@ -8,7 +7,7 @@ namespace Genocs.Persistence.MongoDb.Domain.Repositories; /// Implements IRepository for MongoDB. /// /// Type of the Entity for this repository. -public class MongoDbRepository : MongoDbRepositoryBase, IMongoDbRepository +public class MongoDbRepository : MongoDbBaseRepositoryOfType, IMongoDbRepository where TEntity : IMongoDbEntity { /// diff --git a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs index 7c1b0129..a4988961 100644 --- a/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs +++ b/src/Genocs.Persistence.MongoDb/Repositories/IMongoDbSeeder.cs @@ -11,6 +11,6 @@ public interface IMongoDbSeeder /// Database Seed. /// /// The database. - /// The async Task + /// The async Task. Task SeedAsync(IMongoDatabase database); } \ No newline at end of file From 7da092d0fecec393297dac85cf0a11e6fe6df95c Mon Sep 17 00:00:00 2001 From: Giovanni Nocco Date: Fri, 8 Nov 2024 15:28:12 +0100 Subject: [PATCH 100/104] Refactor null checks and exception handling Refactored the `Delete` method in `MongoDbBaseRepository.cs` to use `ArgumentNullException.ThrowIfNull(predicate)` for null checks, improving code readability and conciseness. Updated the `Get` method in `MongoDbBaseRepositoryOfType.cs` to use a conditional expression for throwing `EntityNotFoundException` when the entity is null, simplifying the logic. --- .../Domain/Repositories/MongoDbBaseRepository.cs | 5 +---- .../Domain/Repositories/MongoDbBaseRepositoryOfType.cs | 9 +++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepository.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepository.cs index fc38402e..d7f91e79 100644 --- a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepository.cs @@ -229,10 +229,7 @@ public void Delete(TKey id) public void Delete(Expression> predicate) { - if (predicate == null) - { - throw new ArgumentNullException(nameof(predicate)); - } + ArgumentNullException.ThrowIfNull(predicate); Collection.DeleteMany(predicate); } diff --git a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs index e53f8a0a..e498574a 100644 --- a/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/MongoDbBaseRepositoryOfType.cs @@ -85,12 +85,9 @@ public override TEntity Get(TKey id) { var filter = Builders.Filter.Eq(m => m.Id, id); var entity = Collection.Find(filter).FirstOrDefault(); - if (entity == null) - { - throw new EntityNotFoundException("There is no such an entity with given primary key. Entity type: " + typeof(TEntity).FullName + ", primary key: " + id); - } - - return entity; + return entity == null + ? throw new EntityNotFoundException("There is no such an entity with given primary key. Entity type: " + typeof(TEntity).FullName + ", primary key: " + id) + : entity; } /// From 106fc319c0411d90a6499bb4477b6f80cbe585f2 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 10 Nov 2024 10:50:45 +0100 Subject: [PATCH 101/104] Update package versions in multiple project files Updated the following package versions: - `MassTransit.RabbitMQ` from `8.3.0` to `8.3.1` in `Genocs.Core.Demo.WebApi.csproj` and `Genocs.Core.Demo.Worker.csproj` - `Scrutor` from `5.0.1` to `5.0.2` in `Genocs.Core.csproj` - `System.Linq.Dynamic.Core` from `1.4.6` to `1.4.8` in `Genocs.QueryBuilder.UnitTests.csproj` - `Azure.Identity` from `1.13.0` to `1.13.1` in `Genocs.Secrets.AzureKeyVault.csproj` --- src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj | 2 +- src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj | 2 +- src/Genocs.Core/Genocs.Core.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 2 +- .../Genocs.Secrets.AzureKeyVault.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index a0142f85..c5de6910 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 410d0eb2..2b3b3dda 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 69c063b8..4e0ab303 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index 02c67b0d..fdb95dd3 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -13,7 +13,7 @@ - + all diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index 514b129e..5e91217c 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -43,7 +43,7 @@ - + From a5f189be8c47d0294ca93dea5804a11b67bcc84d Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 10 Nov 2024 11:35:23 +0100 Subject: [PATCH 102/104] Remove project refs and add using directive Removed references to `Genocs.Secrets.AzureKeyVault` and `Genocs.WebApi` from `Genocs.Core.Demo.WebApi.csproj`. Added `using System.Linq.Expressions` to `IMongoDbBaseRepository.cs` to support advanced querying. --- src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj | 3 --- .../Domain/Repositories/IMongoDbBaseRepository.cs | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index 9c3b21f8..d7b89077 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -31,7 +31,6 @@ - @@ -42,8 +41,6 @@ - - diff --git a/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbBaseRepository.cs b/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbBaseRepository.cs index 9a0acab4..5cdacef2 100644 --- a/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbBaseRepository.cs +++ b/src/Genocs.Persistence.MongoDb/Domain/Repositories/IMongoDbBaseRepository.cs @@ -1,3 +1,4 @@ +using System.Linq.Expressions; using Genocs.Core.CQRS.Queries; using Genocs.Core.Domain.Entities; using Genocs.Core.Domain.Repositories; From 6fdf470b2234bf8a08e70deb251bef4f2cbd4edc Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 10 Nov 2024 11:58:02 +0100 Subject: [PATCH 103/104] Update package references to version 6.4.0 across multiple projects --- src/Genocs.Auth/Genocs.Auth.csproj | 4 +-- .../Genocs.Core.Demo.Contracts.csproj | 2 +- .../Genocs.Core.Demo.Domain.csproj | 4 +-- .../Genocs.Core.Demo.WebApi.csproj | 18 +++++----- .../Genocs.Core.Demo.Worker.csproj | 6 ++-- src/Genocs.Core/Genocs.Core.csproj | 2 +- .../Genocs.Discovery.Consul.csproj | 4 +-- .../Genocs.HTTP.RestEase.csproj | 8 ++--- src/Genocs.HTTP/Genocs.HTTP.csproj | 2 +- .../Genocs.LoadBalancing.Fabio.csproj | 6 ++-- src/Genocs.Logging/Genocs.Logging.csproj | 2 +- ...enocs.MessageBrokers.Outbox.MongoDB.csproj | 4 +-- .../Genocs.MessageBrokers.Outbox.csproj | 2 +- .../Genocs.MessageBrokers.RabbitMQ.csproj | 2 +- .../Genocs.MessageBrokers.csproj | 2 +- src/Genocs.Metrics/Genocs.Metrics.csproj | 2 +- .../Genocs.Monitoring.csproj | 6 ++-- ...enocs.Persistence.MongoDB.UnitTests.csproj | 2 +- .../Genocs.Persistence.MongoDb.csproj | 2 +- .../Genocs.Persistence.Redis.csproj | 2 +- .../Genocs.QueryBuilder.UnitTests.csproj | 4 +-- .../Genocs.Secrets.AzureKeyVault.csproj | 2 +- .../Genocs.Secrets.Vault.csproj | 2 +- src/Genocs.Security/Genocs.Security.csproj | 2 +- .../Genocs.ServiceBusAzure.csproj | 2 +- .../Genocs.Tracing.Jaeger.RabbitMQ.csproj | 4 +-- src/Genocs.Tracing/Genocs.Tracing.csproj | 6 ++-- .../Genocs.WebApi.CQRS.csproj | 4 +-- .../Genocs.WebApi.Security.csproj | 2 +- .../Genocs.WebApi.Swagger.csproj | 2 +- src/Genocs.WebApi/Genocs.WebApi.csproj | 2 +- .../Genocs.APIGateway.csproj | 18 +++++----- .../Genocs.Identities.Application.csproj | 20 +++++------ .../Genocs.Orders.WebApi.csproj | 32 ++++++++--------- .../Genocs.Products.WebApi.csproj | 32 ++++++++--------- .../Genocs.SignalR.WebApi.csproj | 34 +++++++++---------- 36 files changed, 125 insertions(+), 125 deletions(-) diff --git a/src/Genocs.Auth/Genocs.Auth.csproj b/src/Genocs.Auth/Genocs.Auth.csproj index 1c19263c..924792ef 100644 --- a/src/Genocs.Auth/Genocs.Auth.csproj +++ b/src/Genocs.Auth/Genocs.Auth.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj index 26499d5b..69c454cc 100644 --- a/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj +++ b/src/Genocs.Core.Demo.Contracts/Genocs.Core.Demo.Contracts.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj index 7aa9facc..39f3fc59 100644 --- a/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj +++ b/src/Genocs.Core.Demo.Domain/Genocs.Core.Demo.Domain.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj index d7b89077..8b857be6 100644 --- a/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj +++ b/src/Genocs.Core.Demo.WebApi/Genocs.Core.Demo.WebApi.csproj @@ -22,15 +22,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj index 5cc52763..f3eef8fe 100644 --- a/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj +++ b/src/Genocs.Core.Demo.Worker/Genocs.Core.Demo.Worker.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/Genocs.Core/Genocs.Core.csproj b/src/Genocs.Core/Genocs.Core.csproj index 04dbfa18..32e880bc 100644 --- a/src/Genocs.Core/Genocs.Core.csproj +++ b/src/Genocs.Core/Genocs.Core.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj index 39fe5750..fc01345c 100644 --- a/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj +++ b/src/Genocs.Discovery.Consul/Genocs.Discovery.Consul.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj index a0a2dead..1110507f 100644 --- a/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj +++ b/src/Genocs.HTTP.RestEase/Genocs.HTTP.RestEase.csproj @@ -25,10 +25,10 @@ - - - - + + + + diff --git a/src/Genocs.HTTP/Genocs.HTTP.csproj b/src/Genocs.HTTP/Genocs.HTTP.csproj index 4ed79a9a..f7aa5933 100644 --- a/src/Genocs.HTTP/Genocs.HTTP.csproj +++ b/src/Genocs.HTTP/Genocs.HTTP.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj index 937864a2..0f2c4d4b 100644 --- a/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj +++ b/src/Genocs.LoadBalancing.Fabio/Genocs.LoadBalancing.Fabio.csproj @@ -24,9 +24,9 @@ - - - + + + diff --git a/src/Genocs.Logging/Genocs.Logging.csproj b/src/Genocs.Logging/Genocs.Logging.csproj index b6a0a759..68b271d5 100644 --- a/src/Genocs.Logging/Genocs.Logging.csproj +++ b/src/Genocs.Logging/Genocs.Logging.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj index 8ea31f0b..55003bab 100644 --- a/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj +++ b/src/Genocs.MessageBrokers.Outbox.MongoDB/Genocs.MessageBrokers.Outbox.MongoDB.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj index 38920888..40a7ffe0 100644 --- a/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj +++ b/src/Genocs.MessageBrokers.Outbox/Genocs.MessageBrokers.Outbox.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj index a1fb3ace..7ebfcf64 100644 --- a/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj +++ b/src/Genocs.MessageBrokers.RabbitMQ/Genocs.MessageBrokers.RabbitMQ.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj index 8cf8d174..8cb7ec2c 100644 --- a/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj +++ b/src/Genocs.MessageBrokers/Genocs.MessageBrokers.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Metrics/Genocs.Metrics.csproj b/src/Genocs.Metrics/Genocs.Metrics.csproj index af281ff6..fa0e7a00 100644 --- a/src/Genocs.Metrics/Genocs.Metrics.csproj +++ b/src/Genocs.Metrics/Genocs.Metrics.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Monitoring/Genocs.Monitoring.csproj b/src/Genocs.Monitoring/Genocs.Monitoring.csproj index b54034ff..0d5d7ff6 100644 --- a/src/Genocs.Monitoring/Genocs.Monitoring.csproj +++ b/src/Genocs.Monitoring/Genocs.Monitoring.csproj @@ -40,9 +40,9 @@ - - - + + + diff --git a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj index 4e91b225..b564f04d 100644 --- a/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj +++ b/src/Genocs.Persistence.MongoDb.UnitTests/Genocs.Persistence.MongoDB.UnitTests.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj index 26805c3c..7f9f2b16 100644 --- a/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj +++ b/src/Genocs.Persistence.MongoDb/Genocs.Persistence.MongoDb.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj index dc646c6b..0b44127c 100644 --- a/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj +++ b/src/Genocs.Persistence.Redis/Genocs.Persistence.Redis.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj index e2de47d3..e51e8049 100644 --- a/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj +++ b/src/Genocs.QueryBuilder.UnitTests/Genocs.QueryBuilder.UnitTests.csproj @@ -31,8 +31,8 @@ - - + + diff --git a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj index 0fe03ceb..eda6a48d 100644 --- a/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj +++ b/src/Genocs.Secrets.AzureKeyVault/Genocs.Secrets.AzureKeyVault.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj index fb6c47d4..61c373ee 100644 --- a/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj +++ b/src/Genocs.Secrets.Vault/Genocs.Secrets.Vault.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Security/Genocs.Security.csproj b/src/Genocs.Security/Genocs.Security.csproj index 7a1bcb23..911dec65 100644 --- a/src/Genocs.Security/Genocs.Security.csproj +++ b/src/Genocs.Security/Genocs.Security.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj index 8b6bdeb0..c2e209e7 100644 --- a/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj +++ b/src/Genocs.ServiceBusAzure/Genocs.ServiceBusAzure.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj index 75bdcf5c..850a07f9 100644 --- a/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj +++ b/src/Genocs.Tracing.Jaeger.RabbitMQ/Genocs.Tracing.Jaeger.RabbitMQ.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/src/Genocs.Tracing/Genocs.Tracing.csproj b/src/Genocs.Tracing/Genocs.Tracing.csproj index 393c9a8d..5c92a7dd 100644 --- a/src/Genocs.Tracing/Genocs.Tracing.csproj +++ b/src/Genocs.Tracing/Genocs.Tracing.csproj @@ -24,9 +24,9 @@ - - - + + + diff --git a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj index 7aab826a..f43a5c4c 100644 --- a/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj +++ b/src/Genocs.WebApi.CQRS/Genocs.WebApi.CQRS.csproj @@ -23,8 +23,8 @@ - - + + diff --git a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj index 4f4e0b31..e5767a51 100644 --- a/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj +++ b/src/Genocs.WebApi.Security/Genocs.WebApi.Security.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj index 584c32bc..c794b33e 100644 --- a/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj +++ b/src/Genocs.WebApi.Swagger/Genocs.WebApi.Swagger.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Genocs.WebApi/Genocs.WebApi.csproj b/src/Genocs.WebApi/Genocs.WebApi.csproj index b9773d22..aa0b5a0c 100644 --- a/src/Genocs.WebApi/Genocs.WebApi.csproj +++ b/src/Genocs.WebApi/Genocs.WebApi.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj index fb5c8504..6d8537c6 100644 --- a/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj +++ b/src/apps/api-gateway/Genocs.APIGateway/Genocs.APIGateway.csproj @@ -19,15 +19,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj index 5b87a02e..9704def8 100644 --- a/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj +++ b/src/apps/identity/Genocs.Identities.Application/Genocs.Identities.Application.csproj @@ -20,16 +20,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj index 07777352..7018f219 100644 --- a/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj +++ b/src/apps/orders/Genocs.Orders.WebApi/Genocs.Orders.WebApi.csproj @@ -29,22 +29,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj index 851694b3..499fbed1 100644 --- a/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj +++ b/src/apps/products/Genocs.Products.WebApi/Genocs.Products.WebApi.csproj @@ -30,22 +30,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj index 1b17a16c..6409fb9b 100644 --- a/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj +++ b/src/apps/signalr/Genocs.SignalR.WebApi/Genocs.SignalR.WebApi.csproj @@ -31,23 +31,23 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + From 74a96fd04d8a263e3087e91e8c34e2a5d9e6b5f0 Mon Sep 17 00:00:00 2001 From: Nocco Giovanni Emanuele Date: Sun, 10 Nov 2024 12:01:52 +0100 Subject: [PATCH 104/104] Update CHANGELOG for v6.4.0 release with recent changes and improvements --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1193de0..3c87ede3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [v6.4.0](https://github.com/Genocs/genocs-library/compare/v6.3.0...v6.4.0) + +> 10 November 2024 + +- Refactor MongoDB repository structure and base classes [`98e24b1`](https://github.com/Genocs/genocs-library/commit/98e24b1aab96ca4276924a822e0b5ffec50c3e9b) +- Update package references to version 6.4.0 across multiple projects [`6fdf470`](https://github.com/Genocs/genocs-library/commit/6fdf470b2234bf8a08e70deb251bef4f2cbd4edc) +- Refactor: Replace IIdentifiable with IEntity [`a21e330`](https://github.com/Genocs/genocs-library/commit/a21e33004ff115b383556835096ee02bd94c9f0f) +- Update packages, refactor code, and improve readability [`0a2d5be`](https://github.com/Genocs/genocs-library/commit/0a2d5be49e6e3d28e56da01aea2b72c21fa83568) +- Remove project refs and add using directive [`a5f189b`](https://github.com/Genocs/genocs-library/commit/a5f189be8c47d0294ca93dea5804a11b67bcc84d) +- Update to version 6.3.0 and refactor codebase [`713fb84`](https://github.com/Genocs/genocs-library/commit/713fb847400afccc205061d854db1ee22159d62d) +- Standardize property names and update audit fields [`c10e995`](https://github.com/Genocs/genocs-library/commit/c10e995b229fa8958e7f0585679562c711a56c22) +- Refactor MongoDB repository structure and update usings [`c3a8bac`](https://github.com/Genocs/genocs-library/commit/c3a8baca5d49ee7999be1e59384fea5c8b2d36d2) +- Refactor AzureInitializer and update MongoDB.Driver [`42dfe53`](https://github.com/Genocs/genocs-library/commit/42dfe53d120dbd53fe8018bdd418f1d2d9208c0f) +- Refactor null checks and exception handling [`7da092d`](https://github.com/Genocs/genocs-library/commit/7da092d0fecec393297dac85cf0a11e6fe6df95c) +- Update CHANGELOG for v6.3.0 release [`2e5eb47`](https://github.com/Genocs/genocs-library/commit/2e5eb47693439d55f9974402bab3f923993f117c) +- Update package versions in multiple project files [`106fc31`](https://github.com/Genocs/genocs-library/commit/106fc319c0411d90a6499bb4477b6f80cbe585f2) +- Refactor Entity and IAggregateRoot for simplicity [`3ccf665`](https://github.com/Genocs/genocs-library/commit/3ccf665db0c7e8eaceb50fa13d14c1ff4faa22e6) + #### [v6.3.0](https://github.com/Genocs/genocs-library/compare/v6.2.0...v6.3.0) > 3 November 2024

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π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≪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