diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2b2468..08621e5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,6 +49,7 @@ jobs: shell: powershell run: | .\.sonar\scanner\dotnet-sonarscanner begin /k:"csimonapastore_BasicDotnetTemplate" /o:"csimonapastore-github" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.exclusions="**/Migrations/**.cs, **/Models/Database/**.cs, **/Core/Database/**.cs" + dotnet clean dotnet restore dotnet build --no-incremental dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml" diff --git a/MainProject.Tests/Controllers/AuthController_Tests.cs b/MainProject.Tests/Controllers/AuthController_Tests.cs index a1aa508..2b58b55 100644 --- a/MainProject.Tests/Controllers/AuthController_Tests.cs +++ b/MainProject.Tests/Controllers/AuthController_Tests.cs @@ -20,6 +20,7 @@ using BasicDotnetTemplate.MainProject.Models.Api.Common.User; using BasicDotnetTemplate.MainProject.Models.Api.Common.Role; using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer; using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth; +using Microsoft.AspNetCore.Http; namespace BasicDotnetTemplate.MainProject.Tests; @@ -52,34 +53,20 @@ public class AuthController_Tests IConfiguration configuration = TestUtils.CreateConfiguration(); var authServiceMock = new Mock(); var controller = new AuthController(configuration, authServiceMock.Object); - DatabaseSqlServer.User user = new DatabaseSqlServer.User() - { - Username = "test", - FirstName = "test", - LastName = "test", - Email = "test", - PasswordHash = "test", - PasswordSalt = "test", - Password = "test", - Role = new DatabaseSqlServer.Role() - { - Name = "test" - }, - IsTestUser = true - }; + DatabaseSqlServer.User user = ModelsInit.CreateUser(); AuthenticatedUser authenticatedUser = new AuthenticatedUser(user); - var request = new AuthenticateRequest { Data = new AuthenticateRequestData { Username = "user", Password = "pass" } }; + var request = new AuthenticateRequest { Data = new AuthenticateRequestData { Email = "user", Password = "pass" } }; authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny())).ReturnsAsync(authenticatedUser); ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request)); if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 200); + Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 200); + Assert.IsTrue(result.Status == StatusCodes.Status200OK); Assert.IsInstanceOfType(result.Data, typeof(AuthenticatedUser)); } else @@ -111,12 +98,12 @@ public class AuthController_Tests if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 400); + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 400); + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.IsTrue(result.Message == "Request is not well formed"); } else @@ -141,8 +128,8 @@ public class AuthController_Tests { Data = new AuthenticateRequestData() { - Username = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7", - Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7" + Email = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=", + Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=" } }; AuthenticatedUser? authenticatedUser = null; @@ -153,7 +140,7 @@ public class AuthController_Tests if (response != null) { - Assert.IsTrue(response.StatusCode == 404); + Assert.IsTrue(response.StatusCode == StatusCodes.Status404NotFound); } else { @@ -181,12 +168,12 @@ public class AuthController_Tests if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 400); + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 400); + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.IsTrue(result.Message == "Request is not well formed"); } else @@ -209,7 +196,7 @@ public class AuthController_Tests var request = new AuthenticateRequest { - Data = new AuthenticateRequestData { Username = "user", Password = "pass" } + Data = new AuthenticateRequestData { Email = "user", Password = "pass" } }; authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny())).ThrowsAsync(new Exception("Unexpected error")); @@ -220,12 +207,12 @@ public class AuthController_Tests if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 500); + Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 500); + Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); } else diff --git a/MainProject.Tests/Controllers/RootController_Tests.cs b/MainProject.Tests/Controllers/RootController_Tests.cs index fe80b77..199c7f6 100644 --- a/MainProject.Tests/Controllers/RootController_Tests.cs +++ b/MainProject.Tests/Controllers/RootController_Tests.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using BasicDotnetTemplate.MainProject.Models.Api.Response; using BasicDotnetTemplate.MainProject.Models.Settings; +using Microsoft.AspNetCore.Http; namespace BasicDotnetTemplate.MainProject.Tests; @@ -29,7 +30,7 @@ public class RootController_Test if (result != null) { var data = (OkResult)result; - Assert.IsTrue(data.StatusCode == 200); + Assert.IsTrue(data.StatusCode == StatusCodes.Status200OK); } else { @@ -39,7 +40,7 @@ public class RootController_Test catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } } diff --git a/MainProject.Tests/Controllers/UserController_Tests.cs b/MainProject.Tests/Controllers/UserController_Tests.cs index de46d09..4dfd820 100644 --- a/MainProject.Tests/Controllers/UserController_Tests.cs +++ b/MainProject.Tests/Controllers/UserController_Tests.cs @@ -22,6 +22,10 @@ using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlSer using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth; using AutoMapper; using BasicDotnetTemplate.MainProject.Core.Middlewares; +using Microsoft.AspNetCore.Http; +using BasicDotnetTemplate.MainProject.Models.Api.Request.User; +using BasicDotnetTemplate.MainProject.Models.Api.Data.User; +using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; namespace BasicDotnetTemplate.MainProject.Tests; @@ -29,17 +33,17 @@ namespace BasicDotnetTemplate.MainProject.Tests; [TestClass] public class UserControllerTests { - private IMapper? _mapper; + private Mock? _userServiceMock; + private Mock? _roleServiceMock; + private UserController? _userController; [TestInitialize] public void Setup() { - var config = new MapperConfiguration(cfg => - { - cfg.AddProfile(); - }); - - _mapper = config.CreateMapper(); + IConfiguration configuration = TestUtils.CreateConfiguration(); + _userServiceMock = new Mock(); + _roleServiceMock = new Mock(); + _userController = new UserController(configuration, _userServiceMock?.Object, _roleServiceMock.Object); } [TestMethod] @@ -50,7 +54,8 @@ public class UserControllerTests try { var userServiceMock = new Mock(); - _ = new UserController(null, userServiceMock.Object); + var roleServiceMock = new Mock(); + _ = new UserController(null, userServiceMock.Object, roleServiceMock.Object); exception = false; Assert.Fail($"This test should not pass as configuration is null"); } @@ -64,38 +69,24 @@ public class UserControllerTests [TestMethod] public async Task GetUserByGuidAsync_Should_Return_200_When_Successful() { - IConfiguration configuration = TestUtils.CreateConfiguration(); - var userServiceMock = new Mock(); - var controller = new UserController(configuration, userServiceMock.Object); - var guid = Guid.NewGuid().ToString(); - DatabaseSqlServer.User user = new DatabaseSqlServer.User() + if (_userController == null) { - Guid = guid, - Username = "Username", - FirstName = "FirstName", - LastName = "LastName", - Email = "Email", - PasswordHash = "PasswordHash", - PasswordSalt = "PasswordSalt", - Password = "Password", - Role = new DatabaseSqlServer.Role() - { - Name = "Role.Name" - }, - IsTestUser = true - }; + Assert.Fail($"_userController is null"); + } + var guid = Guid.NewGuid().ToString(); + DatabaseSqlServer.User user = ModelsInit.CreateUser(); - userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); - ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid)); + _userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); + ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid)); if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 200); + Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 200); - Assert.IsInstanceOfType(result.Data, typeof(DatabaseSqlServer.User)); + Assert.IsTrue(result.Status == StatusCodes.Status200OK); + Assert.IsInstanceOfType(result.Data, typeof(UserDto)); } else { @@ -111,24 +102,25 @@ public class UserControllerTests [TestMethod] public async Task GetUserByGuidAsync_AuthenticateRequestDataNull() { - IConfiguration configuration = TestUtils.CreateConfiguration(); - var userServiceMock = new Mock(); - var controller = new UserController(configuration, userServiceMock.Object); + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } var guid = String.Empty; DatabaseSqlServer.User? user = null; - userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); - ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid)); + _userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); + ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid)); if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 400); + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 400); + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.IsTrue(result.Message == "Request is not well formed"); } else @@ -145,20 +137,21 @@ public class UserControllerTests [TestMethod] public async Task GetUserByGuidAsync_NotFound() { - IConfiguration configuration = TestUtils.CreateConfiguration(); - var userServiceMock = new Mock(); - var controller = new UserController(configuration, userServiceMock.Object); + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } var guid = Guid.NewGuid().ToString(); DatabaseSqlServer.User? user = null; - userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); - NotFoundResult response = (NotFoundResult)(await controller.GetUserByGuidAsync(guid)); + _userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); + NotFoundResult response = (NotFoundResult)(await _userController.GetUserByGuidAsync(guid)); Assert.IsInstanceOfType(response, typeof(NotFoundResult)); if (response != null) { - Assert.IsTrue(response.StatusCode == 404); + Assert.IsTrue(response.StatusCode == StatusCodes.Status404NotFound); } else { @@ -169,26 +162,27 @@ public class UserControllerTests [TestMethod] public async Task GetUserByGuidAsync_ModelInvalid() { - IConfiguration configuration = TestUtils.CreateConfiguration(); - var userServiceMock = new Mock(); - var controller = new UserController(configuration, userServiceMock.Object); + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } var guid = Guid.NewGuid().ToString(); DatabaseSqlServer.User? user = null; - userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); - controller.ModelState.AddModelError("Data", "Invalid data"); - ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid)); + _userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ReturnsAsync(user); + _userController.ModelState.AddModelError("Data", "Invalid data"); + ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid)); Assert.IsInstanceOfType(response, typeof(ObjectResult)); if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 400); + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 400); + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.IsTrue(result.Message == "Request is not well formed"); } else @@ -205,24 +199,25 @@ public class UserControllerTests [TestMethod] public async Task GetUserByGuidAsync_Exception() { - IConfiguration configuration = TestUtils.CreateConfiguration(); - var userServiceMock = new Mock(); - var controller = new UserController(configuration, userServiceMock.Object); + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } var guid = Guid.NewGuid().ToString(); - userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ThrowsAsync(new Exception("Unexpected error")); - ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid)); + _userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny())).ThrowsAsync(new Exception("Unexpected error")); + ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid)); Assert.IsInstanceOfType(response, typeof(ObjectResult)); if (response != null && response.Value != null) { - Assert.IsTrue(response.StatusCode == 500); + Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); var result = (BaseResponse)response.Value; if (result != null) { - Assert.IsTrue(result.Status == 500); + Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); } else @@ -236,4 +231,367 @@ public class UserControllerTests } } + [TestMethod] + public async Task CreateUserAsync_Should_Return_200_When_Successful() + { + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } + + if (_roleServiceMock == null) + { + Assert.Fail($"_roleServiceMock is null"); + } + + DatabaseSqlServer.User user = ModelsInit.CreateUser(); + DatabaseSqlServer.Role role = ModelsInit.CreateRole(); + + CreateUserRequest request = new CreateUserRequest() + { + Data = new CreateUserRequestData() + { + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password + } + }; + + _userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny(), It.IsAny())).ReturnsAsync(true); + _roleServiceMock.Setup(s => s.GetRoleForUser(null)).ReturnsAsync(role); + _userServiceMock?.Setup(s => s.CreateUserAsync(request.Data, role)).ReturnsAsync(user); + + ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); + if (response != null && response.Value != null) + { + Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); + + var result = (BaseResponse)response.Value; + if (result != null) + { + Assert.IsTrue(result.Status == StatusCodes.Status200OK); + Assert.IsInstanceOfType(result.Data, typeof(UserDto)); + } + else + { + Assert.Fail($"Result value is null"); + } + } + else + { + Assert.Fail($"Response value is null"); + } + } + + [TestMethod] + public async Task CreateUserAsync_InvalidEmail() + { + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } + + DatabaseSqlServer.User user = ModelsInit.CreateUser(); + + CreateUserRequest request = new CreateUserRequest() + { + Data = new CreateUserRequestData() + { + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password + } + }; + + _userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny(), It.IsAny())).ReturnsAsync(false); + + ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); + + if (response != null && response.Value != null) + { + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); + + var result = (BaseResponse)response.Value; + if (result != null) + { + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); + Assert.IsTrue(result.Message == "Invalid email"); + } + else + { + Assert.Fail($"Result value is null"); + } + } + else + { + Assert.Fail($"Response value is null"); + } + } + + [TestMethod] + public async Task CreateUserAsync_RoleNull() + { + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } + + DatabaseSqlServer.User user = ModelsInit.CreateUser(); + + CreateUserRequest request = new CreateUserRequest() + { + Data = new CreateUserRequestData() + { + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password + } + }; + + _userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny(), It.IsAny())).ReturnsAsync(true); + + _userServiceMock?.Setup(s => s.CreateUserAsync( + It.IsAny(), + It.IsAny() + )).ReturnsAsync(user); + + ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); + + if (response != null && response.Value != null) + { + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); + + var result = (BaseResponse)response.Value; + if (result != null) + { + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); + Assert.IsTrue(result.Message == "Role not found"); + } + else + { + Assert.Fail($"Result value is null"); + } + } + else + { + Assert.Fail($"Response value is null"); + } + } + + [TestMethod] + public async Task CreateUserAsync_CreateUserRequestDataNull() + { + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } + + DatabaseSqlServer.User user = ModelsInit.CreateUser(); + + CreateUserRequest request = new CreateUserRequest() + { + Data = null + }; + + _userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny(), It.IsAny())).ReturnsAsync(true); + + _userServiceMock?.Setup(s => s.CreateUserAsync( + It.IsAny(), + It.IsAny() + )).ReturnsAsync(user); + + ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); + + if (response != null && response.Value != null) + { + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); + + var result = (BaseResponse)response.Value; + if (result != null) + { + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); + Assert.IsTrue(result.Message == "Request is not well formed"); + } + else + { + Assert.Fail($"Result value is null"); + } + } + else + { + Assert.Fail($"Response value is null"); + } + } + + [TestMethod] + public async Task CreateUserAsync_NotCreated() + { + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } + + if (_roleServiceMock == null) + { + Assert.Fail($"_roleServiceMock is null"); + } + + DatabaseSqlServer.User user = ModelsInit.CreateUser(); + DatabaseSqlServer.Role role = ModelsInit.CreateRole(); + DatabaseSqlServer.User? expectedUser = null; + + CreateUserRequest request = new CreateUserRequest() + { + Data = new CreateUserRequestData() + { + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password + } + }; + + _userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny(), It.IsAny())).ReturnsAsync(true); + + _roleServiceMock.Setup(s => s.GetRoleForUser(null)).ReturnsAsync(role); + _userServiceMock?.Setup(s => s.CreateUserAsync(request.Data, role)).ReturnsAsync(expectedUser); + + ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); + if (response != null && response.Value != null) + { + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); + + var result = (BaseResponse)response.Value; + if (result != null) + { + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); + Assert.IsTrue(result.Message == "Not created"); + } + else + { + Assert.Fail($"Result value is null"); + } + } + else + { + Assert.Fail($"Response value is null"); + } + } + + [TestMethod] + public async Task CreateUserAsync_ModelInvalid() + { + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } + + DatabaseSqlServer.User user = ModelsInit.CreateUser(); + + CreateUserRequest request = new CreateUserRequest() + { + Data = new CreateUserRequestData() + { + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password + } + }; + + _userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny(), It.IsAny())).ReturnsAsync(true); + + _userServiceMock?.Setup(s => s.CreateUserAsync( + It.IsAny(), + It.IsAny() + )).ReturnsAsync(user); + _userController.ModelState.AddModelError("Data", "Invalid data"); + ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); + + Assert.IsInstanceOfType(response, typeof(ObjectResult)); + + if (response != null && response.Value != null) + { + Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); + + var result = (BaseResponse)response.Value; + if (result != null) + { + Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); + Assert.IsTrue(result.Message == "Request is not well formed"); + } + else + { + Assert.Fail($"Result value is null"); + } + } + else + { + Assert.Fail($"Response is null"); + } + } + + [TestMethod] + public async Task CreateUserAsync_Exception() + { + if (_userController == null) + { + Assert.Fail($"_userController is null"); + } + + if (_roleServiceMock == null) + { + Assert.Fail($"_roleServiceMock is null"); + } + + DatabaseSqlServer.User user = ModelsInit.CreateUser(); + DatabaseSqlServer.Role role = ModelsInit.CreateRole(); + + CreateUserRequest request = new CreateUserRequest() + { + Data = new CreateUserRequestData() + { + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password + } + }; + + _userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny(), It.IsAny())).ReturnsAsync(true); + + _roleServiceMock.Setup(s => s.GetRoleForUser(null)).ReturnsAsync(role); + _userServiceMock?.Setup(s => s.CreateUserAsync(request.Data, role)).ReturnsAsync(user); + + _userServiceMock?.Setup(s => s.CreateUserAsync( + It.IsAny(), + It.IsAny() + )).ThrowsAsync(new Exception("Unexpected error")); + + ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); + Assert.IsInstanceOfType(response, typeof(ObjectResult)); + + if (response != null && response.Value != null) + { + Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); + + var result = (BaseResponse)response.Value; + if (result != null) + { + Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); + Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); + } + else + { + Assert.Fail($"Result value is null"); + } + } + else + { + Assert.Fail($"Response is null"); + } + } } diff --git a/MainProject.Tests/Controllers/VersionController_Tests.cs b/MainProject.Tests/Controllers/VersionController_Tests.cs index f94a96a..7f38ef7 100644 --- a/MainProject.Tests/Controllers/VersionController_Tests.cs +++ b/MainProject.Tests/Controllers/VersionController_Tests.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using BasicDotnetTemplate.MainProject.Models.Api.Response; using BasicDotnetTemplate.MainProject.Models.Settings; +using Microsoft.AspNetCore.Http; namespace BasicDotnetTemplate.MainProject.Tests; @@ -53,7 +54,7 @@ public class VersionController_Tests AppSettings appSettings = new AppSettings(); configuration.GetSection("AppSettings").Bind(appSettings); string version = data.Data != null ? (string)data.Data : ""; - Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == 200) && (version == appSettings.Settings?.Version)); + Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == StatusCodes.Status200OK) && (version == appSettings.Settings?.Version)); } else { @@ -68,7 +69,7 @@ public class VersionController_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -87,7 +88,7 @@ public class VersionController_Tests if (objectResult != null) { var data = (BaseResponse)objectResult; - Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == 200) && String.IsNullOrEmpty(data.Data)); + Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == StatusCodes.Status200OK) && String.IsNullOrEmpty(data.Data)); } else { @@ -97,7 +98,7 @@ public class VersionController_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } } diff --git a/MainProject.Tests/Core/Attributes/JwtAuthorizationAttribute_Tests.cs b/MainProject.Tests/Core/Attributes/JwtAuthorizationAttribute_Tests.cs index 10317e7..1523008 100644 --- a/MainProject.Tests/Core/Attributes/JwtAuthorizationAttribute_Tests.cs +++ b/MainProject.Tests/Core/Attributes/JwtAuthorizationAttribute_Tests.cs @@ -30,22 +30,7 @@ public class JwtAuthorizationAttribute_Tests { _attribute = new JwtAuthorizationAttribute(); - DatabaseSqlServer.User user = new DatabaseSqlServer.User() - { - Guid = Guid.NewGuid().ToString(), - Username = "Username", - FirstName = "FirstName", - LastName = "LastName", - Email = "Email", - PasswordHash = "PasswordHash", - PasswordSalt = "PasswordSalt", - Password = "Password", - Role = new DatabaseSqlServer.Role() - { - Name = "Role.Name" - }, - IsTestUser = true - }; + DatabaseSqlServer.User user = ModelsInit.CreateUser(); _authenticatedUser = new AuthenticatedUser(user); WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); @@ -69,13 +54,6 @@ public class JwtAuthorizationAttribute_Tests return new AuthorizationFilterContext(actionContext, []); } - private static AuthorizationFilterContext CreateAuthorizationContext() - { - var httpContext = new DefaultHttpContext(); - var actionContext = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor()); - return new AuthorizationFilterContext(actionContext, new List()); - } - [TestMethod] public void OnAuthorization_AllowAnonymous_SkipsAuthorization() { @@ -89,14 +67,14 @@ public class JwtAuthorizationAttribute_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } [TestMethod] public void OnAuthorization_NoAuthenticatedUser_ReturnsUnauthorized() { - var context = CreateAuthorizationContext(); + var context = TestUtils.CreateAuthorizationContext(); IConfiguration configuration = TestUtils.CreateConfiguration(); context.HttpContext.RequestServices = new ServiceCollection() @@ -111,7 +89,7 @@ public class JwtAuthorizationAttribute_Tests [TestMethod] public void OnAuthorization_EmptyAuthorizationHeader_ReturnsUnauthorized() { - var context = CreateAuthorizationContext(); + var context = TestUtils.CreateAuthorizationContext(); IConfiguration configuration = TestUtils.CreateConfiguration(); context.HttpContext.RequestServices = new ServiceCollection() @@ -130,7 +108,7 @@ public class JwtAuthorizationAttribute_Tests [TestMethod] public void OnAuthorization_InvalidToken_ReturnsUnauthorized() { - var context = CreateAuthorizationContext(); + var context = TestUtils.CreateAuthorizationContext(); IConfiguration configuration = TestUtils.CreateConfiguration(); context.HttpContext.RequestServices = new ServiceCollection() @@ -150,7 +128,7 @@ public class JwtAuthorizationAttribute_Tests [TestMethod] public void OnAuthorization_ValidToken() { - var context = CreateAuthorizationContext(); + var context = TestUtils.CreateAuthorizationContext(); IConfiguration configuration = TestUtils.CreateConfiguration(); context.HttpContext.RequestServices = new ServiceCollection() diff --git a/MainProject.Tests/Core/Middlewares/AutoMapperConfiguration_Tests.cs b/MainProject.Tests/Core/Middlewares/AutoMapperConfiguration_Tests.cs index d52a962..fd3655b 100644 --- a/MainProject.Tests/Core/Middlewares/AutoMapperConfiguration_Tests.cs +++ b/MainProject.Tests/Core/Middlewares/AutoMapperConfiguration_Tests.cs @@ -37,26 +37,10 @@ public class AutoMapperConfiguration_Tests { try { - DatabaseSqlServer.User user = new DatabaseSqlServer.User() - { - Guid = Guid.NewGuid().ToString(), - Username = "Username", - FirstName = "FirstName", - LastName = "LastName", - Email = "Email", - PasswordHash = "PasswordHash", - PasswordSalt = "PasswordSalt", - Password = "Password", - Role = new DatabaseSqlServer.Role() - { - Name = "Role.Name" - }, - IsTestUser = true - }; + DatabaseSqlServer.User user = ModelsInit.CreateUser(); UserDto? data = _mapper?.Map(user); Assert.IsTrue(data?.Guid == user.Guid); - Assert.IsTrue(data?.Username == user.Username); Assert.IsTrue(data?.FirstName == user.FirstName); Assert.IsTrue(data?.LastName == user.LastName); Assert.IsTrue(data?.Email == user.Email); @@ -64,7 +48,7 @@ public class AutoMapperConfiguration_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject.Tests/MainProject.Tests.csproj b/MainProject.Tests/MainProject.Tests.csproj index c926d4b..a899faa 100644 --- a/MainProject.Tests/MainProject.Tests.csproj +++ b/MainProject.Tests/MainProject.Tests.csproj @@ -11,6 +11,7 @@ + diff --git a/MainProject.Tests/Models/Api/Common/Role/UserRole_Tests.cs b/MainProject.Tests/Models/Api/Common/Role/UserRole_Tests.cs index 817bc33..aaa4fb6 100644 --- a/MainProject.Tests/Models/Api/Common/Role/UserRole_Tests.cs +++ b/MainProject.Tests/Models/Api/Common/Role/UserRole_Tests.cs @@ -22,18 +22,15 @@ public class UserRole_Tests { try { - DatabaseSqlServer.Role role = new DatabaseSqlServer.Role() - { - Name = "test" - }; + DatabaseSqlServer.Role role = ModelsInit.CreateRole(); UserRole userRole = new UserRole(role); - + Assert.IsTrue(userRole.Name == role.Name); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } } \ No newline at end of file diff --git a/MainProject.Tests/Models/Api/Common/User/AuthenticatedUser_Tests.cs b/MainProject.Tests/Models/Api/Common/User/AuthenticatedUser_Tests.cs index b94ab6d..3d22813 100644 --- a/MainProject.Tests/Models/Api/Common/User/AuthenticatedUser_Tests.cs +++ b/MainProject.Tests/Models/Api/Common/User/AuthenticatedUser_Tests.cs @@ -22,24 +22,9 @@ public class AuthenticatedUser_Tests { try { - DatabaseSqlServer.User user = new DatabaseSqlServer.User() - { - Username = "test", - FirstName = "test", - LastName = "test", - Email = "test", - PasswordHash = "test", - PasswordSalt = "test", - Password = "test", - Role = new DatabaseSqlServer.Role() - { - Name = "test" - }, - IsTestUser = true - }; + DatabaseSqlServer.User user = ModelsInit.CreateUser(); AuthenticatedUser authenticatedUser = new AuthenticatedUser(user); - - Assert.IsTrue(authenticatedUser.Username == user.Username); + Assert.IsTrue(authenticatedUser.FirstName == user.FirstName); Assert.IsTrue(authenticatedUser.LastName == user.LastName); Assert.IsTrue(authenticatedUser.Email == user.Email); @@ -48,7 +33,7 @@ public class AuthenticatedUser_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } } \ No newline at end of file diff --git a/MainProject.Tests/Models/Api/Response/ApiResponse_Tests.cs b/MainProject.Tests/Models/Api/Response/ApiResponse_Tests.cs index 5b1bfca..31dcdf8 100644 --- a/MainProject.Tests/Models/Api/Response/ApiResponse_Tests.cs +++ b/MainProject.Tests/Models/Api/Response/ApiResponse_Tests.cs @@ -6,6 +6,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using BasicDotnetTemplate.MainProject; using BasicDotnetTemplate.MainProject.Models.Api.Response; using Microsoft.Extensions.DependencyModel.Resolution; +using Microsoft.AspNetCore.Http; namespace BasicDotnetTemplate.MainProject.Tests; @@ -19,12 +20,12 @@ public class ApiResponse_Tests try { var baseResponse = new BaseResponse(200, null, null); - Assert.IsTrue(baseResponse.Status == 200 && String.IsNullOrEmpty(baseResponse.Message) && baseResponse.Data == null); + Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && String.IsNullOrEmpty(baseResponse.Message) && baseResponse.Data == null); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -34,12 +35,12 @@ public class ApiResponse_Tests try { var baseResponse = new BaseResponse(201, null, null); - Assert.IsFalse(baseResponse.Status == 200); + Assert.IsFalse(baseResponse.Status == StatusCodes.Status200OK); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -49,12 +50,12 @@ public class ApiResponse_Tests try { var baseResponse = new BaseResponse(200, "This is a test message", null); - Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null); + Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == null); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -65,12 +66,12 @@ public class ApiResponse_Tests { string[] data = { "Volvo", "BMW", "Ford", "Mazda" }; var baseResponse = new BaseResponse(200, "This is a test message", data); - Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data); + Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == data); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } } diff --git a/MainProject.Tests/Models/Api/Response/Auth/AuthenticateResponse_Tests.cs b/MainProject.Tests/Models/Api/Response/Auth/AuthenticateResponse_Tests.cs index a80e288..4757b08 100644 --- a/MainProject.Tests/Models/Api/Response/Auth/AuthenticateResponse_Tests.cs +++ b/MainProject.Tests/Models/Api/Response/Auth/AuthenticateResponse_Tests.cs @@ -10,6 +10,7 @@ using BasicDotnetTemplate.MainProject.Models.Api.Common.User; using BasicDotnetTemplate.MainProject.Models.Api.Common.Role; using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer; using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth; +using Microsoft.AspNetCore.Http; namespace BasicDotnetTemplate.MainProject.Tests; @@ -23,12 +24,12 @@ public class AuthenticateResponse_Tests try { var authenticateResponse = new AuthenticateResponse(200, null, null); - Assert.IsTrue(authenticateResponse.Status == 200 && String.IsNullOrEmpty(authenticateResponse.Message) && authenticateResponse.Data == null); + Assert.IsTrue(authenticateResponse.Status == StatusCodes.Status200OK && String.IsNullOrEmpty(authenticateResponse.Message) && authenticateResponse.Data == null); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -38,12 +39,12 @@ public class AuthenticateResponse_Tests try { var authenticateResponse = new AuthenticateResponse(201, null, null); - Assert.IsFalse(authenticateResponse.Status == 200); + Assert.IsFalse(authenticateResponse.Status == StatusCodes.Status200OK); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -53,12 +54,12 @@ public class AuthenticateResponse_Tests try { var authenticateResponse = new AuthenticateResponse(200, "This is a test message", null); - Assert.IsTrue(authenticateResponse.Status == 200 && authenticateResponse.Message == "This is a test message" && authenticateResponse.Data == null); + Assert.IsTrue(authenticateResponse.Status == StatusCodes.Status200OK && authenticateResponse.Message == "This is a test message" && authenticateResponse.Data == null); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -67,29 +68,15 @@ public class AuthenticateResponse_Tests { try { - DatabaseSqlServer.User user = new DatabaseSqlServer.User() - { - Username = "test", - FirstName = "test", - LastName = "test", - Email = "test", - PasswordHash = "test", - PasswordSalt = "test", - Password = "test", - Role = new DatabaseSqlServer.Role() - { - Name = "test" - }, - IsTestUser = true - }; + DatabaseSqlServer.User user = ModelsInit.CreateUser(); AuthenticatedUser data = new AuthenticatedUser(user); var authenticateResponse = new AuthenticateResponse(200, "This is a test message", data); - Assert.IsTrue(authenticateResponse.Status == 200 && authenticateResponse.Message == "This is a test message" && authenticateResponse.Data == data); + Assert.IsTrue(authenticateResponse.Status == StatusCodes.Status200OK && authenticateResponse.Message == "This is a test message" && authenticateResponse.Data == data); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } } diff --git a/MainProject.Tests/Models/Api/Response/User/GetUserResponse_Tests.cs b/MainProject.Tests/Models/Api/Response/User/GetUserResponse_Tests.cs index c1cb1c1..07a4628 100644 --- a/MainProject.Tests/Models/Api/Response/User/GetUserResponse_Tests.cs +++ b/MainProject.Tests/Models/Api/Response/User/GetUserResponse_Tests.cs @@ -12,6 +12,7 @@ using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlSer using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth; using BasicDotnetTemplate.MainProject.Core.Middlewares; using AutoMapper; +using Microsoft.AspNetCore.Http; namespace BasicDotnetTemplate.MainProject.Tests; @@ -38,12 +39,12 @@ public class GetUserResponse_Tests try { var getUserResponse = new GetUserResponse(200, null, null); - Assert.IsTrue(getUserResponse.Status == 200 && String.IsNullOrEmpty(getUserResponse.Message) && getUserResponse.Data == null); + Assert.IsTrue(getUserResponse.Status == StatusCodes.Status200OK && String.IsNullOrEmpty(getUserResponse.Message) && getUserResponse.Data == null); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -53,12 +54,12 @@ public class GetUserResponse_Tests try { var getUserResponse = new GetUserResponse(201, null, null); - Assert.IsFalse(getUserResponse.Status == 200); + Assert.IsFalse(getUserResponse.Status == StatusCodes.Status200OK); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -68,12 +69,12 @@ public class GetUserResponse_Tests try { var getUserResponse = new GetUserResponse(200, "This is a test message", null); - Assert.IsTrue(getUserResponse.Status == 200 && getUserResponse.Message == "This is a test message" && getUserResponse.Data == null); + Assert.IsTrue(getUserResponse.Status == StatusCodes.Status200OK && getUserResponse.Message == "This is a test message" && getUserResponse.Data == null); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -82,29 +83,15 @@ public class GetUserResponse_Tests { try { - DatabaseSqlServer.User user = new DatabaseSqlServer.User() - { - Username = "test", - FirstName = "test", - LastName = "test", - Email = "test", - PasswordHash = "test", - PasswordSalt = "test", - Password = "test", - Role = new DatabaseSqlServer.Role() - { - Name = "test" - }, - IsTestUser = true - }; + DatabaseSqlServer.User user = ModelsInit.CreateUser(); UserDto? data = _mapper?.Map(user); var getUserResponse = new GetUserResponse(200, "This is a test message", data); - Assert.IsTrue(getUserResponse.Status == 200 && getUserResponse.Message == "This is a test message" && getUserResponse.Data == data); + Assert.IsTrue(getUserResponse.Status == StatusCodes.Status200OK && getUserResponse.Message == "This is a test message" && getUserResponse.Data == data); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject.Tests/Models/Settings/Settings_Tests.cs b/MainProject.Tests/Models/Settings/Settings_Tests.cs index 150c7a4..100a587 100644 --- a/MainProject.Tests/Models/Settings/Settings_Tests.cs +++ b/MainProject.Tests/Models/Settings/Settings_Tests.cs @@ -7,6 +7,7 @@ using BasicDotnetTemplate.MainProject; using BasicDotnetTemplate.MainProject.Models.Api.Response; using Microsoft.Extensions.DependencyModel.Resolution; using BasicDotnetTemplate.MainProject.Models.Settings; +using Microsoft.AspNetCore.Http; namespace BasicDotnetTemplate.MainProject.Tests; @@ -43,7 +44,7 @@ public class Settings_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -53,12 +54,12 @@ public class Settings_Tests try { var baseResponse = new BaseResponse(201, null, null); - Assert.IsFalse(baseResponse.Status == 200); + Assert.IsFalse(baseResponse.Status == StatusCodes.Status200OK); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -68,12 +69,12 @@ public class Settings_Tests try { var baseResponse = new BaseResponse(200, "This is a test message", null); - Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null); + Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == null); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -84,12 +85,12 @@ public class Settings_Tests { string[] data = { "Volvo", "BMW", "Ford", "Mazda" }; var baseResponse = new BaseResponse(200, "This is a test message", data); - Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data); + Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == data); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } } diff --git a/MainProject.Tests/Program_Tests.cs b/MainProject.Tests/Program_Tests.cs index dd0d694..93588db 100644 --- a/MainProject.Tests/Program_Tests.cs +++ b/MainProject.Tests/Program_Tests.cs @@ -70,7 +70,7 @@ public class Program_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject.Tests/Services/AuthService_Tests.cs b/MainProject.Tests/Services/AuthService_Tests.cs index c667b44..e55efd5 100644 --- a/MainProject.Tests/Services/AuthService_Tests.cs +++ b/MainProject.Tests/Services/AuthService_Tests.cs @@ -29,19 +29,19 @@ public class AuthService_Tests try { var authService = TestUtils.CreateAuthService(); - if(authService != null) + if (authService != null) { Assert.IsInstanceOfType(authService, typeof(AuthService)); } else { Assert.Fail($"AuthService is null"); - } + } } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -50,16 +50,16 @@ public class AuthService_Tests { try { - var request = new AuthenticateRequest - { - Data = new AuthenticateRequestData - { - Username = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=", - Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=" - } + var request = new AuthenticateRequest + { + Data = new AuthenticateRequestData + { + Email = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=", + Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=" + } }; var authService = TestUtils.CreateAuthService(); - if(authService != null) + if (authService != null) { var authenticatedUser = await authService.AuthenticateAsync(request.Data); Assert.IsTrue(authenticatedUser == null); @@ -72,36 +72,25 @@ public class AuthService_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } -// if(authenticatedUser == null) -// { -// Console.WriteLine(JsonConvert.SerializeObject(authenticatedUser)); -// Assert.IsTrue(authenticatedUser.Username == expectedAuthenticatedUser.Username); -// } -// else -// { -// Console.WriteLine(JsonConvert.SerializeObject(authenticatedUser)); -// Assert.Fail($"authenticatedUser is null"); -// } - [TestMethod] public async Task AuthenticateAsync_UsernamePasswordInvalid() { try { - var request = new AuthenticateRequest - { - Data = new AuthenticateRequestData - { - Username = "WGHWRBE5mVWaV=", - Password = "WGHWRBE5mVWaV=" - } + var request = new AuthenticateRequest + { + Data = new AuthenticateRequestData + { + Email = "WGHWRBE5mVWaV=", + Password = "WGHWRBE5mVWaV=" + } }; var authService = TestUtils.CreateAuthService(); - if(authService != null) + if (authService != null) { var authenticatedUser = await authService.AuthenticateAsync(request.Data); Assert.IsTrue(authenticatedUser == null); @@ -114,7 +103,7 @@ public class AuthService_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject.Tests/Services/JwtService_Tests.cs b/MainProject.Tests/Services/JwtService_Tests.cs index a4150f6..18d4bfc 100644 --- a/MainProject.Tests/Services/JwtService_Tests.cs +++ b/MainProject.Tests/Services/JwtService_Tests.cs @@ -39,7 +39,7 @@ public class JwtService_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -64,7 +64,7 @@ public class JwtService_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject.Tests/Services/RoleService_Tests.cs b/MainProject.Tests/Services/RoleService_Tests.cs new file mode 100644 index 0000000..dfd172e --- /dev/null +++ b/MainProject.Tests/Services/RoleService_Tests.cs @@ -0,0 +1,293 @@ + +using BasicDotnetTemplate.MainProject.Services; +using BasicDotnetTemplate.MainProject.Models.Api.Data.Role; +using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; + + + +namespace BasicDotnetTemplate.MainProject.Tests; + +[TestClass] +public class RoleService_Tests +{ + private static Role? _expectedRole = ModelsInit.CreateRole(); + private static Role? _role; + private static RoleService _roleService = TestUtils.CreateRoleService(); + + + [TestMethod] + public void Inizialize() + { + try + { + var roleService = TestUtils.CreateRoleService(); + if (roleService != null) + { + Assert.IsInstanceOfType(roleService, typeof(RoleService)); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task CheckIfNameIsValid_NameNotExists() + { + try + { + var expectedRole = ModelsInit.CreateRole(); + + if (_roleService != null) + { + var valid = await _roleService.CheckIfNameIsValid(expectedRole.Name); + Assert.IsTrue(valid); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task CreateRoleData() + { + try + { + CreateRoleRequestData data = new CreateRoleRequestData() + { + Name = _expectedRole?.Name ?? String.Empty, + IsNotEditable = false + }; + + if (_roleService != null) + { + var role = await _roleService.CreateRoleAsync(data); + Assert.IsInstanceOfType(role, typeof(Role)); + Assert.IsNotNull(role); + Assert.IsTrue(_expectedRole?.Name == role.Name); + Assert.IsTrue(_expectedRole?.IsNotEditable == role.IsNotEditable); + _role = role; + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task CheckIfNameIsValid_NameCurrentRole() + { + try + { + var expectedRole = ModelsInit.CreateRole(); + if (_roleService != null) + { + var valid = await _roleService.CheckIfNameIsValid(expectedRole.Name, _role?.Guid ?? String.Empty); + Assert.IsTrue(valid); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task CheckIfNameIsValid_NameAlreadyExists() + { + try + { + var expectedRole = ModelsInit.CreateRole(); + + if (_roleService != null) + { + var valid = await _roleService.CheckIfNameIsValid(expectedRole.Name); + Assert.IsFalse(valid); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task GetRoleByIdAsync() + { + try + { + if (_roleService != null) + { + var role = await _roleService.GetRoleByIdAsync(_role?.Id ?? 0); + Assert.IsNotNull(role); + Assert.IsTrue(role.Id == _role?.Id); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task GetRoleByGuidAsync() + { + try + { + if (_roleService != null) + { + var role = await _roleService.GetRoleByGuidAsync(_role?.Guid ?? String.Empty); + Assert.IsNotNull(role); + Assert.IsTrue(role.Guid == _role?.Guid); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task GetRoleByGuidAsync_CurrentRole() + { + try + { + if (_roleService != null) + { + var role = await _roleService.GetRoleForUser(_role?.Guid); + Assert.IsNotNull(role); + Assert.IsTrue(role.Guid == _role?.Guid); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task GetRoleByGuidAsync_Default() + { + try + { + if (_roleService != null) + { + CreateRoleRequestData data = new() + { + Name = "Default", + IsNotEditable = true + }; + var roleCreated = await _roleService.CreateRoleAsync(data); + var role = await _roleService.GetRoleForUser(String.Empty); + Assert.IsNotNull(role); + Assert.IsTrue(roleCreated?.Guid == role?.Guid); + Assert.IsTrue(role?.Name == "Default"); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task GetRoleByGuidAsync_Null() + { + try + { + if (_roleService != null) + { + var role = await _roleService.GetRoleForUser(Guid.NewGuid().ToString()); + Assert.IsNull(role); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task DeleteRoleAsync() + { + try + { + if (_roleService != null) + { + var role = await _roleService.GetRoleByGuidAsync(_role?.Guid ?? String.Empty); + Assert.IsNotNull(role); + var deleted = await _roleService.DeleteRoleAsync(role); + Assert.IsTrue(deleted); + } + else + { + Assert.Fail($"RoleService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + +} + + + + diff --git a/MainProject.Tests/Services/UserService_Tests.cs b/MainProject.Tests/Services/UserService_Tests.cs index 1993592..3af26f7 100644 --- a/MainProject.Tests/Services/UserService_Tests.cs +++ b/MainProject.Tests/Services/UserService_Tests.cs @@ -1,20 +1,7 @@ -using BasicDotnetTemplate.MainProject.Models.Settings; -using Microsoft.AspNetCore.Builder; -using Microsoft.EntityFrameworkCore; -using BasicDotnetTemplate.MainProject.Utils; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Configuration; -using Moq; -using Newtonsoft.Json; -using BasicDotnetTemplate.MainProject.Core.Database; using BasicDotnetTemplate.MainProject.Services; -using BasicDotnetTemplate.MainProject.Models.Api.Response; -using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth; -using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth; -using BasicDotnetTemplate.MainProject.Models.Api.Common.User; -using BasicDotnetTemplate.MainProject.Models.Api.Common.Role; -using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth; -using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer; +using BasicDotnetTemplate.MainProject.Models.Api.Data.User; +using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; +using Newtonsoft.Json; @@ -23,20 +10,23 @@ namespace BasicDotnetTemplate.MainProject.Tests; [TestClass] public class UserService_Tests { + private static User _user = ModelsInit.CreateUser(); + private static UserService _userService = TestUtils.CreateUserService(); + [TestMethod] public void Inizialize() { try { var userService = TestUtils.CreateUserService(); - if(userService != null) + if (userService != null) { Assert.IsInstanceOfType(userService, typeof(UserService)); } else { Assert.Fail($"UserService is null"); - } + } } catch (Exception ex) { @@ -50,11 +40,10 @@ public class UserService_Tests { try { - var userService = TestUtils.CreateUserService(); var testString = "test"; - if(userService != null) + if (_userService != null) { - var user = await userService.GetUserByUsernameAndPassword(testString, testString); + var user = await _userService.GetUserByUsernameAndPassword(testString, testString); Assert.IsTrue(user == null); } else @@ -65,24 +54,19 @@ public class UserService_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } - // TODO - // [TestMethod] - public async Task GetUserByUsernameAndPassword_Success() + [TestMethod] + public async Task CheckIfEmailIsValid_EmailNotExists() { try { - var userService = TestUtils.CreateUserService(); - var testUsername = "test@email.it"; - var testPassword = "password"; - if(userService != null) + if (_userService != null) { - var user = await userService.GetUserByUsernameAndPassword(testUsername, testPassword); - Assert.IsTrue(user != null); - Assert.IsTrue(user.Username == testUsername); + var valid = await _userService.CheckIfEmailIsValid(_user.Email ?? String.Empty); + Assert.IsTrue(valid); } else { @@ -92,7 +76,165 @@ public class UserService_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task CreateUserAsync_Success() + { + try + { + + var expectedUser = ModelsInit.CreateUser(); + + CreateUserRequestData data = new CreateUserRequestData() + { + FirstName = expectedUser.FirstName ?? String.Empty, + LastName = expectedUser.LastName ?? String.Empty, + Email = expectedUser.Email ?? String.Empty + }; + + Role role = new() + { + Name = expectedUser.Role?.Name ?? String.Empty, + IsNotEditable = expectedUser.Role?.IsNotEditable ?? false, + Guid = expectedUser.Role?.Guid ?? String.Empty + }; + + var user = await _userService.CreateUserAsync(data, role); + Assert.IsInstanceOfType(user, typeof(User)); + Assert.IsNotNull(user); + Assert.IsTrue(expectedUser.FirstName == user.FirstName); + Assert.IsTrue(expectedUser.LastName == user.LastName); + Assert.IsTrue(expectedUser.Email == user.Email); + Assert.IsTrue(expectedUser.Role?.Name == user.Role?.Name); + _user = user; + + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task CheckIfEmailIsValid_EmailCurrentUser() + { + try + { + + if (_userService != null) + { + var valid = await _userService.CheckIfEmailIsValid(_user.Email ?? String.Empty, _user.Guid ?? String.Empty); + Assert.IsTrue(valid); + } + else + { + Assert.Fail($"UserService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task CheckIfEmailIsValid_EmailAlreadyExists() + { + try + { + + if (_userService != null) + { + var valid = await _userService.CheckIfEmailIsValid(_user.Email ?? String.Empty); + Assert.IsFalse(valid); + } + else + { + Assert.Fail($"UserService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task GetUserByIdAsync() + { + try + { + + if (_userService != null) + { + var user = await _userService.GetUserByIdAsync(_user.Id); + Assert.IsNotNull(user); + Assert.IsTrue(user.Id == _user?.Id); + } + else + { + Assert.Fail($"UserService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task GetUserByGuidAsync() + { + try + { + + if (_userService != null) + { + var user = await _userService.GetUserByGuidAsync(_user.Guid ?? String.Empty); + Assert.IsNotNull(user); + Assert.IsTrue(user.Guid == _user?.Guid); + } + else + { + Assert.Fail($"UserService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); + } + } + + [TestMethod] + public async Task DeleteUser() + { + try + { + + if (_userService != null) + { + var user = await _userService.GetUserByGuidAsync(_user.Guid ?? String.Empty); + Assert.IsNotNull(user); + var deleted = await _userService.DeleteUserAsync(user); + Assert.IsTrue(deleted); + } + else + { + Assert.Fail($"UserService is null"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -101,4 +243,3 @@ public class UserService_Tests - diff --git a/MainProject.Tests/TestsUtils/ModelsInit.cs b/MainProject.Tests/TestsUtils/ModelsInit.cs new file mode 100644 index 0000000..29541ff --- /dev/null +++ b/MainProject.Tests/TestsUtils/ModelsInit.cs @@ -0,0 +1,35 @@ +using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer; + + +namespace BasicDotnetTemplate.MainProject.Tests; + +public static class ModelsInit +{ + public static DatabaseSqlServer.User CreateUser() + { + DatabaseSqlServer.User user = new DatabaseSqlServer.User() + { + Guid = Guid.NewGuid().ToString(), + FirstName = "FirstName", + LastName = "LastName", + Email = "test-new@email.it", + PasswordHash = "PasswordHash", + PasswordSalt = "PasswordSalt", + Password = "Password", + Role = CreateRole(), + IsTestUser = true + }; + return user; + } + + public static DatabaseSqlServer.Role CreateRole() + { + DatabaseSqlServer.Role role = new DatabaseSqlServer.Role() + { + Guid = Guid.NewGuid().ToString(), + Name = "Name", + IsNotEditable = false + }; + return role; + } +} \ No newline at end of file diff --git a/MainProject.Tests/TestsUtils/TestUtils.cs b/MainProject.Tests/TestsUtils/TestUtils.cs index 129a8af..099777c 100644 --- a/MainProject.Tests/TestsUtils/TestUtils.cs +++ b/MainProject.Tests/TestsUtils/TestUtils.cs @@ -17,12 +17,26 @@ using Microsoft.EntityFrameworkCore; using Moq; using BasicDotnetTemplate.MainProject.Core.Database; using BasicDotnetTemplate.MainProject.Services; +using Microsoft.AspNetCore.Http; +using Newtonsoft.Json; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Mvc.Controllers; namespace BasicDotnetTemplate.MainProject.Tests; public static class TestUtils { + + public static AuthorizationFilterContext CreateAuthorizationContext() + { + var httpContext = new DefaultHttpContext(); + var actionContext = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor()); + return new AuthorizationFilterContext(actionContext, new List()); + } + public static IConfiguration CreateConfiguration() { WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); @@ -43,33 +57,72 @@ public static class TestUtils .Build(); } + public static string GetSqlConnectionString(IConfiguration configuration) + { + AppSettings _appSettings = new AppSettings(); + configuration.GetSection("AppSettings").Bind(_appSettings); + return _appSettings.DatabaseSettings?.SqlServerConnectionString ?? String.Empty; + } + + public static SqlServerContext CreateInMemorySqlContext() + { + var options = new DbContextOptionsBuilder() + .UseSqlite("DataSource=:memory:") // Database in-memory + .Options; + + var context = new SqlServerContext(options); + context.Database.OpenConnection(); + context.Database.EnsureCreated(); + return context; + } + + public static BaseService CreateBaseService() + { + IConfiguration configuration = CreateConfiguration(); + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlServer(GetSqlConnectionString(configuration)); + SqlServerContext sqlServerContext = CreateInMemorySqlContext(); + var httpContextAccessor = new Mock(); + return new BaseService(httpContextAccessor.Object, configuration, sqlServerContext); + } + public static AuthService CreateAuthService() { IConfiguration configuration = CreateConfiguration(); var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlServer("test"); - SqlServerContext sqlServerContext = new SqlServerContext(optionsBuilder.Options); + optionsBuilder.UseSqlServer(GetSqlConnectionString(configuration)); + SqlServerContext sqlServerContext = CreateInMemorySqlContext(); var userServiceMock = new Mock(); - return new AuthService(configuration, sqlServerContext, userServiceMock.Object); + var httpContextAccessor = new Mock(); + return new AuthService(httpContextAccessor.Object, configuration, sqlServerContext, userServiceMock.Object); } public static UserService CreateUserService() { IConfiguration configuration = CreateConfiguration(); - var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlServer("test"); - SqlServerContext sqlServerContext = new SqlServerContext(optionsBuilder.Options); - return new UserService(configuration, sqlServerContext); + SqlServerContext sqlServerContext = CreateInMemorySqlContext(); + var httpContextAccessor = new Mock(); + return new UserService(httpContextAccessor.Object, configuration, sqlServerContext); } public static JwtService CreateJwtService() { IConfiguration configuration = CreateConfiguration(); var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlServer("test"); - SqlServerContext sqlServerContext = new SqlServerContext(optionsBuilder.Options); - var userServiceMock = new Mock(); - return new JwtService(configuration, sqlServerContext, userServiceMock.Object); + optionsBuilder.UseSqlServer(GetSqlConnectionString(configuration)); + SqlServerContext sqlServerContext = CreateInMemorySqlContext(); + var httpContextAccessor = new Mock(); + return new JwtService(httpContextAccessor.Object, configuration, sqlServerContext); + } + + public static RoleService CreateRoleService() + { + IConfiguration configuration = CreateConfiguration(); + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlServer(GetSqlConnectionString(configuration)); + SqlServerContext sqlServerContext = CreateInMemorySqlContext(); + var httpContextAccessor = new Mock(); + return new RoleService(httpContextAccessor.Object, configuration, sqlServerContext); } } diff --git a/MainProject.Tests/Utils/CryptoUtils_Tests.cs b/MainProject.Tests/Utils/CryptoUtils_Tests.cs index a0f7a6c..4d2a7ab 100644 --- a/MainProject.Tests/Utils/CryptoUtils_Tests.cs +++ b/MainProject.Tests/Utils/CryptoUtils_Tests.cs @@ -27,7 +27,7 @@ public class CryptoUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -47,7 +47,7 @@ public class CryptoUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -77,7 +77,7 @@ public class CryptoUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -97,7 +97,7 @@ public class CryptoUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -112,7 +112,7 @@ public class CryptoUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -129,12 +129,12 @@ public class CryptoUtils_Tests AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData"); CryptUtils cryptoUtils = new CryptUtils(appSettings); var encryptedPassword = cryptoUtils.GeneratePassword(password, salt, 0); - Assert.IsTrue(password != encryptedPassword); + Assert.IsTrue(password != encryptedPassword); } catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -158,7 +158,7 @@ public class CryptoUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject.Tests/Utils/JwtTokenUtils_Tests.cs b/MainProject.Tests/Utils/JwtTokenUtils_Tests.cs index d1a2546..b6c4ba5 100644 --- a/MainProject.Tests/Utils/JwtTokenUtils_Tests.cs +++ b/MainProject.Tests/Utils/JwtTokenUtils_Tests.cs @@ -27,7 +27,7 @@ public class JwtTokenUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -46,7 +46,7 @@ public class JwtTokenUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -55,7 +55,7 @@ public class JwtTokenUtils_Tests { try { - WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); + WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData"); JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings); var jwt = jwtUtils.GenerateToken(_guid); @@ -65,7 +65,7 @@ public class JwtTokenUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject.Tests/Utils/ProgramUtils_Tests.cs b/MainProject.Tests/Utils/ProgramUtils_Tests.cs index 5fed702..261236e 100644 --- a/MainProject.Tests/Utils/ProgramUtils_Tests.cs +++ b/MainProject.Tests/Utils/ProgramUtils_Tests.cs @@ -44,7 +44,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -80,7 +80,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -97,7 +97,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -126,7 +126,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -160,7 +160,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -196,7 +196,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -220,7 +220,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -240,7 +240,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -260,7 +260,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -280,7 +280,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } @@ -305,7 +305,7 @@ public class ProgramUtils_Tests catch (Exception ex) { Console.WriteLine(ex.InnerException); - Assert.Fail($"An exception was thrown: {ex.Message}"); + Assert.Fail($"An exception was thrown: {ex}"); } } diff --git a/MainProject/Controllers/AuthController.cs b/MainProject/Controllers/AuthController.cs index eabc071..1baf173 100644 --- a/MainProject/Controllers/AuthController.cs +++ b/MainProject/Controllers/AuthController.cs @@ -32,17 +32,17 @@ namespace BasicDotnetTemplate.MainProject.Controllers { if (!ModelState.IsValid) { - return BadRequest("Request is not well formed"); + return BadRequest(_requestNotWellFormed); } if ( request == null || request.Data == null || - String.IsNullOrEmpty(request.Data.Username) || + String.IsNullOrEmpty(request.Data.Email) || String.IsNullOrEmpty(request.Data.Password) ) { - return BadRequest("Request is not well formed"); + return BadRequest(_requestNotWellFormed); } var data = await this._authService.AuthenticateAsync(request.Data); diff --git a/MainProject/Controllers/BaseController.cs b/MainProject/Controllers/BaseController.cs index efe7d20..b8c8eb4 100644 --- a/MainProject/Controllers/BaseController.cs +++ b/MainProject/Controllers/BaseController.cs @@ -2,13 +2,17 @@ using System.Net; using Microsoft.AspNetCore.Mvc; using BasicDotnetTemplate.MainProject.Models.Api.Response; using BasicDotnetTemplate.MainProject.Models.Settings; +using AutoMapper; +using BasicDotnetTemplate.MainProject.Core.Middlewares; namespace BasicDotnetTemplate.MainProject.Controllers { public abstract class BaseController : ControllerBase { + protected readonly IMapper? _mapper; protected readonly IConfiguration _configuration; protected readonly AppSettings _appSettings; + protected readonly string _requestNotWellFormed = "Request is not well formed"; protected BaseController( IConfiguration configuration @@ -17,6 +21,13 @@ namespace BasicDotnetTemplate.MainProject.Controllers _configuration = configuration; _appSettings = new AppSettings(); _configuration.GetSection("AppSettings").Bind(_appSettings); + + var config = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + + _mapper = config.CreateMapper(); } #nullable enable diff --git a/MainProject/Controllers/UserController.cs b/MainProject/Controllers/UserController.cs index 871feb8..23ab705 100644 --- a/MainProject/Controllers/UserController.cs +++ b/MainProject/Controllers/UserController.cs @@ -2,9 +2,11 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using BasicDotnetTemplate.MainProject.Core.Attributes; using BasicDotnetTemplate.MainProject.Services; -//using BasicDotnetTemplate.MainProject.Models.Api.Request.User; +using BasicDotnetTemplate.MainProject.Models.Api.Request.User; using BasicDotnetTemplate.MainProject.Models.Api.Response; using BasicDotnetTemplate.MainProject.Models.Api.Response.User; +using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; +using BasicDotnetTemplate.MainProject.Models.Api.Common.User; namespace BasicDotnetTemplate.MainProject.Controllers { @@ -12,12 +14,15 @@ namespace BasicDotnetTemplate.MainProject.Controllers public class UserController : BaseController { private readonly IUserService _userService; + private readonly IRoleService _roleService; public UserController( IConfiguration configuration, - IUserService userService + IUserService userService, + IRoleService roleService ) : base(configuration) { this._userService = userService; + this._roleService = roleService; } [JwtAuthorization()] @@ -32,21 +37,23 @@ namespace BasicDotnetTemplate.MainProject.Controllers { if (!ModelState.IsValid) { - return BadRequest("Request is not well formed"); + return BadRequest(_requestNotWellFormed); } if (String.IsNullOrEmpty(guid)) { - return BadRequest("Request is not well formed"); + return BadRequest(_requestNotWellFormed); } - var data = await this._userService.GetUserByGuidAsync(guid); + var user = await this._userService.GetUserByGuidAsync(guid); - if (data == null || String.IsNullOrEmpty(data.Guid)) + if (user == null || String.IsNullOrEmpty(user.Guid)) { return NotFound(); } - return Success(String.Empty, data); + var userDto = _mapper?.Map(user); + + return Success(String.Empty, userDto); } catch (Exception exception) { @@ -59,5 +66,69 @@ namespace BasicDotnetTemplate.MainProject.Controllers } } + + [JwtAuthorization()] + [HttpPost("create")] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType>(StatusCodes.Status400BadRequest)] + [ProducesResponseType>(StatusCodes.Status500InternalServerError)] + public async Task CreateUserAsync([FromBody] CreateUserRequest request) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(_requestNotWellFormed); + } + + if (request == null || request.Data == null || + String.IsNullOrEmpty(request.Data.FirstName) || + String.IsNullOrEmpty(request.Data.LastName) || + String.IsNullOrEmpty(request.Data.Email) || + String.IsNullOrEmpty(request.Data.Password) + ) + { + return BadRequest(_requestNotWellFormed); + } + + if (await this._userService.CheckIfEmailIsValid(request.Data.Email)) + { + var role = await this._roleService.GetRoleForUser(request.Data.RoleGuid); + if (role == null) + { + return BadRequest("Role not found"); + } + + var user = await this._userService.CreateUserAsync(request.Data, role); + + if (user == null || String.IsNullOrEmpty(user.Guid)) + { + return BadRequest("Not created"); + } + + var userDto = _mapper?.Map(user); + + return Success(String.Empty, userDto); + } + else + { + return BadRequest("Invalid email"); + } + + } + catch (Exception exception) + { + var message = "Something went wrong"; + if (!String.IsNullOrEmpty(exception.Message)) + { + message += $". {exception.Message}"; + } + return InternalServerError(message); + } + + } + + + } } \ No newline at end of file diff --git a/MainProject/Core/Database/SqlServerContext.cs b/MainProject/Core/Database/SqlServerContext.cs index 1a7cb22..68ccab1 100644 --- a/MainProject/Core/Database/SqlServerContext.cs +++ b/MainProject/Core/Database/SqlServerContext.cs @@ -13,6 +13,7 @@ namespace BasicDotnetTemplate.MainProject.Core.Database } public DbSet Users { get; set; } + public DbSet Roles { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -21,9 +22,11 @@ namespace BasicDotnetTemplate.MainProject.Core.Database .HasIndex(x => x.Email, "IX_Email"); modelBuilder.Entity() - .HasIndex(x => x.Username, "IX_Username"); + .HasIndex(x => new { x.IsDeleted, x.Guid }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); - modelBuilder.Entity() + + modelBuilder.Entity() .HasIndex(x => new { x.IsDeleted, x.Guid }, "IX_IsDeleted_Guid") .HasFilter("[IsDeleted] = 0"); } diff --git a/MainProject/Migrations/20250316014620_AlterTablesUsersAndRoles.Designer.cs b/MainProject/Migrations/20250316014620_AlterTablesUsersAndRoles.Designer.cs new file mode 100644 index 0000000..a6f300d --- /dev/null +++ b/MainProject/Migrations/20250316014620_AlterTablesUsersAndRoles.Designer.cs @@ -0,0 +1,167 @@ +// +using System; +using BasicDotnetTemplate.MainProject.Core.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MainProject.Migrations +{ + [DbContext(typeof(SqlServerContext))] + [Migration("20250316014620_AlterTablesUsersAndRoles")] + partial class AlterTablesUsersAndRoles + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreationUserId") + .HasColumnType("int"); + + b.Property("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DeletionUserId") + .HasColumnType("int"); + + b.Property("Guid") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("nvarchar(45)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UpdateUserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreationUserId") + .HasColumnType("int"); + + b.Property("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DeletionUserId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Guid") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("nvarchar(45)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("IsTestUser") + .HasColumnType("bit"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordSalt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UpdateUserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex(new[] { "Email" }, "IX_Email"); + + b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b => + { + b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MainProject/Migrations/20250316014620_AlterTablesUsersAndRoles.cs b/MainProject/Migrations/20250316014620_AlterTablesUsersAndRoles.cs new file mode 100644 index 0000000..b3192e0 --- /dev/null +++ b/MainProject/Migrations/20250316014620_AlterTablesUsersAndRoles.cs @@ -0,0 +1,225 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MainProject.Migrations +{ + /// + public partial class AlterTablesUsersAndRoles : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_Role_RoleId", + table: "Users"); + + migrationBuilder.DropIndex( + name: "IX_Username", + table: "Users"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Role", + table: "Role"); + + migrationBuilder.DropColumn( + name: "Username", + table: "Users"); + + migrationBuilder.RenameTable( + name: "Role", + newName: "Roles"); + + migrationBuilder.AlterColumn( + name: "UpdateUserId", + table: "Users", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AlterColumn( + name: "DeletionUserId", + table: "Users", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AlterColumn( + name: "CreationUserId", + table: "Users", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AlterColumn( + name: "UpdateUserId", + table: "Roles", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AlterColumn( + name: "Name", + table: "Roles", + type: "nvarchar(100)", + maxLength: 100, + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "DeletionUserId", + table: "Roles", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AlterColumn( + name: "CreationUserId", + table: "Roles", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddPrimaryKey( + name: "PK_Roles", + table: "Roles", + column: "Id"); + + migrationBuilder.CreateIndex( + name: "IX_IsDeleted_Guid", + table: "Roles", + columns: new[] { "IsDeleted", "Guid" }, + filter: "[IsDeleted] = 0"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Roles_RoleId", + table: "Users", + column: "RoleId", + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_Roles_RoleId", + table: "Users"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Roles", + table: "Roles"); + + migrationBuilder.DropIndex( + name: "IX_IsDeleted_Guid", + table: "Roles"); + + migrationBuilder.RenameTable( + name: "Roles", + newName: "Role"); + + migrationBuilder.AlterColumn( + name: "UpdateUserId", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeletionUserId", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CreationUserId", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AddColumn( + name: "Username", + table: "Users", + type: "nvarchar(200)", + maxLength: 200, + nullable: false, + defaultValue: ""); + + migrationBuilder.AlterColumn( + name: "UpdateUserId", + table: "Role", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "Role", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(100)", + oldMaxLength: 100); + + migrationBuilder.AlterColumn( + name: "DeletionUserId", + table: "Role", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CreationUserId", + table: "Role", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_Role", + table: "Role", + column: "Id"); + + migrationBuilder.CreateIndex( + name: "IX_Username", + table: "Users", + column: "Username"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Role_RoleId", + table: "Users", + column: "RoleId", + principalTable: "Role", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/MainProject/Migrations/20250316212343_AlterBaseUpdateTimeDeletionTimeNullable.Designer.cs b/MainProject/Migrations/20250316212343_AlterBaseUpdateTimeDeletionTimeNullable.Designer.cs new file mode 100644 index 0000000..c7397b5 --- /dev/null +++ b/MainProject/Migrations/20250316212343_AlterBaseUpdateTimeDeletionTimeNullable.Designer.cs @@ -0,0 +1,167 @@ +// +using System; +using BasicDotnetTemplate.MainProject.Core.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MainProject.Migrations +{ + [DbContext(typeof(SqlServerContext))] + [Migration("20250316212343_AlterBaseUpdateTimeDeletionTimeNullable")] + partial class AlterBaseUpdateTimeDeletionTimeNullable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreationUserId") + .HasColumnType("int"); + + b.Property("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DeletionUserId") + .HasColumnType("int"); + + b.Property("Guid") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("nvarchar(45)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UpdateUserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreationUserId") + .HasColumnType("int"); + + b.Property("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DeletionUserId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Guid") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("nvarchar(45)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("IsTestUser") + .HasColumnType("bit"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordSalt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UpdateUserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex(new[] { "Email" }, "IX_Email"); + + b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b => + { + b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MainProject/Migrations/20250316212343_AlterBaseUpdateTimeDeletionTimeNullable.cs b/MainProject/Migrations/20250316212343_AlterBaseUpdateTimeDeletionTimeNullable.cs new file mode 100644 index 0000000..5c7c4c9 --- /dev/null +++ b/MainProject/Migrations/20250316212343_AlterBaseUpdateTimeDeletionTimeNullable.cs @@ -0,0 +1,91 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MainProject.Migrations +{ + /// + public partial class AlterBaseUpdateTimeDeletionTimeNullable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UpdateTime", + table: "Users", + type: "datetime2", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime2"); + + migrationBuilder.AlterColumn( + name: "DeletionTime", + table: "Users", + type: "datetime2", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime2"); + + migrationBuilder.AlterColumn( + name: "UpdateTime", + table: "Roles", + type: "datetime2", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime2"); + + migrationBuilder.AlterColumn( + name: "DeletionTime", + table: "Roles", + type: "datetime2", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime2"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UpdateTime", + table: "Users", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeletionTime", + table: "Users", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UpdateTime", + table: "Roles", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeletionTime", + table: "Roles", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldNullable: true); + } + } +} diff --git a/MainProject/Migrations/20250316212722_AlterTableRoleAddedIsNotEditable.Designer.cs b/MainProject/Migrations/20250316212722_AlterTableRoleAddedIsNotEditable.Designer.cs new file mode 100644 index 0000000..1a82681 --- /dev/null +++ b/MainProject/Migrations/20250316212722_AlterTableRoleAddedIsNotEditable.Designer.cs @@ -0,0 +1,170 @@ +// +using System; +using BasicDotnetTemplate.MainProject.Core.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MainProject.Migrations +{ + [DbContext(typeof(SqlServerContext))] + [Migration("20250316212722_AlterTableRoleAddedIsNotEditable")] + partial class AlterTableRoleAddedIsNotEditable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreationUserId") + .HasColumnType("int"); + + b.Property("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DeletionUserId") + .HasColumnType("int"); + + b.Property("Guid") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("nvarchar(45)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("IsNotEditable") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UpdateUserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("CreationUserId") + .HasColumnType("int"); + + b.Property("DeletionTime") + .HasColumnType("datetime2"); + + b.Property("DeletionUserId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Guid") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("nvarchar(45)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("IsTestUser") + .HasColumnType("bit"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordSalt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("UpdateTime") + .HasColumnType("datetime2"); + + b.Property("UpdateUserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex(new[] { "Email" }, "IX_Email"); + + b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b => + { + b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MainProject/Migrations/20250316212722_AlterTableRoleAddedIsNotEditable.cs b/MainProject/Migrations/20250316212722_AlterTableRoleAddedIsNotEditable.cs new file mode 100644 index 0000000..423f594 --- /dev/null +++ b/MainProject/Migrations/20250316212722_AlterTableRoleAddedIsNotEditable.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MainProject.Migrations +{ + /// + public partial class AlterTableRoleAddedIsNotEditable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsNotEditable", + table: "Roles", + type: "bit", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsNotEditable", + table: "Roles"); + } + } +} diff --git a/MainProject/Migrations/SqlServerContextModelSnapshot.cs b/MainProject/Migrations/SqlServerContextModelSnapshot.cs index e0eb021..293a846 100644 --- a/MainProject/Migrations/SqlServerContextModelSnapshot.cs +++ b/MainProject/Migrations/SqlServerContextModelSnapshot.cs @@ -33,13 +33,13 @@ namespace MainProject.Migrations b.Property("CreationTime") .HasColumnType("datetime2"); - b.Property("CreationUserId") + b.Property("CreationUserId") .HasColumnType("int"); - b.Property("DeletionTime") + b.Property("DeletionTime") .HasColumnType("datetime2"); - b.Property("DeletionUserId") + b.Property("DeletionUserId") .HasColumnType("int"); b.Property("Guid") @@ -50,19 +50,26 @@ namespace MainProject.Migrations b.Property("IsDeleted") .HasColumnType("bit"); + b.Property("IsNotEditable") + .HasColumnType("bit"); + b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); - b.Property("UpdateTime") + b.Property("UpdateTime") .HasColumnType("datetime2"); - b.Property("UpdateUserId") + b.Property("UpdateUserId") .HasColumnType("int"); b.HasKey("Id"); - b.ToTable("Role"); + b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") + .HasFilter("[IsDeleted] = 0"); + + b.ToTable("Roles"); }); modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b => @@ -76,13 +83,13 @@ namespace MainProject.Migrations b.Property("CreationTime") .HasColumnType("datetime2"); - b.Property("CreationUserId") + b.Property("CreationUserId") .HasColumnType("int"); - b.Property("DeletionTime") + b.Property("DeletionTime") .HasColumnType("datetime2"); - b.Property("DeletionUserId") + b.Property("DeletionUserId") .HasColumnType("int"); b.Property("Email") @@ -126,17 +133,12 @@ namespace MainProject.Migrations b.Property("RoleId") .HasColumnType("int"); - b.Property("UpdateTime") + b.Property("UpdateTime") .HasColumnType("datetime2"); - b.Property("UpdateUserId") + b.Property("UpdateUserId") .HasColumnType("int"); - b.Property("Username") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - b.HasKey("Id"); b.HasIndex("RoleId"); @@ -146,8 +148,6 @@ namespace MainProject.Migrations b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid") .HasFilter("[IsDeleted] = 0"); - b.HasIndex(new[] { "Username" }, "IX_Username"); - b.ToTable("Users"); }); diff --git a/MainProject/Models/Api/Common/User/AuthenticatedUser.cs b/MainProject/Models/Api/Common/User/AuthenticatedUser.cs index 946f84e..1791717 100644 --- a/MainProject/Models/Api/Common/User/AuthenticatedUser.cs +++ b/MainProject/Models/Api/Common/User/AuthenticatedUser.cs @@ -7,7 +7,6 @@ public class AuthenticatedUser { #nullable enable public string? Guid { get; set; } - public string? Username { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } public string? Email { get; set; } @@ -17,7 +16,6 @@ public class AuthenticatedUser public AuthenticatedUser(DatabaseSqlServer.User user) { Guid = user.Guid; - Username = user.Username; FirstName = user.FirstName; LastName = user.LastName; Email = user.Email; diff --git a/MainProject/Models/Api/Common/User/UserDto.cs b/MainProject/Models/Api/Common/User/UserDto.cs index cfa52e7..b1505c4 100644 --- a/MainProject/Models/Api/Common/User/UserDto.cs +++ b/MainProject/Models/Api/Common/User/UserDto.cs @@ -7,7 +7,6 @@ public class UserDto { #nullable enable public string? Guid { get; set; } - public string? Username { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } public string? Email { get; set; } diff --git a/MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs b/MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs index 18901f7..ef1c7c1 100644 --- a/MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs +++ b/MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs @@ -3,7 +3,7 @@ namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Auth; public class AuthenticateRequestData { #nullable enable - public string? Username { get; set; } + public string? Email { get; set; } public string? Password { get; set; } #nullable disable } diff --git a/MainProject/Models/Api/Data/Role/CreateRoleRequestData.cs b/MainProject/Models/Api/Data/Role/CreateRoleRequestData.cs new file mode 100644 index 0000000..6831cc0 --- /dev/null +++ b/MainProject/Models/Api/Data/Role/CreateRoleRequestData.cs @@ -0,0 +1,8 @@ +namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Role; + +public class CreateRoleRequestData +{ + public string Name { get; set; } = String.Empty; + public required bool IsNotEditable { get; set; } + +} \ No newline at end of file diff --git a/MainProject/Models/Api/Data/User/CreateUserRequestData.cs b/MainProject/Models/Api/Data/User/CreateUserRequestData.cs new file mode 100644 index 0000000..2202def --- /dev/null +++ b/MainProject/Models/Api/Data/User/CreateUserRequestData.cs @@ -0,0 +1,15 @@ +namespace BasicDotnetTemplate.MainProject.Models.Api.Data.User; + +public class CreateUserRequestData +{ + public string FirstName { get; set; } = String.Empty; + public string LastName { get; set; } = String.Empty; + public string Email { get; set; } = String.Empty; + public string Password { get; set; } = String.Empty; + public string? RoleGuid { get; set; } + +} + + + + diff --git a/MainProject/Models/Api/Request/User/CreateUserRequest.cs b/MainProject/Models/Api/Request/User/CreateUserRequest.cs new file mode 100644 index 0000000..36ba57c --- /dev/null +++ b/MainProject/Models/Api/Request/User/CreateUserRequest.cs @@ -0,0 +1,14 @@ +using BasicDotnetTemplate.MainProject.Models.Api.Data.User; + +namespace BasicDotnetTemplate.MainProject.Models.Api.Request.User; + +public class CreateUserRequest +{ +#nullable enable + public CreateUserRequestData? Data { get; set; } +#nullable disable +} + + + + diff --git a/MainProject/Models/Database/SqlServer/Base.cs b/MainProject/Models/Database/SqlServer/Base.cs index d90ad6a..2d93a6d 100644 --- a/MainProject/Models/Database/SqlServer/Base.cs +++ b/MainProject/Models/Database/SqlServer/Base.cs @@ -10,11 +10,13 @@ public class Base public string Guid { get; set; } public bool IsDeleted { get; set; } public DateTime CreationTime { get; set; } - public int CreationUserId { get; set; } - public DateTime UpdateTime { get; set; } - public int UpdateUserId { get; set; } - public DateTime DeletionTime { get; set; } - public int DeletionUserId { get; set; } +#nullable enable + public int? CreationUserId { get; set; } + public DateTime? UpdateTime { get; set; } + public int? UpdateUserId { get; set; } + public DateTime? DeletionTime { get; set; } + public int? DeletionUserId { get; set; } +#nullable disable } diff --git a/MainProject/Models/Database/SqlServer/Role.cs b/MainProject/Models/Database/SqlServer/Role.cs index e5ef2f4..6c39490 100644 --- a/MainProject/Models/Database/SqlServer/Role.cs +++ b/MainProject/Models/Database/SqlServer/Role.cs @@ -1,10 +1,12 @@ -using System.Text.Json.Serialization; +using System.ComponentModel.DataAnnotations; namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer { public class Role : Base { + [MaxLength(100)] public required string Name { get; set; } + public required bool IsNotEditable { get; set; } } } diff --git a/MainProject/Models/Database/SqlServer/User.cs b/MainProject/Models/Database/SqlServer/User.cs index 4e0f0e8..3bb8f97 100644 --- a/MainProject/Models/Database/SqlServer/User.cs +++ b/MainProject/Models/Database/SqlServer/User.cs @@ -6,8 +6,6 @@ namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer; public class User : Base { - [MaxLength(200)] - public required string Username { get; set; } [MaxLength(200)] public required string FirstName { get; set; } [MaxLength(200)] diff --git a/MainProject/Program.cs b/MainProject/Program.cs index 39bc52b..732a39e 100644 --- a/MainProject/Program.cs +++ b/MainProject/Program.cs @@ -44,6 +44,7 @@ internal static class Program ProgramUtils.AddDbContext(ref builder, appSettings); WebApplication app = builder.Build(); ProgramUtils.AddMiddlewares(ref app); + ProgramUtils.CreateRoles(ref app); Logger.Info("[Program][Initialize] End building"); return app; diff --git a/MainProject/Services/AuthService.cs b/MainProject/Services/AuthService.cs index 9149ac9..3a12ce8 100644 --- a/MainProject/Services/AuthService.cs +++ b/MainProject/Services/AuthService.cs @@ -17,10 +17,11 @@ public class AuthService : BaseService, IAuthService protected readonly IUserService _userService; public AuthService( + IHttpContextAccessor httpContextAccessor, IConfiguration configuration, SqlServerContext sqlServerContext, IUserService userService - ) : base(configuration, sqlServerContext) + ) : base(httpContextAccessor, configuration, sqlServerContext) { _cryptUtils = new CryptUtils(_appSettings); _userService = userService; @@ -29,7 +30,8 @@ public class AuthService : BaseService, IAuthService public async Task AuthenticateAsync(AuthenticateRequestData data) { AuthenticatedUser? authenticatedUser = null; - var decryptedUsername = _cryptUtils.Decrypt(data.Username ?? String.Empty); + + var decryptedUsername = _cryptUtils.Decrypt(data.Email ?? String.Empty); var decryptedPassword = _cryptUtils.Decrypt(data.Password ?? String.Empty); if (!String.IsNullOrEmpty(decryptedUsername) && !String.IsNullOrEmpty(decryptedPassword)) diff --git a/MainProject/Services/BaseService.cs b/MainProject/Services/BaseService.cs index 409edc1..371fdc3 100644 --- a/MainProject/Services/BaseService.cs +++ b/MainProject/Services/BaseService.cs @@ -1,23 +1,43 @@ using BasicDotnetTemplate.MainProject.Core.Database; +using BasicDotnetTemplate.MainProject.Models.Api.Common.User; using BasicDotnetTemplate.MainProject.Models.Settings; namespace BasicDotnetTemplate.MainProject.Services; public class BaseService { + private readonly IHttpContextAccessor _httpContextAccessor; protected readonly IConfiguration _configuration; protected readonly AppSettings _appSettings; protected readonly SqlServerContext _sqlServerContext; public BaseService( + IHttpContextAccessor httpContextAccessor, IConfiguration configuration, SqlServerContext sqlServerContext ) { + _httpContextAccessor = httpContextAccessor; _configuration = configuration; _appSettings = new AppSettings(); _configuration.GetSection("AppSettings").Bind(_appSettings); _sqlServerContext = sqlServerContext; } + + protected int? GetCurrentUserId() + { + int? userId = null; + var user = this.GetCurrentUser(); + if (user != null) + { + userId = this._sqlServerContext.Users.Where(x => !x.IsDeleted && x.Guid == user.Guid).FirstOrDefault()?.Id; + } + return userId; + } + + protected AuthenticatedUser? GetCurrentUser() + { + return _httpContextAccessor.HttpContext?.Items["User"] as AuthenticatedUser; + } } diff --git a/MainProject/Services/JwtService.cs b/MainProject/Services/JwtService.cs index 8d841e3..497debb 100644 --- a/MainProject/Services/JwtService.cs +++ b/MainProject/Services/JwtService.cs @@ -21,10 +21,10 @@ public class JwtService : BaseService, IJwtService private readonly JwtTokenUtils _jwtTokenUtils; public JwtService( + IHttpContextAccessor httpContextAccessor, IConfiguration configuration, - SqlServerContext sqlServerContext, - IUserService userService - ) : base(configuration, sqlServerContext) + SqlServerContext sqlServerContext + ) : base(httpContextAccessor, configuration, sqlServerContext) { _jwtTokenUtils = new JwtTokenUtils(_appSettings); } diff --git a/MainProject/Services/RoleService.cs b/MainProject/Services/RoleService.cs new file mode 100644 index 0000000..96f127b --- /dev/null +++ b/MainProject/Services/RoleService.cs @@ -0,0 +1,151 @@ + +using System.Collections; +using BasicDotnetTemplate.MainProject.Core.Database; +using BasicDotnetTemplate.MainProject.Models.Api.Data.Role; +using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; +using Microsoft.EntityFrameworkCore; + +namespace BasicDotnetTemplate.MainProject.Services; + +public interface IRoleService +{ + Task GetRoleByIdAsync(int id); + Task GetRoleByGuidAsync(string guid); + Task CheckIfNameIsValid(string name, string? guid = ""); + Task CreateRoleAsync(CreateRoleRequestData data); + Task GetRoleForUser(string? guid); + Task DeleteRoleAsync(Role role); +} + +public class RoleService : BaseService, IRoleService +{ + private readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + public RoleService( + IHttpContextAccessor httpContextAccessor, + IConfiguration configuration, + SqlServerContext sqlServerContext + ) : base(httpContextAccessor, configuration, sqlServerContext) + { } + + private IQueryable GetRolesQueryable() + { + return this._sqlServerContext.Roles.Where(x => !x.IsDeleted); + } + private IQueryable GetRoleByNameQueryable(string name) + { + return this.GetRolesQueryable().Where(x => + x.Name.ToString() == name.ToString() + ); + } + + + + private Role CreateRoleData(CreateRoleRequestData data) + { + Role role = new() + { + CreationTime = DateTime.UtcNow, + CreationUserId = this.GetCurrentUserId(), + IsDeleted = false, + Guid = Guid.NewGuid().ToString(), + Name = data.Name, + IsNotEditable = data.IsNotEditable + }; + + return role; + } + + + + + + public async Task GetRoleByIdAsync(int id) + { + return await this.GetRolesQueryable().Where(x => x.Id == id).FirstOrDefaultAsync(); + } + + public async Task GetRoleByGuidAsync(string guid) + { + return await this.GetRolesQueryable().Where(x => x.Guid == guid).FirstOrDefaultAsync(); + } + + public async Task CheckIfNameIsValid(string name, string? guid = "") + { + var valid = false; + + Role? role = await this.GetRoleByNameQueryable(name).FirstOrDefaultAsync(); + if (role != null) + { + if (!String.IsNullOrEmpty(guid)) + { + valid = role.Guid == guid && role.Name == name; + } + } + else + { + valid = true; + } + + return valid; + } + + public async Task CreateRoleAsync(CreateRoleRequestData data) + { + Role? role = null; + + using var transaction = await _sqlServerContext.Database.BeginTransactionAsync(); + + try + { + var tempRole = this.CreateRoleData(data); + await _sqlServerContext.Roles.AddAsync(tempRole); + await _sqlServerContext.SaveChangesAsync(); + await transaction.CommitAsync(); + role = tempRole; + } + catch (Exception exception) + { + await transaction.RollbackAsync(); + Logger.Error(exception, $"[RoleService][CreateRoleAsync]"); + throw; + } + + return role; + } + + public async Task GetRoleForUser(string? guid) + { + Role? role = null; + + if (String.IsNullOrEmpty(guid)) + { + role = await this.GetRoleByNameQueryable("Default").FirstOrDefaultAsync(); + } + else + { + role = await this.GetRoleByGuidAsync(guid); + } + + return role; + } + + public async Task DeleteRoleAsync(Role role) + { + bool? deleted = false; + + using (var transaction = _sqlServerContext.Database.BeginTransactionAsync()) + { + role.IsDeleted = true; + role.DeletionTime = DateTime.UtcNow; + _sqlServerContext.Update(role); + await _sqlServerContext.SaveChangesAsync(); + await (await transaction).CommitAsync(); + deleted = true; + } + + return deleted; + } + + +} + diff --git a/MainProject/Services/UserService.cs b/MainProject/Services/UserService.cs index bf59092..ba471ab 100644 --- a/MainProject/Services/UserService.cs +++ b/MainProject/Services/UserService.cs @@ -1,6 +1,7 @@ using System.Collections; using BasicDotnetTemplate.MainProject.Core.Database; +using BasicDotnetTemplate.MainProject.Models.Api.Data.User; using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; using Microsoft.EntityFrameworkCore; @@ -10,65 +11,137 @@ public interface IUserService { Task GetUserByIdAsync(int id); Task GetUserByGuidAsync(string guid); - Task GetUserByUsernameAndPassword(string username, string password); + Task GetUserByUsernameAndPassword(string email, string password); + Task CheckIfEmailIsValid(string email, string? guid = ""); + Task CreateUserAsync(CreateUserRequestData data, Role role); + Task DeleteUserAsync(User user); } public class UserService : BaseService, IUserService { - + private readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); public UserService( + IHttpContextAccessor httpContextAccessor, IConfiguration configuration, SqlServerContext sqlServerContext - ) : base(configuration, sqlServerContext) + ) : base(httpContextAccessor, configuration, sqlServerContext) { } - private IQueryable GetUsers() + private IQueryable GetUsersQueryable() { return this._sqlServerContext.Users.Where(x => !x.IsDeleted); } - private IQueryable GetUserByUsername(string username) + private IQueryable GetUserByEmailQueryable(string email) { - return this.GetUsers().Where(x => - x.Username.ToString() == username.ToString() + return this.GetUsersQueryable().Where(x => + x.Email.ToString() == email.ToString() ); } + private User CreateUserData(CreateUserRequestData data, Role role) + { + User user = new() + { + CreationTime = DateTime.UtcNow, + CreationUserId = this.GetCurrentUserId(), + IsDeleted = false, + Guid = Guid.NewGuid().ToString(), + FirstName = data.FirstName, + LastName = data.LastName, + Email = data.Email, + PasswordSalt = "", + PasswordHash = "", + Password = "", + Role = role, + IsTestUser = false + }; + + return user; + } + + public async Task GetUserByIdAsync(int id) { - return await this.GetUsers().Where(x => x.Id == id).FirstOrDefaultAsync(); + return await this.GetUsersQueryable().Where(x => x.Id == id).FirstOrDefaultAsync(); } public async Task GetUserByGuidAsync(string guid) { - return await this.GetUsers().Where(x => x.Guid == guid).FirstOrDefaultAsync(); + return await this.GetUsersQueryable().Where(x => x.Guid == guid).FirstOrDefaultAsync(); } - public async Task GetUserByUsernameAndPassword(string username, string password) + public async Task GetUserByUsernameAndPassword(string email, string password) { - User? user = null; - - try + User? user = await this.GetUserByEmailQueryable(email).FirstOrDefaultAsync(); + if (user != null) { - user = await this.GetUserByUsername(username).FirstOrDefaultAsync(); - if (user != null) - { - var encryptedPassword = user.PasswordHash; - Console.WriteLine(encryptedPassword); - } - } - catch (Exception exception) - { - Console.WriteLine(exception.Message); + var encryptedPassword = user.PasswordHash; + Console.WriteLine(encryptedPassword); } return user; } - // public async Task CreateUser(CreateUserRequestData data) - // { + public async Task CheckIfEmailIsValid(string email, string? guid = "") + { + var valid = false; - // } + User? user = await this.GetUserByEmailQueryable(email).FirstOrDefaultAsync(); + if (user != null) + { + if (!String.IsNullOrEmpty(guid)) + { + valid = user.Guid == guid && user.Email == email; + } + } + else + { + valid = true; + } + return valid; + } + + public async Task CreateUserAsync(CreateUserRequestData data, Role role) + { + using var transaction = await _sqlServerContext.Database.BeginTransactionAsync(); + + User? user; + var tempUser = CreateUserData(data, role); + try + { + await _sqlServerContext.Users.AddAsync(tempUser); + await _sqlServerContext.SaveChangesAsync(); + await transaction.CommitAsync(); + user = tempUser; + } + catch (Exception exception) + { + await transaction.RollbackAsync(); + Logger.Error(exception, $"[UserService][CreateUserAsync]"); + throw; + } + + + return user; + } + + public async Task DeleteUserAsync(User user) + { + bool? deleted = false; + + using (var transaction = _sqlServerContext.Database.BeginTransactionAsync()) + { + user.IsDeleted = true; + user.DeletionTime = DateTime.UtcNow; + _sqlServerContext.Update(user); + await _sqlServerContext.SaveChangesAsync(); + await (await transaction).CommitAsync(); + deleted = true; + } + + return deleted; + } } diff --git a/MainProject/Utils/ProgramUtils.cs b/MainProject/Utils/ProgramUtils.cs index 0610f62..7b55858 100644 --- a/MainProject/Utils/ProgramUtils.cs +++ b/MainProject/Utils/ProgramUtils.cs @@ -6,6 +6,8 @@ using BasicDotnetTemplate.MainProject.Core.Database; using BasicDotnetTemplate.MainProject.Core.Middlewares; using BasicDotnetTemplate.MainProject.Models.Settings; using BasicDotnetTemplate.MainProject.Services; +using BasicDotnetTemplate.MainProject.Models.Api.Data.Role; +using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; @@ -213,8 +215,10 @@ public static class ProgramUtils public static void AddScopes(ref WebApplicationBuilder builder) { Logger.Info("[ProgramUtils][AddScopes] Adding scopes"); + builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); Logger.Info("[ProgramUtils][AddScopes] Done scopes"); } @@ -226,4 +230,45 @@ public static class ProgramUtils Logger.Info("[ProgramUtils][AddScopes] Done AutoMapperConfiguration"); } + public static void CreateRoles(ref WebApplication app) + { + Logger.Info("[ProgramUtils][CreateRoles] Adding roles..."); + using (var scope = app.Services.CreateScope()) + { + var roleService = scope.ServiceProvider.GetRequiredService; + CreateRole(roleService, "Administrator"); + CreateRole(roleService, "Default"); + } + + Logger.Info("[ProgramUtils][CreateRoles] Done roles"); + } + + private static void CreateRole(Func roleService, string roleName) + { + Logger.Info($"[ProgramUtils][CreateRole] Adding role {roleName}..."); + if (roleService != null) + { + var isValidThread = Task.Run(() => roleService!.Invoke()?.CheckIfNameIsValid(roleName)); + if (isValidThread.Result) + { + CreateRoleRequestData data = new() + { + Name = roleName, + IsNotEditable = true + }; + var createThread = Task.Run(() => roleService!.Invoke()?.CreateRoleAsync(data)); + Role? role = createThread.Result; + if (role != null) + { + Logger.Info($"[ProgramUtils][CreateRole] Role {roleName} created..."); + } + } + else + { + Logger.Info($"[ProgramUtils][CreateRole] Role {roleName} already exists..."); + } + } + + } + } \ No newline at end of file