diff --git a/src/Application/DTOs/Transaction/GetTransactionsByAccountIdResponse.cs b/src/Application/DTOs/Transaction/GetTransactionsByAccountIdResponse.cs new file mode 100644 index 0000000..2bbb40c --- /dev/null +++ b/src/Application/DTOs/Transaction/GetTransactionsByAccountIdResponse.cs @@ -0,0 +1,7 @@ +namespace Application.DTOs.Transaction; + +public class GetTransactionsByAccountIdResponse +{ + public long AccountId { get; set; } + public List TransactionWithSources = new(); +} \ No newline at end of file diff --git a/src/Application/DTOs/Identity/ChangeRole/ChangeRoleRequest.cs b/src/Application/DTOs/User/ChangeRole/ChangeRoleRequest.cs similarity index 97% rename from src/Application/DTOs/Identity/ChangeRole/ChangeRoleRequest.cs rename to src/Application/DTOs/User/ChangeRole/ChangeRoleRequest.cs index 2d4d905..7cbce05 100644 --- a/src/Application/DTOs/Identity/ChangeRole/ChangeRoleRequest.cs +++ b/src/Application/DTOs/User/ChangeRole/ChangeRoleRequest.cs @@ -1,7 +1,7 @@ -namespace Application.DTOs.Identity.ChangeRole; - -public class ChangeRoleRequest -{ - public string UserName { get; set; } = string.Empty; - public string Role { get; set; } = string.Empty; +namespace Application.DTOs.Identity.ChangeRole; + +public class ChangeRoleRequest +{ + public string UserName { get; set; } = string.Empty; + public string Role { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Application/DTOs/Identity/CreateUser/CreateUserRequest.cs b/src/Application/DTOs/User/CreateUser/CreateUserRequest.cs similarity index 97% rename from src/Application/DTOs/Identity/CreateUser/CreateUserRequest.cs rename to src/Application/DTOs/User/CreateUser/CreateUserRequest.cs index ff1b356..f0c4b9e 100644 --- a/src/Application/DTOs/Identity/CreateUser/CreateUserRequest.cs +++ b/src/Application/DTOs/User/CreateUser/CreateUserRequest.cs @@ -1,11 +1,11 @@ -namespace Application.DTOs.Identity.CreateUser; - -public class CreateUserRequest -{ - public string FirstName { get; set; } = String.Empty; - public string LastName { get; set; } = String.Empty; - public string Email { get; set; } = String.Empty; - public string UserName { get; set; } = String.Empty; - public string Password { get; set; } = String.Empty; - public string Role { get; set; } = String.Empty; +namespace Application.DTOs.Identity.CreateUser; + +public class CreateUserRequest +{ + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + public string Email { get; set; } = String.Empty; + public string UserName { get; set; } = String.Empty; + public string Password { get; set; } = String.Empty; + public string Role { get; set; } = String.Empty; } \ No newline at end of file diff --git a/src/Application/DTOs/Identity/CreateUser/CreateUserResponse.cs b/src/Application/DTOs/User/CreateUser/CreateUserResponse.cs similarity index 97% rename from src/Application/DTOs/Identity/CreateUser/CreateUserResponse.cs rename to src/Application/DTOs/User/CreateUser/CreateUserResponse.cs index b219712..8b25986 100644 --- a/src/Application/DTOs/Identity/CreateUser/CreateUserResponse.cs +++ b/src/Application/DTOs/User/CreateUser/CreateUserResponse.cs @@ -1,10 +1,10 @@ -namespace Application.DTOs.Identity.CreateUser; - -public class CreateUserResponse -{ - public string FirstName { get; set; } = String.Empty; - public string LastName { get; set; } = String.Empty; - public string Email { get; set; } = String.Empty; - public string UserName { get; set; } = String.Empty; - public string Role { get; set; } = String.Empty; +namespace Application.DTOs.Identity.CreateUser; + +public class CreateUserResponse +{ + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + public string Email { get; set; } = String.Empty; + public string UserName { get; set; } = String.Empty; + public string Role { get; set; } = String.Empty; } \ No newline at end of file diff --git a/src/Application/DTOs/Identity/GetUser/GetUserResponse.cs b/src/Application/DTOs/User/GetUser/GetUserResponse.cs similarity index 100% rename from src/Application/DTOs/Identity/GetUser/GetUserResponse.cs rename to src/Application/DTOs/User/GetUser/GetUserResponse.cs diff --git a/src/Application/DTOs/Identity/LoginUser/LoginUserRequest.cs b/src/Application/DTOs/User/LoginUser/LoginUserRequest.cs similarity index 96% rename from src/Application/DTOs/Identity/LoginUser/LoginUserRequest.cs rename to src/Application/DTOs/User/LoginUser/LoginUserRequest.cs index ad6df17..d4c4025 100644 --- a/src/Application/DTOs/Identity/LoginUser/LoginUserRequest.cs +++ b/src/Application/DTOs/User/LoginUser/LoginUserRequest.cs @@ -1,8 +1,8 @@ -namespace Application.DTOs.Identity.LoginUser; - -public class LoginUserRequest -{ - public string? UserName { get; set; } - public string? Email { get; set; } - public string Password { get; set; } = String.Empty; +namespace Application.DTOs.Identity.LoginUser; + +public class LoginUserRequest +{ + public string? UserName { get; set; } + public string? Email { get; set; } + public string Password { get; set; } = String.Empty; } \ No newline at end of file diff --git a/src/Application/DTOs/Identity/LoginUser/LoginUserResponse.cs b/src/Application/DTOs/User/LoginUser/LoginUserResponse.cs similarity index 97% rename from src/Application/DTOs/Identity/LoginUser/LoginUserResponse.cs rename to src/Application/DTOs/User/LoginUser/LoginUserResponse.cs index 64efbdd..9b2697a 100644 --- a/src/Application/DTOs/Identity/LoginUser/LoginUserResponse.cs +++ b/src/Application/DTOs/User/LoginUser/LoginUserResponse.cs @@ -1,11 +1,11 @@ -namespace Application.DTOs.Identity.LoginUser; - -public class LoginUserResponse -{ - public string FirstName { get; set; } = String.Empty; - public string LastName { get; set; } = String.Empty; - public string Email { get; set; } = String.Empty; - public string UserName { get; set; } = String.Empty; - public string Role { get; set; } = String.Empty; - public string Token { get; set; } = String.Empty; +namespace Application.DTOs.Identity.LoginUser; + +public class LoginUserResponse +{ + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + public string Email { get; set; } = String.Empty; + public string UserName { get; set; } = String.Empty; + public string Role { get; set; } = String.Empty; + public string Token { get; set; } = String.Empty; } \ No newline at end of file diff --git a/src/Application/Interfaces/ITokenService.cs b/src/Application/Interfaces/ITokenService.cs index 05303db..fdce667 100644 --- a/src/Application/Interfaces/ITokenService.cs +++ b/src/Application/Interfaces/ITokenService.cs @@ -5,6 +5,4 @@ namespace Application.Interfaces; public interface ITokenService { string GenerateToken(AppUser user, string role); - Task IsTokenInvalidatedAsync(string token); - Task AddInvalidatedTokenAsync(string token); } \ No newline at end of file diff --git a/src/Application/Interfaces/Services/ITransactionService.cs b/src/Application/Interfaces/Services/ITransactionService.cs index 0d316c2..fa26ab5 100644 --- a/src/Application/Interfaces/Services/ITransactionService.cs +++ b/src/Application/Interfaces/Services/ITransactionService.cs @@ -1,4 +1,5 @@ using Application.DTOs; +using Application.DTOs.Transaction; using Domain.Entities; namespace Application.Interfaces.Services; @@ -7,5 +8,5 @@ public interface ITransactionService { Task AddTransactionsFromCsvAsync(string filePath); Task>> GetAllTransactionsAsync(); - Task> GetTransactionsByAccountIdAsync(long accountId); + Task>> GetTransactionsByAccountIdAsync(long accountId); } \ No newline at end of file diff --git a/src/Application/Interfaces/Services/IIdentityService.cs b/src/Application/Interfaces/Services/IUserService.cs similarity index 85% rename from src/Application/Interfaces/Services/IIdentityService.cs rename to src/Application/Interfaces/Services/IUserService.cs index 44c6280..a2ac77c 100644 --- a/src/Application/Interfaces/Services/IIdentityService.cs +++ b/src/Application/Interfaces/Services/IUserService.cs @@ -1,16 +1,15 @@ -using Application.DTOs; -using Application.DTOs.Identity.ChangeRole; -using Application.DTOs.Identity.CreateUser; -using Application.DTOs.Identity.GetUser; -using Application.DTOs.Identity.LoginUser; - -namespace Application.Interfaces.Services; - -public interface IIdentityService -{ - Task> SignUpUser(CreateUserRequest createIdentityDto); - Task> Login(LoginUserRequest loginDto); - Task ChangeRole(ChangeRoleRequest changeRoleRequest); - Task> GetUsersAsync(); - Task Logout(string token); +using Application.DTOs; +using Application.DTOs.Identity.ChangeRole; +using Application.DTOs.Identity.CreateUser; +using Application.DTOs.Identity.GetUser; +using Application.DTOs.Identity.LoginUser; + +namespace Application.Interfaces.Services; + +public interface IUserService +{ + Task> SignUpUser(CreateUserRequest createIdentityDto); + Task> Login(LoginUserRequest loginDto); + Task ChangeRole(ChangeRoleRequest changeRoleRequest); + Task> GetUsersAsync(); } \ No newline at end of file diff --git a/src/Application/Mappers/IdentityMapper.cs b/src/Application/Mappers/UserMapper.cs similarity index 94% rename from src/Application/Mappers/IdentityMapper.cs rename to src/Application/Mappers/UserMapper.cs index 65b1e5c..e485f93 100644 --- a/src/Application/Mappers/IdentityMapper.cs +++ b/src/Application/Mappers/UserMapper.cs @@ -1,57 +1,57 @@ -using Application.DTOs.Identity.CreateUser; -using Application.DTOs.Identity.GetUser; -using Application.DTOs.Identity.LoginUser; -using Domain.Entities; - -namespace Application.Mappers; - -public static class IdentityMapper -{ - public static AppUser ToAppUser(this CreateUserRequest createUserRequest) - { - return new AppUser - { - FirstName = createUserRequest.FirstName, - LastName = createUserRequest.LastName, - Email = createUserRequest.Email, - UserName = createUserRequest.UserName - }; - } - - public static CreateUserResponse ToCreateUserResponse(this AppUser appUser, string role) - { - return new CreateUserResponse - { - FirstName = appUser.FirstName, - LastName = appUser.LastName, - Email = appUser.Email, - UserName = appUser.UserName, - Role = role - }; - } - - public static LoginUserResponse ToLoginUserResponse(this AppUser appUser, string role, string token) - { - return new LoginUserResponse - { - FirstName = appUser.FirstName, - LastName = appUser.LastName, - Email = appUser.Email, - UserName = appUser.UserName, - Role = role, - Token = token - }; - } - - public static GetUserResponse ToGetUserResponse(this AppUser appUser, string role) - { - return new GetUserResponse - { - FirstName = appUser.FirstName, - LastName = appUser.LastName, - Email = appUser.Email, - UserName = appUser.UserName, - Role = role - }; - } +using Application.DTOs.Identity.CreateUser; +using Application.DTOs.Identity.GetUser; +using Application.DTOs.Identity.LoginUser; +using Domain.Entities; + +namespace Application.Mappers; + +public static class UserMapper +{ + public static AppUser ToAppUser(this CreateUserRequest createUserRequest) + { + return new AppUser + { + FirstName = createUserRequest.FirstName, + LastName = createUserRequest.LastName, + Email = createUserRequest.Email, + UserName = createUserRequest.UserName + }; + } + + public static CreateUserResponse ToCreateUserResponse(this AppUser appUser, string role) + { + return new CreateUserResponse + { + FirstName = appUser.FirstName, + LastName = appUser.LastName, + Email = appUser.Email, + UserName = appUser.UserName, + Role = role + }; + } + + public static LoginUserResponse ToLoginUserResponse(this AppUser appUser, string role, string token) + { + return new LoginUserResponse + { + FirstName = appUser.FirstName, + LastName = appUser.LastName, + Email = appUser.Email, + UserName = appUser.UserName, + Role = role, + Token = token + }; + } + + public static GetUserResponse ToGetUserResponse(this AppUser appUser, string role) + { + return new GetUserResponse + { + FirstName = appUser.FirstName, + LastName = appUser.LastName, + Email = appUser.Email, + UserName = appUser.UserName, + Role = role + }; + } } \ No newline at end of file diff --git a/src/Application/Services/DomainService/TransactionService.cs b/src/Application/Services/DomainService/TransactionService.cs index 98b2553..4b13e8f 100644 --- a/src/Application/Services/DomainService/TransactionService.cs +++ b/src/Application/Services/DomainService/TransactionService.cs @@ -49,10 +49,46 @@ public async Task>> GetAllTransactionsAsync() } } - public async Task> GetTransactionsByAccountIdAsync(long accountId) + public async Task>> GetTransactionsByAccountIdAsync(long accountId) { - var source = await _transactionRepository.GetBySourceAccountId(accountId); - var destination = await _transactionRepository.GetByDestinationAccountId(accountId); - return source.Concat(destination).ToList(); + try + { + var result = new List(); + + var transactionsSourceAccountId = await _transactionRepository.GetBySourceAccountId(accountId); + + var transactionsDestinationAccountId = await _transactionRepository.GetByDestinationAccountId(accountId); + + var allTransactions = transactionsSourceAccountId.Concat(transactionsDestinationAccountId).ToList(); + + var groupedTransactions = allTransactions + .GroupBy(t => t.SourceAccountId == accountId ? t.DestinationAccountId : t.SourceAccountId) + .ToList(); + + foreach (var group in groupedTransactions) + { + var response = new GetTransactionsByAccountIdResponse + { + AccountId = group.Key, + TransactionWithSources = group.Select(t => new TransactionCsvModel + { + TransactionID = t.TransactionId, + SourceAcount = t.SourceAccountId, + DestiantionAccount = t.DestinationAccountId, + Amount = t.Amount, + Date = t.Date, + Type = t.Type, + }).ToList() + }; + + result.Add(response); + } + + return Result>.Ok(result); + } + catch (Exception ex) + { + return Result>.Fail($"An error occurred: {ex.Message}"); + } } } \ No newline at end of file diff --git a/src/Application/Services/DomainService/IdentityService.cs b/src/Application/Services/DomainService/UserService.cs similarity index 93% rename from src/Application/Services/DomainService/IdentityService.cs rename to src/Application/Services/DomainService/UserService.cs index 90f2e8e..ca2491e 100644 --- a/src/Application/Services/DomainService/IdentityService.cs +++ b/src/Application/Services/DomainService/UserService.cs @@ -12,12 +12,12 @@ namespace Application.Services.DomainService; -public class IdentityService : IIdentityService +public class UserService : IUserService { private readonly IUserManagerRepository _userManagerRepository; private readonly IRoleManagerRepository _roleManagerRepository; private readonly ITokenService _tokenService; - public IdentityService(IUserManagerRepository userManagerRepository, + public UserService(IUserManagerRepository userManagerRepository, IRoleManagerRepository roleManagerRepository, ITokenService tokenService) { @@ -108,10 +108,4 @@ public async Task> GetUsersAsync() return userWithRoles; } - - public async Task Logout(string token) - { - await _tokenService.AddInvalidatedTokenAsync(token); - return Result.Ok(); - } } \ No newline at end of file diff --git a/src/Web/Controllers/AccountController.cs b/src/Web/Controllers/AccountsController.cs similarity index 90% rename from src/Web/Controllers/AccountController.cs rename to src/Web/Controllers/AccountsController.cs index 167cdcc..f165282 100644 --- a/src/Web/Controllers/AccountController.cs +++ b/src/Web/Controllers/AccountsController.cs @@ -10,22 +10,22 @@ namespace Web.Controllers; [ApiController] -[Route("[controller]/[action]")] -public class AccountController : ControllerBase +[Route("accounts")] +public class AccountsController : ControllerBase { private readonly IAccountService _accountService; - public AccountController(IAccountService accountService) + public AccountsController(IAccountService accountService) { _accountService = accountService; } - [HttpPost] + [HttpPost("upload")] [Authorize] [RequiresAnyRole(Claims.Role, AppRoles.Admin, AppRoles.DataAdmin)] [ProducesResponseType(200)] [ProducesResponseType(400)] - public async Task ImportAccounts([FromForm] IFormFile file) + public async Task UploadAccounts([FromForm] IFormFile file) { if (file.Length == 0) return BadRequest("No file uploaded."); diff --git a/src/Web/Controllers/ProfileController.cs b/src/Web/Controllers/ProfileController.cs index 630478e..aafd0d9 100644 --- a/src/Web/Controllers/ProfileController.cs +++ b/src/Web/Controllers/ProfileController.cs @@ -11,7 +11,7 @@ namespace Web.Controllers; [ApiController] -[Route("[controller]/[action]")] +[Route("profile")] public class ProfileController : ControllerBase { private readonly IProfileService _profileService; @@ -21,7 +21,7 @@ public ProfileController(IProfileService profileService) _profileService = profileService; } - [HttpPut] + [HttpPut("edit-info")] [Authorize] [ProducesResponseType(200)] [ProducesResponseType(400)] @@ -63,7 +63,7 @@ public async Task GetProfileInfo() return Ok(user.ToProfileInfoDto()); } - [HttpPut] + [HttpPut("change-password")] [Authorize] [ProducesResponseType(200)] [ProducesResponseType(400)] diff --git a/src/Web/Controllers/TransactionController.cs b/src/Web/Controllers/TransactionsController.cs similarity index 80% rename from src/Web/Controllers/TransactionController.cs rename to src/Web/Controllers/TransactionsController.cs index db29b36..f744bd0 100644 --- a/src/Web/Controllers/TransactionController.cs +++ b/src/Web/Controllers/TransactionsController.cs @@ -1,81 +1,89 @@ -using Application.Interfaces.Services; -using Domain.Constants; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Web.Helper; -using Web.Identity; -using Web.Mappers; - -namespace Web.Controllers; - -[ApiController] -[Route("[controller]/[action]")] -public class TransactionController : ControllerBase -{ - private readonly ITransactionService _transactionService; - - public TransactionController(ITransactionService transactionService) - { - _transactionService = transactionService; - } - - [HttpPost] - [Authorize] - [RequiresAnyRole(Claims.Role, AppRoles.Admin, AppRoles.DataAdmin)] - [ProducesResponseType(200)] - [ProducesResponseType(400)] - [ProducesResponseType(401)] - [ProducesResponseType(403)] - public async Task ImportTransactions([FromForm] IFormFile file) - { - if (file.Length == 0) - return BadRequest("No file uploaded."); - - var filePath = Path.GetTempFileName(); - - await using (var stream = System.IO.File.Create(filePath)) - { - await file.CopyToAsync(stream); - } - - var result = await _transactionService.AddTransactionsFromCsvAsync(filePath); - - if (!result.Succeed) - { - return BadRequest(result.Message); - } - - return Ok(); - } - - [HttpGet] - [Authorize] - [RequiresAnyRole(Claims.Role, AppRoles.Admin, AppRoles.DataAdmin, AppRoles.DataAnalyst)] - [ProducesResponseType(200)] - [ProducesResponseType(400)] - [ProducesResponseType(401)] - [ProducesResponseType(403)] - public async Task GetAllTransactions() - { - var allTransactions = await _transactionService.GetAllTransactionsAsync(); - if (!allTransactions.Succeed) - { - return BadRequest(Errors.New(nameof(GetAllTransactions), allTransactions.Message)); - } - - var response = allTransactions.Value!; - return Ok(response.ToGotAllTransactionsDto()); - } - - [HttpGet("{accountId}")] - [Authorize] - [RequiresAnyRole(Claims.Role, AppRoles.Admin, AppRoles.DataAdmin, AppRoles.DataAnalyst)] - [ProducesResponseType(200)] - [ProducesResponseType(401)] - [ProducesResponseType(403)] - public async Task GetTransactionsByAccountId(long accountId) - { - var transactions = await _transactionService.GetTransactionsByAccountIdAsync(accountId); - return Ok(transactions.ToGotAllTransactionsDto()); - } +using Application.Interfaces.Services; +using Domain.Constants; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Web.Helper; +using Web.Identity; +using Web.Mappers; + +namespace Web.Controllers; + +[ApiController] +[Route("transactions")] +public class TransactionsController : ControllerBase +{ + private readonly ITransactionService _transactionService; + + public TransactionsController(ITransactionService transactionService) + { + _transactionService = transactionService; + } + + [HttpPost("upload")] + [Authorize] + [RequiresAnyRole(Claims.Role, AppRoles.Admin, AppRoles.DataAdmin)] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + public async Task UploadTransactions([FromForm] IFormFile file) + { + if (file.Length == 0) + return BadRequest("No file uploaded."); + + var filePath = Path.GetTempFileName(); + + await using (var stream = System.IO.File.Create(filePath)) + { + await file.CopyToAsync(stream); + } + + var result = await _transactionService.AddTransactionsFromCsvAsync(filePath); + + if (!result.Succeed) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [HttpGet()] + [Authorize] + [RequiresAnyRole(Claims.Role, AppRoles.Admin, AppRoles.DataAdmin, AppRoles.DataAnalyst)] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + public async Task GetAllTransactions() + { + var allTransactions = await _transactionService.GetAllTransactionsAsync(); + if (!allTransactions.Succeed) + { + return BadRequest(Errors.New(nameof(GetAllTransactions), allTransactions.Message)); + } + + var response = allTransactions.Value!; + return Ok(response.ToGotAllTransactionsDto()); + } + + [HttpGet("by-account/{accountId}")] + [Authorize] + [RequiresAnyRole(Claims.Role, AppRoles.Admin, AppRoles.DataAdmin, AppRoles.DataAnalyst)] + [ProducesResponseType(200)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + public async Task GetTransactionsByAccountId(long accountId) + { + var transactions = await _transactionService.GetTransactionsByAccountIdAsync(accountId); + + if (!transactions.Succeed) + { + return BadRequest(Errors.New(nameof(GetAllTransactions), transactions.Message)); + } + + var response = transactions.Value!; + + return Ok(response); + } } \ No newline at end of file diff --git a/src/Web/Controllers/IdentityController.cs b/src/Web/Controllers/UsersController.cs similarity index 62% rename from src/Web/Controllers/IdentityController.cs rename to src/Web/Controllers/UsersController.cs index 9a0cedf..9391b52 100644 --- a/src/Web/Controllers/IdentityController.cs +++ b/src/Web/Controllers/UsersController.cs @@ -1,105 +1,91 @@ -using Application.Interfaces.Services; -using Domain.Constants; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Web.DTOs.Identity; -using Web.Helper; -using Web.Identity; -using Web.Mappers; - -namespace Web.Controllers; - -[ApiController] -[Route("[controller]/[action]")] -public class IdentityController : ControllerBase -{ - private readonly IIdentityService _identityService; - public IdentityController(IIdentityService identityService) - { - _identityService = identityService; - } - - [HttpPost] - [Authorize] - [RequiresAnyRole(Claims.Role, AppRoles.Admin)] - [ProducesResponseType(200)] - [ProducesResponseType(400)] - [ProducesResponseType(401)] - [ProducesResponseType(403)] - public async Task Signup([FromBody] SignupDto signupDto) - { - var result = await _identityService.SignUpUser(signupDto.ToCreateUserRequest()); - - if (!result.Succeed) - { - return BadRequest(Errors.New(nameof(Signup), result.Message)); - } - - var response = result.Value!; - - return Ok(response.ToUserSignedUpDto()); - } - - [HttpPost] - [ProducesResponseType(200)] - [ProducesResponseType(401)] - public async Task Login([FromBody] LoginDto loginDto) - { - var result = await _identityService.Login(loginDto.ToLoginUserRequest()); - - if (!result.Succeed) - { - return Unauthorized(Errors.New(nameof(Login), result.Message)); - } - - var response = result.Value!; - - return Ok(response.ToUserLoggedInDto()); - } - - [HttpPut] - [Authorize] - [RequiresAnyRole(Claims.Role, AppRoles.Admin)] - [ProducesResponseType(200)] - [ProducesResponseType(400)] - [ProducesResponseType(401)] - [ProducesResponseType(403)] - public async Task ChangeRole([FromBody] ChangeRoleDto changeRoleDto) - { - var result = await _identityService.ChangeRole(changeRoleDto.ToChangeRoleRequest()); - - if (!result.Succeed) - { - return BadRequest(Errors.New(nameof(ChangeRole), result.Message)); - } - - return Ok("Role changed successfully!"); - } - - [HttpGet] - [Authorize] - [RequiresAnyRole(Claims.Role, AppRoles.Admin)] - [ProducesResponseType(200)] - [ProducesResponseType(401)] - [ProducesResponseType(403)] - public async Task GetUsersAsync() - { - var appUsersWithRoles = await _identityService.GetUsersAsync(); - - return Ok(appUsersWithRoles); - } - - [HttpPost] - [Authorize] - public async Task Logout() - { - var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", ""); - var result = await _identityService.Logout(token); - if (!result.Succeed) - { - return BadRequest(Errors.New(nameof(Logout), result.Message)); - } - - return Ok("Logged out successfully!"); - } +using Application.Interfaces.Services; +using Domain.Constants; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Web.DTOs.Identity; +using Web.Helper; +using Web.Identity; +using Web.Mappers; + +namespace Web.Controllers; + +[ApiController] +[Route("identity")] +public class UsersController : ControllerBase +{ + private readonly IUserService _userService; + public UsersController(IUserService userService) + { + _userService = userService; + } + + [HttpPost("signup")] + [Authorize] + [RequiresAnyRole(Claims.Role, AppRoles.Admin)] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + public async Task Signup([FromBody] SignupDto signupDto) + { + var result = await _userService.SignUpUser(signupDto.ToCreateUserRequest()); + + if (!result.Succeed) + { + return BadRequest(Errors.New(nameof(Signup), result.Message)); + } + + var response = result.Value!; + + return Ok(response.ToUserSignedUpDto()); + } + + [HttpPost("login")] + [ProducesResponseType(200)] + [ProducesResponseType(401)] + public async Task Login([FromBody] LoginDto loginDto) + { + var result = await _userService.Login(loginDto.ToLoginUserRequest()); + + if (!result.Succeed) + { + return Unauthorized(Errors.New(nameof(Login), result.Message)); + } + + var response = result.Value!; + + return Ok(response.ToUserLoggedInDto()); + } + + [HttpPatch("change-role")] + [Authorize] + [RequiresAnyRole(Claims.Role, AppRoles.Admin)] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + public async Task ChangeRole([FromBody] ChangeRoleDto changeRoleDto) + { + var result = await _userService.ChangeRole(changeRoleDto.ToChangeRoleRequest()); + + if (!result.Succeed) + { + return BadRequest(Errors.New(nameof(ChangeRole), result.Message)); + } + + return Ok("Role changed successfully!"); + } + + [HttpGet] + [Authorize] + [RequiresAnyRole(Claims.Role, AppRoles.Admin)] + [ProducesResponseType(200)] + [ProducesResponseType(401)] + [ProducesResponseType(403)] + public async Task GetUsersAsync() + { + var appUsersWithRoles = await _userService.GetUsersAsync(); + + return Ok(appUsersWithRoles); + } } \ No newline at end of file diff --git a/src/Web/DTOs/Identity/ChangeRoleDto.cs b/src/Web/DTOs/User/ChangeRoleDto.cs similarity index 95% rename from src/Web/DTOs/Identity/ChangeRoleDto.cs rename to src/Web/DTOs/User/ChangeRoleDto.cs index 8fa86bd..c0396c9 100644 --- a/src/Web/DTOs/Identity/ChangeRoleDto.cs +++ b/src/Web/DTOs/User/ChangeRoleDto.cs @@ -1,11 +1,11 @@ -using System.ComponentModel.DataAnnotations; - -namespace Web.DTOs.Identity; - -public class ChangeRoleDto -{ - [Required] - public string? UserName { get; set; } - [Required] - public string? Role { get; set; } +using System.ComponentModel.DataAnnotations; + +namespace Web.DTOs.Identity; + +public class ChangeRoleDto +{ + [Required] + public string? UserName { get; set; } + [Required] + public string? Role { get; set; } } \ No newline at end of file diff --git a/src/Web/DTOs/Identity/Login/LoginDto.cs b/src/Web/DTOs/User/Login/LoginDto.cs similarity index 96% rename from src/Web/DTOs/Identity/Login/LoginDto.cs rename to src/Web/DTOs/User/Login/LoginDto.cs index f0970d6..35809b6 100644 --- a/src/Web/DTOs/Identity/Login/LoginDto.cs +++ b/src/Web/DTOs/User/Login/LoginDto.cs @@ -1,12 +1,12 @@ -using System.ComponentModel.DataAnnotations; -using System.Runtime.InteropServices.JavaScript; - -namespace Web.DTOs.Identity; - -public class LoginDto -{ - public string? UserName { get; set; } - public string? Email { get; set; } - [Required] - public string? Password { get; set; } +using System.ComponentModel.DataAnnotations; +using System.Runtime.InteropServices.JavaScript; + +namespace Web.DTOs.Identity; + +public class LoginDto +{ + public string? UserName { get; set; } + public string? Email { get; set; } + [Required] + public string? Password { get; set; } } \ No newline at end of file diff --git a/src/Web/DTOs/Identity/Login/UserLoggedInDto.cs b/src/Web/DTOs/User/Login/UserLoggedInDto.cs similarity index 97% rename from src/Web/DTOs/Identity/Login/UserLoggedInDto.cs rename to src/Web/DTOs/User/Login/UserLoggedInDto.cs index f26d6e5..8ef5237 100644 --- a/src/Web/DTOs/Identity/Login/UserLoggedInDto.cs +++ b/src/Web/DTOs/User/Login/UserLoggedInDto.cs @@ -1,11 +1,11 @@ -namespace Web.DTOs.Identity; - -public class UserLoggedInDto -{ - public string FirstName { get; set; } = String.Empty; - public string LastName { get; set; } = String.Empty; - public string Email { get; set; } = String.Empty; - public string UserName { get; set; } = String.Empty; - public string Role { get; set; } = String.Empty; - public string Token { get; set; } = String.Empty; +namespace Web.DTOs.Identity; + +public class UserLoggedInDto +{ + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + public string Email { get; set; } = String.Empty; + public string UserName { get; set; } = String.Empty; + public string Role { get; set; } = String.Empty; + public string Token { get; set; } = String.Empty; } \ No newline at end of file diff --git a/src/Web/DTOs/Identity/Signup/SignupDto.cs b/src/Web/DTOs/User/Signup/SignupDto.cs similarity index 95% rename from src/Web/DTOs/Identity/Signup/SignupDto.cs rename to src/Web/DTOs/User/Signup/SignupDto.cs index 31cc6ec..1ef451a 100644 --- a/src/Web/DTOs/Identity/Signup/SignupDto.cs +++ b/src/Web/DTOs/User/Signup/SignupDto.cs @@ -1,27 +1,27 @@ -using System.ComponentModel.DataAnnotations; - -namespace Web.DTOs.Identity; - -public class SignupDto -{ - [Required] - [MaxLength(50)] - public string? FirstName { get; set; } - [Required] - [MaxLength(50)] - public string? LastName { get; set; } - [Required] - [MaxLength(50)] - [EmailAddress] - public string? Email { get; set; } - [Required] - [MaxLength(50)] - public string? UserName { get; set; } - [Required] - [MaxLength(50)] - [MinLength(8)] - public string? Password { get; set; } - [Required] - [MaxLength(50)] - public string? Role { get; set; } +using System.ComponentModel.DataAnnotations; + +namespace Web.DTOs.Identity; + +public class SignupDto +{ + [Required] + [MaxLength(50)] + public string? FirstName { get; set; } + [Required] + [MaxLength(50)] + public string? LastName { get; set; } + [Required] + [MaxLength(50)] + [EmailAddress] + public string? Email { get; set; } + [Required] + [MaxLength(50)] + public string? UserName { get; set; } + [Required] + [MaxLength(50)] + [MinLength(8)] + public string? Password { get; set; } + [Required] + [MaxLength(50)] + public string? Role { get; set; } } \ No newline at end of file diff --git a/src/Web/DTOs/Identity/Signup/UserSignedUpDto.cs b/src/Web/DTOs/User/Signup/UserSignedUpDto.cs similarity index 97% rename from src/Web/DTOs/Identity/Signup/UserSignedUpDto.cs rename to src/Web/DTOs/User/Signup/UserSignedUpDto.cs index 3bda182..d5dc30d 100644 --- a/src/Web/DTOs/Identity/Signup/UserSignedUpDto.cs +++ b/src/Web/DTOs/User/Signup/UserSignedUpDto.cs @@ -1,10 +1,10 @@ -namespace Web.DTOs.Identity; - -public class UserSignedUpDto -{ - public string FirstName { get; set; } = String.Empty; - public string LastName { get; set; } = String.Empty; - public string Email { get; set; } = String.Empty; - public string UserName { get; set; } = String.Empty; - public string Role { get; set; } = String.Empty; +namespace Web.DTOs.Identity; + +public class UserSignedUpDto +{ + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + public string Email { get; set; } = String.Empty; + public string UserName { get; set; } = String.Empty; + public string Role { get; set; } = String.Empty; } \ No newline at end of file diff --git a/src/Web/Mappers/IdentityMapper.cs b/src/Web/Mappers/UserMapper.cs similarity index 95% rename from src/Web/Mappers/IdentityMapper.cs rename to src/Web/Mappers/UserMapper.cs index 5143ad7..c194a9e 100644 --- a/src/Web/Mappers/IdentityMapper.cs +++ b/src/Web/Mappers/UserMapper.cs @@ -1,67 +1,67 @@ -using Application.DTOs.Identity; -using Application.DTOs.Identity.ChangeRole; -using Application.DTOs.Identity.CreateUser; -using Application.DTOs.Identity.LoginUser; -using Web.DTOs.Identity; - -namespace Web.Mappers; - -public static class IdentityMapper -{ - public static CreateUserRequest ToCreateUserRequest(this SignupDto signupDto) - { - return new CreateUserRequest - { - FirstName = signupDto.FirstName, - LastName = signupDto.LastName, - Email = signupDto.Email, - UserName = signupDto.UserName, - Password = signupDto.Password, - Role = signupDto.Role - }; - } - - public static LoginUserRequest ToLoginUserRequest(this LoginDto loginDto) - { - return new LoginUserRequest - { - UserName = loginDto.UserName, - Email = loginDto.Email, - Password = loginDto.Password - }; - } - - public static UserSignedUpDto ToUserSignedUpDto(this CreateUserResponse createUserResponse) - { - return new UserSignedUpDto - { - FirstName = createUserResponse.FirstName, - LastName = createUserResponse.LastName, - Email = createUserResponse.Email, - UserName = createUserResponse.UserName, - Role = createUserResponse.Role - }; - } - - public static UserLoggedInDto ToUserLoggedInDto(this LoginUserResponse loginUserResponse) - { - return new UserLoggedInDto - { - FirstName = loginUserResponse.FirstName, - LastName = loginUserResponse.LastName, - Email = loginUserResponse.Email, - UserName = loginUserResponse.UserName, - Role = loginUserResponse.Role, - Token = loginUserResponse.Token - }; - } - - public static ChangeRoleRequest ToChangeRoleRequest(this ChangeRoleDto changeRoleDto) - { - return new ChangeRoleRequest - { - UserName = changeRoleDto.UserName, - Role = changeRoleDto.Role - }; - } +using Application.DTOs.Identity; +using Application.DTOs.Identity.ChangeRole; +using Application.DTOs.Identity.CreateUser; +using Application.DTOs.Identity.LoginUser; +using Web.DTOs.Identity; + +namespace Web.Mappers; + +public static class UserMapper +{ + public static CreateUserRequest ToCreateUserRequest(this SignupDto signupDto) + { + return new CreateUserRequest + { + FirstName = signupDto.FirstName, + LastName = signupDto.LastName, + Email = signupDto.Email, + UserName = signupDto.UserName, + Password = signupDto.Password, + Role = signupDto.Role + }; + } + + public static LoginUserRequest ToLoginUserRequest(this LoginDto loginDto) + { + return new LoginUserRequest + { + UserName = loginDto.UserName, + Email = loginDto.Email, + Password = loginDto.Password + }; + } + + public static UserSignedUpDto ToUserSignedUpDto(this CreateUserResponse createUserResponse) + { + return new UserSignedUpDto + { + FirstName = createUserResponse.FirstName, + LastName = createUserResponse.LastName, + Email = createUserResponse.Email, + UserName = createUserResponse.UserName, + Role = createUserResponse.Role + }; + } + + public static UserLoggedInDto ToUserLoggedInDto(this LoginUserResponse loginUserResponse) + { + return new UserLoggedInDto + { + FirstName = loginUserResponse.FirstName, + LastName = loginUserResponse.LastName, + Email = loginUserResponse.Email, + UserName = loginUserResponse.UserName, + Role = loginUserResponse.Role, + Token = loginUserResponse.Token + }; + } + + public static ChangeRoleRequest ToChangeRoleRequest(this ChangeRoleDto changeRoleDto) + { + return new ChangeRoleRequest + { + UserName = changeRoleDto.UserName, + Role = changeRoleDto.Role + }; + } } \ No newline at end of file diff --git a/src/Web/Middleware/TokenValidationMiddleware.cs b/src/Web/Middleware/TokenValidationMiddleware.cs deleted file mode 100644 index af1f68a..0000000 --- a/src/Web/Middleware/TokenValidationMiddleware.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Application.Interfaces; - -namespace Web.Middleware; - -public class TokenValidationMiddleware -{ - private readonly RequestDelegate _next; - private readonly IServiceProvider _serviceProvider; - - public TokenValidationMiddleware(RequestDelegate next, IServiceProvider serviceProvider) - { - _next = next; - _serviceProvider = serviceProvider; - } - - public async Task InvokeAsync(HttpContext context) - { - // Create a scope to resolve scoped services - using var scope = _serviceProvider.CreateScope(); - var tokenService = scope.ServiceProvider.GetRequiredService(); - - var authHeader = context.Request.Headers["Authorization"].FirstOrDefault(); - if (authHeader != null && authHeader.StartsWith("Bearer ")) - { - var token = authHeader.Substring("Bearer ".Length).Trim(); - if (await tokenService.IsTokenInvalidatedAsync(token)) - { - context.Response.StatusCode = StatusCodes.Status401Unauthorized; - return; - } - } - - await _next(context); - } -} \ No newline at end of file diff --git a/src/Web/Services/TokenService.cs b/src/Web/Services/TokenService.cs index 01cfb04..bd730b4 100644 --- a/src/Web/Services/TokenService.cs +++ b/src/Web/Services/TokenService.cs @@ -12,7 +12,6 @@ public class TokenService : ITokenService { private readonly IConfiguration _configuration; private readonly SymmetricSecurityKey _symmetricSecurityKey; - private static readonly ConcurrentDictionary _invalidatedTokens = new(); public TokenService(IConfiguration configuration) { @@ -46,15 +45,4 @@ public string GenerateToken(AppUser user, string role) var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } - - public Task IsTokenInvalidatedAsync(string token) - { - return Task.FromResult(_invalidatedTokens.ContainsKey(token)); - } - - public Task AddInvalidatedTokenAsync(string token) - { - _invalidatedTokens[token] = DateTime.UtcNow; - return Task.CompletedTask; - } } \ No newline at end of file diff --git a/src/Web/Startup/MiddlewareExtensions.cs b/src/Web/Startup/MiddlewareExtensions.cs index 420dd5c..bb61ff8 100644 --- a/src/Web/Startup/MiddlewareExtensions.cs +++ b/src/Web/Startup/MiddlewareExtensions.cs @@ -1,6 +1,4 @@ -using Web.Middleware; - -namespace Web.Startup; +namespace Web.Startup; public static class MiddlewareExtensions { @@ -15,8 +13,6 @@ public static WebApplication UseMiddlewareServices(this WebApplication app) app.UseHttpsRedirection(); app.UseCors("AllowSpecificOrigins"); - app.UseMiddleware(); - app.UseAuthentication(); app.UseAuthorization(); diff --git a/src/Web/Startup/ServiceExtensions.DI.cs b/src/Web/Startup/ServiceExtensions.DI.cs index 9d6374c..46f6623 100644 --- a/src/Web/Startup/ServiceExtensions.DI.cs +++ b/src/Web/Startup/ServiceExtensions.DI.cs @@ -14,7 +14,7 @@ public static void AddApplicationServices(this IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/test/Application.UnitTests/Services/DomainService/IdentityServiceTests.cs b/test/Application.UnitTests/Services/DomainService/UserServiceTests.cs similarity index 91% rename from test/Application.UnitTests/Services/DomainService/IdentityServiceTests.cs rename to test/Application.UnitTests/Services/DomainService/UserServiceTests.cs index 5c3a097..6c3c749 100644 --- a/test/Application.UnitTests/Services/DomainService/IdentityServiceTests.cs +++ b/test/Application.UnitTests/Services/DomainService/UserServiceTests.cs @@ -14,19 +14,19 @@ namespace test.Application.UnitTests.Services.DomainService; -public class IdentityServiceTests +public class UserServiceTests { private readonly IUserManagerRepository _userManagerRepository; private readonly IRoleManagerRepository _roleManagerRepository; private readonly ITokenService _tokenService; - private readonly IdentityService _identityService; + private readonly UserService _userService; - public IdentityServiceTests() + public UserServiceTests() { _userManagerRepository = Substitute.For(); _roleManagerRepository = Substitute.For(); _tokenService = Substitute.For(); - _identityService = new IdentityService(_userManagerRepository, _roleManagerRepository, _tokenService); + _userService = new UserService(_userManagerRepository, _roleManagerRepository, _tokenService); } // Signup Tests @@ -45,7 +45,7 @@ public async Task SignUpUser_WhenRoleDoesNotExist_ReturnsFailResult() _roleManagerRepository.RoleExistsAsync(createUserRequest.Role).Returns(Task.FromResult(false)); // Act - var result = await _identityService.SignUpUser(createUserRequest); + var result = await _userService.SignUpUser(createUserRequest); // Assert Assert.False(result.Succeed); @@ -70,7 +70,7 @@ public async Task SignUpUser_WhenUserCreationFails_ReturnsFailResult() .Returns(Task.FromResult(IdentityResult.Failed(new IdentityError { Description = "User creation failed" }))); // Act - var result = await _identityService.SignUpUser(createUserRequest); + var result = await _userService.SignUpUser(createUserRequest); // Assert Assert.False(result.Succeed); @@ -98,7 +98,7 @@ public async Task SignUpUser_WhenRoleAssignmentFails_ReturnsFailResult() .Returns(Task.FromResult(IdentityResult.Failed(new IdentityError { Description = "Role assignment failed" }))); // Act - var result = await _identityService.SignUpUser(createUserRequest); + var result = await _userService.SignUpUser(createUserRequest); // Assert Assert.False(result.Succeed); @@ -139,7 +139,7 @@ public async Task SignUpUser_WhenUserIsCreatedAndRoleAssignedSuccessfully_Return }; // Act - var result = await _identityService.SignUpUser(createUserRequest); + var result = await _userService.SignUpUser(createUserRequest); // Assert Assert.True(result.Succeed); @@ -168,7 +168,7 @@ public async Task Login_WhenUsernameNotFound_ReturnsFailResult() _userManagerRepository.FindByNameAsync(loginUserRequest.UserName).Returns(Task.FromResult(null)); // Act - var result = await _identityService.Login(loginUserRequest); + var result = await _userService.Login(loginUserRequest); // Assert Assert.False(result.Succeed); @@ -190,7 +190,7 @@ public async Task Login_WhenPasswordIncorrect_ReturnsFailResult() _userManagerRepository.CheckPasswordAsync(appUser, loginUserRequest.Password).Returns(Task.FromResult(false)); // Act - var result = await _identityService.Login(loginUserRequest); + var result = await _userService.Login(loginUserRequest); // Assert Assert.False(result.Succeed); @@ -234,7 +234,7 @@ public async Task Login_WhenLoginSucceeds_ReturnsSuccessResult() .Returns(token); // Act - var result = await _identityService.Login(loginRequest); + var result = await _userService.Login(loginRequest); // Assert Assert.True(result.Succeed); @@ -260,7 +260,7 @@ public async Task ChangeRole_WhenRoleDoesNotExist_ReturnsFailResult() _roleManagerRepository.RoleExistsAsync(changeRoleRequest.Role).Returns(Task.FromResult(false)); // Act - var result = await _identityService.ChangeRole(changeRoleRequest); + var result = await _userService.ChangeRole(changeRoleRequest); // Assert Assert.False(result.Succeed); @@ -281,7 +281,7 @@ public async Task ChangeRole_WhenUserDoesNotExist_ReturnsFailResult() _userManagerRepository.FindByNameAsync(changeRoleRequest.UserName).Returns(Task.FromResult(null)); // Act - var result = await _identityService.ChangeRole(changeRoleRequest); + var result = await _userService.ChangeRole(changeRoleRequest); // Assert Assert.False(result.Succeed); @@ -305,7 +305,7 @@ public async Task ChangeRole_WhenOperationSucceeds_ReturnsSuccessResult() _userManagerRepository.ChangeRoleAsync(appUser, changeRoleRequest.Role).Returns(Task.FromResult(IdentityResult.Success)); // Act - var result = await _identityService.ChangeRole(changeRoleRequest); + var result = await _userService.ChangeRole(changeRoleRequest); // Assert Assert.True(result.Succeed); @@ -341,7 +341,7 @@ public async Task GetUsersAsync_ReturnsUserListWithRoles() .Returns(Task.FromResult(roles[1])); // Act - var result = await _identityService.GetUsersAsync(); + var result = await _userService.GetUsersAsync(); // Assert Assert.NotNull(result); diff --git a/test/Web.UnitTests/Controllers/IdentityControllerTests.cs b/test/Web.UnitTests/Controllers/UsersControllerTests.cs similarity index 91% rename from test/Web.UnitTests/Controllers/IdentityControllerTests.cs rename to test/Web.UnitTests/Controllers/UsersControllerTests.cs index 2a602b7..836d6d6 100644 --- a/test/Web.UnitTests/Controllers/IdentityControllerTests.cs +++ b/test/Web.UnitTests/Controllers/UsersControllerTests.cs @@ -18,15 +18,15 @@ namespace test.Web.UnitTests.Controllers; -public class IdentityControllerTests +public class UsersControllerTests { - private readonly IIdentityService _identityServiceMock; - private readonly IdentityController _controller; + private readonly IUserService _userServiceMock; + private readonly UsersController _controller; - public IdentityControllerTests() + public UsersControllerTests() { - _identityServiceMock = Substitute.For(); - _controller = new IdentityController(_identityServiceMock); + _userServiceMock = Substitute.For(); + _controller = new UsersController(_userServiceMock); } // Signup Tests @@ -45,7 +45,7 @@ public async Task Signup_WhenUserIsNotAdmin_ReturnsForbidden() Role = "DataAnalyst" }; - _identityServiceMock.SignUpUser(Arg.Any()).Returns(Result.Ok(new CreateUserResponse())); + _userServiceMock.SignUpUser(Arg.Any()).Returns(Result.Ok(new CreateUserResponse())); _controller.ControllerContext = new ControllerContext { @@ -79,7 +79,7 @@ public async Task Signup_WhenRoleDoesNotExist_ReturnsBadRequest() Role = "NonExistentRole" }; - _identityServiceMock + _userServiceMock .SignUpUser(Arg.Any()) .Returns(Result.Fail("role does not exist")); @@ -131,7 +131,7 @@ public async Task Signup_WhenSignUpSucceeds_ReturnsOkResult() Role = "Admin" }; - _identityServiceMock + _userServiceMock .SignUpUser(Arg.Any()) .Returns(Result.Ok(createUserResponse)); @@ -178,7 +178,7 @@ public async Task Login_WhenLoginSucceeds_ReturnsOkResult() Token = "FakeToken" }; - _identityServiceMock + _userServiceMock .Login(Arg.Any()) .Returns(Result.Ok(mockResponse)); @@ -203,7 +203,7 @@ public async Task ChangeRole_WhenRoleDoesNotExist_ReturnsBadRequest() Role = "NonExistentRole" }; - _identityServiceMock + _userServiceMock .ChangeRole(Arg.Any()) .Returns(Result.Fail("role does not exist")); @@ -230,7 +230,7 @@ public async Task ChangeRole_WhenOperationSucceeds_ReturnsOk() Role = "Admin" }; - _identityServiceMock + _userServiceMock .ChangeRole(Arg.Any()) .Returns(Result.Ok());