From 6ce680b437dff76e11aabeeeea94353afa3e5bae Mon Sep 17 00:00:00 2001 From: Harish-osmosys <121787291+Harish-osmosys@users.noreply.github.com> Date: Wed, 7 Feb 2024 17:27:23 +0530 Subject: [PATCH] feat: add editor config (#12) * feat: add editor config * fix: update file as per editor config * fix: update files * fix: update file to fix warning --- DotnetFoundation/.editorconfig | 343 ++++++++++++ .../Controllers/AuthenticationController.cs | 58 +- .../Controllers/UserController.cs | 50 +- .../DotnetFoundation.Api/Program.cs | 10 +- .../DependencyInjection.cs | 12 +- .../Persistence/IUsersRepository.cs | 14 +- .../Services/IAuthenticationService.cs | 8 +- .../Interfaces/Services/IUsersService.cs | 6 +- .../Authentication/AuthenticationService.cs | 66 +-- .../Services/UserService/UserService.cs | 48 +- .../DotnetFoundation.Domain/Entities/Roles.cs | 10 +- .../DotnetFoundation.Domain/Entities/User.cs | 6 +- .../DependencyInjection.cs | 72 +-- .../Identity/ApplicationUsers.cs | 4 +- .../Identity/IdentityApplicationUser.cs | 2 +- .../20231201101813_InitialCreate.cs | 523 +++++++++--------- .../Persistence/UserRepository.cs | 230 ++++---- .../SqlDatabaseContext.cs | 36 +- 18 files changed, 920 insertions(+), 578 deletions(-) create mode 100644 DotnetFoundation/.editorconfig diff --git a/DotnetFoundation/.editorconfig b/DotnetFoundation/.editorconfig new file mode 100644 index 0000000..4fe3b6e --- /dev/null +++ b/DotnetFoundation/.editorconfig @@ -0,0 +1,343 @@ +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:silent +dotnet_style_collection_initializer = true:silent +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_style_explicit_tuple_names = true:warning +dotnet_style_prefer_inferred_tuple_names = false:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = false:suggestion +dotnet_style_prefer_compound_assignment = true:silent +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_require_accessibility_modifiers = always:warning +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_code_quality_unused_parameters = non_public:error +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_qualification_for_field = true:warning +dotnet_style_qualification_for_property = true:warning +dotnet_style_qualification_for_method = true:warning +dotnet_style_qualification_for_event = true:warning + +[*.cs] +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:error +csharp_style_namespace_declarations = file_scoped:error +csharp_style_prefer_method_group_conversion = true:suggestion +csharp_style_prefer_top_level_statements = true:silent +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_indent_labels = one_less_than_current +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion +csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion +csharp_style_expression_bodied_local_functions = when_on_single_line:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_inlined_variable_declaration = false:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_prefer_static_local_function = true:warning +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_var_for_built_in_types = false:error +csharp_style_var_when_type_is_apparent = false:error +csharp_style_var_elsewhere = false:error + +csharp_space_around_binary_operators = before_and_after + +# Code analysis rules + +# The cref tag in an XML documentation comment uses a prefix. +dotnet_diagnostic.CA1200.severity = none + +# Do not pass literals as localized parameters +dotnet_diagnostic.CA1303.severity = none + +dotnet_diagnostic.CA1304.severity = suggestion + +dotnet_diagnostic.CA1305.severity = suggestion + +# Specify StringComparison for clarity when comparing string +dotnet_diagnostic.CA1307.severity = suggestion + +# Normalize strings to uppercase +dotnet_diagnostic.CA1308.severity = none + +# Use ordinal StringComparison when comparing string +dotnet_diagnostic.CA1309.severity = suggestion + +# Specify StringComparison for correctness when comparing string +dotnet_diagnostic.CA1310.severity = suggestion + +# Specify a culture or use an invariant version for string to upper or to lower +dotnet_diagnostic.CA1311.severity = none + +# Platform Invocation Services related method should not be exposed +dotnet_diagnostic.CA1401.severity = error + +# The analyzer is enabled by default only for projects that target .NET 5 or later and have an AnalysisLevel of 5 or higher. It can be enabled for target frameworks lower than net5.0 by adding the following config +dotnet_code_quality.enable_platform_analyzer_on_pre_net5_target = true + +# Validate platform compatibility for obsoleted APIs +dotnet_diagnostic.CA1422.severity = suggestion + +# Avoid excessive inheritance (5 or more levels) +dotnet_diagnostic.CA1501.severity = suggestion + +# Avoid excessive cyclomatic complexity +dotnet_diagnostic.CA1502.severity = warning + +# Avoid low maintainability index value code +dotnet_diagnostic.CA1505.severity = suggestion + +# Avoid excessive class coupling +dotnet_diagnostic.CA1506.severity = suggestion + +# Avoid dead conditional code +dotnet_diagnostic.CA1508.severity = warning + +# Invalid entry in code metrics configuration file +dotnet_diagnostic.CA1509.severity = error + +# Avoid redundant length argument +dotnet_diagnostic.CA1514.severity = warning + +# Do not name enum values 'Reserved' +dotnet_diagnostic.CA1700.severity = warning + +# Identifiers should not contain underscores +dotnet_diagnostic.CA1707.severity = warning + +# Identifiers should differ by more than case +dotnet_diagnostic.CA1708.severity = warning + +# Identifiers should have correct suffix +dotnet_diagnostic.CA1710.severity = none + +# Identifiers should not have incorrect suffix +dotnet_diagnostic.CA1711.severity = none + +# Do not prefix enum values with type name +dotnet_diagnostic.CA1712.severity = warning + +# Events should not have before or after prefix +dotnet_diagnostic.CA1713.severity = warning + +# Flags enums should have plural names +dotnet_diagnostic.CA1714.severity = none + +# Identifiers should not match keywords +dotnet_diagnostic.CA1716.severity = warning + +# Only FlagsAttribute enums should have plural names +dotnet_diagnostic.CA1717.severity = none + +# Identifiers should not contain type names +dotnet_diagnostic.CA1718.severity = suggestion + +# Use PascalCase for named placeholders with ILogger +dotnet_diagnostic.CA1727.severity = none + +# Call GC.SuppressFinalize correctly +dotnet_diagnostic.CA1816.severity = warning + +# Rethrow to preserve stack details +dotnet_diagnostic.CA2200.severity = warning + +# Disposable fields should be disposed +dotnet_diagnostic.CA2213.severity = suggestion + +# Do not call overridable methods in constructors +dotnet_diagnostic.CA2214.severity = error + +# Dispose methods should call base class dispose +dotnet_diagnostic.CA2215.severity = warning + +# Disposable types should declare finalizer +dotnet_diagnostic.CA2216.severity = warning + +# Operator overloads have named alternates +dotnet_diagnostic.CA2225.severity = none + +# Collection properties should be read only +dotnet_diagnostic.CA2227.severity = none + +# Overload operator equals on overriding ValueType.Equals +dotnet_diagnostic.CA2231.severity = none + +# Pass System.Uri objects instead of strings +dotnet_diagnostic.CA2234.severity = none + +# Mark ISerializable types with SerializableAttribute +dotnet_diagnostic.CA2237.severity = warning + +# Attribute string literals should parse correctly +dotnet_diagnostic.CA2243.severity = none + +# Do not assign a property to itself +dotnet_diagnostic.CA2245.severity = error + +# Argument passed to TaskCompletionSource constructor should be TaskCreationOptions enum instead of TaskContinuationOptions enum +dotnet_diagnostic.CA2247.severity = warning + +# Consider using String.Contains instead of String.IndexOf +dotnet_diagnostic.CA2249.severity = error + +# Use ThrowIfCancellationRequested +dotnet_diagnostic.CA2250.severity = suggestion + +# Use String.Equals over String.Compare +dotnet_diagnostic.CA2251.severity = error + +# Template should be a static expression +dotnet_diagnostic.CA2254.severity = suggestion + +# The ModuleInitializer attribute should not be used in libraries +dotnet_diagnostic.CA2255.severity = none + +# Dispose objects before losing scope +dotnet_diagnostic.CA2000.severity = warning + +# Do not directly await a Task +dotnet_diagnostic.CA2007.severity = warning + +# Do not call ToImmutableCollection on an ImmutableCollection value +dotnet_diagnostic.CA2009.severity = warning + +# Do not assign property within its setter +dotnet_diagnostic.CA2011.severity = error + +# Do not use ReferenceEquals with value types +dotnet_diagnostic.CA2013.severity = error + +# Do not use stackalloc in loops +dotnet_diagnostic.CA2014.severity = error + +# Forward the CancellationToken parameter to methods that take one +dotnet_diagnostic.CA2016.severity = suggestion + +# Parameter count mismatch +dotnet_diagnostic.CA2017.severity = error + +# Types that own disposable fields should be disposable +dotnet_diagnostic.CA1001.severity = warning + +# Define accessors for attribute arguments +dotnet_diagnostic.CA1019.severity = warning + +# Avoid out parameters +dotnet_diagnostic.CA1021.severity = none + +# Use properties where appropriate +dotnet_diagnostic.CA1024.severity = none + +# Mark enums with FlagsAttribute +dotnet_diagnostic.CA1027.severity = none + +# Do not catch general exception types +dotnet_diagnostic.CA1031.severity = suggestion + +# Implement standard exception constructors +dotnet_diagnostic.CA1032.severity = warning + +# Avoid empty interfaces +dotnet_diagnostic.CA1040.severity = suggestion + +# Declare types in namespaces +dotnet_diagnostic.CA1050.severity = warning + +# Static holder types should be Static or NotInheritable +dotnet_diagnostic.CA1052.severity = suggestion + +# URI parameters should not be strings +dotnet_diagnostic.CA1054.severity = none + +# URI return values should not be strings +dotnet_diagnostic.CA1055.severity = none + +# URI properties should not be strings +dotnet_diagnostic.CA1056.severity = none + +# Enums should not have duplicate values +dotnet_diagnostic.CA1069.severity = error \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Api/Controllers/AuthenticationController.cs b/DotnetFoundation/DotnetFoundation.Api/Controllers/AuthenticationController.cs index b0a4432..be81644 100644 --- a/DotnetFoundation/DotnetFoundation.Api/Controllers/AuthenticationController.cs +++ b/DotnetFoundation/DotnetFoundation.Api/Controllers/AuthenticationController.cs @@ -8,35 +8,35 @@ namespace DotnetFoundation.Api.Controllers; [Route("/api/auth")] public class AuthenticationController : ControllerBase { - private readonly IAuthenticationService _authenticationService; - public AuthenticationController(IAuthenticationService authenticationService) - { - _authenticationService = authenticationService; - } + private readonly IAuthenticationService _authenticationService; + public AuthenticationController(IAuthenticationService authenticationService) + { + _authenticationService = authenticationService; + } - [HttpPost("regiser")] - public async Task RegisterAsync(RegisterRequest request) - { - var result = await _authenticationService.RegisterAsync(request); - return Ok(result); - } + [HttpPost("regiser")] + public async Task RegisterAsync(RegisterRequest request) + { + AuthenticationResponse result = await _authenticationService.RegisterAsync(request).ConfigureAwait(false); + return Ok(result); + } - [HttpPost("login")] - public async Task LoginAsync(LoginRequest request) - { - var result = await _authenticationService.LoginAsync(request); - return Ok(result); - } - [HttpPost("reset-password")] - public async Task ResetPasswordAsync(PasswordResetRequest request) - { - var result = await _authenticationService.ResetPasswordAsync(request); - return Ok(result); - } - [HttpPost("forgot-password")] - public async Task ForgotPasswordAsync(string email) - { - var result = await _authenticationService.ForgotPasswordAsync(email); - return Ok(result); - } + [HttpPost("login")] + public async Task LoginAsync(LoginRequest request) + { + AuthenticationResponse result = await _authenticationService.LoginAsync(request).ConfigureAwait(false); + return Ok(result); + } + [HttpPost("reset-password")] + public async Task ResetPasswordAsync(PasswordResetRequest request) + { + AuthenticationResponse result = await _authenticationService.ResetPasswordAsync(request).ConfigureAwait(false); + return Ok(result); + } + [HttpPost("forgot-password")] + public async Task ForgotPasswordAsync(string email) + { + string result = await _authenticationService.ForgotPasswordAsync(email).ConfigureAwait(false); + return Ok(result); + } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Api/Controllers/UserController.cs b/DotnetFoundation/DotnetFoundation.Api/Controllers/UserController.cs index 19129bc..7c3c38c 100644 --- a/DotnetFoundation/DotnetFoundation.Api/Controllers/UserController.cs +++ b/DotnetFoundation/DotnetFoundation.Api/Controllers/UserController.cs @@ -9,32 +9,32 @@ namespace DotnetFoundation.Api.Controllers; [Route("api/users")] public class UserController : ControllerBase { - private readonly IUserService _userService; - public UserController(IUserService userService) - { - _userService = userService; - } + private readonly IUserService _userService; + public UserController(IUserService userService) + { + _userService = userService; + } - [HttpGet] - [Authorize(Roles = "LEAD")] - public async Task GetAllUsersAsync() - { - var result = await _userService.GetAllUsersAsync(); - return Ok(result); - } + [HttpGet] + [Authorize(Roles = "LEAD")] + public async Task GetAllUsersAsync() + { + List result = await _userService.GetAllUsersAsync().ConfigureAwait(false); + return Ok(result); + } - [HttpGet("{userId}")] - public async Task GetUserByIdAsync(int userId) - { - var result = await _userService.GetUserByIdAsync(userId); - return Ok(result); - } - [Authorize(Roles = "ADMIN")] - [HttpPost("add-role")] - public async Task AddUserRoleAsync(UserRoleRequest roleRequest) - { - var result = await _userService.AddUserRoleAsync(roleRequest.Email, roleRequest.Role); - return Ok(result); - } + [HttpGet("{userId}")] + public async Task GetUserByIdAsync(int userId) + { + UserResponse? result = await _userService.GetUserByIdAsync(userId).ConfigureAwait(false); + return Ok(result); + } + [Authorize(Roles = "ADMIN")] + [HttpPost("add-role")] + public async Task AddUserRoleAsync(UserRoleRequest roleRequest) + { + bool result = await _userService.AddUserRoleAsync(roleRequest.Email, roleRequest.Role).ConfigureAwait(false); + return Ok(result); + } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Api/Program.cs b/DotnetFoundation/DotnetFoundation.Api/Program.cs index b38753e..276a537 100644 --- a/DotnetFoundation/DotnetFoundation.Api/Program.cs +++ b/DotnetFoundation/DotnetFoundation.Api/Program.cs @@ -1,8 +1,8 @@ -using DotnetFoundation.Infrastructure; using DotnetFoundation.Application; -using Microsoft.OpenApi.Models; +using DotnetFoundation.Infrastructure; using Microsoft.AspNetCore.Authentication.JwtBearer; -var builder = WebApplication.CreateBuilder(args); +using Microsoft.OpenApi.Models; +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. @@ -14,7 +14,7 @@ c.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API", Version = "v1" }); // Add JWT authentication - var securityScheme = new OpenApiSecurityScheme + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme { Name = "JWT Authentication", Description = "Enter your JWT token", @@ -38,7 +38,7 @@ builder.Services.AddInfrastructure(builder.Configuration); builder.Services.AddApplication(); -var app = builder.Build(); +WebApplication app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) diff --git a/DotnetFoundation/DotnetFoundation.Application/DependencyInjection.cs b/DotnetFoundation/DotnetFoundation.Application/DependencyInjection.cs index b4ff508..4bfb9a5 100644 --- a/DotnetFoundation/DotnetFoundation.Application/DependencyInjection.cs +++ b/DotnetFoundation/DotnetFoundation.Application/DependencyInjection.cs @@ -6,10 +6,10 @@ namespace DotnetFoundation.Application; using Microsoft.Extensions.DependencyInjection; public static class DependencyInjection { - public static IServiceCollection AddApplication(this IServiceCollection services) - { - services.AddScoped(); - services.AddScoped(); - return services; - } + public static IServiceCollection AddApplication(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + return services; + } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Persistence/IUsersRepository.cs b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Persistence/IUsersRepository.cs index 5adba5d..237f88c 100644 --- a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Persistence/IUsersRepository.cs +++ b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Persistence/IUsersRepository.cs @@ -5,12 +5,12 @@ namespace DotnetFoundation.Application.Interfaces.Persistence; public interface IUserRepository { - public Task AddUserAsync(RegisterRequest request); - public Task LoginUserAsync(LoginRequest request); - public Task> GetAllUsersAsync(); - public Task GetUserByIdAsync(int Id); - public Task ForgotPasswordAsync(string email); - public Task ResetPasswordAsync(string email, string token, string newPassword); - public Task AddUserRoleAsync(string email, int role); + public Task AddUserAsync(RegisterRequest request); + public Task LoginUserAsync(LoginRequest request); + public Task> GetAllUsersAsync(); + public Task GetUserByIdAsync(int Id); + public Task ForgotPasswordAsync(string email); + public Task ResetPasswordAsync(string email, string token, string newPassword); + public Task AddUserRoleAsync(string email, int role); } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IAuthenticationService.cs b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IAuthenticationService.cs index 1a08b8a..fc35406 100644 --- a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IAuthenticationService.cs +++ b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IAuthenticationService.cs @@ -5,8 +5,8 @@ namespace DotnetFoundation.Application.Interfaces.Services; public interface IAuthenticationService { - public Task RegisterAsync(RegisterRequest request); - public Task LoginAsync(LoginRequest request); - public Task ForgotPasswordAsync(string email); - public Task ResetPasswordAsync(PasswordResetRequest request); + public Task RegisterAsync(RegisterRequest request); + public Task LoginAsync(LoginRequest request); + public Task ForgotPasswordAsync(string email); + public Task ResetPasswordAsync(PasswordResetRequest request); } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs index 01af0a5..c96374c 100644 --- a/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs +++ b/DotnetFoundation/DotnetFoundation.Application/Interfaces/Services/IUsersService.cs @@ -3,7 +3,7 @@ namespace DotnetFoundation.Application.Interfaces.Services; public interface IUserService { - public Task GetUserByIdAsync(int Id); - public Task> GetAllUsersAsync(); - public Task AddUserRoleAsync(string email, int role); + public Task GetUserByIdAsync(int Id); + public Task> GetAllUsersAsync(); + public Task AddUserRoleAsync(string email, int role); } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Application/Services/Authentication/AuthenticationService.cs b/DotnetFoundation/DotnetFoundation.Application/Services/Authentication/AuthenticationService.cs index 1913293..cb21360 100644 --- a/DotnetFoundation/DotnetFoundation.Application/Services/Authentication/AuthenticationService.cs +++ b/DotnetFoundation/DotnetFoundation.Application/Services/Authentication/AuthenticationService.cs @@ -1,44 +1,44 @@ -using System.Security.Claims; using DotnetFoundation.Application.DTO.AuthenticationDTO; using DotnetFoundation.Application.Interfaces.Persistence; using DotnetFoundation.Application.Interfaces.Services; using DotnetFoundation.Domain.Entities; +using System.Security.Claims; namespace DotnetFoundation.Application.Services.Authentication; public class AuthenticationService : IAuthenticationService { - private readonly IUserRepository _userRepository; - public AuthenticationService(IUserRepository userRepository) - { - _userRepository = userRepository; - - } - - - - public async Task LoginAsync(LoginRequest request) - { - var res = await _userRepository.LoginUserAsync(request); - return new(Token: res); - } - - public async Task RegisterAsync(RegisterRequest request) - { - var res = await _userRepository.AddUserAsync(request); - return new(Token: res); - - } - public async Task ForgotPasswordAsync(string email) - { - var res = await _userRepository.ForgotPasswordAsync(email); - return res; - } - - public async Task ResetPasswordAsync(PasswordResetRequest request) - { - var res = await _userRepository.ResetPasswordAsync(request.Email, request.Token, request.Password); - return new(Token: res); - } + private readonly IUserRepository _userRepository; + public AuthenticationService(IUserRepository userRepository) + { + _userRepository = userRepository; + + } + + + + public async Task LoginAsync(LoginRequest request) + { + string res = await _userRepository.LoginUserAsync(request).ConfigureAwait(false); + return new(Token: res); + } + + public async Task RegisterAsync(RegisterRequest request) + { + string res = await _userRepository.AddUserAsync(request).ConfigureAwait(false); + return new(Token: res); + + } + public async Task ForgotPasswordAsync(string email) + { + string res = await _userRepository.ForgotPasswordAsync(email).ConfigureAwait(false); + return res; + } + + public async Task ResetPasswordAsync(PasswordResetRequest request) + { + string res = await _userRepository.ResetPasswordAsync(request.Email, request.Token, request.Password).ConfigureAwait(false); + return new(Token: res); + } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Application/Services/UserService/UserService.cs b/DotnetFoundation/DotnetFoundation.Application/Services/UserService/UserService.cs index a1a0684..63c6dcc 100644 --- a/DotnetFoundation/DotnetFoundation.Application/Services/UserService/UserService.cs +++ b/DotnetFoundation/DotnetFoundation.Application/Services/UserService/UserService.cs @@ -6,30 +6,30 @@ namespace DotnetFoundation.Application.Services.UserService; public class UserService : IUserService { - private readonly IUserRepository _userRepository; - private static UserResponse DTOMapper(User user) - { - return new(Id: user.Id, FirstName: user.FirstName, LastName: user.LastName); - } - public UserService(IUserRepository userRepository) - { - _userRepository = userRepository; - } - public async Task> GetAllUsersAsync() - { - var response = (await _userRepository.GetAllUsersAsync()).Select(DTOMapper).ToList(); - return response; - } + private readonly IUserRepository _userRepository; + private static UserResponse DTOMapper(User user) + { + return new(Id: user.Id, FirstName: user.FirstName, LastName: user.LastName); + } + public UserService(IUserRepository userRepository) + { + _userRepository = userRepository; + } + public async Task> GetAllUsersAsync() + { + List response = (await _userRepository.GetAllUsersAsync().ConfigureAwait(false)).Select(DTOMapper).ToList(); + return response; + } - public async Task GetUserByIdAsync(int Id) - { - var res = await _userRepository.GetUserByIdAsync(Id) ?? throw new Exception("No user found"); - return DTOMapper(res); - } + public async Task GetUserByIdAsync(int Id) + { + User res = await _userRepository.GetUserByIdAsync(Id).ConfigureAwait(false) ?? throw new Exception("No user found"); + return DTOMapper(res); + } - public async Task AddUserRoleAsync(string email, int role) - { - var res = await _userRepository.AddUserRoleAsync(email, role); - return res; - } + public async Task AddUserRoleAsync(string email, int role) + { + bool res = await _userRepository.AddUserRoleAsync(email, role).ConfigureAwait(false); + return res; + } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Domain/Entities/Roles.cs b/DotnetFoundation/DotnetFoundation.Domain/Entities/Roles.cs index 6c3483b..8a43229 100644 --- a/DotnetFoundation/DotnetFoundation.Domain/Entities/Roles.cs +++ b/DotnetFoundation/DotnetFoundation.Domain/Entities/Roles.cs @@ -2,9 +2,9 @@ namespace DotnetFoundation.Domain.Entities; public enum Roles { - DEFAULT, - DEVELOPER, - LEAD, - ADMIN, - SUPER_ADMIN + DEFAULT, + DEVELOPER, + LEAD, + ADMIN, + SUPERADMIN } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Domain/Entities/User.cs b/DotnetFoundation/DotnetFoundation.Domain/Entities/User.cs index 6856a8f..a0485de 100644 --- a/DotnetFoundation/DotnetFoundation.Domain/Entities/User.cs +++ b/DotnetFoundation/DotnetFoundation.Domain/Entities/User.cs @@ -4,7 +4,7 @@ namespace DotnetFoundation.Domain.Entities; public class User { - public int Id; - public string FirstName { get; set; } = null!; - public string? LastName { get; set; } + public int Id; + public string FirstName { get; set; } = null!; + public string? LastName { get; set; } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs index f31647d..0f2e3f7 100644 --- a/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs +++ b/DotnetFoundation/DotnetFoundation.Infrastructure/DependencyInjection.cs @@ -1,4 +1,3 @@ -using System.Text; using DotnetFoundation.Application.Interfaces.Persistence; using DotnetFoundation.Infrastructure.Identity; using DotnetFoundation.Infrastructure.Persistence; @@ -8,50 +7,51 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; +using System.Text; namespace DotnetFoundation.Infrastructure; public static class DependencyInjection { - public static IServiceCollection AddInfrastructure(this IServiceCollection services, ConfigurationManager configuration) - { - services.AddDbContext(options => + public static IServiceCollection AddInfrastructure(this IServiceCollection services, ConfigurationManager configuration) { - string connectionString = configuration.GetConnectionString("DBConnection") ?? throw new Exception("Invalid connection string"); - options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); - }); - services.AddIdentity() - .AddEntityFrameworkStores() - .AddDefaultTokenProviders(); + services.AddDbContext(options => + { + string connectionString = configuration.GetConnectionString("DBConnection") ?? throw new Exception("Invalid connection string"); + options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); + }); + services.AddIdentity() + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); - services.AddAuthentication(options => - { + services.AddAuthentication(options => + { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddJwtBearer(options => - { - var JWT_KEY = configuration["Jwt:Key"] ?? throw new Exception("No JWT key specified"); - options.TokenValidationParameters = new TokenValidationParameters - { - ValidateIssuer = true, - ValidateAudience = true, - ValidateLifetime = true, - ValidateIssuerSigningKey = true, - ValidIssuer = configuration["Jwt:Issuer"], - ValidAudience = configuration["Jwt:Audience"], - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT_KEY)) - }; + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + string JWT_KEY = configuration["Jwt:Key"] ?? throw new Exception("No JWT key specified"); + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ValidateIssuerSigningKey = true, + ValidIssuer = configuration["Jwt:Issuer"], + ValidAudience = configuration["Jwt:Audience"], + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT_KEY)) + }; - }); - services.AddAuthorization(options => - { - options.AddPolicy("RequiredAdminRole", policy => policy.RequireRole("ADMIN")); - }); + }); + services.AddAuthorization(options => + { + options.AddPolicy("RequiredAdminRole", policy => policy.RequireRole("ADMIN")); + }); - services.AddScoped(); + services.AddScoped(); - return services; - } + return services; + } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/ApplicationUsers.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/ApplicationUsers.cs index 7cf3224..77e7cd3 100644 --- a/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/ApplicationUsers.cs +++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/ApplicationUsers.cs @@ -3,7 +3,7 @@ namespace DotnetFoundation.Infrastructure.Identity; public class ApplicationUser : User { - public string? IdentityApplicationUserId { get; set; } - public IdentityApplicationUser? IdentityApplicationUser { get; set; } + public string? IdentityApplicationUserId { get; set; } + public IdentityApplicationUser? IdentityApplicationUser { get; set; } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/IdentityApplicationUser.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/IdentityApplicationUser.cs index db8a1b3..c851452 100644 --- a/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/IdentityApplicationUser.cs +++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Identity/IdentityApplicationUser.cs @@ -5,5 +5,5 @@ namespace DotnetFoundation.Infrastructure.Identity; public class IdentityApplicationUser : IdentityUser { - public ApplicationUser ApplicationUser { get; set; } = null!; + public ApplicationUser ApplicationUser { get; set; } = null!; } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20231201101813_InitialCreate.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20231201101813_InitialCreate.cs index ad89fa3..ad29844 100644 --- a/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20231201101813_InitialCreate.cs +++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Migrations/20231201101813_InitialCreate.cs @@ -1,295 +1,294 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; +using System; #nullable disable -namespace DotnetFoundation.Infrastructure.Migrations +namespace DotnetFoundation.Infrastructure.Migrations; + +/// +public partial class InitialCreate : Migration { /// - public partial class InitialCreate : Migration + protected override void Up(MigrationBuilder migrationBuilder) { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterDatabase() - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.AlterDatabase() + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ConcurrencyStamp = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedUserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Email = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedEmail = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - EmailConfirmed = table.Column(type: "tinyint(1)", nullable: false), - PasswordHash = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - SecurityStamp = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ConcurrencyStamp = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - PhoneNumber = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - PhoneNumberConfirmed = table.Column(type: "tinyint(1)", nullable: false), - TwoFactorEnabled = table.Column(type: "tinyint(1)", nullable: false), - LockoutEnd = table.Column(type: "datetime(6)", nullable: true), - LockoutEnabled = table.Column(type: "tinyint(1)", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedUserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Email = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedEmail = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + EmailConfirmed = table.Column(type: "tinyint(1)", nullable: false), + PasswordHash = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + SecurityStamp = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + PhoneNumber = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + PhoneNumberConfirmed = table.Column(type: "tinyint(1)", nullable: false), + TwoFactorEnabled = table.Column(type: "tinyint(1)", nullable: false), + LockoutEnd = table.Column(type: "datetime(6)", nullable: true), + LockoutEnabled = table.Column(type: "tinyint(1)", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - RoleId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimType = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimValue = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + RoleId = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimType = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimValue = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimType = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimValue = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimType = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimValue = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProviderKey = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProviderDisplayName = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderKey = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderDisplayName = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + UserId = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - RoleId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + RoleId = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - LoginProvider = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Name = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + LoginProvider = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateTable( - name: "users", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IdentityApplicationUserId = table.Column(type: "varchar(255)", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - FirstName = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - LastName = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_users", x => x.Id); - table.ForeignKey( - name: "FK_users_AspNetUsers_IdentityApplicationUserId", - column: x => x.IdentityApplicationUserId, - principalTable: "AspNetUsers", - principalColumn: "Id"); - }) - .Annotation("MySql:CharSet", "utf8mb4"); + migrationBuilder.CreateTable( + name: "users", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + IdentityApplicationUserId = table.Column(type: "varchar(255)", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + FirstName = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + LastName = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_users", x => x.Id); + table.ForeignKey( + name: "FK_users_AspNetUsers_IdentityApplicationUserId", + column: x => x.IdentityApplicationUserId, + principalTable: "AspNetUsers", + principalColumn: "Id"); + }) + .Annotation("MySql:CharSet", "utf8mb4"); - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); + migrationBuilder.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true); + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true); - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true); + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true); - migrationBuilder.CreateIndex( - name: "IX_users_IdentityApplicationUserId", - table: "users", - column: "IdentityApplicationUserId", - unique: true); - } + migrationBuilder.CreateIndex( + name: "IX_users_IdentityApplicationUserId", + table: "users", + column: "IdentityApplicationUserId", + unique: true); + } - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); - migrationBuilder.DropTable( - name: "AspNetUserClaims"); + migrationBuilder.DropTable( + name: "AspNetUserClaims"); - migrationBuilder.DropTable( - name: "AspNetUserLogins"); + migrationBuilder.DropTable( + name: "AspNetUserLogins"); - migrationBuilder.DropTable( - name: "AspNetUserRoles"); + migrationBuilder.DropTable( + name: "AspNetUserRoles"); - migrationBuilder.DropTable( - name: "AspNetUserTokens"); + migrationBuilder.DropTable( + name: "AspNetUserTokens"); - migrationBuilder.DropTable( - name: "users"); + migrationBuilder.DropTable( + name: "users"); - migrationBuilder.DropTable( - name: "AspNetRoles"); + migrationBuilder.DropTable( + name: "AspNetRoles"); - migrationBuilder.DropTable( - name: "AspNetUsers"); - } + migrationBuilder.DropTable( + name: "AspNetUsers"); } } diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/Persistence/UserRepository.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/Persistence/UserRepository.cs index c328f00..60b787f 100644 --- a/DotnetFoundation/DotnetFoundation.Infrastructure/Persistence/UserRepository.cs +++ b/DotnetFoundation/DotnetFoundation.Infrastructure/Persistence/UserRepository.cs @@ -1,7 +1,3 @@ -using System.IdentityModel.Tokens.Jwt; -using System.Security.Claims; -using System.Text; -using System.Transactions; using DotnetFoundation.Application.DTO.AuthenticationDTO; using DotnetFoundation.Application.Interfaces.Persistence; using DotnetFoundation.Domain.Entities; @@ -10,42 +6,46 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using System.Transactions; namespace DotnetFoundation.Infrastructure.Persistence; public class UserRepository : IUserRepository { - private readonly IConfiguration _configuration; - private readonly SqlDatabaseContext _dbContext; - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - private readonly RoleManager _roleManager; - public UserRepository(IConfiguration configuration, SqlDatabaseContext sqlDatabaseContext, SignInManager signinManager, RoleManager roleManager, UserManager userManager) - { - _dbContext = sqlDatabaseContext; - _configuration = configuration; - _roleManager = roleManager; - _signInManager = signinManager; - _userManager = userManager; - - } - public string GenerateJwtToken(UserInfo user) - { - var claims = new List + private readonly IConfiguration _configuration; + private readonly SqlDatabaseContext _dbContext; + private readonly SignInManager _signInManager; + private readonly UserManager _userManager; + private readonly RoleManager _roleManager; + public UserRepository(IConfiguration configuration, SqlDatabaseContext sqlDatabaseContext, SignInManager signinManager, RoleManager roleManager, UserManager userManager) + { + _dbContext = sqlDatabaseContext; + _configuration = configuration; + _roleManager = roleManager; + _signInManager = signinManager; + _userManager = userManager; + + } + public string GenerateJwtToken(UserInfo user) + { + List claims = new List { new(ClaimTypes.Email,user.Id.ToString()), new(ClaimTypes.Name, user.Email), // Add additional claims for roles }; - foreach (var role in user.Roles) - { - claims.Add(new Claim(ClaimTypes.Role, role)); - } - var JWT_KEY = _configuration["Jwt:Key"] ?? throw new Exception("No JWT configuration"); - var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT_KEY)); - var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + foreach (string role in user.Roles) + { + claims.Add(new Claim(ClaimTypes.Role, role)); + } + string JWT_KEY = _configuration["Jwt:Key"] ?? throw new Exception("No JWT configuration"); + SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT_KEY)); + SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - var token = new JwtSecurityToken( + JwtSecurityToken token = new JwtSecurityToken( _configuration["Jwt:Issuer"], _configuration["Jwt:Audience"], claims, @@ -53,104 +53,104 @@ public string GenerateJwtToken(UserInfo user) signingCredentials: credentials ); - return new JwtSecurityTokenHandler().WriteToken(token); - } - public async Task AddUserAsync(RegisterRequest request) - { - var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); - - try - { - IdentityApplicationUser newIdentityApplicationUser = new() - { - UserName = request.Email, - Email = request.Email - }; - var identityResult = await _userManager.CreateAsync(newIdentityApplicationUser, request.Password); - if (!identityResult.Succeeded) - { - throw new Exception("Error creating identity user"); - } - var identityApplicationUser = await _userManager.FindByEmailAsync(request.Email) ?? throw new Exception("Error finding user"); - await AddUserRoleAsync(request.Email, 0); - ApplicationUser applicationUser = new() - { - FirstName = request.FirstName, - LastName = request.LastName, - IdentityApplicationUserId = identityApplicationUser.Id - }; - - var res = await _dbContext.ApplicationUsers.AddAsync(applicationUser); - await _dbContext.SaveChangesAsync(); - UserInfo userInfo = new(identityApplicationUser.Id, request.Email, (await _userManager.GetRolesAsync(identityApplicationUser)).ToList()); - - // If everything succeeds, commit the transaction - scope.Complete(); - return GenerateJwtToken(userInfo); + return new JwtSecurityTokenHandler().WriteToken(token); } - catch (Exception ex) + public async Task AddUserAsync(RegisterRequest request) { - return ex.Message; + TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); + + try + { + IdentityApplicationUser newIdentityApplicationUser = new() + { + UserName = request.Email, + Email = request.Email + }; + IdentityResult identityResult = await _userManager.CreateAsync(newIdentityApplicationUser, request.Password).ConfigureAwait(false); + if (!identityResult.Succeeded) + { + throw new Exception("Error creating identity user"); + } + IdentityApplicationUser identityApplicationUser = await _userManager.FindByEmailAsync(request.Email).ConfigureAwait(false) ?? throw new Exception("Error finding user"); + await AddUserRoleAsync(request.Email, 0).ConfigureAwait(false); + ApplicationUser applicationUser = new() + { + FirstName = request.FirstName, + LastName = request.LastName, + IdentityApplicationUserId = identityApplicationUser.Id + }; + + Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry res = await _dbContext.ApplicationUsers.AddAsync(applicationUser).ConfigureAwait(false); + await _dbContext.SaveChangesAsync().ConfigureAwait(false); + UserInfo userInfo = new(identityApplicationUser.Id, request.Email, (await _userManager.GetRolesAsync(identityApplicationUser).ConfigureAwait(false)).ToList()); + + // If everything succeeds, commit the transaction + scope.Complete(); + return GenerateJwtToken(userInfo); + } + catch (Exception ex) + { + return ex.Message; + } + finally + { + scope.Dispose(); // Ensure to dispose the TransactionScope + } } - finally + + + public async Task> GetAllUsersAsync() { - scope.Dispose(); // Ensure to dispose the TransactionScope - } - } + List users = (await _dbContext.ApplicationUsers.ToListAsync().ConfigureAwait(false)).Select(user => new User { Id = user.Id, FirstName = user.FirstName, LastName = user.LastName }).ToList(); + return users; - public async Task> GetAllUsersAsync() - { - var users = (await _dbContext.ApplicationUsers.ToListAsync()).Select(user => new User { Id = user.Id, FirstName = user.FirstName, LastName = user.LastName }).ToList(); - return users; + } + public async Task GetUserByIdAsync(int Id) + { + ApplicationUser? user = await _dbContext.ApplicationUsers.FindAsync(Id).ConfigureAwait(false); + return user; + } - } + public async Task LoginUserAsync(LoginRequest request) + { + SignInResult signInResult = await _signInManager.PasswordSignInAsync(request.Email, request.Password, false, false).ConfigureAwait(false); + if (!signInResult.Succeeded) + { + throw new Exception("Invalid Email or Password"); + } + IdentityApplicationUser user = await _userManager.FindByEmailAsync(request.Email).ConfigureAwait(false) ?? throw new Exception("User does not exist"); + UserInfo userInfo = new(user.Id, request.Email, (await _userManager.GetRolesAsync(user).ConfigureAwait(false)).ToList()); + return GenerateJwtToken(userInfo); + } - public async Task GetUserByIdAsync(int Id) - { - var user = await _dbContext.ApplicationUsers.FindAsync(Id); - return user; - } + public async Task ForgotPasswordAsync(string email) + { + IdentityApplicationUser user = await _userManager.FindByEmailAsync(email).ConfigureAwait(false) ?? throw new Exception("Invalid Email"); + string token = await _userManager.GeneratePasswordResetTokenAsync(user).ConfigureAwait(false); + return token; + } - public async Task LoginUserAsync(LoginRequest request) - { - var signInResult = await _signInManager.PasswordSignInAsync(request.Email, request.Password, false, false); - if (!signInResult.Succeeded) + public async Task ResetPasswordAsync(string email, string token, string newPassword) { - throw new Exception("Invalid Email or Password"); + IdentityApplicationUser user = await _userManager.FindByEmailAsync(email).ConfigureAwait(false) ?? throw new Exception("Invalid Email"); + IdentityResult result = await _userManager.ResetPasswordAsync(user, token, newPassword).ConfigureAwait(false); + if (!result.Succeeded) throw new Exception("Invalid token"); + UserInfo userInfo = new(user.Id, email, (await _userManager.GetRolesAsync(user).ConfigureAwait(false)).ToList()); + return GenerateJwtToken(userInfo); } - IdentityApplicationUser user = await _userManager.FindByEmailAsync(request.Email) ?? throw new Exception("User does not exist"); - UserInfo userInfo = new(user.Id, request.Email, (await _userManager.GetRolesAsync(user)).ToList()); - return GenerateJwtToken(userInfo); - } - - public async Task ForgotPasswordAsync(string email) - { - var user = await _userManager.FindByEmailAsync(email) ?? throw new Exception("Invalid Email"); - var token = await _userManager.GeneratePasswordResetTokenAsync(user); - return token; - } - - public async Task ResetPasswordAsync(string email, string token, string newPassword) - { - var user = await _userManager.FindByEmailAsync(email) ?? throw new Exception("Invalid Email"); - var result = await _userManager.ResetPasswordAsync(user, token, newPassword); - if (!result.Succeeded) throw new Exception("Invalid token"); - UserInfo userInfo = new(user.Id, email, (await _userManager.GetRolesAsync(user)).ToList()); - return GenerateJwtToken(userInfo); - } - - public async Task AddUserRoleAsync(string email, int role) - { - string newRole = ((Roles)role).ToString(); - if (!await _roleManager.RoleExistsAsync(newRole)) + + public async Task AddUserRoleAsync(string email, int role) { - await _roleManager.CreateAsync(new IdentityRole(newRole)); + string newRole = ((Roles)role).ToString(); + if (!await _roleManager.RoleExistsAsync(newRole).ConfigureAwait(false)) + { + await _roleManager.CreateAsync(new IdentityRole(newRole)).ConfigureAwait(false); + } + IdentityApplicationUser identityApplicationUser = await _userManager.FindByEmailAsync(email).ConfigureAwait(false) ?? throw new Exception("Error finding user"); + await _userManager.AddToRoleAsync(identityApplicationUser, newRole).ConfigureAwait(false); + await _userManager.AddClaimAsync(identityApplicationUser, new Claim(ClaimTypes.Role, newRole)).ConfigureAwait(false); + return true; } - var identityApplicationUser = await _userManager.FindByEmailAsync(email) ?? throw new Exception("Error finding user"); - await _userManager.AddToRoleAsync(identityApplicationUser, newRole); - await _userManager.AddClaimAsync(identityApplicationUser, new Claim(ClaimTypes.Role, newRole)); - return true; - } } \ No newline at end of file diff --git a/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs b/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs index 70075e0..20045bd 100644 --- a/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs +++ b/DotnetFoundation/DotnetFoundation.Infrastructure/SqlDatabaseContext.cs @@ -7,24 +7,24 @@ namespace DotnetFoundation.Infrastructure; public class SqlDatabaseContext : IdentityDbContext { - public SqlDatabaseContext(DbContextOptions options) : base(options) - { - - } - public DbSet ApplicationUsers { get; set; } - protected override void OnModelCreating(ModelBuilder builder) - { - base.OnModelCreating(builder); - - builder.Entity() - .HasKey(au => au.Id); - builder.Entity().ToTable("users"); - - builder.Entity() - .HasOne(au => au.IdentityApplicationUser) - .WithOne(iu => iu.ApplicationUser) - .HasForeignKey(au => au.IdentityApplicationUserId); - } + public SqlDatabaseContext(DbContextOptions options) : base(options) + { + + } + public DbSet ApplicationUsers { get; set; } + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.Entity() + .HasKey(au => au.Id); + builder.Entity().ToTable("users"); + + builder.Entity() + .HasOne(au => au.IdentityApplicationUser) + .WithOne(iu => iu.ApplicationUser) + .HasForeignKey(au => au.IdentityApplicationUserId); + } }