diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 2bafc15..ace32b2 100755 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,7 +21,9 @@ "syncfusioninc.blazor-vscode-extensions", "ms-dotnettools.vscode-dotnet-runtime", "ms-dotnettools.blazorwasm-companion", - "PKief.material-icon-theme" + "PKief.material-icon-theme", + "Codeium.codeium", + "sourcegraph.cody-ai" ] } }, diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f2b90a4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,229 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = tab +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = true + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = true +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = true +csharp_style_var_for_built_in_types = true +csharp_style_var_when_type_is_apparent = true + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = true +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = true +csharp_style_expression_bodied_methods = true +csharp_style_expression_bodied_operators = true +csharp_style_expression_bodied_properties = true + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = false +csharp_style_namespace_declarations = file_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_top_level_statements = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = false +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = unused_local_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### 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.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.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 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.vscode/launch.json b/.vscode/launch.json index 46dfaef..16af945 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,22 +2,21 @@ "version": "0.2.0", "configurations": [ { - "name": "RunClient", + "name": "RunBrowlClient", "type": "blazorwasm", "request": "launch", - "preLaunchTask": "build-client", - "cwd": "${workspaceFolder}/Browl.Client", - "url": "https://localhost:5900" + "preLaunchTask": "Browl.Client", + "cwd": "${workspaceFolder}/src/Presentation/Browl.Client/", + "url": "https://localhost:1400" }, { - "name": "RunHabitService", + "name": "RunBrowlServiceMarketDataCollector", "type": "coreclr", "request": "launch", - "preLaunchTask": "build-habit-service", - "program": "${workspaceFolder}/Browl.Service.MarketDataCollector/bin/Debug/net7.0/Browl.Service.MarketDataCollector.dll", + "preLaunchTask": "dotnet: watch Browl.Service.MarketDataCollector.API", + "program": "${workspaceFolder}/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API", "args": [], - "cwd": - "${workspaceFolder}/Browl.Service.MarketDataCollector", + "cwd": "${workspaceFolder}/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API", "stopAtEntry": false, "console": "integratedTerminal" }, @@ -26,8 +25,8 @@ { "name": "Run All", "configurations": [ - "RunHabitService", - "RunClient" + "RunBrowlServiceMarketDataCollector", + "RunBrowlClient" ] } ] diff --git a/.vscode/settings.json b/.vscode/settings.json index c10e08c..544b7b4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,3 @@ { - "thunder-client.saveToWorkspace": true, - "thunder-client.workspaceRelativePath": ".thunder-client" + } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3c84ba6..0a9e385 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,12 +2,12 @@ "version": "2.0.0", "tasks": [ { - "label": "build-client", + "label": "Browl.Client", "type": "shell", "command": "dotnet", "args": [ "build", - "${workspaceFolder}/Browl.Client/Browl.Client.csproj" + "${workspaceFolder}/src/Presentation/Browl.Client/Browl.Client.csproj" ], "group": { "kind": "build", @@ -15,17 +15,26 @@ } }, { - "label": "build-habit-service", + "label": "BrowlServiceMarketDataCollector", "type": "shell", "command": "dotnet", "args": [ "build", - "${workspaceFolder}/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.csproj" + "${workspaceFolder}/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API" ], "group": { "kind": "build", "isDefault": true } }, + { + "type": "dotnet", + "task": "watch Browl.Service.MarketDataCollector.API", + "file": "${workspaceFolder}\\src\\Services\\Browl.Service.MarketDataCollector\\Browl.Service.MarketDataCollector.API\\Browl.Service.MarketDataCollector.API.csproj", + "problemMatcher": [ + "$msCompile" + ], + "label": "dotnet: watch Browl.Service.MarketDataCollector.API" + } ] } \ No newline at end of file diff --git a/Browl.sln b/Browl.sln index 86cc704..0cf6f1f 100644 --- a/Browl.sln +++ b/Browl.sln @@ -80,9 +80,23 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Browl.Service.MarketDataCol EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Browl.Service.MarketDataCollector.Application.Test", "test\Services\Browl.Service.MarketDataCollector.Test\Browl.Service.MarketDataCollector.Application.Test\Browl.Service.MarketDataCollector.Application.Test.csproj", "{D3458E46-B1F2-4CAF-BDFD-94AB31F6528A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Browl.Service.MarketDataCollector.Infrastructure.Test", "test\Services\Browl.Service.MarketDataCollector.Test\Browl.Service.MarketDataCollector.Infrastructure.Test\Browl.Service.MarketDataCollector.Infrastructure.Test.csproj", "{14DFBDD1-124E-4E8F-9F90-270FE83F0704}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Browl.Service.MarketDataCollector.Infrastructure.Test", "test\Services\Browl.Service.MarketDataCollector.Test\Browl.Service.MarketDataCollector.Infrastructure.Test\Browl.Service.MarketDataCollector.Infrastructure.Test.csproj", "{14DFBDD1-124E-4E8F-9F90-270FE83F0704}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Browl.Client.Test", "test\Presentation\Browl.Client.Test\Browl.Client.Test.csproj", "{72694572-0D50-4A39-A657-73133F074AF7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Browl.Client.Test", "test\Presentation\Browl.Client.Test\Browl.Client.Test.csproj", "{72694572-0D50-4A39-A657-73133F074AF7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Browl.Service.MarketDataCollector.FakeData", "test\Services\Browl.Service.MarketDataCollector.Test\Browl.Service.MarketDataCollector.FakeData\Browl.Service.MarketDataCollector.FakeData.csproj", "{7A01F807-7685-48FB-BAD0-9303E96A53B5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FakeData", "FakeData", "{361920A2-8B95-47B1-AA42-C9ADD6D28D23}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Browl.Service.AuthSecurity", "Browl.Service.AuthSecurity", "{09EE67D6-ADE1-4A0A-8766-974D00A71209}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Browl.Service.AuthSecurity.API", "src\Services\Browl.Service.AuthSecurity\Browl.Service.AuthSecurity.API\Browl.Service.AuthSecurity.API.csproj", "{051A7F26-D824-420B-B642-741C6CD41F13}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Browl.Service.AuthSecurity.Test", "Browl.Service.AuthSecurity.Test", "{544648A6-FDBF-43E2-9C7B-93BA0300C4D4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Browl.Service.AuthSecurity.API.Test", "test\Services\Browl.Service.AuthSecurity.Test\Browl.Service.AuthSecurity.API.Test\Browl.Service.AuthSecurity.API.Test.csproj", "{728FCF2F-3429-4A46-A16F-396B3D67741A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{1E1868B1-34EC-4C95-9E41-4AFE56CCB434}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -130,6 +144,18 @@ Global {72694572-0D50-4A39-A657-73133F074AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU {72694572-0D50-4A39-A657-73133F074AF7}.Release|Any CPU.ActiveCfg = Release|Any CPU {72694572-0D50-4A39-A657-73133F074AF7}.Release|Any CPU.Build.0 = Release|Any CPU + {7A01F807-7685-48FB-BAD0-9303E96A53B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A01F807-7685-48FB-BAD0-9303E96A53B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A01F807-7685-48FB-BAD0-9303E96A53B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A01F807-7685-48FB-BAD0-9303E96A53B5}.Release|Any CPU.Build.0 = Release|Any CPU + {051A7F26-D824-420B-B642-741C6CD41F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {051A7F26-D824-420B-B642-741C6CD41F13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {051A7F26-D824-420B-B642-741C6CD41F13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {051A7F26-D824-420B-B642-741C6CD41F13}.Release|Any CPU.Build.0 = Release|Any CPU + {728FCF2F-3429-4A46-A16F-396B3D67741A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {728FCF2F-3429-4A46-A16F-396B3D67741A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {728FCF2F-3429-4A46-A16F-396B3D67741A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {728FCF2F-3429-4A46-A16F-396B3D67741A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -154,6 +180,12 @@ Global {D3458E46-B1F2-4CAF-BDFD-94AB31F6528A} = {DB8F8AA6-A0F4-487D-B807-787C5117DD35} {14DFBDD1-124E-4E8F-9F90-270FE83F0704} = {DB8F8AA6-A0F4-487D-B807-787C5117DD35} {72694572-0D50-4A39-A657-73133F074AF7} = {1B3CDB1E-8F3E-4900-A61F-B13C974872FF} + {7A01F807-7685-48FB-BAD0-9303E96A53B5} = {361920A2-8B95-47B1-AA42-C9ADD6D28D23} + {361920A2-8B95-47B1-AA42-C9ADD6D28D23} = {DB8F8AA6-A0F4-487D-B807-787C5117DD35} + {09EE67D6-ADE1-4A0A-8766-974D00A71209} = {758EAD6C-01B5-4816-97E5-CA0E5F217D34} + {051A7F26-D824-420B-B642-741C6CD41F13} = {09EE67D6-ADE1-4A0A-8766-974D00A71209} + {544648A6-FDBF-43E2-9C7B-93BA0300C4D4} = {9EFCDE84-8614-410C-A41E-F21DA32CEC23} + {728FCF2F-3429-4A46-A16F-396B3D67741A} = {544648A6-FDBF-43E2-9C7B-93BA0300C4D4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {09C8AF50-40D4-48F2-A03D-9BC7AB6D3538} diff --git a/docs/Bot.md b/docs/Bot.md index 5cc6aed..0e2d686 100644 --- a/docs/Bot.md +++ b/docs/Bot.md @@ -1,8 +1,4 @@ -Código de identificação: #7 - -Para refinar ainda mais o diagrama de contexto para compra e venda de criptomoedas, podemos adicionar as referências entre os serviços existentes. -Isso nos ajudará a entender melhor como cada serviço interage com os demais e como eles se comunicam. -O diagrama refinado com as referências pode ser representado da seguinte forma: +Diagrama de contexto para compra e venda de criptomoedas: +-------------------------+ +------------------------+ | Serviço de Coleta de | | Serviço de Análise de | @@ -53,76 +49,3 @@ O diagrama refinado com as referências pode ser representado da seguinte forma: | Serviço de Autenticação | | Serviço de Monitoramento | | Referência:| | e Segurança | | e Registro | | Registro | +-------------------------+ +------------------------+ +------------+ - - - - -Código de identificação: #8 - -Com base no diagrama de contexto e nas necessidades do software descritas anteriormente, -podemos estruturar o projeto em camadas para garantir a escalabilidade, -a segurança e a resiliência do software. Uma possível estrutura de projeto em C# pode ser a seguinte: - -OnePiece/ -├── OnePiece.API/ -│ ├── Controllers/ -│ ├── Models/ -│ ├── Services/ -│ ├── Startup.cs -│ └── appsettings.json -├── OnePiece.BusinessLogic/ -│ ├── DataModels/ -│ ├── Interfaces/ -│ ├── Services/ -│ └── Validators/ -├── OnePiece.DataAccess/ -│ ├── Context/ -│ ├── Migrations/ -│ ├── Repositories/ -│ ├── Entities/ -│ └── ApplicationDbContext.cs -└── OnePiece.Tests/ - ├── Controllers/ - ├── Services/ - └── DataAccess/ - -No diagrama de contexto, vemos que o serviço OnePiece está dividido em duas partes principais: a interface do usuário e o back-end. A interface do usuário (UI) é responsável por receber as entradas do usuário e apresentar as saídas. Já o back-end é responsável por processar as solicitações recebidas, buscar dados de fontes externas, como corretoras de criptomoedas, e retornar as informações relevantes para a interface do usuário. - -A estrutura de projeto em camadas proposta no -Código de Identificação #8 está alinhada com essa divisão em duas partes principais. -A camada OnePiece.API é responsável por expor as APIs para a interface do usuário, -enquanto as camadas OnePiece.BusinessLogic e OnePiece.DataAccess são responsáveis -por fornecer a lógica de negócios e o acesso a dados para o back-end do software. - -Portanto, a estrutura de projeto em camadas ajuda a garantir que as responsabilidades sejam bem definidas e distribuídas em diferentes partes do software, permitindo uma melhor organização e manutenção do código. - -A seguir, detalharemos as responsabilidades de cada camada: - -OnePiece.API: camada responsável por expor as APIs para o front-end ou outros serviços externos. Aqui, serão definidos os Controllers que vão lidar com as requisições HTTP, os Models que vão definir as estruturas dos dados enviados e recebidos nas APIs e os Services que vão orquestrar as chamadas às outras camadas do software. - -OnePiece.BusinessLogic: camada que contém toda a lógica de negócios do software. Aqui, são definidos os DataModels que vão representar os dados de entrada e saída dos serviços, as Interfaces que vão definir os contratos a serem implementados pelos Services e Validators que vão validar os dados de entrada antes de serem enviados às outras camadas. - -OnePiece.DataAccess: camada que contém toda a lógica de acesso a dados do software. Aqui, são definidos os Contexts que vão gerenciar o acesso ao banco de dados, as Migrations que vão controlar as alterações do banco de dados, as Repositories que vão definir as consultas ao banco de dados e as Entities que vão representar as tabelas do banco de dados. - -OnePiece.Tests: camada responsável por conter os testes unitários do software. Aqui, são definidos os Controllers que vão testar as requisições HTTP, os Services que vão testar as chamadas às outras camadas e o DataAccess que vão testar o acesso ao banco de dados. - - -Ao utilizar essa estrutura de projeto em camadas, podemos garantir a separação de responsabilidades e a escalabilidade do software. -Além disso, a divisão em camadas permite a criação de testes unitários de forma mais fácil e ajuda na manutenção do código. - - -Código de identificação: #9 - -A estrutura de projeto em camadas proposta no Código de Identificação #8 está diretamente relacionada com o diagrama de contexto apresentado no Código de Identificação #7. - -No diagrama de contexto, vemos que o serviço OnePiece está dividido em duas partes principais: - a interface do usuário e o back-end. A interface do usuário (UI) é responsável por receber as entradas do usuário e apresentar as saídas. - Já o back-end é responsável por processar as solicitações recebidas, - buscar dados de fontes externas, como corretoras de criptomoedas, e retornar as informações relevantes para a interface do usuário. - -A estrutura de projeto em camadas proposta no Código de Identificação #8 está alinhada com essa divisão em duas partes principais. - A camada OnePiece.API é responsável por expor as APIs para a interface do usuário, - enquanto as camadas OnePiece.BusinessLogic e OnePiece.DataAccess são responsáveis por fornecer a lógica de negócios e o acesso a dados para o back-end do software. - -Portanto, a estrutura de projeto em camadas ajuda a garantir que as responsabilidades sejam bem definidas -e distribuídas em diferentes partes do software, permitindo uma melhor organização e manutenção do código. \ No newline at end of file diff --git "a/docs/C\303\263digo de identifica\303\247\303\243o - 7.md" "b/docs/C\303\263digo de identifica\303\247\303\243o - 7.md" deleted file mode 100644 index 0c97052..0000000 --- "a/docs/C\303\263digo de identifica\303\247\303\243o - 7.md" +++ /dev/null @@ -1,30 +0,0 @@ -Código de identificação: #7 - -O diagrama de contexto apresentado no Código de Identificação #7 representa os serviços envolvidos no processo de compra e venda de criptomoedas. Nesse diagrama, temos uma visão geral do sistema e das principais interações entre os serviços. - -Na parte superior do diagrama, temos o usuário, que interage com o sistema por meio de uma interface de usuário (UI). A interface de usuário é responsável por receber as entradas do usuário e apresentar as saídas. - -Na parte inferior do diagrama, temos as corretoras de criptomoedas, que fornecem informações sobre os livros de ofertas e permitem a compra e venda de criptomoedas. - -Entre a interface do usuário e as corretoras de criptomoedas, temos o serviço CryptoTrader, que é responsável por processar as solicitações recebidas da interface do usuário, buscar dados das corretoras de criptomoedas e apresentar as informações relevantes de volta para a interface do usuário. - -Além disso, temos uma referência para o serviço de carteira, que é responsável por armazenar as criptomoedas compradas pelo usuário e permitir transferências para outras carteiras. - -Esse diagrama de contexto é útil para entendermos as principais interações e componentes do sistema e pode ser usado como base para a definição da arquitetura de software e das funcionalidades necessárias para o sistema funcionar de forma adequada. - - -__// \\__ - -O diagrama de contexto apresentado mostra as principais entidades envolvidas no processo de compra e venda de criptomoedas. A seguir, explicarei cada elemento presente no diagrama: - -Usuário: é a pessoa que utiliza o sistema por meio de uma interface de usuário (UI). A UI é responsável por receber as entradas do usuário e apresentar as saídas. - -Interface de usuário (UI): é a camada mais externa do sistema e fornece a interface para que o usuário possa interagir com o sistema. A UI é responsável por enviar as solicitações do usuário para o serviço OnePiece e apresentar as informações de retorno para o usuário. - -Serviço OnePiece: é responsável por processar as solicitações recebidas da interface do usuário, buscar dados das corretoras de criptomoedas e apresentar as informações relevantes de volta para a interface do usuário. O serviço OnePiece substituiu o serviço CryptoTrader mencionado anteriormente. - -Corretoras de criptomoedas: são as empresas que fornecem informações sobre os livros de ofertas e permitem a compra e venda de criptomoedas. O serviço OnePiece se comunica com as corretoras para obter as informações necessárias. - -Serviço de carteira: é responsável por armazenar as criptomoedas compradas pelo usuário e permitir transferências para outras carteiras. É uma referência para o serviço OnePiece. - -O diagrama de contexto é útil para entendermos as principais interações entre os componentes do sistema. Com base nesse diagrama, podemos iniciar a definição da arquitetura de software e das funcionalidades necessárias para o sistema funcionar de forma adequada. \ No newline at end of file diff --git a/docs/estrutura.md b/docs/estrutura.md deleted file mode 100644 index 0b4d23c..0000000 --- a/docs/estrutura.md +++ /dev/null @@ -1,59 +0,0 @@ -OnePiece -├── OnePiece.Application # Camada de Aplicação -│ ├── Interfaces # Interfaces para entrada e saída da camada de Aplicação -│ ├── Services # Implementações dos serviços da camada de Aplicação -│ ├── DTOs # Objetos de transferência de dados para a camada de Aplicação -│ └── Mappings # Mapeamentos entre DTOs e entidades - -├── OnePiece.Domain # Camada de Domínio -│ ├── Entities # Entidades do domínio -│ ├── Interfaces # Interfaces do domínio -│ └── Services # Serviços do domínio - -├── OnePiece.Infrastructure # Camada de Infraestrutura -│ ├── Data # Repositórios e implementações do acesso a dados -│ ├── Interfaces # Interfaces de Infraestrutura -│ ├── Services # Serviços de Infraestrutura -│ └── Persistence # Configuração e inicialização do banco de dados - -├── OnePiece.Tests # Testes unitários - -├── OnePiece.API # Camada de Apresentação -│ ├── Controllers # Controladores da API -│ ├── DTOs # Objetos de transferência de dados para a API -│ ├── Mappings # Mapeamentos entre DTOs e entidades -│ └── Startup.cs # Configurações iniciais da API - -└── OnePiece.Shared # Camada compartilhada -├── Exceptions # Exceções personalizadas -├── Interfaces # Interfaces compartilhadas -└── Utils # Utilitários compartilhados - - - +-----------------------+ - | OnePiece.API | - +-----------------------+ - | - | depende de - | - +-----------------------+ - | OnePiece.Application | - +-----------------------+ - | - | depende de - | - +-----------------------+ - | OnePiece.Domain | - +-----------------------+ - | - | depende de - | - +-----------------------+ - | OnePiece.Infrastructure| - +-----------------------+ - | - | usa - | - +-----------------------+ - | OnePiece.Shared | - +-----------------------+ diff --git a/docs/responsabilidades .md b/docs/responsabilidades .md deleted file mode 100644 index eb2760d..0000000 --- a/docs/responsabilidades .md +++ /dev/null @@ -1,56 +0,0 @@ -Camada de Apresentação: essa camada é responsável pela interação com o usuário ou outros sistemas externos. Aqui ficam as interfaces gráficas, controladores, rotas e validações de entrada. - -Camada de Aplicação: essa camada é responsável por orquestrar as operações do sistema e realizar a lógica de negócio. Aqui ficam os serviços, interfaces de entrada e saída e os DTOs. - -Camada de Domínio: essa camada contém as entidades e regras de negócio do sistema. Aqui ficam as interfaces do domínio, entidades, enums e exceções personalizadas. - -Camada de Infraestrutura: essa camada é responsável por fornecer a infraestrutura técnica para o sistema, como acesso a banco de dados, serviços externos, cache e logging. Aqui ficam os repositórios, serviços de infraestrutura e as interfaces de infraestrutura. - -Camada compartilhada: essa camada contém interfaces e objetos compartilhados entre as outras camadas. - - - - +--------------------------+ - | Camada de Apresentação| - +--------------------------+ - | Controladores | - | Interfaces de Serviços | - | DTOs | - +--------------------------+ - | - | - +--------------------------+ - | Camada de Aplicação | - +--------------------------+ - | Serviços | - | Interfaces de entrada | - | Interfaces de saída | - | DTOs | - +--------------------------+ - | - | - +--------------------------+ - | Camada de Domínio | - +--------------------------+ - | Entidades | - | Interfaces do Domínio | - | Exceções personalizadas| - | Enums | - +--------------------------+ - | - | - +--------------------------+ - | Camada de Infraestrut| - +--------------------------+ - | Repositórios | - | Serviços de infraestrut| - | Interfaces de Infraestr| - +--------------------------+ - | - | - +--------------------------+ - | Camada compartilhada | - +--------------------------+ - | Interfaces compartilhad| - | Objetos compartilhados | - +--------------------------+ diff --git a/global.json b/global.json new file mode 100644 index 0000000..540ac54 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "7.*" + } +} \ No newline at end of file diff --git a/src/Presentation/Browl.Client/App.razor b/src/Presentation/Browl.Client/App.razor index b80db76..3510ec6 100644 --- a/src/Presentation/Browl.Client/App.razor +++ b/src/Presentation/Browl.Client/App.razor @@ -1,11 +1,15 @@ - - - - - - Not found - -

Sorry, there's nothing at this address.

-
-
-
\ No newline at end of file + + + + + + + + Not found + +

Sorry, there's nothing at this address.

+
+
+
+ +
diff --git a/src/Presentation/Browl.Client/Browl.Client.csproj b/src/Presentation/Browl.Client/Browl.Client.csproj index 9f4ef75..022b3f9 100644 --- a/src/Presentation/Browl.Client/Browl.Client.csproj +++ b/src/Presentation/Browl.Client/Browl.Client.csproj @@ -1,8 +1,8 @@  - - - - + + + + net7.0 enable @@ -11,9 +11,14 @@ + + + + + diff --git a/src/Presentation/Browl.Client/Pages/Accounts/Login.razor b/src/Presentation/Browl.Client/Pages/Accounts/Login.razor new file mode 100644 index 0000000..054d092 --- /dev/null +++ b/src/Presentation/Browl.Client/Pages/Accounts/Login.razor @@ -0,0 +1,93 @@ +@page "/login" +@using System.Text.Json; +@using System.Text; +@using System.Net; +@using Browl.Client.Shared.Providers; +@inject IHttpClientFactory _httpClientFactory; +@inject ILocalStorageService _localStorageService; +@inject AuthenticationStateProvider _authStateProvider; +@inject NavigationManager _navigationManager; +
+ +

User Registration Form

+ +
+
+
+ + + + @if (!string.IsNullOrEmpty(APIErrorMessages)) + { + +

@APIErrorMessages

+ +
+ } + + + + +
+ + Login + +
+
+
+ +@code { + LoginResource loginModel = new LoginResource(); + + LoginValidationResource loginValidator = new LoginValidationResource(); + + MudForm form; + + string APIErrorMessages; + + private async Task LoginAsync() + { + await form.Validate(); + if (form.IsValid) + { + var jsonPayload = JsonSerializer.Serialize(loginModel); + var requestContent = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var httpClient = _httpClientFactory.CreateClient("Dot7Api"); + var response = await httpClient.PostAsync("api/User/login", requestContent); + + if (response.StatusCode == HttpStatusCode.BadRequest) + { + var errors = await response.Content.ReadFromJsonAsync>>(); + if (errors.Count > 0) + { + foreach (var item in errors) + { + foreach (var errorMessage in item.Value) + { + APIErrorMessages = $"{APIErrorMessages} | {errorMessage}"; + } + } + } + } + else if (response.StatusCode == HttpStatusCode.OK) + { + //_navigationManager.NavigateTo("/registration-confirmation"); + var tokenResponse = await response.Content.ReadFromJsonAsync(); + await _localStorageService.SetItemAsync("jwt-access-token", tokenResponse.AccessToken); + (_authStateProvider as CustomAuthProvider).NotifyAuthState(); + _navigationManager.NavigateTo("/fetchdata"); + } + else + { + APIErrorMessages = "Login Failed Plase try after some time"; + + } + } + } +} diff --git a/src/Presentation/Browl.Client/Pages/Accounts/Registration.razor b/src/Presentation/Browl.Client/Pages/Accounts/Registration.razor new file mode 100644 index 0000000..b18c6f4 --- /dev/null +++ b/src/Presentation/Browl.Client/Pages/Accounts/Registration.razor @@ -0,0 +1,106 @@ +@page "/registration" +@using System.Text.Json; +@using System.Text; +@using System.Net; +@inject IHttpClientFactory _httpClientFactory +@inject NavigationManager _navigationManager +
+ +

User Registration Form

+ +
+
+
+ + + + @if (!string.IsNullOrEmpty(APIErrorMessages)) + { + +

@APIErrorMessages

+ +
+ } + + + + + +
+ + Register + +
+
+
+ + +@code { + RegistrationResource registrationModel = new RegistrationResource(); + + RegistrationValidationResource validationModel ; + + + + MudForm form; + + string APIErrorMessages; + + protected override Task OnInitializedAsync() + { + var httpClient = _httpClientFactory.CreateClient("Dot7Api"); + validationModel = new RegistrationValidationResource(httpClient); + return base.OnInitializedAsync(); + } + + private async Task RegisterAsync() + { + await form.Validate(); + if (form.IsValid) + { + var jsonPayload = JsonSerializer.Serialize(registrationModel); + var requestContent = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + var httpClient = _httpClientFactory.CreateClient("Dot7Api"); + var response = await httpClient.PostAsync("api/user/register", requestContent); + + if(response.StatusCode == HttpStatusCode.BadRequest) + { + var errors = await response.Content.ReadFromJsonAsync>>(); + if(errors.Count > 0) + { + foreach (var item in errors) + { + foreach (var errorMessage in item.Value) + { + APIErrorMessages = $"{APIErrorMessages} | {errorMessage}"; + } + } + } + } + else if(response.StatusCode == HttpStatusCode.OK) + { + _navigationManager.NavigateTo("/registration-confirmation"); + } + else + { + APIErrorMessages = "Failed to register the user, please try after some time"; + + } + } + } +} diff --git a/src/Presentation/Browl.Client/Pages/Accounts/RegistrationConfirmation.razor b/src/Presentation/Browl.Client/Pages/Accounts/RegistrationConfirmation.razor new file mode 100644 index 0000000..9d2d3c0 --- /dev/null +++ b/src/Presentation/Browl.Client/Pages/Accounts/RegistrationConfirmation.razor @@ -0,0 +1,12 @@ +@page "/registration-confirmation" + +
+ +

Registration Success. Please Login!

+ +
+
+ +@code { + +} diff --git a/src/Presentation/Browl.Client/Pages/Index.razor b/src/Presentation/Browl.Client/Pages/Index.razor index d778782..ecef91f 100644 --- a/src/Presentation/Browl.Client/Pages/Index.razor +++ b/src/Presentation/Browl.Client/Pages/Index.razor @@ -4,7 +4,6 @@ Hello, world! Welcome to your new app, powered by MudBlazor! -You can find documentation and examples on our website here: www.mudblazor.com
diff --git a/src/Presentation/Browl.Client/Program.cs b/src/Presentation/Browl.Client/Program.cs index 6ef6a48..2b11c7d 100644 --- a/src/Presentation/Browl.Client/Program.cs +++ b/src/Presentation/Browl.Client/Program.cs @@ -1,15 +1,18 @@ using Browl.Client; + using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; + using MudBlazor.Services; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add("#app"); + builder.RootComponents.Add("head::after"); builder.Services.AddScoped(sp => new HttpClient { - BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) + BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddMudServices(); diff --git a/src/Presentation/Browl.Client/Properties/launchSettings.json b/src/Presentation/Browl.Client/Properties/launchSettings.json index cdba9c3..a07c0d5 100644 --- a/src/Presentation/Browl.Client/Properties/launchSettings.json +++ b/src/Presentation/Browl.Client/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:1408", + "applicationUrl": "http://localhost:1400", "sslPort": 44398 } }, @@ -18,10 +18,10 @@ }, "Browl": { "commandName": "Project", - "dotnetRunMessages": "true", + "dotnetRunMessages": true, "launchBrowser": true, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:1408", + "applicationUrl": "https://localhost:1400", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Presentation/Browl.Client/Resources/Accounts/JwtTokenResponseResource.cs b/src/Presentation/Browl.Client/Resources/Accounts/JwtTokenResponseResource.cs new file mode 100644 index 0000000..9ce9824 --- /dev/null +++ b/src/Presentation/Browl.Client/Resources/Accounts/JwtTokenResponseResource.cs @@ -0,0 +1,6 @@ +namespace Browl.Client.Resources.Accounts; + +public class JwtTokenResponseResource +{ + public string AccessToken { get; set; } +} diff --git a/src/Presentation/Browl.Client/Resources/Accounts/LoginResource.cs b/src/Presentation/Browl.Client/Resources/Accounts/LoginResource.cs new file mode 100644 index 0000000..5376e7d --- /dev/null +++ b/src/Presentation/Browl.Client/Resources/Accounts/LoginResource.cs @@ -0,0 +1,7 @@ +namespace Browl.Client.Resources.Accounts; + +public class LoginResource +{ + public string Email { get; set; } + public string Password { get; set; } +} diff --git a/src/Presentation/Browl.Client/Resources/Accounts/LoginValidationResource.cs b/src/Presentation/Browl.Client/Resources/Accounts/LoginValidationResource.cs new file mode 100644 index 0000000..b3d107a --- /dev/null +++ b/src/Presentation/Browl.Client/Resources/Accounts/LoginValidationResource.cs @@ -0,0 +1,31 @@ +using FluentValidation; + +namespace Browl.Client.Resources.Accounts; + +public class LoginValidationResource : AbstractValidator +{ + public LoginValidationResource() + { + RuleFor(_ => _.Email) + .NotEmpty() + .EmailAddress() + .WithMessage("Invalid Email"); + + RuleFor(x => x.Password).NotEmpty().WithMessage("Invalid Credentials") + .MinimumLength(6).WithMessage("Invalid Credentials") + .MaximumLength(16).WithMessage("Invalid Credentials") + .Matches(@"[A-Z]+").WithMessage("Invalid Credentials") + .Matches(@"[a-z]+").WithMessage("Invalid Credentials") + .Matches(@"[0-9]+").WithMessage("Invalid Credentials") + .Matches(@"[\@\!\?\*\.]+").WithMessage("Invalid Credentials"); + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = + await ValidateAsync(ValidationContext.CreateWithOptions((LoginResource)model, x => x.IncludeProperties(propertyName))); + if (result.IsValid) + return Array.Empty(); + return result.Errors.Select(e => e.ErrorMessage); + }; +} diff --git a/src/Presentation/Browl.Client/Resources/Accounts/RegistrationResource.cs b/src/Presentation/Browl.Client/Resources/Accounts/RegistrationResource.cs new file mode 100644 index 0000000..b35be19 --- /dev/null +++ b/src/Presentation/Browl.Client/Resources/Accounts/RegistrationResource.cs @@ -0,0 +1,10 @@ +namespace Browl.Client.Resources.Accounts; + +public class RegistrationResource +{ + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public string Password { get; set; } + public string ConfirmPassword { get; set; } +} diff --git a/src/Presentation/Browl.Client/Resources/Accounts/RegistrationValidationResource.cs b/src/Presentation/Browl.Client/Resources/Accounts/RegistrationValidationResource.cs new file mode 100644 index 0000000..6f8f0f9 --- /dev/null +++ b/src/Presentation/Browl.Client/Resources/Accounts/RegistrationValidationResource.cs @@ -0,0 +1,57 @@ +using FluentValidation; + +using System.Text.RegularExpressions; + +namespace Browl.Client.Resources.Accounts; + + +public class RegistrationValidationResource : AbstractValidator +{ + private readonly HttpClient _httpClient; + public RegistrationValidationResource(HttpClient httpClient) + { + RuleFor(x => x.FirstName).NotEmpty(); + RuleFor(x => x.LastName).NotEmpty(); + RuleFor(x => x.Email).NotEmpty().EmailAddress() + .MustAsync(async (value, CancellationToken) => await UniqueEmail(value)) + .When(_ => !string.IsNullOrEmpty(_.Email) && Regex.IsMatch(_.Email, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase), ApplyConditionTo.CurrentValidator) + .WithMessage("Email Is Already Exist"); + RuleFor(x => x.Password).NotEmpty().WithMessage("Your password cannot be empty") + .MinimumLength(6).WithMessage("Your password length must be at least 6.") + .MaximumLength(16).WithMessage("Your password length must not exceed 16.") + .Matches(@"[A-Z]+").WithMessage("Your password must contain at least one uppercase letter.") + .Matches(@"[a-z]+").WithMessage("Your password must contain at least one lowercase letter.") + .Matches(@"[0-9]+").WithMessage("Your password must contain at least one number.") + .Matches(@"[\@\!\?\*\.]+").WithMessage("Your password must contain at least one (@!? *.)."); + RuleFor(x => x.ConfirmPassword).Equal(_ => _.Password).WithMessage("'Confirm Password' must be equal 'Password'"); + _httpClient = httpClient; + + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = + await ValidateAsync(ValidationContext.CreateWithOptions((RegistrationResource)model, x => x.IncludeProperties(propertyName))); + if (result.IsValid) + return Array.Empty(); + return result.Errors.Select(e => e.ErrorMessage); + }; + + private async Task UniqueEmail(string email) + { + try + { + var url = $"/api/User/unique-user-email?email={email}"; + var response = await _httpClient.GetAsync(url); + response.EnsureSuccessStatusCode(); + + var content = await response.Content.ReadAsStringAsync(); + return Convert.ToBoolean(content); + } + catch (Exception ex) + { + return false; + } + + } +} diff --git a/src/Presentation/Browl.Client/Shared/MainLayout.razor b/src/Presentation/Browl.Client/Shared/MainLayout.razor index a758d02..2cb10e2 100644 --- a/src/Presentation/Browl.Client/Shared/MainLayout.razor +++ b/src/Presentation/Browl.Client/Shared/MainLayout.razor @@ -1,39 +1,45 @@ -@inherits LayoutComponentBase +@using System.Security.Claims; +@inherits LayoutComponentBase - - - - - - - - Browl - - - - - - - @Body - - + + + JWt Auth Demo + + + Wether ForeCast + + + + + + @UserDisplyaName(context.User.Claims.ToList()) + + + Login + Registration + + + + + + @Body + - -@code { - bool _drawerOpen = true; - - void DrawerToggle() - { - _drawerOpen = !_drawerOpen; - } +@code{ + private string UserDisplyaName(List claims) + { + var firstName = claims.Where(_ => _.Type == "FirstName").Select(_ => _.Value).FirstOrDefault(); + var lastName = claims.Where(_ => _.Type == "LastName").Select(_ => _.Value).FirstOrDefault(); + if(!string.IsNullOrEmpty(firstName) || !string.IsNullOrEmpty(lastName)) + { + return $"{firstName} {lastName}"; + } + var email = claims.Where(_ => _.Type == "Email").Select(_ => _.Value).FirstOrDefault(); + return email; + } } \ No newline at end of file diff --git a/src/Presentation/Browl.Client/Shared/MainLayout.razor.css b/src/Presentation/Browl.Client/Shared/MainLayout.razor.css new file mode 100644 index 0000000..c865427 --- /dev/null +++ b/src/Presentation/Browl.Client/Shared/MainLayout.razor.css @@ -0,0 +1,81 @@ +.page { + position: relative; + display: flex; + flex-direction: column; +} + +main { + flex: 1; +} + +.sidebar { + background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); +} + +.top-row { + background-color: #f7f7f7; + border-bottom: 1px solid #d6d5d5; + justify-content: flex-end; + height: 3.5rem; + display: flex; + align-items: center; +} + + .top-row ::deep a, .top-row ::deep .btn-link { + white-space: nowrap; + margin-left: 1.5rem; + text-decoration: none; + } + + .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { + text-decoration: underline; + } + + .top-row ::deep a:first-child { + overflow: hidden; + text-overflow: ellipsis; + } + +@media (max-width: 640.98px) { + .top-row:not(.auth) { + display: none; + } + + .top-row.auth { + justify-content: space-between; + } + + .top-row ::deep a, .top-row ::deep .btn-link { + margin-left: 0; + } +} + +@media (min-width: 641px) { + .page { + flex-direction: row; + } + + .sidebar { + width: 250px; + height: 100vh; + position: sticky; + top: 0; + } + + .top-row { + position: sticky; + top: 0; + z-index: 1; + } + + .top-row.auth ::deep a:first-child { + flex: 1; + text-align: right; + width: 0; + } + + .top-row, article { + padding-left: 2rem !important; + padding-right: 1.5rem !important; + } +} diff --git a/src/Presentation/Browl.Client/Shared/NavMenu.razor b/src/Presentation/Browl.Client/Shared/NavMenu.razor index 0de1a85..519bbed 100644 --- a/src/Presentation/Browl.Client/Shared/NavMenu.razor +++ b/src/Presentation/Browl.Client/Shared/NavMenu.razor @@ -1,3 +1,39 @@ - - Home - + + + + +@code { + private bool collapseNavMenu = true; + + private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; + + private void ToggleNavMenu() + { + collapseNavMenu = !collapseNavMenu; + } +} diff --git a/src/Presentation/Browl.Client/Shared/NavMenu.razor.css b/src/Presentation/Browl.Client/Shared/NavMenu.razor.css new file mode 100644 index 0000000..604b7a1 --- /dev/null +++ b/src/Presentation/Browl.Client/Shared/NavMenu.razor.css @@ -0,0 +1,68 @@ +.navbar-toggler { + background-color: rgba(255, 255, 255, 0.1); +} + +.top-row { + height: 3.5rem; + background-color: rgba(0,0,0,0.4); +} + +.navbar-brand { + font-size: 1.1rem; +} + +.oi { + width: 2rem; + font-size: 1.1rem; + vertical-align: text-top; + top: -2px; +} + +.nav-item { + font-size: 0.9rem; + padding-bottom: 0.5rem; +} + + .nav-item:first-of-type { + padding-top: 1rem; + } + + .nav-item:last-of-type { + padding-bottom: 1rem; + } + + .nav-item ::deep a { + color: #d7d7d7; + border-radius: 4px; + height: 3rem; + display: flex; + align-items: center; + line-height: 3rem; + } + +.nav-item ::deep a.active { + background-color: rgba(255,255,255,0.25); + color: white; +} + +.nav-item ::deep a:hover { + background-color: rgba(255,255,255,0.1); + color: white; +} + +@media (min-width: 641px) { + .navbar-toggler { + display: none; + } + + .collapse { + /* Never collapse the sidebar for wide screens */ + display: block; + } + + .nav-scrollable { + /* Allow sidebar to scroll for tall menus */ + height: calc(100vh - 3.5rem); + overflow-y: auto; + } +} diff --git a/src/Presentation/Browl.Client/Shared/Providers/CustomAuthProvider.cs b/src/Presentation/Browl.Client/Shared/Providers/CustomAuthProvider.cs new file mode 100644 index 0000000..e417d09 --- /dev/null +++ b/src/Presentation/Browl.Client/Shared/Providers/CustomAuthProvider.cs @@ -0,0 +1,52 @@ +using Blazored.LocalStorage; + +using Microsoft.AspNetCore.Components.Authorization; + +using System.Security.Claims; +using System.Text.Json; + +namespace Browl.Client.Shared.Providers; + +public class CustomAuthProvider : AuthenticationStateProvider +{ + private readonly ILocalStorageService _localStorageService; + public CustomAuthProvider(ILocalStorageService localStorageService) + { + _localStorageService = localStorageService; + } + public override async Task GetAuthenticationStateAsync() + { + var jwtToken = await _localStorageService.GetItemAsync("jwt-access-token"); + if (string.IsNullOrEmpty(jwtToken)) + { + return new AuthenticationState( + new ClaimsPrincipal(new ClaimsIdentity())); + } + + return new AuthenticationState(new ClaimsPrincipal( + new ClaimsIdentity(ParseClaimsFromJwt(jwtToken), "JwtAuth"))); + } + + private static IEnumerable ParseClaimsFromJwt(string jwt) + { + var payload = jwt.Split('.')[1]; + var jsonBytes = ParseBase64WithoutPadding(payload); + var keyValuePairs = JsonSerializer.Deserialize>(jsonBytes); + return keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())); + } + + private static byte[] ParseBase64WithoutPadding(string base64) + { + switch (base64.Length % 4) + { + case 2: base64 += "=="; break; + case 3: base64 += "="; break; + } + return Convert.FromBase64String(base64); + } + + public void NotifyAuthState() + { + NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); + } +} diff --git a/src/Presentation/Browl.Client/Shared/Providers/CustomHttpHandler.cs b/src/Presentation/Browl.Client/Shared/Providers/CustomHttpHandler.cs new file mode 100644 index 0000000..13fb2fb --- /dev/null +++ b/src/Presentation/Browl.Client/Shared/Providers/CustomHttpHandler.cs @@ -0,0 +1,28 @@ +using Blazored.LocalStorage; + +namespace Browl.Client.Shared.Providers; + +public class CustomHttpHandler : DelegatingHandler +{ + private readonly ILocalStorageService _localStorageService; + public CustomHttpHandler(ILocalStorageService localStorageService) + { + _localStorageService = localStorageService; + } + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (request.RequestUri.AbsolutePath.ToLower().Contains("login") || + request.RequestUri.AbsolutePath.ToLower().Contains("register")) + { + return await base.SendAsync(request, cancellationToken); + } + + var token = await _localStorageService.GetItemAsync("jwt-access-token"); + if (!string.IsNullOrEmpty(token)) + { + request.Headers.Add("Authorization", $"Bearer {token}"); + } + + return await base.SendAsync(request, cancellationToken); + } +} diff --git a/src/Presentation/Browl.Client/_Imports.razor b/src/Presentation/Browl.Client/_Imports.razor index a4b490a..ed50256 100644 --- a/src/Presentation/Browl.Client/_Imports.razor +++ b/src/Presentation/Browl.Client/_Imports.razor @@ -9,3 +9,7 @@ @using MudBlazor @using Browl.Client @using Browl.Client.Shared +@using Browl.Client.Resources.Accounts +@using FluentValidation +@using Blazored.LocalStorage +@using Microsoft.AspNetCore.Components.Authorization \ No newline at end of file diff --git a/src/Presentation/Browl.Client/wwwroot/css/app.min.css b/src/Presentation/Browl.Client/wwwroot/css/app.min.css index 9e21629..468e12e 100644 --- a/src/Presentation/Browl.Client/wwwroot/css/app.min.css +++ b/src/Presentation/Browl.Client/wwwroot/css/app.min.css @@ -485,6 +485,9 @@ video { --tw-backdrop-saturate: ; --tw-backdrop-sepia: ; } +.collapse { + visibility: collapse; +} .m-10 { margin: 2.5rem; } @@ -492,19 +495,27 @@ video { margin-left: auto; margin-right: auto; } -.my-16 { - margin-top: 4rem; - margin-bottom: 4rem; -} .mb-8 { margin-bottom: 2rem; } +.ml-2 { + margin-left: 0.5rem; +} +.ml-auto { + margin-left: auto; +} +.mr-2 { + margin-right: 0.5rem; +} .mt-8 { margin-top: 2rem; } .flex { display: flex; } +.justify-center { + justify-content: center; +} .rounded-md { border-radius: 0.375rem; } @@ -519,6 +530,10 @@ video { .p-4 { padding: 1rem; } +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} .px-4 { padding-left: 1rem; padding-right: 1rem; @@ -527,8 +542,8 @@ video { padding-top: 3rem; padding-bottom: 3rem; } -.pt-16 { - padding-top: 4rem; +.ps-3 { + padding-inline-start: 0.75rem; } .text-white { --tw-text-opacity: 1; diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Browl.Service.AuthSecurity.API.csproj b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Browl.Service.AuthSecurity.API.csproj new file mode 100644 index 0000000..d823ef5 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Browl.Service.AuthSecurity.API.csproj @@ -0,0 +1,21 @@ + + + + net7.0 + enable + enable + + + + + + + + + + + + + + + diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/ApiConfig.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/ApiConfig.cs new file mode 100644 index 0000000..d5ffe29 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/ApiConfig.cs @@ -0,0 +1,57 @@ +using Browl.Service.AuthSecurity.API.Service; +using Browl.Service.AuthSecurity.API.Services; +using Browl.Service.AuthSecurity.API.Services.Interfaces; + +namespace Browl.Service.AuthSecurity.API.Configuration; + +public static class ApiConfig +{ + public static IServiceCollection AddApiConfiguration(this IServiceCollection services, IWebHostEnvironment hostEnvironment, IConfiguration configuration) + { + _ = services.AddControllers(); + _ = services.AddEndpointsApiExplorer(); + + services.AddScoped(); + services.AddScoped(); + + services.AddCors(options => + { + options.AddPolicy(name: "BrowlCors", + policy => + { + policy.WithOrigins("https://localhost:7219") + .AllowAnyHeader() + .AllowAnyMethod(); + }); + }); + + var builder = new ConfigurationBuilder() + .SetBasePath(hostEnvironment.ContentRootPath) + .AddJsonFile("appsettings.json", true, true) + .AddJsonFile($"appsettings.{hostEnvironment.EnvironmentName}.json", true, true) + .AddEnvironmentVariables(); + + if (hostEnvironment.IsDevelopment()) + { + _ = builder.AddUserSecrets(); + } + + return services; + } + + public static IApplicationBuilder UseApiConfiguration(this IApplicationBuilder app, IWebHostEnvironment env) + { + + app.UseHttpsRedirection(); + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseCors("BrowlCors"); + app.UseEndpoints(endpoints => + { + var unused = endpoints.MapControllers(); + }); + + return app; + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/IdentityConfig.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/IdentityConfig.cs new file mode 100644 index 0000000..0be7d64 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/IdentityConfig.cs @@ -0,0 +1,64 @@ +using System.Text; + +using Browl.Service.AuthSecurity.API.Data; +using Browl.Service.AuthSecurity.API.Entities; + +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; + +namespace Browl.Service.AuthSecurity.API.Configuration; + +public static class IdentityConfig +{ + public static IServiceCollection AddIdentityConfiguration(this IServiceCollection services, + IConfiguration configuration) + { + var unused3 = services.AddDbContext(options => + options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"))); + + var unused2 = services.AddDefaultIdentity() + .AddRoles() + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); + + // JWT + + var appSettingsSection = configuration.GetSection("AppSettings"); + var unused1 = services.Configure(appSettingsSection); + + var appSettings = appSettingsSection.Get(); + var key = Encoding.ASCII.GetBytes(appSettings.Secret); + + var unused = services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }).AddJwtBearer(bearerOptions => + { + bearerOptions.RequireHttpsMetadata = true; + bearerOptions.SaveToken = true; + bearerOptions.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(key), + ValidateIssuer = true, + ValidateAudience = true, + ValidAudience = appSettings.ValidOn, + ValidIssuer = appSettings.Issuer + }; + }); + + return services; + } + + public static IApplicationBuilder UseIdentityConfiguration(this IApplicationBuilder app) + { + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); + + return app; + } + +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/SwaggerConfig.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/SwaggerConfig.cs new file mode 100644 index 0000000..95b6564 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Configuration/SwaggerConfig.cs @@ -0,0 +1,34 @@ +using Microsoft.OpenApi.Models; + +namespace Browl.Service.AuthSecurity.API.Configuration; + +public static class SwaggerConfig +{ + public static IServiceCollection AddSwaggerConfiguration(this IServiceCollection services) + { + var unused = services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo() + { + Title = "Browl Service AuthSecurity API", + Description = "This API guarantees the security and proper authentication of users in the application.", + Contact = new OpenApiContact() { Name = "Rondinele Guimarães", Email = "dev@cia3r.com.br" }, + License = new OpenApiLicense() { Name = "MIT", Url = new Uri("https://opensource.org/licenses/MIT") } + }); + + }); + + return services; + } + + public static IApplicationBuilder UseSwaggerConfiguration(this IApplicationBuilder app) + { + var unused1 = app.UseSwagger(); + var unused = app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"); + }); + + return app; + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/AuthController.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/AuthController.cs new file mode 100644 index 0000000..96fde85 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/AuthController.cs @@ -0,0 +1,99 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; + +using Browl.Service.AuthSecurity.API.Controllers.Base; +using Browl.Service.AuthSecurity.API.Entities; +using Browl.Service.AuthSecurity.API.Services.Interfaces; + +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace Browl.Service.AuthSecurity.API.Controllers; + + +[Route("api/identity/auth")] +public class AuthController : MainController +{ + private readonly SignInManager _signInManager; + private readonly UserManager _userManager; + private readonly AppSettings _appSettings; + private readonly IAuthenticateService _authenticateService; + public AuthController(SignInManager signInManager, + UserManager userManager, + IOptions appSettings, + IAuthenticateService authenticateService) + { + _signInManager = signInManager; + _userManager = userManager; + _appSettings = appSettings.Value; + _authenticateService = authenticateService; + } + + [HttpPost("new-account")] + public async Task Register(UserRegister userRegister) + { + if (!ModelState.IsValid) + { + return CustomResponse(ModelState); + } + + var identityUser = new User + { + UserName = userRegister.UserName, + FirstName = userRegister.FirstName, + LastName = userRegister.LastName, + UserNameChangeLimit = userRegister.UserNameChangeLimit, + ProfilePicture = userRegister.ProfilePicture, + Email = userRegister.Email, + EmailConfirmed = true, + Password = userRegister.Password, + PasswordConfirmation = userRegister.PasswordConfirmation + }; + + var result = await _userManager.CreateAsync(identityUser, userRegister.Password); + + if (result.Succeeded) + { + return CustomResponse(await _authenticateService.GenerateJWT(userRegister.Email)); + } + + foreach (var error in result.Errors) + { + AddErrorProcessing(error.Description); + } + + return CustomResponse(); + } + + + [HttpPost("authenticate")] + public async Task Login(UserLogin usuarioLogin) + { + if (!ModelState.IsValid) + { + return CustomResponse(ModelState); + } + + var result = await _signInManager.PasswordSignInAsync(usuarioLogin.Email, usuarioLogin.Password, + false, true); + + if (result.Succeeded) + { + return CustomResponse(await _authenticateService.GenerateJWT(usuarioLogin.Email)); + } + + if (result.IsLockedOut) + { + AddErrorProcessing("User temporarily blocked for invalid attempts"); + return CustomResponse(); + } + + AddErrorProcessing("Incorrect username or password"); + return CustomResponse(); + } + +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/Base/MainController.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/Base/MainController.cs new file mode 100644 index 0000000..5a43f42 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/Base/MainController.cs @@ -0,0 +1,65 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Browl.Service.AuthSecurity.API.Controllers.Base; + +/// +/// Abstract base controller class that provides common functionality for API controllers. +/// +/// +/// This abstract class defines: +/// - Errors: An IList property to hold a list of error strings. +/// - CustomResponse(): A protected method that returns an ActionResult with custom error handling. +/// - AddErrorProcessing(): A protected method to add an error string to the Errors collection. +/// - ClearErrorsProcessing(): A protected method to clear the Errors collection. +/// +/// Controllers that inherit from this base class can utilize these common members and methods for consistent error handling and responses. +/// +[ApiController] +public abstract class MainController : Controller +{ + // Collection to store error messages + protected IList Errors = new List(); + + /// + /// Custom response method to handle API responses + /// + /// Optional result object + /// Action result + protected ActionResult CustomResponse(object? result = null) + { + // Check if the model state is valid and there are no errors + if (ModelState.IsValid && Errors.Count == 0) + { + return Ok(result); + } + + var errorDictionary = new Dictionary(); + + // Add model state errors to the dictionary + if (ModelState.ErrorCount > 0) + { + var modelErrors = ModelState.Values.SelectMany(v => v.Errors); + errorDictionary.Add("Messages", modelErrors.Select(e => e.ErrorMessage).ToArray()); + } + + // Add custom errors to the dictionary + if (Errors.Count > 0) + { + errorDictionary.Add("Messages", Errors.ToArray()); + } + + // Return a bad request response with the validation problem details + return BadRequest(new ValidationProblemDetails(errorDictionary)); + } + + /// + /// Add an error message to the collection + /// + /// Error message + protected void AddErrorProcessing(string error) => Errors.Add(error); + + /// + /// Clear all error messages from the collection + /// + protected void ClearErrorsProcessing() => Errors.Clear(); +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/UserController.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/UserController.cs new file mode 100644 index 0000000..d382930 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Controllers/UserController.cs @@ -0,0 +1,47 @@ +using Browl.Service.AuthSecurity.API.Resources; +using Browl.Service.AuthSecurity.API.Services.Interfaces; + +using Microsoft.AspNetCore.Mvc; + +namespace Browl.Service.AuthSecurity.API.Controllers; + +[Route("api/[controller]")] +[ApiController] +public class UserController : ControllerBase +{ + private readonly IUserService _userService; + public UserController(IUserService userService) + { + _userService = userService; + } + + [HttpPost("register")] + public async Task UserRegistration(UserRegistrationResources userRegistration) + { + var result = await _userService.RegisterNewUserAsync(userRegistration); + if (result.IsUserRegistered) + { + return Ok(result.Message); + } + + ModelState.AddModelError("Email", result.Message); + return BadRequest(ModelState); + } + [HttpGet("unique-user-email")] + public IActionResult CheckUniqueUserEmail(string email) + { + var result = _userService.CheckUserUniqueEmail(email); + return Ok(result); + } + [HttpPost("login")] + public async Task LoginAsync(LoginResource payload) + { + var result = await _userService.LoginAsync(payload); + if (result.IsLoginSuccess) + { + return Ok(result.TokeResponse); + } + ModelState.AddModelError("LoginError", "Invalid Credentials"); + return BadRequest(ModelState); + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Data/BrowlAuthSecurityDbContext.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Data/BrowlAuthSecurityDbContext.cs new file mode 100644 index 0000000..503d4b3 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Data/BrowlAuthSecurityDbContext.cs @@ -0,0 +1,57 @@ +using Browl.Service.AuthSecurity.API.Entities; + +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; + +namespace Browl.Service.AuthSecurity.API.Data; + +public class BrowlAuthSecurityDbContext : IdentityDbContext +{ + + public DbSet User { get; set; } + + public BrowlAuthSecurityDbContext(DbContextOptions options) + : base(options) + { + } + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + var unused14 = builder.HasDefaultSchema("Identity"); + var unused13 = builder.Entity(entity => + { + var unused12 = entity.ToTable(name: "User"); + }); + + var unused11 = builder.Entity(entity => + { + var unused10 = entity.ToTable(name: "Role"); + }); + var unused9 = builder.Entity>(entity => + { + var unused8 = entity.ToTable("UserRoles"); + }); + + var unused7 = builder.Entity>(entity => + { + var unused6 = entity.ToTable("UserClaims"); + }); + + var unused5 = builder.Entity>(entity => + { + var unused4 = entity.ToTable("UserLogins"); + }); + + var unused3 = builder.Entity>(entity => + { + var unused2 = entity.ToTable("RoleClaims"); + + }); + + var unused1 = builder.Entity>(entity => + { + var unused = entity.ToTable("UserTokens"); + }); + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Data/ContextSeed.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Data/ContextSeed.cs new file mode 100644 index 0000000..15b5279 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Data/ContextSeed.cs @@ -0,0 +1,45 @@ +using Browl.Service.AuthSecurity.API.Entities; + +using Microsoft.AspNetCore.Identity; + +namespace Browl.Service.AuthSecurity.API.Data; + +public static class ContextSeed +{ + public static async Task SeedRolesAsync(UserManager userManager, RoleManager roleManager) + { + //Seed Roles + _ = await roleManager.CreateAsync(new IdentityRole(Enums.Roles.SuperAdmin.ToString())); + _ = await roleManager.CreateAsync(new IdentityRole(Enums.Roles.Admin.ToString())); + _ = await roleManager.CreateAsync(new IdentityRole(Enums.Roles.Moderator.ToString())); + _ = await roleManager.CreateAsync(new IdentityRole(Enums.Roles.Basic.ToString())); + } + public static async Task SeedSuperAdminAsync(UserManager userManager, RoleManager roleManager) + { + //Seed Default User + var defaultUser = new User + { + UserName = "rondineleg", + Email = "superadmin@gmail.com", + FirstName = "Rondinele", + LastName = "Guimaraes", + UserNameChangeLimit = 10, + EmailConfirmed = true, + PhoneNumberConfirmed = true, + + }; + if (userManager.Users.All(u => u.Id != defaultUser.Id)) + { + var user = await userManager.FindByEmailAsync(defaultUser.Email); + if (user == null) + { + var unused4 = await userManager.CreateAsync(defaultUser, "123Pa$$word."); + var unused3 = await userManager.AddToRoleAsync(defaultUser, Enums.Roles.Basic.ToString()); + var unused2 = await userManager.AddToRoleAsync(defaultUser, Enums.Roles.Moderator.ToString()); + var unused1 = await userManager.AddToRoleAsync(defaultUser, Enums.Roles.Admin.ToString()); + var unused = await userManager.AddToRoleAsync(defaultUser, Enums.Roles.SuperAdmin.ToString()); + } + + } + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/AppSettings.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/AppSettings.cs new file mode 100644 index 0000000..cfc562f --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/AppSettings.cs @@ -0,0 +1,9 @@ +namespace Browl.Service.AuthSecurity.API.Entities; + +public class AppSettings +{ + public string Secret { get; set; } + public int ExpirationHours { get; set; } + public string Issuer { get; set; } + public string ValidOn { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/ManageUserRoles.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/ManageUserRoles.cs new file mode 100644 index 0000000..d8e2a1f --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/ManageUserRoles.cs @@ -0,0 +1,8 @@ +namespace Browl.Service.AuthSecurity.API.Entities; + +public class ManageUserRoles +{ + public required string RoleId { get; set; } + public required string RoleName { get; set; } + public bool Selected { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/User.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/User.cs new file mode 100644 index 0000000..cf5f03a --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/User.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Identity; + +namespace Browl.Service.AuthSecurity.API.Entities; +public class User : IdentityUser +{ + public int Id { get; set; } + + public string UserName { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public int UserNameChangeLimit { get; set; } = 5; + public byte[] ProfilePicture { get; set; } + public string Email { get; set; } + public string Password { get; set; } + public string PasswordConfirmation { get; set; } + +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserClaim.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserClaim.cs new file mode 100644 index 0000000..a21a716 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserClaim.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.AuthSecurity.API.Entities; + +public class UserClaim +{ + public required string Value { get; set; } + public required string Type { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserLogin.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserLogin.cs new file mode 100644 index 0000000..8485340 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserLogin.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace Browl.Service.AuthSecurity.API.Entities; + +public class UserLogin +{ + [Required(ErrorMessage = "Field {0} is mandatory")] + [EmailAddress(ErrorMessage = "Field {0} is in an invalid format")] + public string Email { get; set; } + + [Required(ErrorMessage = "Field {0} is mandatory")] + [StringLength(100, ErrorMessage = "Field {0} must be between {2} and {1} characters", MinimumLength = 6)] + public string Password { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserRegister.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserRegister.cs new file mode 100644 index 0000000..46fd9da --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserRegister.cs @@ -0,0 +1,40 @@ +using System.ComponentModel.DataAnnotations; + +namespace Browl.Service.AuthSecurity.API.Entities; + +public class UserRegister +{ + public UserRegister(string userName, string firstName, string lastName, int userNameChangeLimit, byte[] profilePicture, string email, string password, string passwordConfirmation) + { + UserName = userName; + FirstName = firstName; + LastName = lastName; + UserNameChangeLimit = userNameChangeLimit; + ProfilePicture = profilePicture; + Email = email; + Password = password; + PasswordConfirmation = passwordConfirmation; + } + + [Required(ErrorMessage = "Field {0} is mandatory")] + public string UserName { get; set; } + + [Required(ErrorMessage = "Field {0} is mandatory")] + public string FirstName { get; set; } + [Required(ErrorMessage = "Field {0} is mandatory")] + public string LastName { get; set; } + public int UserNameChangeLimit { get; set; } = 5; + [Required(ErrorMessage = "Field {0} is mandatory")] + public byte[] ProfilePicture { get; set; } + + [Required(ErrorMessage = "Field {0} is mandatory")] + [EmailAddress(ErrorMessage = "Field {0} is in an invalid format")] + public string Email { get; set; } + + [Required(ErrorMessage = "Field {0} is mandatory")] + [StringLength(100, ErrorMessage = "Field {0} must be between {2} and {1} characters", MinimumLength = 6)] + public string Password { get; set; } + + [Compare("Password", ErrorMessage = "Passwords don't match.")] + public string PasswordConfirmation { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserResponse.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserResponse.cs new file mode 100644 index 0000000..89b0a63 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserResponse.cs @@ -0,0 +1,8 @@ +namespace Browl.Service.AuthSecurity.API.Entities; +public class UserResponse +{ + public required string AccessToken { get; set; } + public double ExpiresIn { get; set; } + public required UserToken UserToken { get; set; } +} + diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserRoles.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserRoles.cs new file mode 100644 index 0000000..7de4f76 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserRoles.cs @@ -0,0 +1,11 @@ +namespace Browl.Service.AuthSecurity.API.Entities; + +public class UserRoles +{ + public required string UserId { get; set; } + public required string FirstName { get; set; } + public required string LastName { get; set; } + public required string UserName { get; set; } + public required string Email { get; set; } + public required IEnumerable Roles { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserToken.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserToken.cs new file mode 100644 index 0000000..1fda473 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Entities/UserToken.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.AuthSecurity.API.Entities; +public class UserToken +{ + public string Id { get; set; } + public string Email { get; set; } + public IEnumerable UserClaims { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Enums/Roles.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Enums/Roles.cs new file mode 100644 index 0000000..80b1c5e --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Enums/Roles.cs @@ -0,0 +1,9 @@ +namespace Browl.Service.AuthSecurity.API.Enums; + +public enum Roles +{ + SuperAdmin, + Admin, + Moderator, + Basic +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230916004956_InicialCreate.Designer.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230916004956_InicialCreate.Designer.cs new file mode 100644 index 0000000..e2b6fad --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230916004956_InicialCreate.Designer.cs @@ -0,0 +1,309 @@ +// +using System; +using Browl.Service.AuthSecurity.API.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Browl.Service.AuthSecurity.API.Migrations +{ + [DbContext(typeof(BrowlAuthSecurityDbContext))] + [Migration("20230916004956_InicialCreate")] + partial class InicialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Identity") + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Browl.Service.AuthSecurity.Domain.Entities.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordConfirmation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("ProfilePicture") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("UserNameChangeLimit") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("User", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("Role", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Browl.Service.AuthSecurity.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Browl.Service.AuthSecurity.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Browl.Service.AuthSecurity.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Browl.Service.AuthSecurity.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230916004956_InicialCreate.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230916004956_InicialCreate.cs new file mode 100644 index 0000000..935a0fa --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230916004956_InicialCreate.cs @@ -0,0 +1,252 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Browl.Service.AuthSecurity.API.Migrations; + +/// +public partial class InicialCreate : Migration +{ + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + var unused27 = migrationBuilder.EnsureSchema( + name: "Identity"); + + var unused26 = migrationBuilder.CreateTable( + name: "Role", + schema: "Identity", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + var unused25 = table.PrimaryKey("PK_Role", x => x.Id); + }); + + var unused24 = migrationBuilder.CreateTable( + name: "User", + schema: "Identity", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + FirstName = table.Column(type: "nvarchar(max)", nullable: false), + LastName = table.Column(type: "nvarchar(max)", nullable: false), + UserNameChangeLimit = table.Column(type: "int", nullable: false), + ProfilePicture = table.Column(type: "varbinary(max)", nullable: false), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Password = table.Column(type: "nvarchar(max)", nullable: false), + PasswordConfirmation = table.Column(type: "nvarchar(max)", nullable: false), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + var unused23 = table.PrimaryKey("PK_User", x => x.Id); + }); + + var unused22 = migrationBuilder.CreateTable( + name: "RoleClaims", + schema: "Identity", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + var unused21 = table.PrimaryKey("PK_RoleClaims", x => x.Id); + var unused20 = table.ForeignKey( + name: "FK_RoleClaims_Role_RoleId", + column: x => x.RoleId, + principalSchema: "Identity", + principalTable: "Role", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + var unused19 = migrationBuilder.CreateTable( + name: "UserClaims", + schema: "Identity", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + var unused18 = table.PrimaryKey("PK_UserClaims", x => x.Id); + var unused17 = table.ForeignKey( + name: "FK_UserClaims_User_UserId", + column: x => x.UserId, + principalSchema: "Identity", + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + var unused16 = migrationBuilder.CreateTable( + name: "UserLogins", + schema: "Identity", + columns: table => new + { + LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderKey = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + var unused15 = table.PrimaryKey("PK_UserLogins", x => new { x.LoginProvider, x.ProviderKey }); + var unused14 = table.ForeignKey( + name: "FK_UserLogins_User_UserId", + column: x => x.UserId, + principalSchema: "Identity", + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + var unused13 = migrationBuilder.CreateTable( + name: "UserRoles", + schema: "Identity", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + var unused12 = table.PrimaryKey("PK_UserRoles", x => new { x.UserId, x.RoleId }); + var unused11 = table.ForeignKey( + name: "FK_UserRoles_Role_RoleId", + column: x => x.RoleId, + principalSchema: "Identity", + principalTable: "Role", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + var unused10 = table.ForeignKey( + name: "FK_UserRoles_User_UserId", + column: x => x.UserId, + principalSchema: "Identity", + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + var unused9 = migrationBuilder.CreateTable( + name: "UserTokens", + schema: "Identity", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + var unused8 = table.PrimaryKey("PK_UserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + var unused7 = table.ForeignKey( + name: "FK_UserTokens_User_UserId", + column: x => x.UserId, + principalSchema: "Identity", + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + var unused6 = migrationBuilder.CreateIndex( + name: "RoleNameIndex", + schema: "Identity", + table: "Role", + column: "NormalizedName", + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + var unused5 = migrationBuilder.CreateIndex( + name: "IX_RoleClaims_RoleId", + schema: "Identity", + table: "RoleClaims", + column: "RoleId"); + + var unused4 = migrationBuilder.CreateIndex( + name: "EmailIndex", + schema: "Identity", + table: "User", + column: "NormalizedEmail"); + + var unused3 = migrationBuilder.CreateIndex( + name: "UserNameIndex", + schema: "Identity", + table: "User", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + + var unused2 = migrationBuilder.CreateIndex( + name: "IX_UserClaims_UserId", + schema: "Identity", + table: "UserClaims", + column: "UserId"); + + var unused1 = migrationBuilder.CreateIndex( + name: "IX_UserLogins_UserId", + schema: "Identity", + table: "UserLogins", + column: "UserId"); + + var unused = migrationBuilder.CreateIndex( + name: "IX_UserRoles_RoleId", + schema: "Identity", + table: "UserRoles", + column: "RoleId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + _ = migrationBuilder.DropTable( + name: "RoleClaims", + schema: "Identity"); + _ = migrationBuilder.DropTable( + name: "UserClaims", + schema: "Identity"); + _ = migrationBuilder.DropTable( + name: "UserLogins", + schema: "Identity"); + _ = migrationBuilder.DropTable( + name: "UserRoles", + schema: "Identity"); + _ = migrationBuilder.DropTable( + name: "UserTokens", + schema: "Identity"); + _ = migrationBuilder.DropTable( + name: "Role", + schema: "Identity"); + _ = migrationBuilder.DropTable( + name: "User", + schema: "Identity"); + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230917173751_AddEntitieUser.Designer.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230917173751_AddEntitieUser.Designer.cs new file mode 100644 index 0000000..880410a --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230917173751_AddEntitieUser.Designer.cs @@ -0,0 +1,309 @@ +// +using System; +using Browl.Service.AuthSecurity.API.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Browl.Service.AuthSecurity.API.Migrations +{ + [DbContext(typeof(BrowlAuthSecurityDbContext))] + [Migration("20230917173751_AddEntitieUser")] + partial class AddEntitieUser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Identity") + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Browl.Service.AuthSecurity.API.Entities.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordConfirmation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("ProfilePicture") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("UserNameChangeLimit") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("User", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("Role", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230917173751_AddEntitieUser.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230917173751_AddEntitieUser.cs new file mode 100644 index 0000000..33a5dda --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/20230917173751_AddEntitieUser.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Browl.Service.AuthSecurity.API.Migrations +{ + /// + public partial class AddEntitieUser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/BrowlAuthSecurityDbContextModelSnapshot.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/BrowlAuthSecurityDbContextModelSnapshot.cs new file mode 100644 index 0000000..02fbdcc --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Migrations/BrowlAuthSecurityDbContextModelSnapshot.cs @@ -0,0 +1,306 @@ +// +using System; +using Browl.Service.AuthSecurity.API.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Browl.Service.AuthSecurity.API.Migrations +{ + [DbContext(typeof(BrowlAuthSecurityDbContext))] + partial class BrowlAuthSecurityDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Identity") + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Browl.Service.AuthSecurity.API.Entities.User", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordConfirmation") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("ProfilePicture") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("UserNameChangeLimit") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("User", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("Role", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", "Identity"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Browl.Service.AuthSecurity.API.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Program.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Program.cs new file mode 100644 index 0000000..a852463 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Program.cs @@ -0,0 +1,48 @@ +using Browl.Service.AuthSecurity.API.Configuration; +using Browl.Service.AuthSecurity.API.Data; +using Browl.Service.AuthSecurity.API.Entities; + +using Microsoft.AspNetCore.Identity; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddIdentityConfiguration(builder.Configuration); +builder.Services.AddApiConfiguration(builder.Environment, builder.Configuration); +builder.Services.AddSwaggerConfiguration(); + +var app = builder.Build(); + +app.UseIdentityConfiguration(); +app.UseSwaggerConfiguration(); + +var services = app.Services; +var loggerFactory = services.GetRequiredService(); +var logger = loggerFactory.CreateLogger("app"); +try +{ + var ser = builder.Services; + + using (var scope = services.CreateScope()) + { + var context = services.GetRequiredService(); + var userManager = services.GetRequiredService>(); + var roleManager = services.GetRequiredService>(); + await ContextSeed.SeedRolesAsync(userManager, roleManager); + await ContextSeed.SeedSuperAdminAsync(userManager, roleManager); + } + + if (app.Environment.IsDevelopment()) + { + logger.LogWarning(app.Environment.EnvironmentName, $"EnvironmentName {app.Environment.EnvironmentName}"); + Console.WriteLine("Is dev"); + } + app.Run(); +} +catch (Exception ex) +{ + logger.LogWarning(ex, "An error occurred seeding the DB"); +} +finally +{ + app.Run(); +} + diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Properties/launchSettings.json b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Properties/launchSettings.json new file mode 100644 index 0000000..4505321 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:1400", + "sslPort": 44312 + } + }, + "profiles": { + "Browl.Service.AuthSecurity.API": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:1401", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/JWTTokenResponseResource.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/JWTTokenResponseResource.cs new file mode 100644 index 0000000..8c3559b --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/JWTTokenResponseResource.cs @@ -0,0 +1,6 @@ +namespace Browl.Service.AuthSecurity.API.Resources; + +public class JWTTokenResponseResource +{ + public string AccessToken { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/LoginResource.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/LoginResource.cs new file mode 100644 index 0000000..afad3c4 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/LoginResource.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.AuthSecurity.API.Resources; + +public class LoginResource +{ + public string Email { get; set; } + public string Password { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/UserRegistrationResources.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/UserRegistrationResources.cs new file mode 100644 index 0000000..d61fee8 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Resources/UserRegistrationResources.cs @@ -0,0 +1,9 @@ +namespace Browl.Service.AuthSecurity.API.Resources; +public class UserRegistrationResources +{ + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public string Password { get; set; } + public string ConfirmPassword { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/AuthenticateService.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/AuthenticateService.cs new file mode 100644 index 0000000..cc7475d --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/AuthenticateService.cs @@ -0,0 +1,102 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; + +using Browl.Service.AuthSecurity.API.Entities; +using Browl.Service.AuthSecurity.API.Services.Interfaces; + +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace Browl.Service.AuthSecurity.API.Services; + +public class AuthenticateService : IAuthenticateService +{ + + private readonly SignInManager _signInManager; + private readonly UserManager _userManager; + private readonly AppSettings _appSettings; + + public AuthenticateService(SignInManager signInManager, + UserManager userManager, + IOptions appSettings) + { + _signInManager = signInManager; + _userManager = userManager; + _appSettings = appSettings.Value; + } + public async Task GenerateJWT(string email) + { + var user = await _userManager.FindByEmailAsync(email).ConfigureAwait(false); + var claims = await _userManager.GetClaimsAsync(user).ConfigureAwait(false); + var identityClaims = await GetClaimsUser(claims, user).ConfigureAwait(false); + var encodedToken = EncodeToken(identityClaims); + return GetResponseToken(encodedToken, user, claims); + } + + private async Task GetClaimsUser(ICollection claims, IdentityUser user) + { + var userRoles = await _userManager.GetRolesAsync(user); + claims.Add(new Claim(JwtRegisteredClaimNames.Sub, user.Id)); + claims.Add(new Claim(JwtRegisteredClaimNames.Email, user.Email)); + claims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())); + claims.Add(new Claim(JwtRegisteredClaimNames.Nbf, ToUnixEpochDate(DateTime.UtcNow).ToString())); + claims.Add(new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(DateTime.UtcNow).ToString(), ClaimValueTypes.Integer64)); + foreach (var userRole in userRoles) + { + claims.Add(new Claim("role", userRole)); + } + ClaimsIdentity identityClaims = new(); + identityClaims.AddClaims(claims); + + return identityClaims; + } + + private string EncodeToken(ClaimsIdentity identityClaims) + { + JwtSecurityTokenHandler tokenHandler = new(); + var key = Encoding.ASCII.GetBytes(_appSettings.Secret); + var token = tokenHandler.CreateToken(new SecurityTokenDescriptor + { + Issuer = _appSettings.Issuer, + Audience = _appSettings.ValidOn, + Subject = identityClaims, + Expires = DateTime.UtcNow.AddHours(_appSettings.ExpirationHours), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + }); + + return tokenHandler.WriteToken(token); + } + + private UserResponse GetResponseToken(string encodedToken, IdentityUser user, IEnumerable claims) + { + if (string.IsNullOrEmpty(user?.Email)) + { + throw new ArgumentException("User email cannot be empty or null.", nameof(user)); + } + + var expiresIn = TimeSpan.FromHours(_appSettings.ExpirationHours).TotalSeconds; + var userClaims = claims.Select(c => new UserClaim { Type = c.Type, Value = c.Value }).ToList(); + + var response = new UserResponse + { + AccessToken = encodedToken, + ExpiresIn = expiresIn, + UserToken = new UserToken + { + Id = user.Id, + Email = user.Email, + UserClaims = userClaims + } + }; + + return response; + } + + + public long ToUnixEpochDate(DateTime date) + { + return DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/Interfaces/IAuthenticateService.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/Interfaces/IAuthenticateService.cs new file mode 100644 index 0000000..8a826ab --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/Interfaces/IAuthenticateService.cs @@ -0,0 +1,12 @@ +using System.Security.Claims; + +using Browl.Service.AuthSecurity.API.Entities; + +using Microsoft.AspNetCore.Identity; + +namespace Browl.Service.AuthSecurity.API.Services.Interfaces; + +public interface IAuthenticateService +{ + Task GenerateJWT(string email); +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/Interfaces/IUserService.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/Interfaces/IUserService.cs new file mode 100644 index 0000000..0f10c9b --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/Interfaces/IUserService.cs @@ -0,0 +1,12 @@ +using Browl.Service.AuthSecurity.API.Resources; + +namespace Browl.Service.AuthSecurity.API.Services.Interfaces; + +public interface IUserService +{ + Task<(bool IsUserRegistered, string Message)> RegisterNewUserAsync(UserRegistrationResources userRegistration); + + bool CheckUserUniqueEmail(string email); + + Task<(bool IsLoginSuccess, JWTTokenResponseResource TokeResponse)> LoginAsync(LoginResource loginPayload); +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/UserService.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/UserService.cs new file mode 100644 index 0000000..70232c3 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Services/UserService.cs @@ -0,0 +1,143 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; + +using Browl.Service.AuthSecurity.API.Data; +using Browl.Service.AuthSecurity.API.Entities; +using Browl.Service.AuthSecurity.API.Resources; +using Browl.Service.AuthSecurity.API.Services.Interfaces; +using Browl.Service.AuthSecurity.API.Shared.Settings; + +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace Browl.Service.AuthSecurity.API.Service; + +public class UserService : IUserService +{ + private readonly BrowlAuthSecurityDbContext _browlAuthSecurityDbContext; + private readonly TokenSettings _tokenSettings; + public UserService(BrowlAuthSecurityDbContext browlAuthSecurityDbContext, + IOptions tokenSettings) + { + _browlAuthSecurityDbContext = browlAuthSecurityDbContext; + _tokenSettings = tokenSettings.Value; + } + + private User FromUserRegistrationModelToUserModel(UserRegistrationResources userRegistration) + { + return new User + { + Email = userRegistration.Email, + FirstName = userRegistration.FirstName, + LastName = userRegistration.LastName, + Password = userRegistration.Password, + }; + } + + private string HashPassword(string plainPassword) + { + var salt = new byte[16]; + using (var rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(salt); + } + + var rfcPassord = new Rfc2898DeriveBytes(plainPassword, salt, 1000, HashAlgorithmName.SHA1); + var rfcPasswordHash = rfcPassord.GetBytes(20); + + var passwordHash = new byte[36]; + Array.Copy(salt, 0, passwordHash, 0, 16); + Array.Copy(rfcPasswordHash, 0, passwordHash, 16, 20); + + return Convert.ToBase64String(passwordHash); + } + public async Task<(bool IsUserRegistered, string Message)> RegisterNewUserAsync(UserRegistrationResources userRegistration) + { + var isUserExist = _browlAuthSecurityDbContext.User.Any(_ => _.Email.ToLower() == userRegistration.Email.ToLower()); + if (isUserExist) + { + return (false, "Email Address Already Registred"); + } + + var newUser = FromUserRegistrationModelToUserModel(userRegistration); + newUser.Password = HashPassword(newUser.Password); + + _browlAuthSecurityDbContext.User.Add(newUser); + await _browlAuthSecurityDbContext.SaveChangesAsync(); + return (true, "Success"); + } + + public bool CheckUserUniqueEmail(string email) + { + var userAlreadyExist = _browlAuthSecurityDbContext.User.Any(_ => _.Email.ToLower() == email.ToLower()); + return !userAlreadyExist; + } + + private bool PasswordVerification(string plainPassword, string dbPassword) + { + var dbPasswordHash = Convert.FromBase64String(dbPassword); + + var salt = new byte[16]; + Array.Copy(dbPasswordHash, 0, salt, 0, 16); + + var rfcPassord = new Rfc2898DeriveBytes(plainPassword, salt, 1000, HashAlgorithmName.SHA1); + var rfcPasswordHash = rfcPassord.GetBytes(20); + + for (var i = 0; i < rfcPasswordHash.Length; i++) + { + if (dbPasswordHash[i + 16] != rfcPasswordHash[i]) + { + return false; + } + } + return true; + } + + private string GenerateJwtToken(User user) + { + var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenSettings.SecretKey)); + + var credentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256); + + var cliams = new List(); + cliams.Add(new Claim("Sub", user.Id.ToString())); + cliams.Add(new Claim("FirstName", user.FirstName)); + cliams.Add(new Claim("LastName", user.LastName)); + cliams.Add(new Claim("Email", user.Email)); + + var securityToken = new JwtSecurityToken( + issuer: _tokenSettings.Issuer, + audience: _tokenSettings.Audience, + expires: DateTime.Now.AddMinutes(30), + signingCredentials: credentials, + claims: cliams); + + return new JwtSecurityTokenHandler().WriteToken(securityToken); + } + + public async Task<(bool IsLoginSuccess, JWTTokenResponseResource TokeResponse)> LoginAsync(LoginResource loginPayload) + { + if (string.IsNullOrEmpty(loginPayload.Email) || string.IsNullOrEmpty(loginPayload.Password)) + { + return (false, null); + } + + var user = await _browlAuthSecurityDbContext.User.Where(_ => _.Email.ToLower() == loginPayload.Email.ToLower()).FirstOrDefaultAsync(); + + if (user == null) { return (false, null); } + + var validPassword = PasswordVerification(loginPayload.Password, user.Password); + if (!validPassword) { return (false, null); } + + var jwtAccessToken = GenerateJwtToken(user); + + var result = new JWTTokenResponseResource + { + AccessToken = jwtAccessToken, + }; + return (true, result); + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Shared/Settings/TokenSettings.cs b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Shared/Settings/TokenSettings.cs new file mode 100644 index 0000000..259d5dd --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/Shared/Settings/TokenSettings.cs @@ -0,0 +1,8 @@ +namespace Browl.Service.AuthSecurity.API.Shared.Settings; + +public class TokenSettings +{ + public string SecretKey { get; set; } + public string Issuer { get; set; } + public string Audience { get; set; } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/appsettings.Development.json b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/appsettings.Development.json new file mode 100644 index 0000000..c0c56cc --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/appsettings.Development.json @@ -0,0 +1,18 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=BrowlServiceAuthSecurityDB;Integrated Security=True" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AppSettings": { + "Secret": "MySuperSecretBrowlBrowlServiceAuthSecurityAPI", + "ExpiracaoHoras": 2, + "Emissor": "BrowlServiceAuthSecurityAPI", + "ValidoEm": "https://localhost" + } +} diff --git a/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/appsettings.json b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/appsettings.json new file mode 100644 index 0000000..c166af5 --- /dev/null +++ b/src/Services/Browl.Service.AuthSecurity/Browl.Service.AuthSecurity.API/appsettings.json @@ -0,0 +1,28 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Server=NB-RONDINELE;Database=BrowlDB;Trusted_Connection=True;MultipleActiveResultSets=true" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AppSettings": { + "Secret": "MySuperSecretBrowlBrowlServiceAuthSecurityAPI", + "ExpiracaoHoras": 2, + "Emissor": "Browl.Service.AuthSecurity.API", + "ValidoEm": "https://localhost" + }, + "JWT": { + "Key": "This is my supper secret key for jwt", + "Issuer": "https://localhost", + "Audience": "https://localhost" + }, + "TokenSettings": { + "SecretKey": "hY8VrXxCSaSC447XIwZOXPK5PqI0BC3tmZgJfp77", + "Issuer": "localhost:1401", + "Audience": "localhost:1400" + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Browl.Service.MarketDataCollector.API.csproj b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Browl.Service.MarketDataCollector.API.csproj index de99f08..bc9ad01 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Browl.Service.MarketDataCollector.API.csproj +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Browl.Service.MarketDataCollector.API.csproj @@ -10,7 +10,6 @@ - diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/AutoMapperConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/AutoMapperConfiguration.cs index 264e641..8a2d4de 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/AutoMapperConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/AutoMapperConfiguration.cs @@ -1,14 +1,14 @@ using Browl.Service.MarketDataCollector.Application.Mappings; -namespace Browl.Service.MarketDataCollector.Configuration; +namespace Browl.Service.MarketDataCollector.API.Configurations; public static class AutoMapperConfiguration { - public static void AddAutoMapperConfiguration(this IServiceCollection services) - { - services.AddAutoMapper( - typeof(NovoClienteMappingProfile), - typeof(AlteraClienteMappingProfile), - typeof(UsuarioMappingProfile)); - } -} \ No newline at end of file + public static void AddAutoMapperConfiguration(this IServiceCollection services) + { + services.AddAutoMapper( + typeof(CustomerNewProfile), + typeof(CustomerUpdateProfile), + typeof(UserProfile)); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DataBaseConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DataBaseConfiguration.cs index 3428b9e..ec20a1a 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DataBaseConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DataBaseConfiguration.cs @@ -1,20 +1,19 @@ using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; + using Microsoft.EntityFrameworkCore; -namespace Browl.Service.MarketDataCollector.Configuration; +namespace Browl.Service.MarketDataCollector.API.Configurations; public static class DataBaseConfiguration { - public static void AddDatabaseConfiguration(this IServiceCollection services, IConfiguration configuration) - { - services.AddDbContext(options => options.UseSqlServer(configuration.GetConnectionString("SQLConnection"))); - services.AddDbContext(options => { options.UseInMemoryDatabase(configuration.GetConnectionString("memory") ?? "data-in-memory"); }); - } + public static void AddDatabaseConfiguration(this IServiceCollection services, IConfiguration configuration) + { + _ = services.AddDbContext(options => options.UseSqlServer(configuration.GetConnectionString("SQLConnection"))); + _ = services.AddDbContext(options => { _ = options.UseInMemoryDatabase(configuration.GetConnectionString("memory") ?? "data-in-memory"); }); + } - public static void UseDatabaseConfiguration(this IApplicationBuilder app) - { - using var serviceScope = app.ApplicationServices.GetRequiredService().CreateScope(); - using var context = serviceScope.ServiceProvider.GetService(); - //context.Database.Migrate(); - // context.Database.EnsureCreated(); - } -} \ No newline at end of file + public static void UseDatabaseConfiguration(this IApplicationBuilder app) + { + using var serviceScope = app.ApplicationServices.GetRequiredService().CreateScope(); + using var context = serviceScope.ServiceProvider.GetService(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DependencyInjectionConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DependencyInjectionConfiguration.cs index 8d62ba5..92a6b8b 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DependencyInjectionConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/DependencyInjectionConfiguration.cs @@ -7,28 +7,28 @@ using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; using Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; -namespace Browl.Service.MarketDataCollector.Configuration; +namespace Browl.Service.MarketDataCollector.API.Configurations; public static class DependencyInjectionConfiguration { - public static void AddDependencyInjectionConfiguration(this IServiceCollection services, IConfiguration configuration) - { - services.AddScoped(); - services.AddScoped(); - services.Configure(configuration.GetSection(nameof(TenantSettings))); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.Configure(options => options.LowercaseUrls = true); - services.AddControllers().ConfigureApiBehaviorOptions(options => - { - options.InvalidModelStateResponseFactory = InvalidModelStateResponse.ProduceErrorResponse; - }); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - } -} \ No newline at end of file + public static void AddDependencyInjectionConfiguration(this IServiceCollection services, IConfiguration configuration) + { + services.AddScoped(); + services.AddScoped(); + services.Configure(configuration.GetSection(nameof(TenantSettings))); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.Configure(options => options.LowercaseUrls = true); + services.AddControllers().ConfigureApiBehaviorOptions(options => + { + options.InvalidModelStateResponseFactory = InvalidModelStateResponse.ProduceErrorResponse; + }); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/FluentValidationConfig.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/FluentValidationConfig.cs index c8096dd..06dae31 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/FluentValidationConfig.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/FluentValidationConfig.cs @@ -1,33 +1,37 @@ -using Browl.Service.MarketDataCollector.Application.Validator; +using System.Globalization; +using System.Text.Json.Serialization; + +using Browl.Service.MarketDataCollector.Application.Validator; + using FluentValidation.AspNetCore; + using MicroElements.Swashbuckle.FluentValidation.AspNetCore; + using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using System.Globalization; -using System.Text.Json.Serialization; namespace Browl.Service.MarketDataCollector.API.Configurations; public static class FluentValidationConfig { - public static void AddFluentValidationConfiguration(this IServiceCollection services) - { - services.AddControllers() - .AddNewtonsoftJson(x => - { - x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - x.SerializerSettings.Converters.Add(new StringEnumConverter()); - }) - .AddJsonOptions(p => p.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())) - .AddFluentValidation(p => - { - p.RegisterValidatorsFromAssemblyContaining(); - p.RegisterValidatorsFromAssemblyContaining(); - p.RegisterValidatorsFromAssemblyContaining(); - p.RegisterValidatorsFromAssemblyContaining(); - p.ValidatorOptions.LanguageManager.Culture = new CultureInfo("pt-BR"); - }); + public static void AddFluentValidationConfiguration(this IServiceCollection services) + { + services.AddControllers() + .AddNewtonsoftJson(x => + { + x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + x.SerializerSettings.Converters.Add(new StringEnumConverter()); + }) + .AddJsonOptions(p => p.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())) + .AddFluentValidation(p => + { + p.RegisterValidatorsFromAssemblyContaining(); + p.RegisterValidatorsFromAssemblyContaining(); + p.RegisterValidatorsFromAssemblyContaining(); + p.RegisterValidatorsFromAssemblyContaining(); + p.ValidatorOptions.LanguageManager.Culture = new CultureInfo("pt-BR"); + }); - services.AddFluentValidationRulesToSwagger(); - } -} \ No newline at end of file + _ = services.AddFluentValidationRulesToSwagger(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/JwtConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/JwtConfiguration.cs index 4dd691d..6dd62f9 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/JwtConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/JwtConfiguration.cs @@ -1,44 +1,43 @@ -using Browl.Service.MarketDataCollector.Application.Services; -using Browl.Service.MarketDataCollector.Infrastructure.Services; +using System.Text; + using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; -using System.Text; -namespace Browl.Service.MarketDataCollector.Configuration; +namespace Browl.Service.MarketDataCollector.API.Configurations; public static class JwtConfiguration { - public static void AddJwtTConfiguration(this IServiceCollection services, IConfiguration configuration) - { - // services.AddSingleton(); + public static void AddJwtTConfiguration(this IServiceCollection services, IConfiguration configuration) + { + // services.AddSingleton(); - var chave = Encoding.ASCII.GetBytes(configuration.GetSection("JWT:Secret").Value); + var chave = Encoding.ASCII.GetBytes(configuration.GetSection("JWT:Secret").Value); - services.AddAuthentication(p => - { - p.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - p.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(p => - { - p.RequireHttpsMetadata = false; - p.SaveToken = true; - p.TokenValidationParameters = new TokenValidationParameters - { - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(chave), - ValidateIssuer = true, - ValidIssuer = configuration.GetSection("JWT:Issuer").Value, - ValidateAudience = true, - ValidAudience = configuration.GetSection("JWT:Audience").Value, - ValidateLifetime = true - }; - }); - } + _ = services.AddAuthentication(p => + { + p.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + p.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(p => + { + p.RequireHttpsMetadata = false; + p.SaveToken = true; + p.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(chave), + ValidateIssuer = true, + ValidIssuer = configuration.GetSection("JWT:Issuer").Value, + ValidateAudience = true, + ValidAudience = configuration.GetSection("JWT:Audience").Value, + ValidateLifetime = true + }; + }); + } - public static void UseJwtConfiguration(this IApplicationBuilder app) - { - app.UseAuthentication(); - app.UseAuthorization(); - } -} \ No newline at end of file + public static void UseJwtConfiguration(this IApplicationBuilder app) + { + _ = app.UseAuthentication(); + _ = app.UseAuthorization(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/InvalidModelStateResponse.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/InvalidModelStateResponse.cs index 60f3da3..7617196 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/InvalidModelStateResponse.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/InvalidModelStateResponse.cs @@ -1,17 +1,17 @@ -using Browl.Service.MarketDataCollector.Application.Resources; -using Browl.Service.MarketDataCollector.Domain.Extensions; +using Browl.Service.MarketDataCollector.API.Extensions; +using Browl.Service.MarketDataCollector.Domain.Resources.Erro; + using Microsoft.AspNetCore.Mvc; -namespace Browl.Service.MarketDataCollector.API.Configurations.MainController +namespace Browl.Service.MarketDataCollector.API.Configurations.MainController; + +public static class InvalidModelStateResponse { - public static class InvalidModelStateResponse - { - public static IActionResult ProduceErrorResponse(ActionContext context) - { - var errors = context.ModelState.GetErrorMessages(); - var response = new ErrorResource(messages: errors); + public static IActionResult ProduceErrorResponse(ActionContext context) + { + var errors = context.ModelState.GetErrorMessages(); + ErrorResource response = new(messages: errors); - return new BadRequestObjectResult(response); - } - } + return new BadRequestObjectResult(response); + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/MainController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/MainController.cs index c9fc7e3..db7f5d6 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/MainController.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/MainController/MainController.cs @@ -1,11 +1,10 @@ using Microsoft.AspNetCore.Mvc; -namespace Browl.Service.MarketDataCollector.API.Configurations.BaseApiController +namespace Browl.Service.MarketDataCollector.API.Configurations.MainController; + +[Route("/api/[controller]")] +[Produces("application/json")] +[ApiController] +public abstract class MainController : ControllerBase { - [Route("/api/[controller]")] - [Produces("application/json")] - [ApiController] - public abstract class MainController : ControllerBase - { - } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/SwaggerConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/SwaggerConfiguration.cs index b7510c1..17f94ef 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/SwaggerConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Configurations/SwaggerConfiguration.cs @@ -1,71 +1,72 @@ -using Microsoft.OpenApi.Models; -using System.Reflection; +using System.Reflection; -namespace Browl.Service.MarketDataCollector.Configuration; +using Microsoft.OpenApi.Models; + +namespace Browl.Service.MarketDataCollector.API.Configurations; public static class SwaggerConfiguration { - public static IServiceCollection AddSwaggerConfiguration(this IServiceCollection services) - { - services.AddSwaggerGen(configuration => - { - configuration.SwaggerDoc("v1", new OpenApiInfo - { - Title = "Browl", - Version = "v1", - Description = "API for Market Data Collection", - Contact = new OpenApiContact - { - Name = "Rondinele Guimarães", - Email = "rondineleg@gmail.com", - Url = new Uri("https://github.com/rondineleg") - }, - License = new OpenApiLicense - { - Name = "MIT", - Url = new Uri("https://www.mit.edu/~amini/LICENSE.md") - }, - TermsOfService = new Uri("https://www.mit.edu/~amini/LICENSE.md") - }); + public static IServiceCollection AddSwaggerConfiguration(this IServiceCollection services) + { + _ = services.AddSwaggerGen(configuration => + { + configuration.SwaggerDoc("v1", new OpenApiInfo + { + Title = "Browl", + Version = "v1", + Description = "API for Market Data Collection", + Contact = new OpenApiContact + { + Name = "Rondinele Guimarães", + Email = "rondineleg@gmail.com", + Url = new Uri("https://github.com/rondineleg") + }, + License = new OpenApiLicense + { + Name = "MIT", + Url = new Uri("https://www.mit.edu/~amini/LICENSE.md") + }, + TermsOfService = new Uri("https://www.mit.edu/~amini/LICENSE.md") + }); - var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - configuration.IncludeXmlComments(xmlPath); + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + configuration.IncludeXmlComments(xmlPath); - configuration.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - { - In = ParameterLocation.Header, - Description = "Token", - Name = "Authorization", - Type = SecuritySchemeType.ApiKey - }); + configuration.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + In = ParameterLocation.Header, + Description = "Token", + Name = "Authorization", + Type = SecuritySchemeType.ApiKey + }); - configuration.AddSecurityRequirement(new OpenApiSecurityRequirement { - { - new OpenApiSecurityScheme - { - Reference= new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id ="Bearer" - } - }, - Array.Empty() - } - }); + configuration.AddSecurityRequirement(new OpenApiSecurityRequirement { + { + new OpenApiSecurityScheme + { + Reference= new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id ="Bearer" + } + }, + Array.Empty() + } + }); - }); - return services; - } + }); + return services; + } - public static IApplicationBuilder UseSwaggerConfiguration(this IApplicationBuilder app) - { - app.UseSwagger().UseSwaggerUI(options => - { - options.SwaggerEndpoint("/swagger/v1/swagger.json", "Browl.Service.MarketDataCollector.API"); - options.DocumentTitle = "Browl.Service.MarketDataCollector.API"; - }); - return app; - } + public static IApplicationBuilder UseSwaggerConfiguration(this IApplicationBuilder app) + { + _ = app.UseSwagger().UseSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/v1/swagger.json", "Browl.Service.MarketDataCollector.API"); + options.DocumentTitle = "Browl.Service.MarketDataCollector.API"; + }); + return app; + } } diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/CategoriesController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/CategoriesController.cs index f78ead6..a0a5db3 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/CategoriesController.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/CategoriesController.cs @@ -1,99 +1,101 @@ using AutoMapper; -using Browl.Service.MarketDataCollector.API.Configurations.BaseApiController; -using Browl.Service.MarketDataCollector.Application.Resources; + +using Browl.Service.MarketDataCollector.API.Configurations.MainController; using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; +using Browl.Service.MarketDataCollector.Domain.Resources.Category; +using Browl.Service.MarketDataCollector.Domain.Resources.Erro; + using Microsoft.AspNetCore.Mvc; -namespace Browl.Service.MarketDataCollector.API.Controllers +namespace Browl.Service.MarketDataCollector.API.Controllers; + +public class CategoriesController : MainController { - public class CategoriesController : MainController - { - private readonly ICategoryService _categoryService; - private readonly IMapper _mapper; + private readonly ICategoryService _categoryService; + private readonly IMapper _mapper; - public CategoriesController(ICategoryService categoryService, IMapper mapper) - { - _categoryService = categoryService; - _mapper = mapper; - } + public CategoriesController(ICategoryService categoryService, IMapper mapper) + { + _categoryService = categoryService; + _mapper = mapper; + } - /// - /// Lists all categories. - /// - /// List os categories. - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), 200)] - public async Task> ListAsync() - { - var categories = await _categoryService.ListAsync(); - return _mapper.Map>(categories); - } + /// + /// Lists all categories. + /// + /// List os categories. + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), 200)] + public async Task> ListAsync() + { + var categories = await _categoryService.ListAsync(); + return _mapper.Map>(categories); + } - /// - /// Saves a new category. - /// - /// Category data. - /// Response for the request. - [HttpPost] - [ProducesResponseType(typeof(CategoryResource), 201)] - [ProducesResponseType(typeof(ErrorResource), 400)] - public async Task PostAsync([FromBody] SaveCategoryResource resource) - { - var category = _mapper.Map(resource); - var result = await _categoryService.SaveAsync(category); + /// + /// Saves a new category. + /// + /// Category data. + /// Response for the request. + [HttpPost] + [ProducesResponseType(typeof(CategoryResource), 201)] + [ProducesResponseType(typeof(ErrorResource), 400)] + public async Task PostAsync([FromBody] CategorySaveResource resource) + { + var category = _mapper.Map(resource); + var result = await _categoryService.SaveAsync(category); - if (!result.Success) - { - return BadRequest(new ErrorResource(result.Message!)); - } + if (!result.Success) + { + return BadRequest(new ErrorResource(result.Message!)); + } - var categoryResource = _mapper.Map(result.Resource!); - return Ok(categoryResource); - } + var categoryResource = _mapper.Map(result.Resource!); + return Ok(categoryResource); + } - /// - /// Updates an existing category according to an identifier. - /// - /// Category identifier. - /// Updated category data. - /// Response for the request. - [HttpPut("{id}")] - [ProducesResponseType(typeof(CategoryResource), 200)] - [ProducesResponseType(typeof(ErrorResource), 400)] - public async Task PutAsync(int id, [FromBody] SaveCategoryResource resource) - { - var category = _mapper.Map(resource); - var result = await _categoryService.UpdateAsync(id, category); + /// + /// Updates an existing category according to an identifier. + /// + /// Category identifier. + /// Updated category data. + /// Response for the request. + [HttpPut("{id}")] + [ProducesResponseType(typeof(CategoryResource), 200)] + [ProducesResponseType(typeof(ErrorResource), 400)] + public async Task PutAsync(int id, [FromBody] CategorySaveResource resource) + { + var category = _mapper.Map(resource); + var result = await _categoryService.UpdateAsync(id, category); - if (!result.Success) - { - return BadRequest(new ErrorResource(result.Message!)); - } + if (!result.Success) + { + return BadRequest(new ErrorResource(result.Message!)); + } - var categoryResource = _mapper.Map(result.Resource!); - return Ok(categoryResource); - } + var categoryResource = _mapper.Map(result.Resource!); + return Ok(categoryResource); + } - /// - /// Deletes a given category according to an identifier. - /// - /// Category identifier. - /// Response for the request. - [HttpDelete("{id}")] - [ProducesResponseType(typeof(CategoryResource), 200)] - [ProducesResponseType(typeof(ErrorResource), 400)] - public async Task DeleteAsync(int id) - { - var result = await _categoryService.DeleteAsync(id); + /// + /// Deletes a given category according to an identifier. + /// + /// Category identifier. + /// Response for the request. + [HttpDelete("{id}")] + [ProducesResponseType(typeof(CategoryResource), 200)] + [ProducesResponseType(typeof(ErrorResource), 400)] + public async Task DeleteAsync(int id) + { + var result = await _categoryService.DeleteAsync(id); - if (!result.Success) - { - return BadRequest(new ErrorResource(result.Message!)); - } + if (!result.Success) + { + return BadRequest(new ErrorResource(result.Message!)); + } - var categoryResource = _mapper.Map(result.Resource!); - return Ok(categoryResource); - } - } -} \ No newline at end of file + var categoryResource = _mapper.Map(result.Resource!); + return Ok(categoryResource); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ClientesController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ClientesController.cs deleted file mode 100644 index c57b20f..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ClientesController.cs +++ /dev/null @@ -1,113 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; -using Microsoft.AspNetCore.Mvc; -using SerilogTimings; - -namespace Browl.Service.MarketDataCollector.Controller; - -[Route("api/[controller]")] -[ApiController] -public class ClientesController : ControllerBase -{ - private readonly IClienteManager clienteManager; - private readonly ILogger logger; - - public ClientesController(IClienteManager clienteManager, ILogger logger) - { - this.clienteManager = clienteManager; - this.logger = logger; - } - - /// - /// Retorna todos clientes cadastrados na base. - /// - [HttpGet] - [ProducesResponseType(typeof(ClienteView), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] - public async Task Get() - { - var clientes = await clienteManager.GetClientesAsync(); - if (clientes.Any()) - { - return Ok(clientes); - } - return NotFound(); - } - - /// - /// Retorna um cliente consultado pelo id. - /// - /// Id do cliente. - [HttpGet("{id}")] - [ProducesResponseType(typeof(ClienteView), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] - public async Task Get(int id) - { - var cliente = await clienteManager.GetClienteAsync(id); - if (cliente.Id == 0) - { - return NotFound(); - } - return Ok(cliente); - } - - /// - /// Insere um novo cliente - /// - /// - [HttpPost] - [ProducesResponseType(typeof(ClienteView), StatusCodes.Status201Created)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] - public async Task Post(NovoCliente novoCliente) - { - logger.LogInformation("Objeto recebido {@novoCliente}", novoCliente); - - ClienteView clienteInserido; - using (Operation.Time("Tempo de adição de um novo cliente.")) - { - logger.LogInformation("Foi requisitada a inserção de um novo cliente."); - clienteInserido = await clienteManager.InsertClienteAsync(novoCliente); - } - return CreatedAtAction(nameof(Get), new { id = clienteInserido.Id }, clienteInserido); - } - - /// - /// Altera um cliente. - /// - /// - [HttpPut] - [ProducesResponseType(typeof(ClienteView), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] - public async Task Put(AlteraCliente alteraCliente) - { - var clienteAtualizado = await clienteManager.UpdateClienteAsync(alteraCliente); - if (clienteAtualizado == null) - { - return NotFound(); - } - return Ok(clienteAtualizado); - } - - /// - /// Exclui um cliente. - /// - /// Id do cliente - /// Ao excluir um cliente o mesmo será removido permanentemente da base. - [HttpDelete("{id}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] - [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] - public async Task Delete(int id) - { - var clienteExcliudo = await clienteManager.DeleteClienteAsync(id); - if (clienteExcliudo == null) - { - return NotFound(); - } - return NoContent(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/CustomersController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/CustomersController.cs new file mode 100644 index 0000000..3d79ec8 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/CustomersController.cs @@ -0,0 +1,116 @@ +using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +using Microsoft.AspNetCore.Mvc; + +using SerilogTimings; + +namespace Browl.Service.MarketDataCollector.Controller; + +[Route("api/[controller]")] +[ApiController] +public class CustomersController : ControllerBase +{ + private readonly ICustomerManager clienteManager; + private readonly ILogger logger; + + public CustomersController(ICustomerManager clienteManager, ILogger logger) + { + this.clienteManager = clienteManager; + this.logger = logger; + } + + /// + /// Lists all customers. + /// + /// List os customers. + [HttpGet] + [ProducesResponseType(typeof(CustomerViewResource), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task Get() + { + var clientes = await clienteManager.GetAsync(); + if (clientes.Any()) + { + return Ok(clientes); + } + return NotFound(); + } + + /// + /// Return customer searching by id. + /// + /// Id + [HttpGet("{id}")] + [ProducesResponseType(typeof(CustomerViewResource), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task Get(int id) + { + var cliente = await clienteManager.GetAsync(id); + if (cliente.Id == 0) + { + return NotFound(); + } + return Ok(cliente); + } + + /// + /// Create new customer + /// + /// + [HttpPost] + [ProducesResponseType(typeof(CustomerViewResource), StatusCodes.Status201Created)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task Post(CustomerResource customerResource) + { + logger.LogInformation("Objeto recebido {@novoCliente}", customerResource); + + CustomerViewResource clienteInserido; + using (Operation.Time("Tempo de adição de um novo cliente.")) + { + logger.LogInformation("Foi requisitada a inserção de um novo cliente."); + clienteInserido = await clienteManager.PostAsync(customerResource); + } + return CreatedAtAction(nameof(Get), new { id = clienteInserido.Id }, clienteInserido); + } + + /// + /// Update customer. + /// + /// + [HttpPut] + [ProducesResponseType(typeof(CustomerViewResource), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task Put(CustomerUpdateResource customerUpdateResource) + { + var clienteAtualizado = await clienteManager.PutAsync(customerUpdateResource); + if (clienteAtualizado == null) + { + return NotFound(); + } + return Ok(clienteAtualizado); + } + + /// + /// Delete customer. + /// + /// Id + /// When deleting a customer, it will be permanently removed from the base. + [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task Delete(int id) + { + var clienteExcliudo = await clienteManager.DeleteAsync(id); + if (clienteExcliudo == null) + { + return NotFound(); + } + return NoContent(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ErrorController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ErrorController.cs index cef4f8c..d1cec4b 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ErrorController.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ErrorController.cs @@ -1,18 +1,20 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Erro; +using Browl.Service.MarketDataCollector.Domain.Resources.Erro; + using Microsoft.AspNetCore.Mvc; + using System.Diagnostics; -namespace CL.WebApi.Controllers; +namespace Browl.Service.MarketDataCollector.API.Controllers; [ApiExplorerSettings(IgnoreApi = true)] [ApiController] public class ErrorController : ControllerBase { - [Route("error")] - public ErrorResponse Error() - { - Response.StatusCode = 500; - var id = Activity.Current?.Id ?? HttpContext?.TraceIdentifier; - return new ErrorResponse(id); - } -} \ No newline at end of file + [Route("error")] + public ErrorResponseResource Error() + { + Response.StatusCode = 500; + var id = Activity.Current?.Id ?? HttpContext?.TraceIdentifier; + return new ErrorResponseResource(id); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/HabitsController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/HabitsController.cs index 745df84..b9fed3d 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/HabitsController.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/HabitsController.cs @@ -1,11 +1,13 @@ using AutoMapper; -using Browl.Service.MarketDataCollector.Domain.Dtos.Habit; + using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; +using Browl.Service.MarketDataCollector.Domain.Resources.Habit; + using Microsoft.AspNetCore.JsonPatch; using Microsoft.AspNetCore.JsonPatch.Exceptions; using Microsoft.AspNetCore.Mvc; -namespace Browl.Service.MarketDataCollector.Controller; +namespace Browl.Service.MarketDataCollector.API.Controllers; [ApiController] @@ -14,85 +16,88 @@ namespace Browl.Service.MarketDataCollector.Controller; [ApiVersion("1.0")] public class HabitsController : ControllerBase { - private readonly ILogger _logger; - private readonly IHabitService _habitService; - private IMapper _mapper; - public HabitsController(ILogger logger, IHabitService habitService, IMapper mapper) - { - _logger = logger; - _habitService = habitService; - _mapper = mapper; - } - - - [MapToApiVersion("1.0")] - [HttpGet("version")] - public virtual async Task GetVersion() - { - return Ok("Response from version 1.0"); - } - - [HttpGet("{id}")] - public async Task GetAsync(int id) - { - return Ok(_mapper.Map(await _habitService.GetById(id))); - } - - [HttpGet] - public async Task GetAsync() - { - return Ok(_mapper.Map>(await _habitService.GetAll())); - } - - [HttpPost] - public async Task CreateAsync(CreateHabitDto request) - { - var habit = await _habitService.Create(request.Name, request.Description); - var habitDto = _mapper.Map(habit); - return CreatedAtAction("Get", "Habits", new - { - id = - habitDto.Id - }, habitDto); - } - - - [HttpPut("{id}")] - public async Task UpdateAsync(int id, UpdateHabitDto request) - { - var habit = await _habitService.UpdateById(id, request); - if (habit == null) return NotFound(); - return Ok(habit); - } - - [HttpPatch("{id}")] - public async Task UpdateAsync(int id, [FromBody] JsonPatchDocument patch) - { - var habit = await _habitService.GetById(id); - if (habit == null) return NotFound(); - var updateHabitDto = new UpdateHabitDto - { - Name = habit.Name, - Description = habit.Description - }; - try - { - patch.ApplyTo(updateHabitDto, ModelState); - if (!TryValidateModel(updateHabitDto)) return - ValidationProblem(ModelState); - await _habitService.UpdateById(id, updateHabitDto); - return NoContent(); - } - catch (JsonPatchException ex) - { - return BadRequest(new { error = ex.Message }); - } - } - - [HttpDelete("{id}")] - public async Task DeleteAsync(int id) - { - await _habitService.DeleteById(id); - return NoContent(); - } -} \ No newline at end of file + private readonly ILogger _logger; + private readonly IHabitService _habitService; + private readonly IMapper _mapper; + public HabitsController(ILogger logger, IHabitService habitService, IMapper mapper) + { + _logger = logger; + _habitService = habitService; + _mapper = mapper; + } + + + [MapToApiVersion("1.0")] + [HttpGet("version")] + public virtual IActionResult GetVersion() => Ok("Response from version 1.0"); + + [HttpGet("{id}")] + public async Task GetAsync(int id) => Ok(_mapper.Map(await _habitService.GetById(id))); + + + /// + /// Lists all habits. + /// + /// List os habits. + [HttpGet] + public async Task GetAsync() => Ok(_mapper.Map>(await _habitService.GetAll())); + + [HttpPost] + public async Task CreateAsync(CreateHabitResource request) + { + var habit = await _habitService.Create(request.Name, request.Description); + var habitDto = _mapper.Map(habit); + return CreatedAtAction("Get", "Habits", new + { + id = + habitDto.Id + }, habitDto); + } + + + [HttpPut("{id}")] + public async Task UpdateAsync(int id, UpdateHabitResource request) + { + var habit = await _habitService.UpdateById(id, request); + return habit == null ? NotFound() : Ok(habit); + } + + [HttpPatch("{id}")] + public async Task UpdateAsync(int id, [FromBody] JsonPatchDocument patch) + { + var habit = await _habitService.GetById(id); + if (habit == null) + { + return NotFound(); + } + + UpdateHabitResource updateHabitDto = new() + { + Name = habit.Name, + Description = habit.Description + }; + try + { + patch.ApplyTo(updateHabitDto, ModelState); + if (!TryValidateModel(updateHabitDto)) + { + return + ValidationProblem(ModelState); + } + + _ = await _habitService.UpdateById(id, updateHabitDto); + return NoContent(); + } + catch (JsonPatchException ex) + { + return BadRequest(new { error = ex.Message }); + } + } + + [HttpDelete("{id}")] + public async Task DeleteAsync(int id) + { + await _habitService.DeleteById(id); + return NoContent(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ProductsController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ProductsController.cs index 938ab0f..4ce9b05 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ProductsController.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/ProductsController.cs @@ -1,102 +1,106 @@ using AutoMapper; -using Browl.Service.MarketDataCollector.API.Configurations.BaseApiController; + +using Browl.Service.MarketDataCollector.API.Configurations.MainController; using Browl.Service.MarketDataCollector.Application.Resources; using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; using Browl.Service.MarketDataCollector.Domain.Queries; +using Browl.Service.MarketDataCollector.Domain.Resources.Erro; +using Browl.Service.MarketDataCollector.Domain.Resources.Product; +using Browl.Service.MarketDataCollector.Domain.Resources.Query; + using Microsoft.AspNetCore.Mvc; -namespace Browl.Service.MarketDataCollector.API.Controllers +namespace Browl.Service.MarketDataCollector.API.Controllers; + +public class ProductsController : MainController { - public class ProductsController : MainController - { - private readonly IProductService _productService; - private readonly IMapper _mapper; - - public ProductsController(IProductService productService, IMapper mapper) - { - _productService = productService; - _mapper = mapper; - } - - /// - /// Lists all existing products according to query filters. - /// - /// List of products. - [HttpGet] - [ProducesResponseType(typeof(QueryResultResource), 200)] - public async Task> ListAsync([FromQuery] ProductsQueryResource query) - { - var productsQuery = _mapper.Map(query); - var queryResult = await _productService.ListAsync(productsQuery); - - return _mapper.Map>(queryResult); - } - - /// - /// Saves a new product. - /// - /// Product data. - /// Response for the request. - [HttpPost] - [ProducesResponseType(typeof(ProductResource), 201)] - [ProducesResponseType(typeof(ErrorResource), 400)] - public async Task PostAsync([FromBody] SaveProductResource resource) - { - var product = _mapper.Map(resource); - var result = await _productService.SaveAsync(product); - - if (!result.Success) - { - return BadRequest(new ErrorResource(result.Message!)); - } - - var productResource = _mapper.Map(result.Resource!); - return Ok(productResource); - } - - /// - /// Updates an existing product according to an identifier. - /// - /// Product identifier. - /// Product data. - /// Response for the request. - [HttpPut("{id}")] - [ProducesResponseType(typeof(ProductResource), 201)] - [ProducesResponseType(typeof(ErrorResource), 400)] - public async Task PutAsync(int id, [FromBody] SaveProductResource resource) - { - var product = _mapper.Map(resource); - var result = await _productService.UpdateAsync(id, product); - - if (!result.Success) - { - return BadRequest(new ErrorResource(result.Message!)); - } - - var productResource = _mapper.Map(result.Resource!); - return Ok(productResource); - } - - /// - /// Deletes a given product according to an identifier. - /// - /// Product identifier. - /// Response for the request. - [HttpDelete("{id}")] - [ProducesResponseType(typeof(ProductResource), 200)] - [ProducesResponseType(typeof(ErrorResource), 400)] - public async Task DeleteAsync(int id) - { - var result = await _productService.DeleteAsync(id); - - if (!result.Success) - { - return BadRequest(new ErrorResource(result.Message!)); - } - - var categoryResource = _mapper.Map(result.Resource!); - return Ok(categoryResource); - } - } -} \ No newline at end of file + private readonly IProductService _productService; + private readonly IMapper _mapper; + + public ProductsController(IProductService productService, IMapper mapper) + { + _productService = productService; + _mapper = mapper; + } + + /// + /// Lists all existing products according to query filters. + /// + /// List of products. + [HttpGet] + [ProducesResponseType(typeof(QueryResultResource), 200)] + public async Task> GetAsync([FromQuery] ProductsQueryResource query) + { + var productsQuery = _mapper.Map(query); + var queryResult = await _productService.ListAsync(productsQuery); + + return _mapper.Map>(queryResult); + } + + /// + /// Saves a new product. + /// + /// Product data. + /// Response for the request. + [HttpPost] + [ProducesResponseType(typeof(ProductResource), 201)] + [ProducesResponseType(typeof(ErrorResource), 400)] + public async Task PostAsync([FromBody] ProductSaveResource resource) + { + var product = _mapper.Map(resource); + var result = await _productService.SaveAsync(product); + + if (!result.Success) + { + return BadRequest(new ErrorResource(result.Message!)); + } + + var productResource = _mapper.Map(result.Resource!); + return Ok(productResource); + } + + /// + /// Updates an existing product according to an identifier. + /// + /// Product identifier. + /// Product data. + /// Response for the request. + [HttpPut("{id}")] + [ProducesResponseType(typeof(ProductResource), 201)] + [ProducesResponseType(typeof(ErrorResource), 400)] + public async Task PutAsync(int id, [FromBody] ProductSaveResource resource) + { + var product = _mapper.Map(resource); + var result = await _productService.UpdateAsync(id, product); + + if (!result.Success) + { + return BadRequest(new ErrorResource(result.Message!)); + } + + var productResource = _mapper.Map(result.Resource!); + return Ok(productResource); + } + + /// + /// Deletes a given product according to an identifier. + /// + /// Product identifier. + /// Response for the request. + [HttpDelete("{id}")] + [ProducesResponseType(typeof(ProductResource), 200)] + [ProducesResponseType(typeof(ErrorResource), 400)] + public async Task DeleteAsync(int id) + { + var result = await _productService.DeleteAsync(id); + + if (!result.Success) + { + return BadRequest(new ErrorResource(result.Message!)); + } + + var categoryResource = _mapper.Map(result.Resource!); + return Ok(categoryResource); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/UsersController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/UsersController.cs new file mode 100644 index 0000000..e9b1f4b --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/UsersController.cs @@ -0,0 +1,52 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; +using Browl.Service.MarketDataCollector.Domain.Resources.User; + +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Browl.Service.MarketDataCollector.Controller; +[Route("api/[controller]")] +[ApiController] +public class UsersController : ControllerBase +{ + private readonly IUserManager manager; + + public UsersController(IUserManager manager) + { + this.manager = manager; + } + + [HttpGet] + [Route("Login")] + public async Task Login([FromBody] User usuario) + { + var usuarioLogado = await manager.ValidaUsuarioEGeraTokenAsync(usuario); + if (usuarioLogado != null) + { + return Ok(usuarioLogado); + } + return Unauthorized(); + } + + + /// + /// Lists all users. + /// + /// List os users. + [Authorize(Roles = "Presidente, Lider")] + [HttpGet] + public async Task Get() + { + string login = User.Identity.Name; + var usuario = await manager.GetAsync(login); + return Ok(usuario); + } + + [HttpPost] + public async Task Post(UserNewResource usuario) + { + var usuarioInserido = await manager.InsertAsync(usuario); + return CreatedAtAction(nameof(Get), new { login = usuario.Login }, usuarioInserido); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/UsuariosController.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/UsuariosController.cs deleted file mode 100644 index 454a8c5..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Controllers/UsuariosController.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; -using Browl.Service.MarketDataCollector.Domain.Entities; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -namespace Browl.Service.MarketDataCollector.Controller; - -[Route("api/[controller]")] -[ApiController] -public class UsuariosController : ControllerBase -{ - private readonly IUsuarioManager manager; - - public UsuariosController(IUsuarioManager manager) - { - this.manager = manager; - } - - [HttpGet] - [Route("Login")] - public async Task Login([FromBody] Usuario usuario) - { - var usuarioLogado = await manager.ValidaUsuarioEGeraTokenAsync(usuario); - if (usuarioLogado != null) - { - return Ok(usuarioLogado); - } - return Unauthorized(); - } - - [Authorize(Roles = "Presidente, Lider")] - [HttpGet] - public async Task Get() - { - string login = User.Identity.Name; - var usuario = await manager.GetAsync(login); - return Ok(usuario); - } - - [HttpPost] - public async Task Post(NovoUsuario usuario) - { - var usuarioInserido = await manager.InsertAsync(usuario); - return CreatedAtAction(nameof(Get), new { login = usuario.Login }, usuarioInserido); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ModelStateExtensions.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ModelStateExtensions.cs index ff653ea..bb476c8 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ModelStateExtensions.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ModelStateExtensions.cs @@ -1,14 +1,8 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; -namespace Browl.Service.MarketDataCollector.Domain.Extensions +namespace Browl.Service.MarketDataCollector.API.Extensions; + +public static class ModelStateExtensions { - public static class ModelStateExtensions - { - public static List GetErrorMessages(this ModelStateDictionary dictionary) - { - return dictionary.SelectMany(m => m.Value!.Errors) - .Select(m => m.ErrorMessage) - .ToList(); - } - } -} \ No newline at end of file + public static List GetErrorMessages(this ModelStateDictionary dictionary) => dictionary.SelectMany(m => m.Value!.Errors).Select(m => m.ErrorMessage).ToList(); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ServiceCollectionExtensions.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ServiceCollectionExtensions.cs index 88f3f03..022cf72 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ServiceCollectionExtensions.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Extensions/ServiceCollectionExtensions.cs @@ -1,44 +1,37 @@ using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; + using Microsoft.EntityFrameworkCore; namespace Browl.Service.MarketDataCollector.API.Extensions; public static class ServiceCollectionExtensions { - public static IServiceCollection AddAndMigrateDatabases(this IServiceCollection services, IConfiguration config) - { - var options = services.GetOptions(nameof(TenantSettings)); - var defaultConnectionString = options.DefaultConnectionString; - services.AddDbContext(m => m.UseSqlServer(e => e.MigrationsAssembly(typeof(BrowlDbContext).Assembly.FullName))); - var tenants = options.Tenants; - foreach (var tenant in tenants) - { - string connectionString; - if (string.IsNullOrEmpty(tenant.ConnectionString)) - { - connectionString = defaultConnectionString; - } - else - { - connectionString = tenant.ConnectionString; - } - using var scope = services - .BuildServiceProvider().CreateScope(); - var dbContext = scope.ServiceProvider.GetRequiredService(); - dbContext.Database.SetConnectionString(connectionString); - if (dbContext.Database.GetMigrations().Count() > 0) - { - //dbContext.Database.Migrate(); - } - } - return services; - } - public static T GetOptions(this IServiceCollection services, string sectionName) where T : new() - { - using var serviceProvider = services.BuildServiceProvider(); - var configuration = serviceProvider.GetRequiredService(); - var section = configuration.GetSection(sectionName); - var options = new T(); - section.Bind(options); - return options; - } + public static IServiceCollection AddAndMigrateDatabases(this IServiceCollection services, IConfiguration config) + { + var options = services.GetOptions(nameof(TenantSettings)); + var defaultConnectionString = options.DefaultConnectionString; + _ = services.AddDbContext(m => m.UseSqlServer(e => e.MigrationsAssembly(typeof(BrowlDbContext).Assembly.FullName))); + var tenants = options.Tenants; + foreach (var tenant in tenants) + { + var connectionString = string.IsNullOrEmpty(tenant.ConnectionString) ? defaultConnectionString : tenant.ConnectionString; + using var scope = services + .BuildServiceProvider().CreateScope(); + var dbContext = scope.ServiceProvider.GetRequiredService(); + dbContext.Database.SetConnectionString(connectionString); + if (dbContext.Database.GetMigrations().Count() > 0) + { + //dbContext.Database.Migrate(); + } + } + return services; + } + public static T GetOptions(this IServiceCollection services, string sectionName) where T : new() + { + using var serviceProvider = services.BuildServiceProvider(); + var configuration = serviceProvider.GetRequiredService(); + var section = configuration.GetSection(sectionName); + T options = new(); + section.Bind(options); + return options; + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Program.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Program.cs index 40056d5..b685d9a 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Program.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Program.cs @@ -1,21 +1,22 @@ using Browl.Service.MarketDataCollector.API.Configurations; using Browl.Service.MarketDataCollector.API.Extensions; -using Browl.Service.MarketDataCollector.Configuration; + using Microsoft.AspNetCore.Mvc.Versioning; + using Serilog; var builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpContextAccessor(); builder.Services.AddApiVersioning(opt => { - opt.DefaultApiVersion = new - Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); - opt.AssumeDefaultVersionWhenUnspecified = true; - opt.ReportApiVersions = true; - opt.ApiVersionReader = ApiVersionReader.Combine(new - UrlSegmentApiVersionReader(), - new HeaderApiVersionReader("x-api-version"), - new MediaTypeApiVersionReader("x-api-version")); + opt.DefaultApiVersion = new + Microsoft.AspNetCore.Mvc.ApiVersion(1, 0); + opt.AssumeDefaultVersionWhenUnspecified = true; + opt.ReportApiVersions = true; + opt.ApiVersionReader = ApiVersionReader.Combine(new + UrlSegmentApiVersionReader(), + new HeaderApiVersionReader("x-api-version"), + new MediaTypeApiVersionReader("x-api-version")); }); builder.Services.AddDependencyInjectionConfiguration(builder.Configuration); builder.Services.AddAndMigrateDatabases(builder.Configuration); @@ -28,18 +29,18 @@ builder.Services.AddMemoryCache(); var ambiente = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); var configuration = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json") - .AddJsonFile($"appsettings.{ambiente}.json", optional: true) - .Build(); + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json") + .AddJsonFile($"appsettings.{ambiente}.json", optional: true) + .Build(); Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger(); builder.Host.UseSerilog((ctx, lc) => lc.WriteTo.Console()); var app = builder.Build(); if (app.Environment.IsDevelopment()) { - app.UseDeveloperExceptionPage(); - app.UseSwaggerConfiguration(); + _ = app.UseDeveloperExceptionPage(); + _ = app.UseSwaggerConfiguration(); } app.UseHttpsRedirection(); app.UseRouting(); diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Properties/launchSettings.json b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Properties/launchSettings.json index 863064d..940cbe6 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Properties/launchSettings.json +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.API/Properties/launchSettings.json @@ -24,7 +24,7 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "https://localhost:5001;http://localhost:5000" + "applicationUrl": "https://localhost:1401" } } } diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/ClienteManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/ClienteManager.cs deleted file mode 100644 index 11203ff..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/ClienteManager.cs +++ /dev/null @@ -1,59 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; -using Browl.Service.MarketDataCollector.Domain.Entities; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; -using Microsoft.Extensions.Logging; - -namespace Browl.Service.MarketDataCollector.Application.Implementation; - -public class ClienteManager : IClienteManager -{ - private readonly IClienteRepository clienteRepository; - private readonly IMapper mapper; - private readonly ILogger logger; - - public ClienteManager() - { - - } - public ClienteManager(IClienteRepository clienteRepository, IMapper mapper, ILogger logger) - { - this.clienteRepository = clienteRepository; - this.mapper = mapper; - this.logger = logger; - } - - public async Task> GetClientesAsync() - { - var clientes = await clienteRepository.GetClientesAsync(); - return mapper.Map, IEnumerable>(clientes); - } - - public async Task GetClienteAsync(int id) - { - var cliente = await clienteRepository.GetClienteAsync(id); - return mapper.Map(cliente); - } - - public async Task DeleteClienteAsync(int id) - { - var cliente = await clienteRepository.DeleteClienteAsync(id); - return mapper.Map(cliente); - } - - public async Task InsertClienteAsync(NovoCliente novoCliente) - { - logger.LogInformation("Chamada de negócio para inserir um cliente."); - var cliente = mapper.Map(novoCliente); - cliente = await clienteRepository.InsertClienteAsync(cliente); - return mapper.Map(cliente); - } - - public async Task UpdateClienteAsync(AlteraCliente alteraCliente) - { - var cliente = mapper.Map(alteraCliente); - cliente = await clienteRepository.UpdateClienteAsync(cliente); - return mapper.Map(cliente); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/CustomerManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/CustomerManager.cs new file mode 100644 index 0000000..5aa1196 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/CustomerManager.cs @@ -0,0 +1,57 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +using Microsoft.Extensions.Logging; + +namespace Browl.Service.MarketDataCollector.Application.Implementation; + +public class CustomerManager : ICustomerManager +{ + private readonly ICustomerRepository _customerRepository; + private readonly IMapper _mapper; + private readonly ILogger _logger; + + public CustomerManager(ICustomerRepository customerRepository, IMapper mapper, ILogger logger) + { + _customerRepository = customerRepository; + _mapper = mapper; + _logger = logger; + } + + public async Task> GetAsync() + { + var clientes = await _customerRepository.GetAsync(); + return _mapper.Map, IEnumerable>(clientes); + } + + public async Task GetAsync(int id) + { + var cliente = await _customerRepository.GetAsync(id); + return _mapper.Map(cliente); + } + + public async Task DeleteAsync(int id) + { + var cliente = await _customerRepository.DeleteAsync(id); + return _mapper.Map(cliente); + } + + public async Task PostAsync(CustomerResource novoCliente) + { + _logger.LogInformation("Chamada de negócio para inserir um cliente."); + var cliente = _mapper.Map(novoCliente); + cliente = await _customerRepository.PostAsync(cliente); + return _mapper.Map(cliente); + } + + public async Task PutAsync(CustomerUpdateResource alteraCliente) + { + var cliente = _mapper.Map(alteraCliente); + cliente = await _customerRepository.PutAsync(cliente); + return _mapper.Map(cliente); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/UserManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/UserManager.cs new file mode 100644 index 0000000..0faa934 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/UserManager.cs @@ -0,0 +1,90 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; +using Browl.Service.MarketDataCollector.Domain.Resources.User; + +using Microsoft.AspNetCore.Identity; + +namespace Browl.Service.MarketDataCollector.Application.Implementation; + +public class UserManager : IUserManager +{ + private readonly IUserRepository _userRepository; + private readonly IMapper _mapper; + private readonly IJwtService _jwtService; + public UserManager(IUserRepository repository, IMapper mapper, IJwtService jwtService) + { + _userRepository = repository; + _mapper = mapper; + _jwtService = jwtService; + } + + public async Task> GetAsync() + { + return _mapper.Map, IEnumerable>(await _userRepository.GetAsync()); + } + + public async Task GetAsync(string login) + { + return _mapper.Map(await _userRepository.GetAsync(login)); + } + + public async Task InsertAsync(UserNewResource novoUsuario) + { + var usuario = _mapper.Map(novoUsuario); + ConverteSenhaEmHash(usuario); + return _mapper.Map(await _userRepository.InsertAsync(usuario)); + } + + private static void ConverteSenhaEmHash(User usuario) + { + var passwordHasher = new PasswordHasher(); + usuario.Password = passwordHasher.HashPassword(usuario, usuario.Password); + } + + public async Task UpdateMedicoAsync(User usuario) + { + ConverteSenhaEmHash(usuario); + return _mapper.Map(await _userRepository.UpdateAsync(usuario)); + } + + public async Task ValidaUsuarioEGeraTokenAsync(User usuario) + { + var usuarioConsultado = await _userRepository.GetAsync(usuario.Login); + if (usuarioConsultado == null) + { + return null; + } + if (await ValidateAndUpdateHashAsync(usuario, usuarioConsultado.Password)) + { + var usuarioLogado = _mapper.Map(usuarioConsultado); + usuarioLogado.Token = _jwtService.GenerateToken(usuarioConsultado); + return usuarioLogado; + } + return null; + } + + private async Task ValidateAndUpdateHashAsync(User usuario, string hash) + { + var passwordHasher = new PasswordHasher(); + var status = passwordHasher.VerifyHashedPassword(usuario, hash, usuario.Password); + switch (status) + { + case Microsoft.AspNetCore.Identity.PasswordVerificationResult.Failed: + return false; + + case Microsoft.AspNetCore.Identity.PasswordVerificationResult.Success: + return true; + + case Microsoft.AspNetCore.Identity.PasswordVerificationResult.SuccessRehashNeeded: + await UpdateMedicoAsync(usuario); + return true; + + default: + throw new InvalidOperationException(); + } + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/UsuarioManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/UsuarioManager.cs deleted file mode 100644 index a889cfe..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Implementation/UsuarioManager.cs +++ /dev/null @@ -1,93 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; -using Browl.Service.MarketDataCollector.Domain.Entities; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; -using Microsoft.AspNetCore.Identity; - -namespace Browl.Service.MarketDataCollector.Application.Implementation; - -public class UsuarioManager : IUsuarioManager -{ - private readonly IUsuarioRepository repository; - private readonly IMapper mapper; - private readonly IJwtService jwt; - - public UsuarioManager() - { - - } - public UsuarioManager(IUsuarioRepository repository, IMapper mapper, IJwtService jwt) - { - this.repository = repository; - this.mapper = mapper; - this.jwt = jwt; - } - - public async Task> GetAsync() - { - return mapper.Map, IEnumerable>(await repository.GetAsync()); - } - - public async Task GetAsync(string login) - { - return mapper.Map(await repository.GetAsync(login)); - } - - public async Task InsertAsync(NovoUsuario novoUsuario) - { - var usuario = mapper.Map(novoUsuario); - ConverteSenhaEmHash(usuario); - return mapper.Map(await repository.InsertAsync(usuario)); - } - - private static void ConverteSenhaEmHash(Usuario usuario) - { - var passwordHasher = new PasswordHasher(); - usuario.Senha = passwordHasher.HashPassword(usuario, usuario.Senha); - } - - public async Task UpdateMedicoAsync(Usuario usuario) - { - ConverteSenhaEmHash(usuario); - return mapper.Map(await repository.UpdateAsync(usuario)); - } - - public async Task ValidaUsuarioEGeraTokenAsync(Usuario usuario) - { - var usuarioConsultado = await repository.GetAsync(usuario.Login); - if (usuarioConsultado == null) - { - return null; - } - if (await ValidaEAtualizaHashAsync(usuario, usuarioConsultado.Senha)) - { - var usuarioLogado = mapper.Map(usuarioConsultado); - usuarioLogado.Token = jwt.GenerateToken(usuarioConsultado); - return usuarioLogado; - } - return null; - } - - private async Task ValidaEAtualizaHashAsync(Usuario usuario, string hash) - { - var passwordHasher = new PasswordHasher(); - var status = passwordHasher.VerifyHashedPassword(usuario, hash, usuario.Senha); - switch (status) - { - case Microsoft.AspNetCore.Identity.PasswordVerificationResult.Failed: - return false; - - case Microsoft.AspNetCore.Identity.PasswordVerificationResult.Success: - return true; - - case Microsoft.AspNetCore.Identity.PasswordVerificationResult.SuccessRehashNeeded: - await UpdateMedicoAsync(usuario); - return true; - - default: - throw new InvalidOperationException(); - } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappers/HabitMapper.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappers/HabitMapper.cs deleted file mode 100644 index 63e5e34..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappers/HabitMapper.cs +++ /dev/null @@ -1,12 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Domain.Dtos.Habit; -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Application.Mappers; -public class HabitMapper : Profile -{ - public HabitMapper() - { - CreateMap(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mapping/ModelToResourceProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mapping/ModelToResourceProfile.cs deleted file mode 100644 index 94e7482..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mapping/ModelToResourceProfile.cs +++ /dev/null @@ -1,22 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Application.Resources; -using Browl.Service.MarketDataCollector.Domain.Entities; -using Browl.Service.MarketDataCollector.Domain.Extensions; -using Browl.Service.MarketDataCollector.Domain.Queries; - -namespace Browl.Service.MarketDataCollector.Infrastructure.Mapping -{ - public class ModelToResourceProfile : Profile - { - public ModelToResourceProfile() - { - CreateMap(); - - CreateMap() - .ForMember(src => src.UnitOfMeasurement, - opt => opt.MapFrom(src => src.UnitOfMeasurement.ToDescriptionString())); - - CreateMap, QueryResultResource>(); - } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mapping/ResourceToModelProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mapping/ResourceToModelProfile.cs deleted file mode 100644 index 73bd8dc..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mapping/ResourceToModelProfile.cs +++ /dev/null @@ -1,21 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Application.Resources; -using Browl.Service.MarketDataCollector.Domain.Entities; -using Browl.Service.MarketDataCollector.Domain.Enums; -using Browl.Service.MarketDataCollector.Domain.Queries; - -namespace Browl.Service.MarketDataCollector.Infrastructure.Mapping -{ - public class ResourceToModelProfile : Profile - { - public ResourceToModelProfile() - { - CreateMap(); - - CreateMap() - .ForMember(src => src.UnitOfMeasurement, opt => opt.MapFrom(src => (UnitOfMeasurement)src.UnitOfMeasurement)); - - CreateMap(); - } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/AlteraClienteMappingProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/AlteraClienteMappingProfile.cs deleted file mode 100644 index 9f66199..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/AlteraClienteMappingProfile.cs +++ /dev/null @@ -1,15 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Application.Mappings; - -public class AlteraClienteMappingProfile : Profile -{ - public AlteraClienteMappingProfile() - { - CreateMap() - .ForMember(d => d.UltimaAtualizacao, o => o.MapFrom(_ => DateTime.Now)) - .ForMember(d => d.DataNascimento, o => o.MapFrom(x => x.DataNascimento.Date)); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/CustomerNewProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/CustomerNewProfile.cs new file mode 100644 index 0000000..cf6efdc --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/CustomerNewProfile.cs @@ -0,0 +1,24 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Resources.Address; +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; +using Browl.Service.MarketDataCollector.Domain.Resources.Telephone; + +namespace Browl.Service.MarketDataCollector.Application.Mappings; + +public class CustomerNewProfile : Profile +{ + public CustomerNewProfile() + { + CreateMap() + .ForMember(d => d.Criacao, o => o.MapFrom(_ => DateTime.Now)) + .ForMember(d => d.DataNascimento, o => o.MapFrom(x => x.DataNascimento.Date)); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/CustomerUpdateProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/CustomerUpdateProfile.cs new file mode 100644 index 0000000..4de935f --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/CustomerUpdateProfile.cs @@ -0,0 +1,12 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +namespace Browl.Service.MarketDataCollector.Application.Mappings; + +public class CustomerUpdateProfile : Profile +{ + public CustomerUpdateProfile() => _ = CreateMap() + .ForMember(d => d.UltimaAtualizacao, o => o.MapFrom(_ => DateTime.Now)) + .ForMember(d => d.DataNascimento, o => o.MapFrom(x => x.DataNascimento.Date)); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/HabitProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/HabitProfile.cs new file mode 100644 index 0000000..f705932 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/HabitProfile.cs @@ -0,0 +1,13 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Resources.Habit; + +namespace Browl.Service.MarketDataCollector.Application.Mappings; +public class HabitProfile : Profile +{ + public HabitProfile() + { + CreateMap(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/ModelToResourceProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/ModelToResourceProfile.cs new file mode 100644 index 0000000..ae9fc96 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/ModelToResourceProfile.cs @@ -0,0 +1,25 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Application.Resources; +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Extensions; +using Browl.Service.MarketDataCollector.Domain.Queries.Base; +using Browl.Service.MarketDataCollector.Domain.Resources.Category; +using Browl.Service.MarketDataCollector.Domain.Resources.Product; + +namespace Browl.Service.MarketDataCollector.Application.Mappings +{ + public class ModelToResourceProfile : Profile + { + public ModelToResourceProfile() + { + CreateMap(); + + CreateMap() + .ForMember(src => src.UnitOfMeasurement, + opt => opt.MapFrom(src => src.UnitOfMeasurement.ToDescriptionString())); + + CreateMap, QueryResultResource>(); + } + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/NovoClienteMappingProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/NovoClienteMappingProfile.cs deleted file mode 100644 index e433036..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/NovoClienteMappingProfile.cs +++ /dev/null @@ -1,23 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; -using Browl.Service.MarketDataCollector.Domain.Dtos.Endereco; -using Browl.Service.MarketDataCollector.Domain.Dtos.Telefone; -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Application.Mappings; - -public class NovoClienteMappingProfile : Profile -{ - public NovoClienteMappingProfile() - { - CreateMap() - .ForMember(d => d.Criacao, o => o.MapFrom(_ => DateTime.Now)) - .ForMember(d => d.DataNascimento, o => o.MapFrom(x => x.DataNascimento.Date)); - - CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/ResourceToModelProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/ResourceToModelProfile.cs new file mode 100644 index 0000000..405a525 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/ResourceToModelProfile.cs @@ -0,0 +1,24 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Application.Resources; +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Enums; +using Browl.Service.MarketDataCollector.Domain.Queries; +using Browl.Service.MarketDataCollector.Domain.Resources.Category; +using Browl.Service.MarketDataCollector.Domain.Resources.Product; + +namespace Browl.Service.MarketDataCollector.Application.Mappings +{ + public class ResourceToModelProfile : Profile + { + public ResourceToModelProfile() + { + CreateMap(); + + CreateMap() + .ForMember(src => src.UnitOfMeasurement, opt => opt.MapFrom(src => (UnitOfMeasurement)src.UnitOfMeasurement)); + + CreateMap(); + } + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/UserProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/UserProfile.cs new file mode 100644 index 0000000..fcec574 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/UserProfile.cs @@ -0,0 +1,18 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Resources.User; + +namespace Browl.Service.MarketDataCollector.Application.Mappings; + +public class UserProfile : Profile +{ + public UserProfile() + { + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/UsuarioMappingProfile.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/UsuarioMappingProfile.cs deleted file mode 100644 index 393a955..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Mappings/UsuarioMappingProfile.cs +++ /dev/null @@ -1,17 +0,0 @@ -using AutoMapper; -using Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Application.Mappings; - -public class UsuarioMappingProfile : Profile -{ - public UsuarioMappingProfile() - { - CreateMap().ReverseMap(); - CreateMap().ReverseMap(); - CreateMap().ReverseMap(); - CreateMap().ReverseMap(); - CreateMap().ReverseMap(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/CategoryResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/CategoryResource.cs deleted file mode 100644 index d0a6542..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/CategoryResource.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Application.Resources; - -public record CategoryResource -{ - public int Id { get; init; } - public string Name { get; init; } = null!; -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ErrorResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ErrorResource.cs deleted file mode 100644 index a195517..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ErrorResource.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Application.Resources -{ - public record ErrorResource - { - public bool Success => false; - public List Messages { get; private set; } - - public ErrorResource(List messages) - { - Messages = messages ?? new(); - } - - public ErrorResource(string message) - { - Messages = new(); - - if (!string.IsNullOrWhiteSpace(message)) - { - Messages.Add(message); - } - } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ProductResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ProductResource.cs deleted file mode 100644 index 9d9cc5b..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ProductResource.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Application.Resources -{ - public record ProductResource - { - public int Id { get; init; } - public string Name { get; init; } = null!; - public int QuantityInPackage { get; init; } - public string UnitOfMeasurement { get; init; } = null!; - public CategoryResource Category { get; init; } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ProductsQueryResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ProductsQueryResource.cs deleted file mode 100644 index c5fe92b..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/ProductsQueryResource.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Application.Resources -{ - public record ProductsQueryResource : QueryResource - { - public int CategoryId { get; init; } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/QueryResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/QueryResource.cs deleted file mode 100644 index a65a11a..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/QueryResource.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Application.Resources -{ - public record QueryResource - { - public int Page { get; init; } - public int ItemsPerPage { get; init; } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/QueryResultResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/QueryResultResource.cs deleted file mode 100644 index 87b49d3..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/QueryResultResource.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Application.Resources -{ - public record QueryResultResource - { - public int TotalItems { get; init; } = 0; - public List Items { get; init; } = new(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/SaveCategoryResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/SaveCategoryResource.cs deleted file mode 100644 index a91c2bc..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/SaveCategoryResource.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Browl.Service.MarketDataCollector.Application.Resources -{ - public record SaveCategoryResource - { - [Required] - [MaxLength(30)] - public string Name { get; init; } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/SaveProductResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/SaveProductResource.cs deleted file mode 100644 index 4e78f43..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Resources/SaveProductResource.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Browl.Service.MarketDataCollector.Application.Resources -{ - public record SaveProductResource - { - [Required] - [MaxLength(50)] - public string Name { get; init; } - - [Required] - [Range(0, 100)] - public short QuantityInPackage { get; init; } - - [Required] - [Range(1, 5)] - public int UnitOfMeasurement { get; init; } - - [Required] - public int CategoryId { get; init; } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/CategoryService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/CategoryService.cs index 3733c87..d56d5e1 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/CategoryService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/CategoryService.cs @@ -3,101 +3,101 @@ using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; using Browl.Service.MarketDataCollector.Infrastructure.Cache; + using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; -namespace Browl.Service.MarketDataCollector.Application.Services +namespace Browl.Service.MarketDataCollector.Application.Services; + +public class CategoryService : ICategoryService { - public class CategoryService : ICategoryService - { - private readonly ICategoryRepository _categoryRepository; - private readonly IUnitOfWork _unitOfWork; - private readonly IMemoryCache _cache; - private readonly ILogger _logger; + private readonly ICategoryRepository _categoryRepository; + private readonly IUnitOfWork _unitOfWork; + private readonly IMemoryCache _cache; + private readonly ILogger _logger; - public CategoryService - ( - ICategoryRepository categoryRepository, - IUnitOfWork unitOfWork, - IMemoryCache cache, - ILogger logger - ) - { - _categoryRepository = categoryRepository; - _unitOfWork = unitOfWork; - _cache = cache; - _logger = logger; - } + public CategoryService + ( + ICategoryRepository categoryRepository, + IUnitOfWork unitOfWork, + IMemoryCache cache, + ILogger logger + ) + { + _categoryRepository = categoryRepository; + _unitOfWork = unitOfWork; + _cache = cache; + _logger = logger; + } - public async Task> ListAsync() - { - var categories = await _cache.GetOrCreateAsync(CacheKeys.CategoriesList, (entry) => - { - entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1); - return _categoryRepository.ListAsync(); - }); + public async Task> ListAsync() + { + var categories = await _cache.GetOrCreateAsync(CacheKeys.CategoriesList, (entry) => + { + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1); + return _categoryRepository.ListAsync(); + }); - return categories ?? new List(); - } + return categories ?? new List(); + } - public async Task> SaveAsync(Category category) - { - try - { - await _categoryRepository.AddAsync(category); - await _unitOfWork.CompleteAsync(); + public async Task> SaveAsync(Category category) + { + try + { + await _categoryRepository.AddAsync(category); + await _unitOfWork.CompleteAsync(); - return new Response(category); - } - catch (Exception ex) - { - _logger.LogError(ex, "Could not save category."); - return new Response($"An error occurred when saving the category: {ex.Message}"); - } - } + return new Response(category); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not save category."); + return new Response($"An error occurred when saving the category: {ex.Message}"); + } + } - public async Task> UpdateAsync(int id, Category category) - { - var existingCategory = await _categoryRepository.FindByIdAsync(id); - if (existingCategory == null) - { - return new Response("Category not found."); - } + public async Task> UpdateAsync(int id, Category category) + { + var existingCategory = await _categoryRepository.FindByIdAsync(id); + if (existingCategory == null) + { + return new Response("Category not found."); + } - existingCategory.Name = category.Name; + existingCategory.Name = category.Name; - try - { - await _unitOfWork.CompleteAsync(); - return new Response(existingCategory); - } - catch (Exception ex) - { - _logger.LogError(ex, "Could not update category with ID {id}.", id); - return new Response($"An error occurred when updating the category: {ex.Message}"); - } - } + try + { + await _unitOfWork.CompleteAsync(); + return new Response(existingCategory); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not update category with ID {id}.", id); + return new Response($"An error occurred when updating the category: {ex.Message}"); + } + } - public async Task> DeleteAsync(int id) - { - var existingCategory = await _categoryRepository.FindByIdAsync(id); - if (existingCategory == null) - { - return new Response("Category not found."); - } + public async Task> DeleteAsync(int id) + { + var existingCategory = await _categoryRepository.FindByIdAsync(id); + if (existingCategory == null) + { + return new Response("Category not found."); + } - try - { - _categoryRepository.Remove(existingCategory); - await _unitOfWork.CompleteAsync(); + try + { + _categoryRepository.Remove(existingCategory); + await _unitOfWork.CompleteAsync(); - return new Response(existingCategory); - } - catch (Exception ex) - { - _logger.LogError(ex, "Could not delete category with ID {id}.", id); - return new Response($"An error occurred when deleting the category: {ex.Message}"); - } - } - } + return new Response(existingCategory); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not delete category with ID {id}.", id); + return new Response($"An error occurred when deleting the category: {ex.Message}"); + } + } } diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/HabitService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/HabitService.cs index 0dcebbc..f329c0f 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/HabitService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/HabitService.cs @@ -1,41 +1,46 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Habit; -using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; +using Browl.Service.MarketDataCollector.Domain.Resources.Habit; using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; + using Microsoft.EntityFrameworkCore; -namespace Browl.Service.MarketDataCollector.Application.Services +namespace Browl.Service.MarketDataCollector.Application.Services; + +public class HabitService : IHabitService { - public class HabitService : IHabitService - { - private readonly BrowlDbContext _dbContext; - public HabitService(BrowlDbContext dbContext) => _dbContext = dbContext; - public async Task Create(string name, string description) - { - var habit = _dbContext.Habits!.Add(new Habit { Name = name, Description = description }).Entity; - await _dbContext.SaveChangesAsync(); - return habit; - } - - public async Task> GetAll() => await _dbContext.Habits!.ToListAsync(); - - public async Task GetById(int id) => await _dbContext.Habits.FindAsync(id); - - public async Task DeleteById(int id) - { - var habit = await _dbContext.Habits!.FindAsync(id) ?? throw new ArgumentException("User not found"); - _dbContext.Habits.Remove(habit); - await _dbContext.SaveChangesAsync(); - } - public async Task UpdateById(int id, UpdateHabitDto request) - { - var habit = await _dbContext.Habits!.FindAsync(id); - if (habit == null) return null; - habit.Name = request.Name; - habit.Description = request.Description; - await _dbContext.SaveChangesAsync(); - return habit; - } - - } -} \ No newline at end of file + private readonly BrowlDbContext _dbContext; + public HabitService(BrowlDbContext dbContext) => _dbContext = dbContext; + + public async Task Create(string name, string description) + { + var habit = _dbContext.Habits!.Add(new Habit { Name = name, Description = description }).Entity; + _ = await _dbContext.SaveChangesAsync(); + return habit; + } + + public async Task> GetAll() => await _dbContext.Habits!.ToListAsync(); + + public async Task GetById(int id) => await _dbContext.Habits.FindAsync(id); + + public async Task DeleteById(int id) + { + var habit = await _dbContext.Habits!.FindAsync(id) ?? throw new ArgumentException("User not found"); + _ = _dbContext.Habits.Remove(habit); + _ = await _dbContext.SaveChangesAsync(); + } + public async Task UpdateById(int id, UpdateHabitResource request) + { + var habit = await _dbContext.Habits!.FindAsync(id); + if (habit == null) + { + return null; + } + + habit.Name = request.Name; + habit.Description = request.Description; + _ = await _dbContext.SaveChangesAsync(); + return habit; + } + +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/IJWTService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/IJWTService.cs deleted file mode 100644 index 4a500d3..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/IJWTService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Application.Services; - -public interface IJwtService -{ - string GerarToken(Usuario usuario); -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/ProductService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/ProductService.cs index 981390d..3648d92 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/ProductService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/ProductService.cs @@ -3,131 +3,137 @@ using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; using Browl.Service.MarketDataCollector.Domain.Queries; +using Browl.Service.MarketDataCollector.Domain.Queries.Base; using Browl.Service.MarketDataCollector.Infrastructure.Cache; + using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; -namespace Browl.Service.MarketDataCollector.Application.Services +namespace Browl.Service.MarketDataCollector.Application.Services; + +public class ProductService : IProductService { - public class ProductService : IProductService - { - private readonly IProductRepository _productRepository; - private readonly ICategoryRepository _categoryRepository; - private readonly IUnitOfWork _unitOfWork; - private readonly IMemoryCache _cache; - private readonly ILogger _logger; - - - public ProductService - ( - IProductRepository productRepository, - ICategoryRepository categoryRepository, - IUnitOfWork unitOfWork, - IMemoryCache cache, - ILogger logger - ) - { - _productRepository = productRepository; - _categoryRepository = categoryRepository; - _unitOfWork = unitOfWork; - _cache = cache; - _logger = logger; - } - - public async Task> ListAsync(ProductsQuery query) - { - // Here I list the query result from cache if they exist, but now the data can vary according to the category ID, page and amount of - // items per page. I have to compose a cache to avoid returning wrong data. - string cacheKey = GetCacheKeyForProductsQuery(query); - - var products = await _cache.GetOrCreateAsync(cacheKey, (entry) => - { - entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1); - return _productRepository.ListAsync(query); - }); - - return products!; - } - - public async Task> SaveAsync(Product product) - { - try - { - /* + private readonly IProductRepository _productRepository; + private readonly ICategoryRepository _categoryRepository; + private readonly IUnitOfWork _unitOfWork; + private readonly IMemoryCache _cache; + private readonly ILogger _logger; + + + public ProductService + ( + IProductRepository productRepository, + ICategoryRepository categoryRepository, + IUnitOfWork unitOfWork, + IMemoryCache cache, + ILogger logger + ) + { + _productRepository = productRepository; + _categoryRepository = categoryRepository; + _unitOfWork = unitOfWork; + _cache = cache; + _logger = logger; + } + + public async Task> ListAsync(ProductsQuery query) + { + // Here I list the query result from cache if they exist, but now the data can vary according to the category ID, page and amount of + // items per page. I have to compose a cache to avoid returning wrong data. + var cacheKey = GetCacheKeyForProductsQuery(query); + + var products = await _cache.GetOrCreateAsync(cacheKey, (entry) => + { + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1); + return _productRepository.ListAsync(query); + }); + + return products!; + } + + public async Task> SaveAsync(Product product) + { + try + { + /* Notice here we have to check if the category ID is valid before adding the product, to avoid errors. You can create a method into the CategoryService class to return the category and inject the service here if you prefer, but it doesn't matter given the API scope. */ - var existingCategory = await _categoryRepository.FindByIdAsync(product.CategoryId); - if (existingCategory == null) - return new Response("Invalid category."); - - await _productRepository.AddAsync(product); - await _unitOfWork.CompleteAsync(); - - return new Response(product); - } - catch (Exception ex) - { - _logger.LogError(ex, "Could not save product."); - return new Response($"An error occurred when saving the product: {ex.Message}"); - } - } - - public async Task> UpdateAsync(int id, Product product) - { - var existingProduct = await _productRepository.FindByIdAsync(id); - - if (existingProduct == null) - return new Response("Product not found."); - - var existingCategory = await _categoryRepository.FindByIdAsync(product.CategoryId); - if (existingCategory == null) - return new Response("Invalid category."); - - existingProduct.Name = product.Name; - existingProduct.UnitOfMeasurement = product.UnitOfMeasurement; - existingProduct.QuantityInPackage = product.QuantityInPackage; - existingProduct.CategoryId = product.CategoryId; - - try - { - _productRepository.Update(existingProduct); - await _unitOfWork.CompleteAsync(); - - return new Response(existingProduct); - } - catch (Exception ex) - { - _logger.LogError(ex, "Could not update product with ID {id}.", id); - return new Response($"An error occurred when updating the product: {ex.Message}"); - } - } - - public async Task> DeleteAsync(int id) - { - var existingProduct = await _productRepository.FindByIdAsync(id); - - if (existingProduct == null) - return new Response("Product not found."); - - try - { - _productRepository.Remove(existingProduct); - await _unitOfWork.CompleteAsync(); - - return new Response(existingProduct); - } - catch (Exception ex) - { - _logger.LogError(ex, "Could not delete product with ID {id}.", id); - return new Response($"An error occurred when deleting the product: {ex.Message}"); - } - } - - private string GetCacheKeyForProductsQuery(ProductsQuery query) - { - return $"{CacheKeys.ProductsList}_{query.CategoryId}_{query.Page}_{query.ItemsPerPage}"; - } - } + var existingCategory = await _categoryRepository.FindByIdAsync(product.CategoryId); + if (existingCategory == null) + { + return new Response("Invalid category."); + } + + await _productRepository.AddAsync(product); + await _unitOfWork.CompleteAsync(); + + return new Response(product); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not save product."); + return new Response($"An error occurred when saving the product: {ex.Message}"); + } + } + + public async Task> UpdateAsync(int id, Product product) + { + var existingProduct = await _productRepository.FindByIdAsync(id); + + if (existingProduct == null) + { + return new Response("Product not found."); + } + + var existingCategory = await _categoryRepository.FindByIdAsync(product.CategoryId); + if (existingCategory == null) + { + return new Response("Invalid category."); + } + + existingProduct.Name = product.Name; + existingProduct.UnitOfMeasurement = product.UnitOfMeasurement; + existingProduct.QuantityInPackage = product.QuantityInPackage; + existingProduct.CategoryId = product.CategoryId; + + try + { + _productRepository.Update(existingProduct); + await _unitOfWork.CompleteAsync(); + + return new Response(existingProduct); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not update product with ID {id}.", id); + return new Response($"An error occurred when updating the product: {ex.Message}"); + } + } + + public async Task> DeleteAsync(int id) + { + var existingProduct = await _productRepository.FindByIdAsync(id); + + if (existingProduct == null) + { + return new Response("Product not found."); + } + + try + { + _productRepository.Remove(existingProduct); + await _unitOfWork.CompleteAsync(); + + return new Response(existingProduct); + } + catch (Exception ex) + { + _logger.LogError(ex, "Could not delete product with ID {id}.", id); + return new Response($"An error occurred when deleting the product: {ex.Message}"); + } + } + + private string GetCacheKeyForProductsQuery(ProductsQuery query) => $"{CacheKeys.ProductsList}_{query.CategoryId}_{query.Page}_{query.ItemsPerPage}"; } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/TenantService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/TenantService.cs index 58eda3b..96c5e91 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/TenantService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Services/TenantService.cs @@ -1,41 +1,49 @@ using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; + using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; -namespace Browl.Service.MarketDataCollector.Application.Services +namespace Browl.Service.MarketDataCollector.Application.Services; + +public class TenantService : ITenantService { - public class TenantService : ITenantService - { - private readonly TenantSettings _tenantSettings; - private HttpContext _httpContext; - private Tenant _tenant; - public TenantService(IOptions tenantSettings, IHttpContextAccessor contextAccessor) - { - _tenantSettings = tenantSettings.Value; - _httpContext = contextAccessor.HttpContext!; - if (_httpContext != null) - { - if (_httpContext.Request.Headers.TryGetValue("tenant", out var tenantId)) - { - SetTenant(tenantId!); - } - else - { - throw new Exception("Invalid Tenant!"); - } - } - } - private void SetTenant(string tenantId) - { - _tenant = _tenantSettings!.Tenants.Where(a => a.TenantName == tenantId).FirstOrDefault(); - if (_tenant == null) throw new Exception("Invalid Tenant!"); - if (string.IsNullOrEmpty(_tenant.ConnectionString)) - SetDefaultConnectionStringToCurrentTenant(); - } - private void - SetDefaultConnectionStringToCurrentTenant() => _tenant.ConnectionString = _tenantSettings.DefaultConnectionString; - public string GetConnectionString() => _tenant?.ConnectionString!; - public Tenant GetTenant() => _tenant; - } + private readonly TenantSettings _tenantSettings; + private readonly HttpContext _httpContext; + private Tenant _tenant; + public TenantService(IOptions tenantSettings, IHttpContextAccessor contextAccessor) + { + _tenantSettings = tenantSettings.Value; + _httpContext = contextAccessor.HttpContext!; + if (_httpContext != null) + { + if (_httpContext.Request.Headers.TryGetValue("tenant", out var tenantId)) + { + SetTenant(tenantId!); + } + else + { + throw new Exception("Invalid Tenant!"); + } + } + } + private void SetTenant(string tenantId) + { + _tenant = _tenantSettings!.Tenants.Where(a => a.TenantName == tenantId).FirstOrDefault(); + if (_tenant == null) + { + throw new Exception("Invalid Tenant!"); + } + + if (string.IsNullOrEmpty(_tenant.ConnectionString)) + { + SetDefaultConnectionStringToCurrentTenant(); + } + } + private void + SetDefaultConnectionStringToCurrentTenant() => _tenant.ConnectionString = _tenantSettings.DefaultConnectionString; + + public string GetConnectionString() => _tenant?.ConnectionString!; + + public Tenant GetTenant() => _tenant; } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/AddressNewValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/AddressNewValidator.cs new file mode 100644 index 0000000..c3f71cf --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/AddressNewValidator.cs @@ -0,0 +1,18 @@ +using Browl.Service.MarketDataCollector.Domain.Resources.Address; + +using FluentValidation; + +namespace Browl.Service.MarketDataCollector.Application.Validator; + +public class AddressNewValidator : AbstractValidator +{ + public AddressNewValidator() + { + _ = RuleFor(p => p.CEP).NotEmpty().NotNull(); + _ = RuleFor(p => p.Estado).NotNull(); + _ = RuleFor(p => p.Cidade).NotEmpty().NotNull().MaximumLength(200); + _ = RuleFor(p => p.Logradouro).NotEmpty().NotNull().MaximumLength(200); + _ = RuleFor(p => p.Numero).NotEmpty().NotNull().MaximumLength(10); + _ = RuleFor(p => p.Complemento).MaximumLength(200); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/AlteraClienteValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/AlteraClienteValidator.cs deleted file mode 100644 index 079d518..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/AlteraClienteValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; -using FluentValidation; - -namespace Browl.Service.MarketDataCollector.Application.Validator; - -public class AlteraClienteValidator : AbstractValidator -{ - public AlteraClienteValidator() - { - RuleFor(p => p.Id).NotNull().NotEmpty().GreaterThan(0); - Include(new NovoClienteValidator()); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/CustomerNewValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/CustomerNewValidator.cs new file mode 100644 index 0000000..9dd8d46 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/CustomerNewValidator.cs @@ -0,0 +1,17 @@ +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +using FluentValidation; + +namespace Browl.Service.MarketDataCollector.Application.Validator; + +public class CustomerNewValidator : AbstractValidator +{ + public CustomerNewValidator() + { + _ = RuleFor(x => x.Nome).NotNull().NotEmpty().MinimumLength(10).MaximumLength(150); + _ = RuleFor(x => x.Documento).NotNull().NotEmpty().MinimumLength(4).MaximumLength(14); + _ = RuleFor(x => x.Telefones).NotNull().NotEmpty(); + _ = RuleFor(x => x.Sexo).NotNull(); + _ = RuleFor(x => x.Endereco).SetValidator(new AddressNewValidator()); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/CustomerUpdateValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/CustomerUpdateValidator.cs new file mode 100644 index 0000000..68a41f5 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/CustomerUpdateValidator.cs @@ -0,0 +1,12 @@ +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; +using FluentValidation; + +namespace Browl.Service.MarketDataCollector.Application.Validator; + +public class CustomerUpdateValidator : AbstractValidator +{ + public CustomerUpdateValidator() + { + _ = RuleFor(p => p.Id).NotNull().NotEmpty().GreaterThan(0); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoClienteValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoClienteValidator.cs deleted file mode 100644 index 7833681..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoClienteValidator.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; -using FluentValidation; - -namespace Browl.Service.MarketDataCollector.Application.Validator; - -public class NovoClienteValidator : AbstractValidator -{ - public NovoClienteValidator() - { - RuleFor(x => x.Nome).NotNull().NotEmpty().MinimumLength(10).MaximumLength(150); - RuleFor(x => x.DataNascimento).NotNull().NotEmpty().LessThan(DateTime.Now).GreaterThan(DateTime.Now.AddYears(-130)); - RuleFor(x => x.Documento).NotNull().NotEmpty().MinimumLength(4).MaximumLength(14); - RuleFor(x => x.Telefones).NotNull().NotEmpty(); - RuleFor(x => x.Sexo).NotNull(); - RuleFor(x => x.Endereco).SetValidator(new NovoEnderecoValidator()); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoEnderecoValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoEnderecoValidator.cs deleted file mode 100644 index c67f8ab..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoEnderecoValidator.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Endereco; -using FluentValidation; - -namespace Browl.Service.MarketDataCollector.Application.Validator; - -public class NovoEnderecoValidator : AbstractValidator -{ - public NovoEnderecoValidator() - { - RuleFor(p => p.CEP).NotEmpty().NotNull(); - RuleFor(p => p.Estado).NotNull(); - RuleFor(p => p.Cidade).NotEmpty().NotNull().MaximumLength(200); - RuleFor(p => p.Logradouro).NotEmpty().NotNull().MaximumLength(200); - RuleFor(p => p.Numero).NotEmpty().NotNull().MaximumLength(10); - RuleFor(p => p.Complemento).MaximumLength(200); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoTelefoneValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoTelefoneValidator.cs deleted file mode 100644 index 6a8229c..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/NovoTelefoneValidator.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Telefone; -using FluentValidation; - -namespace Browl.Service.MarketDataCollector.Application.Validator; - -public class NovoTelefoneValidator : AbstractValidator -{ - public NovoTelefoneValidator() - { - RuleFor(p => p.Numero).Matches("[1-9][0-9]{10}").WithMessage("O telefone tem que ter o formato [2-9][0-9]{10}"); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/TelephoneNewValidator.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/TelephoneNewValidator.cs new file mode 100644 index 0000000..b01e780 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Application/Validator/TelephoneNewValidator.cs @@ -0,0 +1,10 @@ +using Browl.Service.MarketDataCollector.Domain.Resources.Telephone; + +using FluentValidation; + +namespace Browl.Service.MarketDataCollector.Application.Validator; + +public class TelephoneNewValidator : AbstractValidator +{ + public TelephoneNewValidator() => _ = RuleFor(p => p.Numero).Matches("[1-9][0-9]{10}").WithMessage("O telefone tem que ter o formato [2-9][0-9]{10}"); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Browl.Service.MarketDataCollector.Domain.csproj b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Browl.Service.MarketDataCollector.Domain.csproj index a6e729d..f87b370 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Browl.Service.MarketDataCollector.Domain.csproj +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Browl.Service.MarketDataCollector.Domain.csproj @@ -1,4 +1,4 @@ - + net7.0 diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Communication/Response.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Communication/Response.cs index 01268cf..2f21fe8 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Communication/Response.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Communication/Response.cs @@ -1,23 +1,22 @@ -namespace Browl.Service.MarketDataCollector.Domain.Communication +namespace Browl.Service.MarketDataCollector.Domain.Communication; + +public record Response { - public record Response - { - public bool Success { get; init; } - public string? Message { get; init; } - public T? Resource { get; init; } + public bool Success { get; init; } + public string? Message { get; init; } + public T? Resource { get; init; } - public Response(T resource) - { - Success = true; - Message = null; - Resource = resource; - } + public Response(T resource) + { + Success = true; + Message = null; + Resource = resource; + } - public Response(string message) - { - Success = false; - Message = message; - Resource = default; - } - } + public Response(string message) + { + Success = false; + Message = message; + Resource = default; + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/AlteraCliente.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/AlteraCliente.cs deleted file mode 100644 index 6b80168..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/AlteraCliente.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; - -public class AlteraCliente : NovoCliente -{ - public int Id { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/ClienteView.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/ClienteView.cs deleted file mode 100644 index d90709d..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/ClienteView.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Endereco; -using Browl.Service.MarketDataCollector.Domain.Dtos.Telefone; - -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; - -public class ClienteView : ICloneable -{ - public int Id { get; set; } - public string Nome { get; set; } - public DateTime DataNascimento { get; set; } - - public SexoView Sexo { get; set; } - public ICollection Telefones { get; set; } - - public string Documento { get; set; } - public DateTime Criacao { get; set; } - public DateTime? UltimaAtualizacao { get; set; } - - public EnderecoView Endereco { get; set; } - - public object Clone() - { - var cliente = (ClienteView)MemberwiseClone(); - cliente.Endereco = (EnderecoView)cliente.Endereco.Clone(); - var telefones = new List(); - cliente.Telefones.ToList().ForEach(p => telefones.Add((TelefoneView)p.Clone())); - cliente.Telefones = telefones; - return cliente; - } - - public ClienteView CloneTipado() - { - return (ClienteView)Clone(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/NovoCliente.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/NovoCliente.cs deleted file mode 100644 index 7dbba10..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/NovoCliente.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Endereco; -using Browl.Service.MarketDataCollector.Domain.Dtos.Telefone; - -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; - -/// -/// Objeto utilizado para inserção de um novo cliente. -/// -public class NovoCliente -{ - /// - /// Nome do cliente - /// - /// João do Caminhão - public string Nome { get; set; } - - /// - /// Data do nascimento do cliente. - /// - /// 1980-01-01 - public DateTime DataNascimento { get; set; } - - /// - /// Sexo do cliente - /// - /// M - public SexoView Sexo { get; set; } - - /// - /// Documento do cliente: CNH, CPF, RG - /// - /// 12341231312 - public string Documento { get; set; } - - public NovoEndereco Endereco { get; set; } - - public ICollection Telefones { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/SexoView.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/SexoView.cs deleted file mode 100644 index de59187..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Cliente/SexoView.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; - -public enum SexoView -{ - M, - F -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/EnderecoView.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/EnderecoView.cs deleted file mode 100644 index 7ba7d38..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/EnderecoView.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Endereco; - -public class EnderecoView : ICloneable -{ - public int CEP { get; set; } - public EstadoView Estado { get; set; } - public string Cidade { get; set; } - public string Logradouro { get; set; } - public string Numero { get; set; } - public string Complemento { get; set; } - - public object Clone() - { - return MemberwiseClone(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/EstadoView.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/EstadoView.cs deleted file mode 100644 index aa657b0..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/EstadoView.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Endereco; - -public enum EstadoView -{ - AC, - AL, - AP, - AM, - BA, - CE, - DF, - ES, - GO, - MA, - MT, - MS, - MG, - PA, - PB, - PR, - PE, - PI, - RJ, - RN, - RS, - RO, - RR, - SC, - SP, - SE, - TO -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/NovoEndereco.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/NovoEndereco.cs deleted file mode 100644 index 972603f..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Endereco/NovoEndereco.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Endereco; - -public class NovoEndereco -{ - ///49000000 - public int CEP { get; set; } - - public EstadoView Estado { get; set; } - - ///Aracaju - public string Cidade { get; set; } - - ///Rua A - public string Logradouro { get; set; } - - ///15 - public string Numero { get; set; } - - ///Ao lado do posto - public string Complemento { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Erro/ErrorResponse.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Erro/ErrorResponse.cs deleted file mode 100644 index 87da2d6..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Erro/ErrorResponse.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Erro; - -public class ErrorResponse -{ - public string Id { get; set; } - public DateTime Data { get; set; } - public string Mensagem { get; set; } - - public ErrorResponse(string id) - { - Id = id; - Data = DateTime.Now; - Mensagem = "Erro inesperado."; - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/CreateHabitDto.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/CreateHabitDto.cs deleted file mode 100644 index 3d71bad..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/CreateHabitDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Habit; - -public class CreateHabitDto -{ - public string Name { get; set; } - public int UserId { get; set; } - public string Description { get; set; } = default!; -} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/GetGoodHabitDetailDto.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/GetGoodHabitDetailDto.cs deleted file mode 100644 index 4469d04..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/GetGoodHabitDetailDto.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Habit; - -public class GetGoodHabitDetailDto -{ - public int Id { get; set; } - public string Name { get; set; } - public string UserName { get; set; } - public string GoalName { get; set; } - public string Duration { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/GetGoodHabitDto.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/GetGoodHabitDto.cs deleted file mode 100644 index d5b0fcc..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/GetGoodHabitDto.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Habit; -public class GetGoodHabitDto -{ - public int Id { get; set; } - public string Name { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/HabitDetailDto.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/HabitDetailDto.cs deleted file mode 100644 index 4371f51..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/HabitDetailDto.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Habit; - -public class HabitDetailDto -{ - public int Id { get; set; } - public string Name { get; set; } = default!; - public string UserName { get; set; } = default!; - public string GoalName { get; set; } = default!; - public string Duration { get; set; } = default!; -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/HabitDto.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/HabitDto.cs deleted file mode 100644 index 6f2bf99..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/HabitDto.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Habit; -public class HabitDto -{ - public int Id { get; set; } = default!; - public string Name { get; set; } = default!; - public string Description { get; set; } = default!; -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/UpdateHabitDto.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/UpdateHabitDto.cs deleted file mode 100644 index 30b1cea..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Habit/UpdateHabitDto.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Habit; -public class UpdateHabitDto -{ - public string Name { get; set; } = default!; - public string Description { get; set; } = default!; -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Telefone/NovoTelefone.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Telefone/NovoTelefone.cs deleted file mode 100644 index a9ce228..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Telefone/NovoTelefone.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Telefone; - -public class NovoTelefone -{ - /// - /// Telefone do cliente - /// - /// 79999887744 - public string Numero { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Telefone/TelefoneView.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Telefone/TelefoneView.cs deleted file mode 100644 index be203d5..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Telefone/TelefoneView.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Telefone; - -public class TelefoneView : ICloneable -{ - public int Id { get; set; } - public string Numero { get; set; } - - public object Clone() - { - return MemberwiseClone(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/FuncaoView.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/FuncaoView.cs deleted file mode 100644 index f23671a..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/FuncaoView.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; - -public class FuncaoView -{ - public int Id { get; set; } - public string Descricao { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/NovoUsuario.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/NovoUsuario.cs deleted file mode 100644 index bc1cecf..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/NovoUsuario.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; - -public class NovoUsuario -{ - public string Login { get; set; } - public string Senha { get; set; } - - public ICollection Funcoes { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/ReferenciaFuncao.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/ReferenciaFuncao.cs deleted file mode 100644 index cc80e2e..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/ReferenciaFuncao.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; - -public class ReferenciaFuncao -{ - public int Id { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/UsuarioLogado.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/UsuarioLogado.cs deleted file mode 100644 index 2f93a74..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/UsuarioLogado.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; - -public class UsuarioLogado -{ - public string Login { get; set; } - public ICollection Funcoes { get; set; } - public string Token { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/UsuarioView.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/UsuarioView.cs deleted file mode 100644 index f9dc7d8..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Dtos/Usuario/UsuarioView.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; - -public class UsuarioView -{ - public string Login { get; set; } - - public ICollection Funcoes { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Address.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Address.cs new file mode 100644 index 0000000..00bcfca --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Address.cs @@ -0,0 +1,12 @@ +namespace Browl.Service.MarketDataCollector.Domain.Entities; +public class Address +{ + public int ClienteId { get; set; } + public int CEP { get; set; } + public State Estado { get; set; } + public required string Cidade { get; set; } + public required string Logradouro { get; set; } + public required string Numero { get; set; } + public required string Complemento { get; set; } + public required Customer Cliente { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Category.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Category.cs index c6fd10b..cedf935 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Category.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Category.cs @@ -1,9 +1,24 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities +using Browl.Service.MarketDataCollector.Domain.Resources.Category; + +namespace Browl.Service.MarketDataCollector.Domain.Entities; + +public class Category { - public class Category - { - public int Id { get; set; } - public string Name { get; set; } = null!; - public List Products { get; set; } = new(); - } + public int Id { get; set; } + public string Name { get; set; } = null!; + public List Products { get; set; } = new(); + + protected Category() { } + + public Category(CategoryResource categoryResource) + { + Id = categoryResource.Id; + Name = categoryResource.Name; + } + + public Category(int id, string name) + { + Id = id; + Name = name; + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Cliente.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Cliente.cs deleted file mode 100644 index c157950..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Cliente.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities; - -public class Cliente -{ - public int Id { get; set; } - public string Nome { get; set; } - public DateTime DataNascimento { get; set; } - public Sexo Sexo { get; set; } - public ICollection Telefones { get; set; } - public string Documento { get; set; } - public DateTime Criacao { get; set; } - public DateTime? UltimaAtualizacao { get; set; } - - public Endereco Endereco { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Customer.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Customer.cs new file mode 100644 index 0000000..31ebeed --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Customer.cs @@ -0,0 +1,15 @@ +namespace Browl.Service.MarketDataCollector.Domain.Entities; + +public class Customer +{ + public int Id { get; set; } + public string Nome { get; set; } + public DateTime DataNascimento { get; set; } + public Gender Sexo { get; set; } + public ICollection Telefones { get; set; } + public string Documento { get; set; } + public DateTime Criacao { get; set; } + public DateTime? UltimaAtualizacao { get; set; } + + public Address Endereco { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Endereco.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Endereco.cs deleted file mode 100644 index 7c83404..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Endereco.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities; -public class Endereco -{ - public int ClienteId { get; set; } - public int CEP { get; set; } - public Estado Estado { get; set; } - public string Cidade { get; set; } - public string Logradouro { get; set; } - public string Numero { get; set; } - public string Complemento { get; set; } - public Cliente Cliente { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Estado.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Estado.cs deleted file mode 100644 index 270666c..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Estado.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities; -public enum Estado -{ - AC, - AL, - AP, - AM, - BA, - CE, - DF, - ES, - GO, - MA, - MT, - MS, - MG, - PA, - PB, - PR, - PE, - PI, - RJ, - RN, - RS, - RO, - RR, - SC, - SP, - SE, - TO -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Funcao.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Funcao.cs deleted file mode 100644 index 78387b6..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Funcao.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities; -public class Funcao -{ - public int Id { get; set; } - public string Descricao { get; set; } - - public ICollection Usuarios { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Sexo.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Gender.cs similarity index 69% rename from src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Sexo.cs rename to src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Gender.cs index 8ea956b..8e2d33e 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Sexo.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Gender.cs @@ -1,6 +1,6 @@ namespace Browl.Service.MarketDataCollector.Domain.Entities; -public enum Sexo +public enum Gender { - M, - F + M, + F } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Goal.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Goal.cs index ffc1f02..6367c82 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Goal.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Goal.cs @@ -2,7 +2,7 @@ namespace Browl.Service.MarketDataCollector.Domain.Entities; public class Goal { - public int Id { get; set; } - public int HabitId { get; set; } - public virtual Habit Habit { get; set; } = default!; + public int Id { get; set; } + public int HabitId { get; set; } + public virtual Habit Habit { get; set; } = default!; } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Habit.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Habit.cs index 710aa5e..ad404e9 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Habit.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Habit.cs @@ -4,14 +4,14 @@ namespace Browl.Service.MarketDataCollector.Domain.Entities; public class Habit : IHasTenant { - public int Id { get; set; } - public string Name { get; set; } = default!; - public string Description { get; set; } = default!; - public int UserId { get; set; } - public virtual ICollection ProgressUpdates { get; set; } = default!; - public virtual ICollection Reminders { get; set; } = default!; - public virtual Goal Goal { get; set; } = default!; - public Duration Duration { get; set; } - public string TenantName { get; set; } = default!; + public int Id { get; set; } + public string Name { get; set; } = default!; + public string Description { get; set; } = default!; + public int UserId { get; set; } + public virtual ICollection ProgressUpdates { get; set; } = default!; + public virtual ICollection Reminders { get; set; } = default!; + public virtual Goal Goal { get; set; } = default!; + public Duration Duration { get; set; } + public string TenantName { get; set; } = default!; } public enum Duration { DayLong, WeekLong, MonthLong } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Product.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Product.cs index 535b6e3..a06cea4 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Product.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Product.cs @@ -1,15 +1,14 @@ using Browl.Service.MarketDataCollector.Domain.Enums; -namespace Browl.Service.MarketDataCollector.Domain.Entities -{ - public class Product - { - public int Id { get; set; } - public string Name { get; set; } = null!; - public short QuantityInPackage { get; set; } - public UnitOfMeasurement UnitOfMeasurement { get; set; } +namespace Browl.Service.MarketDataCollector.Domain.Entities; - public int CategoryId { get; set; } - public Category Category { get; set; } - } -} \ No newline at end of file +public class Product +{ + public int Id { get; set; } + public string Name { get; set; } = null!; + public short QuantityInPackage { get; set; } + public UnitOfMeasurement UnitOfMeasurement { get; set; } + + public int CategoryId { get; set; } + public Category Category { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Progress.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Progress.cs index 46f0ff8..73778f6 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Progress.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Progress.cs @@ -2,8 +2,8 @@ namespace Browl.Service.MarketDataCollector.Domain.Entities; public class Progress { - public int Id { get; set; } - public DateTime Date { get; set; } - public int HabitId { get; set; } - public virtual Habit Habit { get; set; } = default!; + public int Id { get; set; } + public DateTime Date { get; set; } + public int HabitId { get; set; } + public virtual Habit Habit { get; set; } = default!; } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Reminder.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Reminder.cs index 59aa56d..1476b2a 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Reminder.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Reminder.cs @@ -2,9 +2,9 @@ namespace Browl.Service.MarketDataCollector.Domain.Entities; public class Reminder { - public int Id { get; set; } - public Frequency Frequency { get; set; } - public int HabitId { get; set; } - public virtual Habit Habit { get; set; } = default!; + public int Id { get; set; } + public Frequency Frequency { get; set; } + public int HabitId { get; set; } + public virtual Habit Habit { get; set; } = default!; } public enum Frequency { Daily, Weekly, Monthly } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Role.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Role.cs new file mode 100644 index 0000000..a0947d1 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Role.cs @@ -0,0 +1,8 @@ +namespace Browl.Service.MarketDataCollector.Domain.Entities; +public class Role +{ + public int Id { get; set; } + public required string Descricao { get; set; } + + public required ICollection Usuarios { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/State.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/State.cs new file mode 100644 index 0000000..a37d74c --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/State.cs @@ -0,0 +1,31 @@ +namespace Browl.Service.MarketDataCollector.Domain.Entities; +public enum State +{ + AC, + AL, + AP, + AM, + BA, + CE, + DF, + ES, + GO, + MA, + MT, + MS, + MG, + PA, + PB, + PR, + PE, + PI, + RJ, + RN, + RS, + RO, + RR, + SC, + SP, + SE, + TO +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Telefone.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Telefone.cs deleted file mode 100644 index aa52f4f..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Telefone.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities; -public class Telefone -{ - public int ClienteId { get; set; } - public string Numero { get; set; } - public Cliente Cliente { get; set; } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Telephone.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Telephone.cs new file mode 100644 index 0000000..74b95bd --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Telephone.cs @@ -0,0 +1,8 @@ +namespace Browl.Service.MarketDataCollector.Domain.Entities; +public class Telephone +{ + public int ClienteId { get; set; } + public required string Numero { get; set; } + public required Customer Cliente { get; set; } + public int Id { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Tenant.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Tenant.cs index e0b7117..43cfe44 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Tenant.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Tenant.cs @@ -2,6 +2,6 @@ public class Tenant { - public string? TenantName { get; set; } - public string? ConnectionString { get; set; } + public string? TenantName { get; set; } + public string? ConnectionString { get; set; } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/TenantSettings.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/TenantSettings.cs index eb681df..569d9a0 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/TenantSettings.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/TenantSettings.cs @@ -2,6 +2,6 @@ namespace Browl.Service.MarketDataCollector.Domain.Entities; public class TenantSettings { - public string? DefaultConnectionString { get; set; } - public List? Tenants { get; set; } + public string? DefaultConnectionString { get; set; } + public List? Tenants { get; set; } } diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/User.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/User.cs index 0ec8a31..8f007a9 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/User.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/User.cs @@ -1,10 +1,13 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities; - +namespace Browl.Service.MarketDataCollector.Domain.Entities; public class User { - public int Id { get; set; } - public string FirstName { get; set; } = default!; - public string LastName { get; set; } = default!; - public string Email { get; set; } = default!; + public int Id { get; set; } + public string FirstName { get; set; } = default!; + public string LastName { get; set; } = default!; + public string Email { get; set; } = default!; + public string Login { get; set; } + public string Password { get; set; } + public ICollection Roles { get; set; } -} \ No newline at end of file + public User() => Roles = new HashSet(); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Usuario.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Usuario.cs deleted file mode 100644 index 0feef75..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Entities/Usuario.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Entities; -public class Usuario -{ - public string Login { get; set; } - public string Senha { get; set; } - - public ICollection Funcoes { get; set; } - - public Usuario() - { - Funcoes = new HashSet(); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Enums/Gender.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Enums/Gender.cs new file mode 100644 index 0000000..e24ecb7 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Enums/Gender.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.MarketDataCollector.Domain.Enums; + +public enum Gender +{ + M = 1, + F = 2, +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Enums/UnitOfMeasurement.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Enums/UnitOfMeasurement.cs index 5373ec9..d046d39 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Enums/UnitOfMeasurement.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Enums/UnitOfMeasurement.cs @@ -1,22 +1,21 @@ using System.ComponentModel; -namespace Browl.Service.MarketDataCollector.Domain.Enums +namespace Browl.Service.MarketDataCollector.Domain.Enums; + +public enum UnitOfMeasurement : byte { - public enum UnitOfMeasurement : byte - { - [Description("UN")] - Unity = 1, + [Description("UN")] + Unity = 1, - [Description("MG")] - Milligram = 2, + [Description("MG")] + Milligram = 2, - [Description("G")] - Gram = 3, + [Description("G")] + Gram = 3, - [Description("KG")] - Kilogram = 4, + [Description("KG")] + Kilogram = 4, - [Description("L")] - Liter = 5 - } + [Description("L")] + Liter = 5 } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Extensions/EnumExtensions.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Extensions/EnumExtensions.cs index 411894c..e585d24 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Extensions/EnumExtensions.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Extensions/EnumExtensions.cs @@ -1,22 +1,21 @@ using System.ComponentModel; -namespace Browl.Service.MarketDataCollector.Domain.Extensions +namespace Browl.Service.MarketDataCollector.Domain.Extensions; + +public static class EnumExtensions { - public static class EnumExtensions - { - public static string ToDescriptionString(this TEnum? value) where TEnum : Enum - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + public static string ToDescriptionString(this TEnum? value) where TEnum : Enum + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } - var valueAsString = value.ToString(); - var valueType = value.GetType(); - var fieldInfo = valueType.GetField(valueAsString)!; - var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); + var valueAsString = value.ToString(); + var valueType = value.GetType(); + var fieldInfo = valueType.GetField(valueAsString)!; + var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); - return attributes?[0].Description ?? valueAsString; - } - } + return attributes?[0].Description ?? valueAsString; + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IClienteManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IClienteManager.cs deleted file mode 100644 index 7086cab..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IClienteManager.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Cliente; - -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; - -public interface IClienteManager -{ - Task DeleteClienteAsync(int id); - - Task GetClienteAsync(int id); - - Task> GetClientesAsync(); - - Task InsertClienteAsync(NovoCliente cliente); - - Task UpdateClienteAsync(AlteraCliente cliente); -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/ICustomerManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/ICustomerManager.cs new file mode 100644 index 0000000..4fe94fa --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/ICustomerManager.cs @@ -0,0 +1,16 @@ +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; + +public interface ICustomerManager +{ + Task DeleteAsync(int id); + + Task GetAsync(int id); + + Task> GetAsync(); + + Task PostAsync(CustomerResource cliente); + + Task PutAsync(CustomerUpdateResource cliente); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IUserManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IUserManager.cs new file mode 100644 index 0000000..4eaab7e --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IUserManager.cs @@ -0,0 +1,17 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Resources.User; + +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; + +public interface IUserManager +{ + Task> GetAsync(); + + Task GetAsync(string login); + + Task InsertAsync(UserNewResource usuario); + + Task UpdateMedicoAsync(User usuario); + + Task ValidaUsuarioEGeraTokenAsync(User usuario); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IUsuarioManager.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IUsuarioManager.cs deleted file mode 100644 index 2c04d4b..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Managers/IUsuarioManager.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Usuario; -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; - -public interface IUsuarioManager -{ - Task> GetAsync(); - - Task GetAsync(string login); - - Task InsertAsync(NovoUsuario usuario); - - Task UpdateMedicoAsync(Usuario usuario); - - Task ValidaUsuarioEGeraTokenAsync(Usuario usuario); -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/ICategoryRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/ICategoryRepository.cs index 6ba40a0..2adec37 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/ICategoryRepository.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/ICategoryRepository.cs @@ -1,13 +1,12 @@ using Browl.Service.MarketDataCollector.Domain.Entities; -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; + +public interface ICategoryRepository { - public interface ICategoryRepository - { - Task> ListAsync(); - Task AddAsync(Category category); - Task FindByIdAsync(int id); - void Update(Category category); - void Remove(Category category); - } + Task> ListAsync(); + Task AddAsync(Category category); + Task FindByIdAsync(int id); + void Update(Category category); + void Remove(Category category); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IClienteRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IClienteRepository.cs deleted file mode 100644 index 445bdbe..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IClienteRepository.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; - -public interface IClienteRepository -{ - Task DeleteClienteAsync(int id); - - Task GetClienteAsync(int id); - - Task> GetClientesAsync(); - - Task InsertClienteAsync(Cliente cliente); - - Task UpdateClienteAsync(Cliente cliente); -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/ICustomerRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/ICustomerRepository.cs new file mode 100644 index 0000000..39e852d --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/ICustomerRepository.cs @@ -0,0 +1,16 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; + +public interface ICustomerRepository +{ + Task DeleteAsync(int id); + + Task GetAsync(int id); + + Task> GetAsync(); + + Task PostAsync(Customer cliente); + + Task PutAsync(Customer cliente); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IProductRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IProductRepository.cs index 6f168ec..ad9abb9 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IProductRepository.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IProductRepository.cs @@ -1,14 +1,14 @@ using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Queries; +using Browl.Service.MarketDataCollector.Domain.Queries.Base; -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; + +public interface IProductRepository { - public interface IProductRepository - { - Task> ListAsync(ProductsQuery query); - Task AddAsync(Product product); - Task FindByIdAsync(int id); - void Update(Product product); - void Remove(Product product); - } + Task> ListAsync(ProductsQuery query); + Task AddAsync(Product product); + Task FindByIdAsync(int id); + void Update(Product product); + void Remove(Product product); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUnitOfWork.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUnitOfWork.cs index 8a58708..f512004 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUnitOfWork.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUnitOfWork.cs @@ -1,7 +1,6 @@ -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; + +public interface IUnitOfWork { - public interface IUnitOfWork - { - Task CompleteAsync(); - } + Task CompleteAsync(); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUserRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUserRepository.cs new file mode 100644 index 0000000..3ea8ae6 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUserRepository.cs @@ -0,0 +1,14 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; + +public interface IUserRepository +{ + Task> GetAsync(); + + Task GetAsync(string login); + + Task InsertAsync(User usuario); + + Task UpdateAsync(User usuario); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUsuarioRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUsuarioRepository.cs deleted file mode 100644 index 961b5dc..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Repositories/IUsuarioRepository.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; - -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; - -public interface IUsuarioRepository -{ - Task> GetAsync(); - - Task GetAsync(string login); - - Task InsertAsync(Usuario usuario); - - Task UpdateAsync(Usuario usuario); -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ICategoryService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ICategoryService.cs index ed523b9..eb78980 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ICategoryService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ICategoryService.cs @@ -1,13 +1,12 @@ using Browl.Service.MarketDataCollector.Domain.Communication; using Browl.Service.MarketDataCollector.Domain.Entities; -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services; + +public interface ICategoryService { - public interface ICategoryService - { - Task> ListAsync(); - Task> SaveAsync(Category category); - Task> UpdateAsync(int id, Category category); - Task> DeleteAsync(int id); - } + Task> ListAsync(); + Task> SaveAsync(Category category); + Task> UpdateAsync(int id, Category category); + Task> DeleteAsync(int id); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHabitService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHabitService.cs index 2f63c91..275ab94 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHabitService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHabitService.cs @@ -1,13 +1,13 @@ -using Browl.Service.MarketDataCollector.Domain.Dtos.Habit; -using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Resources.Habit; namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services; public interface IHabitService { - Task Create(string name, string description); - Task GetById(int id); - Task> GetAll(); - Task DeleteById(int id); - Task UpdateById(int id, UpdateHabitDto request); -} \ No newline at end of file + Task Create(string name, string description); + Task GetById(int id); + Task> GetAll(); + Task DeleteById(int id); + Task UpdateById(int id, UpdateHabitResource request); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHasTenant.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHasTenant.cs index 4e07922..c7cc9cd 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHasTenant.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IHasTenant.cs @@ -2,5 +2,5 @@ namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services; public interface IHasTenant { - public string TenantName { get; set; } + public string TenantName { get; set; } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IJWTService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IJWTService.cs index bf7dac7..e7ba15e 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IJWTService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IJWTService.cs @@ -4,5 +4,5 @@ namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services; public interface IJwtService { - string GenerateToken(Usuario usuario); -} \ No newline at end of file + string GenerateToken(User user); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IProductService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IProductService.cs index bcea15a..b360af4 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IProductService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/IProductService.cs @@ -1,14 +1,14 @@ using Browl.Service.MarketDataCollector.Domain.Communication; using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Queries; +using Browl.Service.MarketDataCollector.Domain.Queries.Base; -namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services +namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services; + +public interface IProductService { - public interface IProductService - { - Task> ListAsync(ProductsQuery query); - Task> SaveAsync(Product product); - Task> UpdateAsync(int id, Product product); - Task> DeleteAsync(int id); - } + Task> ListAsync(ProductsQuery query); + Task> SaveAsync(Product product); + Task> UpdateAsync(int id, Product product); + Task> DeleteAsync(int id); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ITenantService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ITenantService.cs index ed236f7..18654e4 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ITenantService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Interfaces/Services/ITenantService.cs @@ -3,6 +3,6 @@ namespace Browl.Service.MarketDataCollector.Domain.Interfaces.Services; public interface ITenantService { - public string GetConnectionString(); - public Tenant GetTenant(); + public string GetConnectionString(); + public Tenant GetTenant(); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Base/Query.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Base/Query.cs new file mode 100644 index 0000000..87192ce --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Base/Query.cs @@ -0,0 +1,23 @@ +namespace Browl.Service.MarketDataCollector.Domain.Queries.Base; + +public class Query +{ + public int Page { get; protected set; } + public int ItemsPerPage { get; protected set; } + + public Query(int page, int itemsPerPage) + { + Page = page; + ItemsPerPage = itemsPerPage; + + if (Page <= 0) + { + Page = 1; + } + + if (ItemsPerPage <= 0) + { + ItemsPerPage = 10; + } + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Base/QueryResult.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Base/QueryResult.cs new file mode 100644 index 0000000..e1ef360 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Base/QueryResult.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.MarketDataCollector.Domain.Queries.Base; + +public class QueryResult +{ + public List Items { get; set; } = new List(); + public int TotalItems { get; set; } = 0; +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/ProductsQuery.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/ProductsQuery.cs index aaf89fa..f5f5f22 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/ProductsQuery.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/ProductsQuery.cs @@ -1,12 +1,10 @@ -namespace Browl.Service.MarketDataCollector.Domain.Queries +using Browl.Service.MarketDataCollector.Domain.Queries.Base; + +namespace Browl.Service.MarketDataCollector.Domain.Queries; + +public class ProductsQuery : Query { - public class ProductsQuery : Query - { - public int? CategoryId { get; set; } + public int? CategoryId { get; set; } - public ProductsQuery(int? categoryId, int page, int itemsPerPage) : base(page, itemsPerPage) - { - CategoryId = categoryId; - } - } -} \ No newline at end of file + public ProductsQuery(int? categoryId, int page, int itemsPerPage) : base(page, itemsPerPage) => CategoryId = categoryId; +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Query.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Query.cs deleted file mode 100644 index 805a6ba..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/Query.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Queries -{ - public class Query - { - public int Page { get; protected set; } - public int ItemsPerPage { get; protected set; } - - public Query(int page, int itemsPerPage) - { - Page = page; - ItemsPerPage = itemsPerPage; - - if (Page <= 0) - { - Page = 1; - } - - if (ItemsPerPage <= 0) - { - ItemsPerPage = 10; - } - } - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/QueryResult.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/QueryResult.cs deleted file mode 100644 index a6b1f90..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Queries/QueryResult.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Queries -{ - public class QueryResult - { - public List Items { get; set; } = new List(); - public int TotalItems { get; set; } = 0; - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/AddressNewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/AddressNewResource.cs new file mode 100644 index 0000000..4332133 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/AddressNewResource.cs @@ -0,0 +1,21 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Address; + +public class AddressNewResource +{ + ///49000000 + public int CEP { get; set; } + + public StateViewResource Estado { get; set; } + + ///Aracaju + public required string Cidade { get; set; } + + ///Rua A + public required string Logradouro { get; set; } + + ///15 + public required string Numero { get; set; } + + ///Ao lado do posto + public required string Complemento { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/AddressViewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/AddressViewResource.cs new file mode 100644 index 0000000..55c8931 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/AddressViewResource.cs @@ -0,0 +1,13 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Address; + +public class AddressViewResource : ICloneable +{ + public int CEP { get; set; } + public StateViewResource Estado { get; set; } + public required string Cidade { get; set; } + public required string Logradouro { get; set; } + public required string Numero { get; set; } + public required string Complemento { get; set; } + + public object Clone() => MemberwiseClone(); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/StateViewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/StateViewResource.cs new file mode 100644 index 0000000..147c89f --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Address/StateViewResource.cs @@ -0,0 +1,32 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Address; + +public enum StateViewResource +{ + AC, + AL, + AP, + AM, + BA, + CE, + DF, + ES, + GO, + MA, + MT, + MS, + MG, + PA, + PB, + PR, + PE, + PI, + RJ, + RN, + RS, + RO, + RR, + SC, + SP, + SE, + TO +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Category/CategoryResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Category/CategoryResource.cs new file mode 100644 index 0000000..404c4f4 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Category/CategoryResource.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Category; + +public record CategoryResource +{ + public int Id { get; init; } + public string Name { get; init; } = null!; +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Category/CategorySaveResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Category/CategorySaveResource.cs new file mode 100644 index 0000000..541ddbe --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Category/CategorySaveResource.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace Browl.Service.MarketDataCollector.Domain.Resources.Category; + +public record CategorySaveResource +{ + [Required] + [MaxLength(30)] + public required string Name { get; init; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerResource.cs new file mode 100644 index 0000000..14eeba7 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerResource.cs @@ -0,0 +1,39 @@ +using Browl.Service.MarketDataCollector.Domain.Enums; +using Browl.Service.MarketDataCollector.Domain.Resources.Address; +using Browl.Service.MarketDataCollector.Domain.Resources.Telephone; + +namespace Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +/// +/// Objeto utilizado para inserção de um novo cliente. +/// +public class CustomerResource +{ + /// + /// Nome do cliente + /// + /// João do Caminhão + public required string Nome { get; set; } + + /// + /// Data do nascimento do cliente. + /// + /// 1980-01-01 + public DateTime DataNascimento { get; set; } + + /// + /// Sexo do cliente + /// + /// M + public Gender Sexo { get; set; } + + /// + /// Documento do cliente: CNH, CPF, RG + /// + /// 12341231312 + public required string Documento { get; set; } + + public required AddressNewResource Endereco { get; set; } + + public required ICollection Telefones { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerUpdateResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerUpdateResource.cs new file mode 100644 index 0000000..b73fb0e --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerUpdateResource.cs @@ -0,0 +1,6 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +public class CustomerUpdateResource : CustomerResource +{ + public int Id { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerViewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerViewResource.cs new file mode 100644 index 0000000..cadf91e --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Customer/CustomerViewResource.cs @@ -0,0 +1,33 @@ +using Browl.Service.MarketDataCollector.Domain.Enums; +using Browl.Service.MarketDataCollector.Domain.Resources.Address; +using Browl.Service.MarketDataCollector.Domain.Resources.Telephone; + +namespace Browl.Service.MarketDataCollector.Domain.Resources.Customer; + +public class CustomerViewResource : ICloneable +{ + public int Id { get; set; } + public required string Nome { get; set; } + public DateTime DataNascimento { get; set; } + + public Gender Sexo { get; set; } + public required ICollection Telefones { get; set; } + + public required string Documento { get; set; } + public DateTime Criacao { get; set; } + public DateTime? UltimaAtualizacao { get; set; } + + public required AddressViewResource Endereco { get; set; } + + public object Clone() + { + var cliente = (CustomerViewResource)MemberwiseClone(); + cliente.Endereco = (AddressViewResource)cliente.Endereco.Clone(); + List telefones = new(); + cliente.Telefones.ToList().ForEach(p => telefones.Add((TelephoneViewResource)p.Clone())); + cliente.Telefones = telefones; + return cliente; + } + + public CustomerViewResource CloneTipado() => (CustomerViewResource)Clone(); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Erro/ErrorResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Erro/ErrorResource.cs new file mode 100644 index 0000000..78fb8d3 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Erro/ErrorResource.cs @@ -0,0 +1,19 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Erro; + +public record ErrorResource +{ + public bool Success => false; + public List Messages { get; private set; } + + public ErrorResource(List messages) => Messages = messages ?? new(); + + public ErrorResource(string message) + { + Messages = new(); + + if (!string.IsNullOrWhiteSpace(message)) + { + Messages.Add(message); + } + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Erro/ErrorResponseResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Erro/ErrorResponseResource.cs new file mode 100644 index 0000000..4180150 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Erro/ErrorResponseResource.cs @@ -0,0 +1,15 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Erro; + +public class ErrorResponseResource +{ + public string Id { get; set; } + public DateTime Data { get; set; } + public string Mensagem { get; set; } + + public ErrorResponseResource(string id) + { + Id = id; + Data = DateTime.Now; + Mensagem = "Erro inesperado."; + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/CreateHabitResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/CreateHabitResource.cs new file mode 100644 index 0000000..89ef3b0 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/CreateHabitResource.cs @@ -0,0 +1,8 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Habit; + +public class CreateHabitResource +{ + public required string Name { get; set; } + public int UserId { get; set; } + public string Description { get; set; } = default!; +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/GetGoodHabitDetailResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/GetGoodHabitDetailResource.cs new file mode 100644 index 0000000..59153c1 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/GetGoodHabitDetailResource.cs @@ -0,0 +1,10 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Habit; + +public class GetGoodHabitDetailResource +{ + public int Id { get; set; } + public required string Name { get; set; } + public required string UserName { get; set; } + public required string GoalName { get; set; } + public required string Duration { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/GetGoodHabitResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/GetGoodHabitResource.cs new file mode 100644 index 0000000..ab2633d --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/GetGoodHabitResource.cs @@ -0,0 +1,6 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Habit; +public class GetGoodHabitResource +{ + public int Id { get; set; } + public required string Name { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/HabitDetailResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/HabitDetailResource.cs new file mode 100644 index 0000000..a69dac7 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/HabitDetailResource.cs @@ -0,0 +1,10 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Habit; + +public class HabitDetailResource +{ + public int Id { get; set; } + public string Name { get; set; } = default!; + public string UserName { get; set; } = default!; + public string GoalName { get; set; } = default!; + public string Duration { get; set; } = default!; +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/HabitResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/HabitResource.cs new file mode 100644 index 0000000..3825503 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/HabitResource.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Habit; +public class HabitResource +{ + public int Id { get; set; } = default!; + public string Name { get; set; } = default!; + public string Description { get; set; } = default!; +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/UpdateHabitResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/UpdateHabitResource.cs new file mode 100644 index 0000000..2710e3a --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Habit/UpdateHabitResource.cs @@ -0,0 +1,6 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Habit; +public class UpdateHabitResource +{ + public string Name { get; set; } = default!; + public string Description { get; set; } = default!; +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductResource.cs new file mode 100644 index 0000000..c8c36e5 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductResource.cs @@ -0,0 +1,12 @@ +using Browl.Service.MarketDataCollector.Domain.Resources.Category; + +namespace Browl.Service.MarketDataCollector.Domain.Resources.Product; + +public record ProductResource +{ + public int Id { get; init; } + public string Name { get; init; } = null!; + public int QuantityInPackage { get; init; } + public string UnitOfMeasurement { get; init; } = null!; + public required CategoryResource Category { get; init; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductSaveResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductSaveResource.cs new file mode 100644 index 0000000..6a098ba --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductSaveResource.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; + +namespace Browl.Service.MarketDataCollector.Domain.Resources.Product; + +public record ProductSaveResource +{ + [Required] + [MaxLength(50)] + public required string Name { get; init; } + + [Required] + [Range(0, 100)] + public short QuantityInPackage { get; init; } + + [Required] + [Range(1, 5)] + public int UnitOfMeasurement { get; init; } + + [Required] + public int CategoryId { get; init; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductsQueryResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductsQueryResource.cs new file mode 100644 index 0000000..46a6459 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Product/ProductsQueryResource.cs @@ -0,0 +1,8 @@ +using Browl.Service.MarketDataCollector.Domain.Resources.Query; + +namespace Browl.Service.MarketDataCollector.Domain.Resources.Product; + +public record ProductsQueryResource : QueryResource +{ + public int CategoryId { get; init; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Query/QueryResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Query/QueryResource.cs new file mode 100644 index 0000000..c5b23d5 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Query/QueryResource.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Query; + +public record QueryResource +{ + public int Page { get; init; } + public int ItemsPerPage { get; init; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Query/QueryResultResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Query/QueryResultResource.cs new file mode 100644 index 0000000..62b885f --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Query/QueryResultResource.cs @@ -0,0 +1,9 @@ +namespace Browl.Service.MarketDataCollector.Application.Resources +{ + public record QueryResultResource + { + public int TotalItems { get; init; } = 0; + public List Items { get; init; } = new(); + } +} + diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Telephone/TelephoneNewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Telephone/TelephoneNewResource.cs new file mode 100644 index 0000000..3f72059 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Telephone/TelephoneNewResource.cs @@ -0,0 +1,10 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Telephone; + +public class TelephoneNewResource +{ + /// + /// Telefone do cliente + /// + /// 79999887744 + public required string Numero { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Telephone/TelephoneViewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Telephone/TelephoneViewResource.cs new file mode 100644 index 0000000..40c8f68 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/Telephone/TelephoneViewResource.cs @@ -0,0 +1,9 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.Telephone; + +public class TelephoneViewResource : ICloneable +{ + public int Id { get; set; } + public required string Numero { get; set; } + + public object Clone() => MemberwiseClone(); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/ReferenceRoleResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/ReferenceRoleResource.cs new file mode 100644 index 0000000..9679a76 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/ReferenceRoleResource.cs @@ -0,0 +1,6 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.User; + +public class ReferenceRoleResource +{ + public int Id { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/RoleViewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/RoleViewResource.cs new file mode 100644 index 0000000..fca4164 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/RoleViewResource.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.User; + +public class RoleViewResource +{ + public int Id { get; set; } + public required string Descricao { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserLoggedResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserLoggedResource.cs new file mode 100644 index 0000000..3373977 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserLoggedResource.cs @@ -0,0 +1,8 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.User; + +public class UserLoggedResource +{ + public required string Login { get; set; } + public required ICollection Funcoes { get; set; } + public required string Token { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserNewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserNewResource.cs new file mode 100644 index 0000000..7e5e797 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserNewResource.cs @@ -0,0 +1,9 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.User; + +public class UserNewResource +{ + public string Login { get; set; } + public string Senha { get; set; } + + public ICollection Funcoes { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserViewResource.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserViewResource.cs new file mode 100644 index 0000000..932016e --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Domain/Resources/User/UserViewResource.cs @@ -0,0 +1,7 @@ +namespace Browl.Service.MarketDataCollector.Domain.Resources.User; + +public class UserViewResource +{ + public required string Login { get; set; } + public required ICollection Funcoes { get; set; } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Cache/CacheKeys.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Cache/CacheKeys.cs index f321119..202c220 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Cache/CacheKeys.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Cache/CacheKeys.cs @@ -1,8 +1,7 @@ -namespace Browl.Service.MarketDataCollector.Infrastructure.Cache +namespace Browl.Service.MarketDataCollector.Infrastructure.Cache; + +public enum CacheKeys : byte { - public enum CacheKeys : byte - { - CategoriesList, - ProductsList, - } + CategoriesList, + ProductsList, } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/AddressConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/AddressConfiguration.cs new file mode 100644 index 0000000..1336f0e --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/AddressConfiguration.cs @@ -0,0 +1,16 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; + +public class AddressConfiguration : IEntityTypeConfiguration
+{ + public void Configure(EntityTypeBuilder
builder) + { + _ = builder.HasKey(p => p.ClienteId); + _ = builder.Property(p => p.Estado).HasConversion( + p => p.ToString(), + p => (State)Enum.Parse(typeof(State), p)); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/CategoryConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/CategoryConfiguration.cs index 3945b2e..111890e 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/CategoryConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/CategoryConfiguration.cs @@ -1,18 +1,18 @@ using Browl.Service.MarketDataCollector.Domain.Entities; + using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; + +public class CategoryConfiguration : IEntityTypeConfiguration { - public class CategoryConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Categories"); - builder.HasKey(p => p.Id); - builder.Property(p => p.Id).IsRequired().ValueGeneratedOnAdd(); - builder.Property(p => p.Name).IsRequired().HasMaxLength(30); - builder.HasMany(p => p.Products).WithOne(p => p.Category).HasForeignKey(p => p.CategoryId); - } - } + public void Configure(EntityTypeBuilder builder) + { + _ = builder.ToTable("Categories"); + _ = builder.HasKey(p => p.Id); + _ = builder.Property(p => p.Id).IsRequired().ValueGeneratedOnAdd(); + _ = builder.Property(p => p.Name).IsRequired().HasMaxLength(30); + _ = builder.HasMany(p => p.Products).WithOne(p => p.Category).HasForeignKey(p => p.CategoryId); + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/ClienteConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/ClienteConfiguration.cs deleted file mode 100644 index 4f7cf2b..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/ClienteConfiguration.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; - -public class ClienteConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.Property(p => p.Nome).HasMaxLength(200).IsRequired(); - builder.Property(p => p.Sexo).HasConversion( - p => p.ToString(), - p => (Sexo)Enum.Parse(typeof(Sexo), p)); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/CustomerConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/CustomerConfiguration.cs new file mode 100644 index 0000000..ae32b62 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/CustomerConfiguration.cs @@ -0,0 +1,16 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; + +public class CustomerConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + _ = builder.Property(p => p.Nome).HasMaxLength(200).IsRequired(); + _ = builder.Property(p => p.Sexo).HasConversion( + p => p.ToString(), + p => (Gender)Enum.Parse(typeof(Gender), p)); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/EnderecoConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/EnderecoConfiguration.cs deleted file mode 100644 index 5b5e29d..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/EnderecoConfiguration.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; - -public class EnderecoConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.HasKey(p => p.ClienteId); - builder.Property(p => p.Estado).HasConversion( - p => p.ToString(), - p => (Estado)Enum.Parse(typeof(Estado), p)); - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/ProductConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/ProductConfiguration.cs index facd0e3..eb7a5f9 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/ProductConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/ProductConfiguration.cs @@ -1,19 +1,19 @@ using Browl.Service.MarketDataCollector.Domain.Entities; + using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; + +public class ProductConfiguration : IEntityTypeConfiguration { - public class ProductConfiguration : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Products"); - builder.HasKey(p => p.Id); - builder.Property(p => p.Id).IsRequired().ValueGeneratedOnAdd(); - builder.Property(p => p.Name).IsRequired().HasMaxLength(50); - builder.Property(p => p.QuantityInPackage).IsRequired(); - builder.Property(p => p.UnitOfMeasurement).IsRequired(); - } - } + public void Configure(EntityTypeBuilder builder) + { + _ = builder.ToTable("Products"); + _ = builder.HasKey(p => p.Id); + _ = builder.Property(p => p.Id).IsRequired().ValueGeneratedOnAdd(); + _ = builder.Property(p => p.Name).IsRequired().HasMaxLength(50); + _ = builder.Property(p => p.QuantityInPackage).IsRequired(); + _ = builder.Property(p => p.UnitOfMeasurement).IsRequired(); + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/TelefoneConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/TelephoneConfiguration.cs similarity index 53% rename from src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/TelefoneConfiguration.cs rename to src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/TelephoneConfiguration.cs index 7d5233e..a12380d 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/TelefoneConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/TelephoneConfiguration.cs @@ -1,13 +1,11 @@ using Browl.Service.MarketDataCollector.Domain.Entities; + using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; -public class TelefoneConfiguration : IEntityTypeConfiguration +public class TelephoneConfiguration : IEntityTypeConfiguration { - public void Configure(EntityTypeBuilder builder) - { - builder.HasKey(p => new { p.ClienteId, p.Numero }); - } -} \ No newline at end of file + public void Configure(EntityTypeBuilder builder) => _ = builder.HasKey(p => new { p.ClienteId, p.Numero }); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/UsuarioConfiguration.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/UserConfiguration.cs similarity index 56% rename from src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/UsuarioConfiguration.cs rename to src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/UserConfiguration.cs index 125d0d8..bbb9048 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/UsuarioConfiguration.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Configurations/UserConfiguration.cs @@ -1,13 +1,11 @@ using Browl.Service.MarketDataCollector.Domain.Entities; + using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; -public class UsuarioConfiguration : IEntityTypeConfiguration +public class UserConfiguration : IEntityTypeConfiguration { - public void Configure(EntityTypeBuilder builder) - { - builder.HasKey(k => k.Login); - } -} \ No newline at end of file + public void Configure(EntityTypeBuilder builder) => _ = builder.HasKey(k => k.Login); +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Contexts/BrowlDbContext.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Contexts/BrowlDbContext.cs index 392c587..9a2d6c4 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Contexts/BrowlDbContext.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Contexts/BrowlDbContext.cs @@ -1,57 +1,55 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; +using System.Reflection; + +using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; using Browl.Service.MarketDataCollector.Infrastructure.Data.Configurations; + using Microsoft.EntityFrameworkCore; -using System.Reflection; namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; public class BrowlDbContext : DbContext { - private readonly ITenantService _tenantService; - public BrowlDbContext(DbContextOptions options, ITenantService service) : base(options) => _tenantService = service; - public string TenantName - { - get => _tenantService.GetTenant()?.TenantName ?? string.Empty; - } + private readonly ITenantService _tenantService; + public BrowlDbContext(DbContextOptions options, ITenantService service) : base(options) => _tenantService = service; + + public string TenantName => _tenantService.GetTenant()?.TenantName ?? string.Empty; + + public DbSet Categories { get; set; } + public DbSet Products { get; set; } + public DbSet? Habits { get; set; } + public DbSet? Progress { get; set; } + public DbSet? Reminders { get; set; } + public DbSet? Goals { get; set; } + public DbSet Customers { get; set; } + public DbSet
Addresses { get; set; } + public DbSet Telephones { get; set; } + public DbSet Users { get; set; } + public DbSet Roles { get; set; } - public DbSet Categories { get; set; } - public DbSet Products { get; set; } - public DbSet? Habits { get; set; } - public DbSet? Users { get; set; } - public DbSet? Progress { get; set; } - public DbSet? Reminders { get; set; } - public DbSet? Goals { get; set; } - public DbSet Clientes { get; set; } - public DbSet Enderecos { get; set; } - public DbSet Telefones { get; set; } - public DbSet Usuarios { get; set; } - public DbSet Funcoes { get; set; } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - var tenantConnectionString = _tenantService.GetConnectionString(); - if (!string.IsNullOrEmpty(tenantConnectionString)) - { - optionsBuilder.UseSqlServer(_tenantService.GetConnectionString()); - } - } - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - modelBuilder.Entity().HasQueryFilter(a => a.TenantName == TenantName); - modelBuilder.ApplyConfiguration(new ClienteConfiguration()); - modelBuilder.ApplyConfiguration(new EnderecoConfiguration()); - modelBuilder.ApplyConfiguration(new TelefoneConfiguration()); - modelBuilder.ApplyConfiguration(new UsuarioConfiguration()); - modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); - //SeedData.Seed(modelBuilder); - } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + var tenantConnectionString = _tenantService.GetConnectionString(); + if (!string.IsNullOrEmpty(tenantConnectionString)) + { + _ = optionsBuilder.UseSqlServer(_tenantService.GetConnectionString()); + } + } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + _ = modelBuilder.Entity().HasQueryFilter(a => a.TenantName == TenantName); + _ = modelBuilder.ApplyConfiguration(new CustomerConfiguration()); + _ = modelBuilder.ApplyConfiguration(new AddressConfiguration()); + _ = modelBuilder.ApplyConfiguration(new TelephoneConfiguration()); + _ = modelBuilder.ApplyConfiguration(new UserConfiguration()); + _ = modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); + } - public override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) - { - ChangeTracker.Entries() - .Where(entry => entry.State == EntityState.Added || entry.State == EntityState.Modified) - .ToList().ForEach(entry => entry.Entity.TenantName = TenantName); - return await base.SaveChangesAsync(cancellationToken); - } -} \ No newline at end of file + public override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) + { + ChangeTracker.Entries() + .Where(entry => entry.State is EntityState.Added or EntityState.Modified) + .ToList().ForEach(entry => entry.Entity.TenantName = TenantName); + return await base.SaveChangesAsync(cancellationToken); + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/BaseRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/BaseRepository.cs index 355a8cb..653a024 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/BaseRepository.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/BaseRepository.cs @@ -1,14 +1,10 @@ using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; + +public abstract class BaseRepository { - public abstract class BaseRepository - { - protected readonly BrowlDbContext _browlDbContext; + protected readonly BrowlDbContext _browlDbContext; - public BaseRepository(BrowlDbContext bowlDbContext) - { - _browlDbContext = bowlDbContext; - } - } + public BaseRepository(BrowlDbContext bowlDbContext) => _browlDbContext = bowlDbContext; } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/CategoryRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/CategoryRepository.cs index 2b17a61..8a99b1c 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/CategoryRepository.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/CategoryRepository.cs @@ -1,22 +1,22 @@ using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; + using Microsoft.EntityFrameworkCore; -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; + +public class CategoryRepository : BaseRepository, ICategoryRepository { - public class CategoryRepository : BaseRepository, ICategoryRepository - { - public CategoryRepository(BrowlDbContext context) : base(context) { } + public CategoryRepository(BrowlDbContext context) : base(context) { } - public async Task> ListAsync() => await _browlDbContext.Categories.AsNoTracking().ToListAsync(); + public async Task> ListAsync() => await _browlDbContext.Categories.AsNoTracking().ToListAsync(); - public async Task AddAsync(Category category) => await _browlDbContext.Categories.AddAsync(category); + public async Task AddAsync(Category category) => _ = await _browlDbContext.Categories.AddAsync(category); - public async Task FindByIdAsync(int id) => await _browlDbContext.Categories.FindAsync(id); + public async Task FindByIdAsync(int id) => await _browlDbContext.Categories.FindAsync(id); - public void Update(Category category) => _browlDbContext.Categories.Update(category); + public void Update(Category category) => _ = _browlDbContext.Categories.Update(category); - public void Remove(Category category) => _browlDbContext.Categories.Remove(category); - } + public void Remove(Category category) => _ = _browlDbContext.Categories.Remove(category); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/ClienteRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/ClienteRepository.cs deleted file mode 100644 index be6bfe9..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/ClienteRepository.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; -using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; -using Microsoft.EntityFrameworkCore; - -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; - -public class ClienteRepository : BaseRepository, IClienteRepository -{ - private readonly BrowlDbContext _browlDbContext; - - public ClienteRepository(BrowlDbContext context) : base(context) { } - - public async Task> GetClientesAsync() - { - return await _browlDbContext.Clientes - .Include(p => p.Endereco) - .Include(p => p.Telefones) - .AsNoTracking().ToListAsync(); - } - - public async Task GetClienteAsync(int id) - { - return await _browlDbContext.Clientes - .Include(p => p.Endereco) - .Include(p => p.Telefones) - .SingleOrDefaultAsync(p => p.Id == id); - } - - public async Task InsertClienteAsync(Cliente cliente) - { - await _browlDbContext.Clientes.AddAsync(cliente); - await _browlDbContext.SaveChangesAsync(); - return cliente; - } - - public async Task UpdateClienteAsync(Cliente cliente) - { - var clienteConsultado = await _browlDbContext.Clientes - .Include(p => p.Endereco) - .Include(p => p.Telefones) - .FirstOrDefaultAsync(p => p.Id == cliente.Id); - if (clienteConsultado == null) - { - return null; - } - _browlDbContext.Entry(clienteConsultado).CurrentValues.SetValues(cliente); - clienteConsultado.Endereco = cliente.Endereco; - UpdateClienteTelefones(cliente, clienteConsultado); - await _browlDbContext.SaveChangesAsync(); - return clienteConsultado; - } - - private static void UpdateClienteTelefones(Cliente cliente, Cliente clienteConsultado) - { - clienteConsultado.Telefones.Clear(); - foreach (var telefone in cliente.Telefones) - { - clienteConsultado.Telefones.Add(telefone); - } - } - - public async Task DeleteClienteAsync(int id) - { - var clienteConsultado = await _browlDbContext.Clientes.FindAsync(id); - if (clienteConsultado == null) - { - return null; - } - var clienteRemovido = _browlDbContext.Clientes.Remove(clienteConsultado); - await _browlDbContext.SaveChangesAsync(); - return clienteRemovido.Entity; - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/CustomerRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/CustomerRepository.cs new file mode 100644 index 0000000..2a09172 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/CustomerRepository.cs @@ -0,0 +1,68 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; +using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; +using Microsoft.EntityFrameworkCore; + +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; + +public class CustomerRepository : BaseRepository, ICustomerRepository +{ + private new readonly BrowlDbContext _browlDbContext; + + public CustomerRepository(BrowlDbContext context) : base(context) { } + + public async Task> GetAsync() => await _browlDbContext.Customers + .Include(p => p.Endereco) + .Include(p => p.Telefones) + .AsNoTracking().ToListAsync(); + + public async Task GetAsync(int id) => await _browlDbContext.Customers + .Include(p => p.Endereco) + .Include(p => p.Telefones) + .SingleOrDefaultAsync(p => p.Id == id); + + public async Task PostAsync(Customer cliente) + { + _ = await _browlDbContext.Customers.AddAsync(cliente); + _ = await _browlDbContext.SaveChangesAsync(); + return cliente; + } + + public async Task PutAsync(Customer cliente) + { + var clienteConsultado = await _browlDbContext.Customers + .Include(p => p.Endereco) + .Include(p => p.Telefones) + .FirstOrDefaultAsync(p => p.Id == cliente.Id); + if (clienteConsultado == null) + { + return null; + } + _browlDbContext.Entry(clienteConsultado).CurrentValues.SetValues(cliente); + clienteConsultado.Endereco = cliente.Endereco; + UpdateClienteTelefones(cliente, clienteConsultado); + _ = await _browlDbContext.SaveChangesAsync(); + return clienteConsultado; + } + + private static void UpdateClienteTelefones(Customer cliente, Customer clienteConsultado) + { + clienteConsultado.Telefones.Clear(); + foreach (var telefone in cliente.Telefones) + { + clienteConsultado.Telefones.Add(telefone); + } + } + + public async Task DeleteAsync(int id) + { + var clienteConsultado = await _browlDbContext.Customers.FindAsync(id); + if (clienteConsultado == null) + { + return null; + } + var clienteRemovido = _browlDbContext.Customers.Remove(clienteConsultado); + _ = await _browlDbContext.SaveChangesAsync(); + return clienteRemovido.Entity; + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/ProductRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/ProductRepository.cs index 5a7efa5..1909014 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/ProductRepository.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/ProductRepository.cs @@ -1,59 +1,48 @@ using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; using Browl.Service.MarketDataCollector.Domain.Queries; +using Browl.Service.MarketDataCollector.Domain.Queries.Base; using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; + using Microsoft.EntityFrameworkCore; -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; + +public class ProductRepository : BaseRepository, IProductRepository { - public class ProductRepository : BaseRepository, IProductRepository - { - public ProductRepository(BrowlDbContext context) : base(context) { } - - public async Task> ListAsync(ProductsQuery query) - { - IQueryable queryable = _browlDbContext.Products - .Include(p => p.Category) - .AsNoTracking(); - - if (query.CategoryId.HasValue && query.CategoryId > 0) - { - queryable = queryable.Where(p => p.CategoryId == query.CategoryId); - } - - int totalItems = await queryable.CountAsync(); - - List products = await queryable.Skip((query.Page - 1) * query.ItemsPerPage) - .Take(query.ItemsPerPage) - .ToListAsync(); - - return new QueryResult - { - Items = products, - TotalItems = totalItems, - }; - } - - public async Task FindByIdAsync(int id) - { - return await _browlDbContext.Products - .Include(p => p.Category) - .FirstOrDefaultAsync(p => p.Id == id); - } - - public async Task AddAsync(Product product) - { - await _browlDbContext.Products.AddAsync(product); - } - - public void Update(Product product) - { - _browlDbContext.Products.Update(product); - } - - public void Remove(Product product) - { - _browlDbContext.Products.Remove(product); - } - } + public ProductRepository(BrowlDbContext context) : base(context) { } + + public async Task> ListAsync(ProductsQuery query) + { + var queryable = _browlDbContext.Products + .Include(p => p.Category) + .AsNoTracking(); + + if (query.CategoryId.HasValue && query.CategoryId > 0) + { + queryable = queryable.Where(p => p.CategoryId == query.CategoryId); + } + + var totalItems = await queryable.CountAsync(); + + var products = await queryable.Skip((query.Page - 1) * query.ItemsPerPage) + .Take(query.ItemsPerPage) + .ToListAsync(); + + return new QueryResult + { + Items = products, + TotalItems = totalItems, + }; + } + + public async Task FindByIdAsync(int id) => await _browlDbContext.Products + .Include(p => p.Category) + .FirstOrDefaultAsync(p => p.Id == id); + + public async Task AddAsync(Product product) => _ = await _browlDbContext.Products.AddAsync(product); + + public void Update(Product product) => _ = _browlDbContext.Products.Update(product); + + public void Remove(Product product) => _ = _browlDbContext.Products.Remove(product); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UnitOfWork.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UnitOfWork.cs index d5a10e1..eab3651 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UnitOfWork.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UnitOfWork.cs @@ -1,19 +1,12 @@ using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; + +public class UnitOfWork : IUnitOfWork { - public class UnitOfWork : IUnitOfWork - { - private readonly BrowlDbContext _context; + private readonly BrowlDbContext _context; - public UnitOfWork(BrowlDbContext context) - { - _context = context; - } - public async Task CompleteAsync() - { - await _context.SaveChangesAsync(); - } - } + public UnitOfWork(BrowlDbContext context) => _context = context; + public async Task CompleteAsync() => _ = await _context.SaveChangesAsync(); } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UserRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UserRepository.cs new file mode 100644 index 0000000..c72a252 --- /dev/null +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UserRepository.cs @@ -0,0 +1,51 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; +using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; +using Microsoft.EntityFrameworkCore; + +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; + +public class UserRepository : BaseRepository, IUserRepository +{ + public UserRepository(BrowlDbContext bowlDbContext) : base(bowlDbContext) + { + } + + public async Task> GetAsync() => await _browlDbContext.Users.AsNoTracking().ToListAsync(); + + public async Task GetAsync(string login) => await _browlDbContext.Users + .Include(p => p.Roles) + .AsNoTracking() + .SingleOrDefaultAsync(p => p.Login == login); + + public async Task InsertAsync(User usuario) + { + await InsertUsuarioFuncaoAsync(usuario); + _ = await _browlDbContext.Users.AddAsync(usuario); + _ = await _browlDbContext.SaveChangesAsync(); + return usuario; + } + + private async Task InsertUsuarioFuncaoAsync(User usuario) + { + List searchingRoles = new(); + foreach (var funcao in usuario.Roles) + { + var role = await _browlDbContext.Roles.FindAsync(funcao.Id); + searchingRoles.Add(role); + } + usuario.Roles = searchingRoles; + } + + public async Task UpdateAsync(User user) + { + var usuarioConsultado = await _browlDbContext.Users.FindAsync(user.Login); + if (usuarioConsultado == null) + { + return null; + } + _browlDbContext.Entry(usuarioConsultado).CurrentValues.SetValues(user); + _ = await _browlDbContext.SaveChangesAsync(); + return usuarioConsultado; + } +} diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UsuarioRepository.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UsuarioRepository.cs deleted file mode 100644 index aedb4bf..0000000 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Repositories/UsuarioRepository.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; -using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; -using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; -using Microsoft.EntityFrameworkCore; - -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Repositories; - -public class UsuarioRepository :BaseRepository, IUsuarioRepository -{ - private readonly BrowlDbContext _browlDbContext; - - public UsuarioRepository(BrowlDbContext context) : base(context) { } - - public async Task> GetAsync() - { - return await _browlDbContext.Usuarios.AsNoTracking().ToListAsync(); - } - - public async Task GetAsync(string login) - { - return await _browlDbContext.Usuarios - .Include(p => p.Funcoes) - .AsNoTracking() - .SingleOrDefaultAsync(p => p.Login == login); - } - - public async Task InsertAsync(Usuario usuario) - { - await InsertUsuarioFuncaoAsync(usuario); - await _browlDbContext.Usuarios.AddAsync(usuario); - await _browlDbContext.SaveChangesAsync(); - return usuario; - } - - private async Task InsertUsuarioFuncaoAsync(Usuario usuario) - { - var funcoesConsultas = new List(); - foreach (var funcao in usuario.Funcoes) - { - var funcaoConsultada = await _browlDbContext.Funcoes.FindAsync(funcao.Id); - funcoesConsultas.Add(funcaoConsultada); - } - usuario.Funcoes = funcoesConsultas; - } - - public async Task UpdateAsync(Usuario usuario) - { - var usuarioConsultado = await _browlDbContext.Usuarios.FindAsync(usuario.Login); - if (usuarioConsultado == null) - { - return null; - } - _browlDbContext.Entry(usuarioConsultado).CurrentValues.SetValues(usuario); - await _browlDbContext.SaveChangesAsync(); - return usuarioConsultado; - } -} \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Seed/SeedData.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Seed/SeedData.cs index 9957a69..594b749 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Seed/SeedData.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Data/Seed/SeedData.cs @@ -2,42 +2,41 @@ using Browl.Service.MarketDataCollector.Domain.Enums; using Browl.Service.MarketDataCollector.Infrastructure.Data.Contexts; -namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Seed +namespace Browl.Service.MarketDataCollector.Infrastructure.Data.Seed; + +public static class SeedData { - public static class SeedData - { - public static async Task Seed(BrowlDbContext context) - { - var products = new List - { - new Product - { - Id = 100, - Name = "Apple", - QuantityInPackage = 1, - UnitOfMeasurement = UnitOfMeasurement.Unity, - CategoryId = 100 - }, - new Product - { - Id = 101, - Name = "Milk", - QuantityInPackage = 2, - UnitOfMeasurement = UnitOfMeasurement.Liter, - CategoryId = 101, - } - }; + public static async Task Seed(BrowlDbContext context) + { + List products = new() + { + new Product + { + Id = 100, + Name = "Apple", + QuantityInPackage = 1, + UnitOfMeasurement = UnitOfMeasurement.Unity, + CategoryId = 100 + }, + new Product + { + Id = 101, + Name = "Milk", + QuantityInPackage = 2, + UnitOfMeasurement = UnitOfMeasurement.Liter, + CategoryId = 101, + } + }; - var categories = new List - { - new Category { Id = 100, Name = "Fruits and Vegetables" }, - new Category { Id = 101, Name = "Dairy" } - }; + List categories = new() + { + new Category(100, "Fruits and Vegetables" ), + new Category(101,"Dairy" ) + }; - context.Products.AddRange(products); - context.Categories.AddRange(categories); + context.Products.AddRange(products); + context.Categories.AddRange(categories); - await context.SaveChangesAsync(); - } - } + _ = await context.SaveChangesAsync(); + } } \ No newline at end of file diff --git a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Services/JWTService.cs b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Services/JWTService.cs index 82ef051..7d5c0de 100644 --- a/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Services/JWTService.cs +++ b/src/Services/Browl.Service.MarketDataCollector/Browl.Service.MarketDataCollector.Infrastructure/Services/JWTService.cs @@ -1,41 +1,40 @@ -using Browl.Service.MarketDataCollector.Domain.Entities; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; + +using Browl.Service.MarketDataCollector.Domain.Entities; using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; + using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using System.Text; namespace Browl.Service.MarketDataCollector.Infrastructure.Services; public class JwtService : IJwtService { - private readonly IConfiguration _configuration; + private readonly IConfiguration _configuration; - public JwtService(IConfiguration configuration) - { - _configuration = configuration; - } + public JwtService(IConfiguration configuration) => _configuration = configuration; - public string GenerateToken(Usuario usuario) - { - var tokenHandler = new JwtSecurityTokenHandler(); - var key = Encoding.ASCII.GetBytes(_configuration.GetSection("JWT:Secret").Value); - var claims = new List - { - new Claim(ClaimTypes.Name, usuario.Login) - }; - claims.AddRange(usuario.Funcoes.Select(p => new Claim(ClaimTypes.Role, p.Descricao))); - var tokenDescriptor = new SecurityTokenDescriptor - { - Subject = new ClaimsIdentity(claims), - Audience = _configuration.GetSection("JWT:Audience").Value, - Issuer = _configuration.GetSection("JWT:Issuer").Value, - Expires = DateTime.UtcNow.AddMinutes(Convert.ToInt32(_configuration.GetSection("JWT:ExpiraEmMinutos").Value)), - SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature) - }; + public string GenerateToken(User usuario) + { + JwtSecurityTokenHandler tokenHandler = new(); + var key = Encoding.ASCII.GetBytes(_configuration.GetSection("JWT:Secret").Value); + List claims = new() + { + new Claim(ClaimTypes.Name, usuario.Login) + }; + claims.AddRange(usuario.Roles.Select(p => new Claim(ClaimTypes.Role, p.Descricao))); + SecurityTokenDescriptor tokenDescriptor = new() + { + Subject = new ClaimsIdentity(claims), + Audience = _configuration.GetSection("JWT:Audience").Value, + Issuer = _configuration.GetSection("JWT:Issuer").Value, + Expires = DateTime.UtcNow.AddMinutes(Convert.ToInt32(_configuration.GetSection("JWT:ExpiraEmMinutos").Value)), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature) + }; - var token = tokenHandler.CreateToken(tokenDescriptor); - return tokenHandler.WriteToken(token); - } -} \ No newline at end of file + var token = tokenHandler.CreateToken(tokenDescriptor); + return tokenHandler.WriteToken(token); + } +} diff --git a/test/Presentation/Browl.Client.Test/EdgeDriverTest.cs b/test/Presentation/Browl.Client.Test/EdgeDriverTest.cs index 8b7ac53..fbedc4b 100644 --- a/test/Presentation/Browl.Client.Test/EdgeDriverTest.cs +++ b/test/Presentation/Browl.Client.Test/EdgeDriverTest.cs @@ -1,45 +1,37 @@ using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; using OpenQA.Selenium.Edge; -using OpenQA.Selenium.Interactions; -using System; -using System.ComponentModel; -namespace Browl.Client.Test +namespace Browl.Client.Test; + +public class EdgeDriverTest : IDisposable { - public class EdgeDriverTest : IDisposable - { - private IWebDriver _webDriver; + private readonly IWebDriver _webDriver; - public EdgeDriverTest() - { - var edgeOptions = new EdgeOptions(); - edgeOptions.AddArgument("--headless"); - _webDriver = new EdgeDriver(edgeOptions); - } + public EdgeDriverTest() + { + EdgeOptions edgeOptions = new(); + edgeOptions.AddArgument("--headless"); + _webDriver = new EdgeDriver(edgeOptions); + } - [Fact] - public void ShouldDisplayBingHomePageTitle() - { - _webDriver.Url = "https://www.bing.com"; - Assert.Equal("Bing", _webDriver.Title); - Dispose(); - } + [Fact] + public void ShouldDisplayBingHomePageTitle() + { + _webDriver.Url = "https://www.bing.com"; + Assert.Equal("Bing", _webDriver.Title); + Dispose(); + } - [Theory] - [InlineData("https://www.bing.com", "Bing")] - [InlineData("https://www.google.com", "Google")] - public void ShouldDisplayCorrectPageTitle(string url, string expectedTitle) - { - _webDriver.Url = url; - Assert.Equal(expectedTitle, _webDriver.Title); - Dispose(); - } + [Theory] + [InlineData("https://www.bing.com", "Bing")] + [InlineData("https://www.google.com", "Google")] + public void ShouldDisplayCorrectPageTitle(string url, string expectedTitle) + { + _webDriver.Url = url; + Assert.Equal(expectedTitle, _webDriver.Title); + Dispose(); + } - public void Dispose() - { - _webDriver.Quit(); - } - } -} \ No newline at end of file + public void Dispose() => _webDriver.Quit(); +} diff --git a/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/AuthControllerTest.cs b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/AuthControllerTest.cs new file mode 100644 index 0000000..3039563 --- /dev/null +++ b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/AuthControllerTest.cs @@ -0,0 +1,63 @@ +using Browl.Service.AuthSecurity.API.Controllers; +using Browl.Service.AuthSecurity.API.Entities; +using Browl.Service.AuthSecurity.API.Test.Builder; + +using FluentAssertions; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; + +using NSubstitute; + +namespace Browl.Service.AuthSecurity.API.Test +{ + public class AuthControllerTest + { + private readonly AuthController _authController; + private readonly SignInManager _signInManager; + private readonly UserManager _userManager; + private readonly IOptions _appSettings; + + public AuthControllerTest() + { + _signInManager = Substitute.For>( + Substitute.For>( + Substitute.For>(), null, null, null, null, null), + Substitute.For(), + Substitute.For>(), + null, null, null, null); + + _userManager = Substitute.For>( + Substitute.For>(), + null, null, null, null, null, null, null, null); + + _appSettings = Substitute.For>(); + _appSettings.Value.Returns(new AppSettings()); + + _authController = new AuthController(_signInManager, _userManager, _appSettings); + } + + [Fact] + public async Task Register_IsValidModel_ReturnsOkResult() + { + // Arrange + var randomUser = RandomUserGenerator.GenerateRandomUser(); + + // Configurar o mock para retornar IdentityResult.Success + _userManager.CreateAsync(Arg.Any(), Arg.Any()) + .Returns(Task.FromResult(IdentityResult.Success)); + + // Act + var result = await _authController.Register(randomUser); + + // Assert + var okResult = result.Should().BeOfType().Subject; + var userResponse = okResult.Value.Should().BeAssignableTo().Subject; + + // Adicione asserções adicionais, se necessário + } + + } +} diff --git a/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Browl.Service.AuthSecurity.API.Test.csproj b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Browl.Service.AuthSecurity.API.Test.csproj new file mode 100644 index 0000000..27ec3d3 --- /dev/null +++ b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Browl.Service.AuthSecurity.API.Test.csproj @@ -0,0 +1,31 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Builder/RandomUserGenerator.cs b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Builder/RandomUserGenerator.cs new file mode 100644 index 0000000..b83e71a --- /dev/null +++ b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Builder/RandomUserGenerator.cs @@ -0,0 +1,48 @@ +using System; +using System.Text; + +using Browl.Service.AuthSecurity.API.Entities; + +namespace Browl.Service.AuthSecurity.API.Test.Builder; + +public static class RandomUserGenerator +{ + private static readonly Random Random = new Random(); + + public static UserRegister GenerateRandomUser() + { + var userName = GenerateRandomString(8); + var firstName = GenerateRandomString(6); + var lastName = GenerateRandomString(6); + var userNameChangeLimit = Random.Next(0, 10); + var profilePicture = GenerateRandomBytes(64); // Tamanho do perfil da imagem em bytes + var email = GenerateRandomEmail(); + var password = GenerateRandomString(10); + var passwordConfirmation = password; + + return new UserRegister(userName, firstName, lastName, userNameChangeLimit, profilePicture, email, password, passwordConfirmation); + } + + private static string GenerateRandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[Random.Next(s.Length)]) + .ToArray()); + } + + private static byte[] GenerateRandomBytes(int length) + { + var buffer = new byte[length]; + Random.NextBytes(buffer); + return buffer; + } + + private static string GenerateRandomEmail() + { + string[] domains = { "example.com", "test.org", "sample.net" }; + var userName = GenerateRandomString(8); + var domain = domains[Random.Next(domains.Length)]; + return $"{userName}@{domain}"; + } +} diff --git a/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Usings.cs b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/test/Services/Browl.Service.AuthSecurity.Test/Browl.Service.AuthSecurity.API.Test/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.API.Test/UnitTest1.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.API.Test/UnitTest1.cs deleted file mode 100644 index 5622f13..0000000 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.API.Test/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Browl.Service.MarketDataCollector.API.Test -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - } -} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.API.Test/Usings.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.API.Test/Usings.cs index 8c927eb..e69de29 100644 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.API.Test/Usings.cs +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.API.Test/Usings.cs @@ -1 +0,0 @@ -global using Xunit; \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Browl.Service.MarketDataCollector.Application.Test.csproj b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Browl.Service.MarketDataCollector.Application.Test.csproj index 8b95746..8b38c4b 100644 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Browl.Service.MarketDataCollector.Application.Test.csproj +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Browl.Service.MarketDataCollector.Application.Test.csproj @@ -10,7 +10,12 @@ + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -22,4 +27,10 @@ + + + + + + diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Builders/CategoryResourceBuilder.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Builders/CategoryResourceBuilder.cs new file mode 100644 index 0000000..a6acee5 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Builders/CategoryResourceBuilder.cs @@ -0,0 +1,23 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Resources.Category; + +namespace Browl.Service.MarketDataCollector.Application.Test.Builders; + +public class CategoryResourceBuilder +{ + private readonly int _id = 1; + private string _name = "My new Category"; + public Category Build() => new(BuildResource()); + + public CategoryResource BuildResource() => new() + { + Id = _id, + Name = _name + }; + + public CategoryResourceBuilder WithName(string name) + { + _name = name; + return this; + } +} diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Manager/CustomerManagerTest.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Manager/CustomerManagerTest.cs new file mode 100644 index 0000000..1547590 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Manager/CustomerManagerTest.cs @@ -0,0 +1,154 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Application.Implementation; +using Browl.Service.MarketDataCollector.Application.Mappings; +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Managers; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; +using Browl.Service.MarketDataCollector.Domain.Resources.Customer; +using Browl.Service.MarketDataCollector.FakeData.CustomerData; + +using FluentAssertions; + +using Microsoft.Extensions.Logging; + +using NSubstitute; +using NSubstitute.ReturnsExtensions; + +namespace Browl.Service.MarketDataCollector.Application.Test.Manager; + +public class CustomerManagerTest +{ + private readonly ICustomerRepository repository; + private readonly ILogger logger; + private readonly IMapper mapper; + private readonly ICustomerManager manager; + private readonly Customer Customer; + private readonly Customer NovoCustomer; + private readonly Customer AlteraCustomer; + private readonly CustomerFaker CustomerFaker; + private readonly CustomerNewFaker NovoCustomerFaker; + private readonly CustomerUpdateFaker AlteraCustomerFaker; + + public CustomerManagerTest() + { + repository = Substitute.For(); + logger = Substitute.For>(); + mapper = new MapperConfiguration(p => p.AddProfile()).CreateMapper(); + manager = new CustomerManager(repository, mapper, logger); + CustomerFaker = new CustomerFaker(); + NovoCustomerFaker = new CustomerNewFaker(); + AlteraCustomerFaker = new CustomerUpdateFaker(); + + Customer = CustomerFaker.Generate(); + NovoCustomer = NovoCustomerFaker.Generate()!; + AlteraCustomer = AlteraCustomerFaker.Generate()!; + } + + [Fact] + public async Task GetCustomersAsync_Sucesso() + { + var listaCustomers = CustomerFaker.Generate(10); + _ = repository.GetAsync().Returns(listaCustomers); + var controle = mapper.Map, IEnumerable>(listaCustomers); + var retorno = await manager.GetAsync(); + + _ = await repository.Received().GetAsync(); + _ = retorno.Should().BeEquivalentTo(controle); + } + + [Fact] + public async Task GetCustomersAsync_Vazio() + { + _ = repository.GetAsync().Returns(new List()); + + var retorno = await manager.GetAsync(); + + _ = await repository.Received().GetAsync(); + _ = retorno.Should().BeEquivalentTo(new List()); + } + + [Fact] + public async Task GetAsync_Sucesso() + { + _ = repository.GetAsync(Arg.Any()).Returns(Customer); + var controle = mapper.Map(Customer); + var retorno = await manager.GetAsync(Customer.Id); + + _ = await repository.Received().GetAsync(Arg.Any()); + _ = retorno.Should().BeEquivalentTo(controle); + } + + [Fact] + public async Task GetAsync_NaoEncontrado() + { + _ = repository.GetAsync(Arg.Any()).Returns(new Customer()); + var controle = mapper.Map(new Customer()); + var retorno = await manager.GetAsync(1); + + _ = await repository.Received().GetAsync(Arg.Any()); + _ = retorno.Should().BeEquivalentTo(controle); + } + + [Fact] + public async Task PostAsync_Sucesso() + { + _ = repository.PostAsync(Arg.Any()).Returns(Customer); + var controle = mapper.Map(Customer); + + var novoCustomerResource = mapper.Map(NovoCustomer); + + var retorno = await manager.PostAsync(novoCustomerResource); + + _ = await repository.Received().PostAsync(Arg.Any()); + _ = retorno.Should().BeEquivalentTo(controle); + } + + [Fact] + public async Task PutAsync_Sucesso() + { + _ = repository.PutAsync(Arg.Any()).Returns(Customer); + var controle = mapper.Map(Customer); + var novoCustomerResource = mapper.Map(AlteraCustomer); + + var retorno = await manager.PutAsync(novoCustomerResource); + + _ = await repository.Received().PutAsync(Arg.Any()); + _ = retorno.Should().BeEquivalentTo(controle); + } + + [Fact] + public async Task PutAsync_NaoEncontrado() + { + _ = repository.PutAsync(Arg.Any()).ReturnsNull(); + + var novoCustomerResource = mapper.Map(AlteraCustomer); + + var retorno = await manager.PutAsync(novoCustomerResource); + + _ = await repository.Received().PutAsync(Arg.Any()); + _ = retorno.Should().BeNull(); + } + + [Fact] + public async Task DeleteAsync_Sucesso() + { + _ = repository.DeleteAsync(Arg.Any()).Returns(Customer); + var controle = mapper.Map(Customer); + var retorno = await manager.DeleteAsync(Customer.Id); + + _ = await repository.Received().DeleteAsync(Arg.Any()); + _ = retorno.Should().BeEquivalentTo(controle); + } + + [Fact] + public async Task DeleteAsync_NaoEncontrado() + { + _ = repository.DeleteAsync(Arg.Any()).ReturnsNull(); + + var retorno = await manager.DeleteAsync(1); + + _ = await repository.Received().DeleteAsync(Arg.Any()); + _ = retorno.Should().BeNull(); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Services/CategoryServiceTest.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Services/CategoryServiceTest.cs new file mode 100644 index 0000000..af0b66c --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/Services/CategoryServiceTest.cs @@ -0,0 +1,71 @@ +using AutoMapper; + +using Browl.Service.MarketDataCollector.Application.Mappings; +using Browl.Service.MarketDataCollector.Application.Services; +using Browl.Service.MarketDataCollector.Application.Test.Builders; +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Repositories; +using Browl.Service.MarketDataCollector.Domain.Interfaces.Services; +using Browl.Service.MarketDataCollector.Domain.Resources.Category; +using Browl.Service.MarketDataCollector.FakeData.CategoryData; + +using FluentAssertions; + +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Logging; + +using NSubstitute; + +namespace Browl.Service.MarketDataCollector.Application.Test.Services; + +public class CategoryServiceTest +{ + private readonly ICategoryService _categoryService; + private readonly ICategoryRepository _categoryRepository; + private readonly IUnitOfWork _unitOfWork; + private readonly IMapper _mapper; + private readonly IMemoryCache _memoryCache; + private readonly ILogger logger; + private readonly Category Category; + private readonly CategoryFaker _categoryFaker; + public CategoryServiceTest() + { + _categoryRepository = Substitute.For(); + _unitOfWork = Substitute.For(); + _mapper = new MapperConfiguration(p => p.AddProfile()).CreateMapper(); + _memoryCache = Substitute.For(); + logger = Substitute.For>(); + _categoryService = new CategoryService(_categoryRepository, _unitOfWork, _memoryCache, logger); + _categoryFaker = new CategoryFaker(); + Category = _categoryFaker.Generate(); + } + + [Fact] + public async Task AddNewCategory() + { + // Arrange + CategoryResourceBuilder resourceBuilder = new(); + var categoryResource = resourceBuilder.BuildResource(); + Category category = new(categoryResource); + + // Act + _ = await _categoryService.SaveAsync(category); + + // Assert + await _categoryRepository.Received(1).AddAsync(Arg.Is(c => + c.Id == categoryResource.Id && + c.Name == categoryResource.Name)); + } + [Fact] + public async Task InsertClienteAsync_Sucesso() + { + var controle = _mapper.Map(Category); + var retorno = await _categoryService.SaveAsync(Category); ; + + await _categoryRepository.Received().AddAsync(Arg.Any()); + + _ = retorno.Should().BeEquivalentTo(controle); + } +} + + diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/UnitTest1.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/UnitTest1.cs deleted file mode 100644 index de40a44..0000000 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Application.Test/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Application.Test -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - } -} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Domain.Test/UnitTest1.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Domain.Test/UnitTest1.cs deleted file mode 100644 index 33d425e..0000000 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Domain.Test/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Domain.Test -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - } -} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Domain.Test/Usings.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Domain.Test/Usings.cs index 8c927eb..e69de29 100644 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Domain.Test/Usings.cs +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Domain.Test/Usings.cs @@ -1 +0,0 @@ -global using Xunit; \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressFaker.cs new file mode 100644 index 0000000..d097862 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressFaker.cs @@ -0,0 +1,17 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.FakeData.AddressData; + +public class AddressFaker : Faker
+{ + public AddressFaker(int clientId) + { + _ = RuleFor(o => o.ClienteId, _ => clientId); + _ = RuleFor(o => o.Numero, f => f.Address.BuildingNumber()); + _ = RuleFor(o => o.CEP, f => Convert.ToInt32(f.Address.ZipCode().Replace("-", ""))); + _ = RuleFor(o => o.Cidade, f => f.Address.City()); + _ = RuleFor(o => o.Estado, f => f.PickRandom()); + _ = RuleFor(o => o.Logradouro, f => f.Address.StreetName()); + _ = RuleFor(o => o.Complemento, f => f.Lorem.Sentence(10)); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressNewFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressNewFaker.cs new file mode 100644 index 0000000..136b146 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressNewFaker.cs @@ -0,0 +1,16 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.FakeData.AddressData; + +public class AddressNewFaker : Faker
+{ + public AddressNewFaker() + { + _ = RuleFor(p => p.Numero, f => f.Address.BuildingNumber()); + _ = RuleFor(p => p.CEP, f => Convert.ToInt32(f.Address.ZipCode().Replace("-", ""))); + _ = RuleFor(p => p.Cidade, f => f.Address.City()); + _ = RuleFor(p => p.Estado, f => f.PickRandom()); + _ = RuleFor(p => p.Logradouro, f => f.Address.StreetName()); + _ = RuleFor(p => p.Complemento, f => f.Lorem.Sentence(20)); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressViewFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressViewFaker.cs new file mode 100644 index 0000000..2b73a28 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/AddressData/AddressViewFaker.cs @@ -0,0 +1,16 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.FakeData.AddressData; + +public class AddressViewFaker : Faker
+{ + public AddressViewFaker() + { + _ = RuleFor(p => p.Numero, f => f.Address.BuildingNumber()); + _ = RuleFor(p => p.CEP, f => Convert.ToInt32(f.Address.ZipCode().Replace("-", ""))); + _ = RuleFor(p => p.Cidade, f => f.Address.City()); + _ = RuleFor(p => p.Estado, f => f.PickRandom()); + _ = RuleFor(p => p.Logradouro, f => f.Address.StreetName()); + _ = RuleFor(p => p.Complemento, f => f.Lorem.Sentence(20)); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/Browl.Service.MarketDataCollector.FakeData.csproj b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/Browl.Service.MarketDataCollector.FakeData.csproj new file mode 100644 index 0000000..5c34175 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/Browl.Service.MarketDataCollector.FakeData.csproj @@ -0,0 +1,21 @@ + + + + net7.0 + enable + enable + + + + + + + + + + + + + + + diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CategoryData/CategoryFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CategoryData/CategoryFaker.cs new file mode 100644 index 0000000..279628d --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CategoryData/CategoryFaker.cs @@ -0,0 +1,13 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.FakeData.CategoryData; + +public class CategoryFaker : Faker +{ + public CategoryFaker() + { + var id = new Faker().Random.Number(1, 999999); + var unused1 = RuleFor(o => o.Id, _ => id); + var unused = RuleFor(o => o.Name, f => f.Random.Word()); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerFaker.cs new file mode 100644 index 0000000..cf7148c --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerFaker.cs @@ -0,0 +1,23 @@ +using Bogus.Extensions.Brazil; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.FakeData.AddressData; +using Browl.Service.MarketDataCollector.FakeData.TelephoneData; + +namespace Browl.Service.MarketDataCollector.FakeData.CustomerData; + +public class CustomerFaker : Faker +{ + public CustomerFaker() + { + var id = new Faker().Random.Number(1, 999999); + _ = RuleFor(o => o.Id, _ => id); + _ = RuleFor(o => o.Nome, f => f.Person.FullName); + _ = RuleFor(o => o.Sexo, f => f.PickRandom()); + _ = RuleFor(o => o.Documento, f => f.Person.Cpf()); + _ = RuleFor(o => o.Criacao, f => f.Date.Past()); + _ = RuleFor(o => o.UltimaAtualizacao, f => f.Date.Past()); + _ = RuleFor(o => o.Telefones, _ => new TelephoneFaker(id).Generate(3)); + _ = RuleFor(o => o.Endereco, _ => new AddressFaker(id).Generate()); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerNewFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerNewFaker.cs new file mode 100644 index 0000000..009a549 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerNewFaker.cs @@ -0,0 +1,20 @@ +using Bogus.Extensions.Brazil; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.FakeData.AddressData; +using Browl.Service.MarketDataCollector.FakeData.TelephoneData; + +namespace Browl.Service.MarketDataCollector.FakeData.CustomerData; + +public class CustomerNewFaker : Faker +{ + public CustomerNewFaker() + { + _ = RuleFor(p => p.Nome, f => f.Person.FullName); + _ = RuleFor(p => p.Sexo, f => f.PickRandom()); + _ = RuleFor(p => p.Documento, f => f.Person.Cpf()); + _ = RuleFor(p => p.DataNascimento, f => f.Date.Past()); + _ = RuleFor(p => p.Telefones, _ => new TelephoneNewFaker().Generate(3)); + _ = RuleFor(p => p.Endereco, _ => new AddressNewFaker().Generate()); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerUpdateFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerUpdateFaker.cs new file mode 100644 index 0000000..f8bbd10 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerUpdateFaker.cs @@ -0,0 +1,18 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.FakeData.AddressData; +using Browl.Service.MarketDataCollector.FakeData.TelephoneData; + +namespace Browl.Service.MarketDataCollector.FakeData.CustomerData; + +public class CustomerUpdateFaker : Faker +{ + public CustomerUpdateFaker() + { + var id = new Faker().Random.Number(1, 100); + _ = RuleFor(o => o.Id, _ => id); + _ = RuleFor(o => o.Nome, f => f.Person.FullName); + _ = RuleFor(o => o.Sexo, f => f.PickRandom()); + _ = RuleFor(o => o.Telefones, _ => new TelephoneNewFaker().Generate(3)); + _ = RuleFor(o => o.Endereco, _ => new AddressNewFaker().Generate()); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerViewFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerViewFaker.cs new file mode 100644 index 0000000..955d843 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/CustomerData/CustomerViewFaker.cs @@ -0,0 +1,25 @@ +using Bogus.Extensions.Brazil; + +using Browl.Service.MarketDataCollector.Domain.Entities; +using Browl.Service.MarketDataCollector.FakeData.AddressData; +using Browl.Service.MarketDataCollector.FakeData.TelephoneData; + +namespace Browl.Service.MarketDataCollector.FakeData.CustomerData; + +public class CustomerViewFaker : Faker +{ + public CustomerViewFaker() + { + var id = new Faker().Random.Number(1, 999999); + _ = RuleFor(p => p.Id, + _ => id); + _ = RuleFor(p => p.Nome, f => f.Person.FullName); + _ = RuleFor(p => p.Sexo, f => f.PickRandom()); + _ = RuleFor(p => p.Documento, f => f.Person.Cpf()); + _ = RuleFor(p => p.Criacao, f => f.Date.Past()); + _ = RuleFor(p => p.UltimaAtualizacao, f => f.Date.Past()); + _ = RuleFor(p => p.DataNascimento, f => f.Date.Past()); + _ = RuleFor(p => p.Telefones, _ => new TelephoneViewFaker().Generate(3)); + _ = RuleFor(p => p.Endereco, _ => new AddressViewFaker().Generate()); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneFaker.cs new file mode 100644 index 0000000..7ba6805 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneFaker.cs @@ -0,0 +1,12 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.FakeData.TelephoneData; + +public class TelephoneFaker : Faker +{ + public TelephoneFaker(int clientId) + { + _ = RuleFor(o => o.ClienteId, _ => clientId); + _ = RuleFor(o => o.Numero, f => f.Person.Phone); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneNewFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneNewFaker.cs new file mode 100644 index 0000000..7c11a6f --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneNewFaker.cs @@ -0,0 +1,8 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.FakeData.TelephoneData; + +public class TelephoneNewFaker : Faker +{ + public TelephoneNewFaker() => _ = RuleFor(p => p.Numero, f => f.Person.Phone); +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneViewFaker.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneViewFaker.cs new file mode 100644 index 0000000..331c3f7 --- /dev/null +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.FakeData/TelephoneData/TelephoneViewFaker.cs @@ -0,0 +1,12 @@ +using Browl.Service.MarketDataCollector.Domain.Entities; + +namespace Browl.Service.MarketDataCollector.FakeData.TelephoneData; + +public class TelephoneViewFaker : Faker +{ + public TelephoneViewFaker() + { + _ = RuleFor(p => p.Id, f => f.Random.Number(1, 10)); + _ = RuleFor(p => p.Numero, f => f.Person.Phone); + } +} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Infrastructure.Test/UnitTest1.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Infrastructure.Test/UnitTest1.cs deleted file mode 100644 index 2bdd699..0000000 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Infrastructure.Test/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Browl.Service.MarketDataCollector.Infrastructure.Test -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - } -} \ No newline at end of file diff --git a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Infrastructure.Test/Usings.cs b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Infrastructure.Test/Usings.cs index 8c927eb..e69de29 100644 --- a/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Infrastructure.Test/Usings.cs +++ b/test/Services/Browl.Service.MarketDataCollector.Test/Browl.Service.MarketDataCollector.Infrastructure.Test/Usings.cs @@ -1 +0,0 @@ -global using Xunit; \ No newline at end of file