26 Commits

Author SHA1 Message Date
c4ef564d71 Fixing sonarcloud issues 2025-06-22 22:55:19 +02:00
9e95ad1cc8 Fixing sonarcloud issues 2025-06-22 22:00:12 +02:00
4c3aa30cbb Fixing sonarcloud issues 2025-06-21 17:42:04 +02:00
Caterina Simona Pastore
54a5106314 Sprint 8 (#43) 2025-06-21 01:11:02 +02:00
87adaffa3e Minor fixes for sonarcloud 2025-06-21 01:00:21 +02:00
fa4f1c0791 Added new tests 2025-06-21 00:51:58 +02:00
a6193c3c94 Adding tests for CRUD operations on users 2025-06-20 20:37:40 +02:00
12b4a4d0c8 Removed obsolete tests 2025-06-19 23:37:25 +02:00
63fab9d827 Removing duplicated lines 2025-06-19 23:28:28 +02:00
e1d1381a5c Adding tests for ValidationActionFilter 2025-06-19 23:14:43 +02:00
2d7db3d919 Minor fixes for model validation 2025-06-19 20:48:17 +02:00
73043970a8 Fixing sonarcloud issues 2025-06-19 20:08:34 +02:00
5c1eacd85e Fixing sonarcloud issues 2025-06-19 19:45:02 +02:00
e03db76496 Fixing sonarcloud issues 2025-06-19 19:29:05 +02:00
1fc8e6cc1c Fixing sonarcloud issues 2025-06-19 00:53:52 +02:00
8bc50f8135 Removing duplicated lines - wip 2025-06-19 00:30:16 +02:00
e1a249c07a Adding crud operations for users 2025-06-17 23:08:21 +02:00
8986e3d77e Minor fixes 2025-06-17 21:11:35 +02:00
56a7e76785 Fixed password generation 2025-06-17 21:01:57 +02:00
061ce4cb3d Fixed issues "Do not negate boolean assertions, instead use the opposite assertion" 2025-06-17 19:58:02 +02:00
11a9696bdd Fixing security hotspots + issues 2025-06-17 19:47:56 +02:00
ad1909ef57 Minor fixes 2025-06-17 00:11:14 +02:00
1877c29e68 Fixing user password generation/validation - wip 2025-06-17 00:01:29 +02:00
14d9b45413 Added strong password validation 2025-06-16 22:43:02 +02:00
a4b8458542 Changed target branch for dependabot 2025-05-28 00:58:17 +02:00
Caterina Simona Pastore
c950556104 Sprint 7 - Dependabot (#42) 2025-05-28 00:57:28 +02:00
98 changed files with 2308 additions and 1042 deletions

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
# top-most EditorConfig file
root = true
# Core EditorConfig properties
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
csharp_prefer_braced_block = true:suggestion
csharp_preserve_single_line_blocks = true
csharp_style_expression_bodied_methods = when_on_single_line:suggestion

View File

@@ -5,11 +5,11 @@ updates:
schedule: schedule:
interval: "daily" interval: "daily"
open-pull-requests-limit: 5 open-pull-requests-limit: 5
target-branch: "sprints/7" target-branch: "main"
- package-ecosystem: "nuget" - package-ecosystem: "nuget"
directory: "/MainProject.Tests" directory: "/MainProject.Tests"
schedule: schedule:
interval: "daily" interval: "daily"
open-pull-requests-limit: 5 open-pull-requests-limit: 5
target-branch: "sprints/7" target-branch: "main"

View File

@@ -61,12 +61,12 @@ public class AuthController_Tests
ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request)); ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(AuthenticatedUser)); Assert.IsInstanceOfType(result.Data, typeof(AuthenticatedUser));
} }
else else
@@ -81,42 +81,6 @@ public class AuthController_Tests
} }
} }
[TestMethod]
public async Task AuthenticateAsync_AuthenticateRequestDataNull()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var authServiceMock = new Mock<IAuthService>();
var controller = new AuthController(configuration, authServiceMock.Object);
var request = new AuthenticateRequest
{
Data = null
};
AuthenticatedUser? authenticatedUser = null;
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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] [TestMethod]
public async Task AuthenticateAsync_NotFound() public async Task AuthenticateAsync_NotFound()
{ {
@@ -140,46 +104,7 @@ public class AuthController_Tests
if (response != null) if (response != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status404NotFound); Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task AuthenticateAsync_ModelInvalid()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var authServiceMock = new Mock<IAuthService>();
var controller = new AuthController(configuration, authServiceMock.Object);
var request = new AuthenticateRequest
{
Data = null
};
AuthenticatedUser? authenticatedUser = null;
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
controller.ModelState.AddModelError("Data", "Invalid data");
ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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 else
{ {
@@ -207,13 +132,13 @@ public class AuthController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
} }
else else
{ {

View File

@@ -70,12 +70,12 @@ public class RoleController_Tests
ObjectResult response = (ObjectResult)(await _roleController.GetRoleByGuidAsync(guid)); ObjectResult response = (ObjectResult)(await _roleController.GetRoleByGuidAsync(guid));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(RoleDto)); Assert.IsInstanceOfType(result.Data, typeof(RoleDto));
} }
else else
@@ -89,41 +89,6 @@ public class RoleController_Tests
} }
} }
[TestMethod]
public async Task GetRoleByGuidAsync_GuidIsEmpty()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = String.Empty;
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.GetRoleByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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] [TestMethod]
public async Task GetRoleByGuidAsync_NotFound() public async Task GetRoleByGuidAsync_NotFound()
{ {
@@ -141,44 +106,7 @@ public class RoleController_Tests
if (response != null) if (response != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status404NotFound); Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task GetRoleByGuidAsync_ModelInvalid()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleController.ModelState.AddModelError("Data", "Invalid data");
ObjectResult response = (ObjectResult)(await _roleController.GetRoleByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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 else
{ {
@@ -202,13 +130,13 @@ public class RoleController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
} }
else else
{ {
@@ -255,12 +183,12 @@ public class RoleController_Tests
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request)); ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(RoleDto)); Assert.IsInstanceOfType(result.Data, typeof(RoleDto));
} }
else else
@@ -297,57 +225,13 @@ public class RoleController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.IsTrue(result.Message == "Invalid name"); Assert.AreEqual("Invalid name", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateRoleAsync_CreateRoleRequestDataNull()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = null
};
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.CreateRoleAsync(
It.IsAny<CreateRoleRequestData>()
)).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest);
Assert.IsTrue(result.Message == "Request is not well formed");
} }
else else
{ {
@@ -391,13 +275,13 @@ public class RoleController_Tests
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request)); ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.IsTrue(result.Message == "Not created"); Assert.AreEqual("Not created", result.Message);
} }
else else
{ {
@@ -410,56 +294,6 @@ public class RoleController_Tests
} }
} }
[TestMethod]
public async Task CreateRoleAsync_ModelInvalid()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.CreateRoleAsync(
It.IsAny<CreateRoleRequestData>()
)).ReturnsAsync(role);
_roleController.ModelState.AddModelError("Data", "Invalid data");
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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] [TestMethod]
public async Task CreateRoleAsync_Exception() public async Task CreateRoleAsync_Exception()
{ {
@@ -494,13 +328,13 @@ public class RoleController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
} }
else else
{ {
@@ -531,42 +365,7 @@ public class RoleController_Tests
ObjectResult response = (ObjectResult)(await _roleController.DeleteRoleByGuidAsync(guid)); ObjectResult response = (ObjectResult)(await _roleController.DeleteRoleByGuidAsync(guid));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_GuidIsEmpty()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = String.Empty;
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.DeleteRoleByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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 else
{ {
@@ -591,44 +390,7 @@ public class RoleController_Tests
if (response != null) if (response != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status404NotFound); Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_ModelInvalid()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleController.ModelState.AddModelError("Data", "Invalid data");
ObjectResult response = (ObjectResult)(await _roleController.DeleteRoleByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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 else
{ {
@@ -652,13 +414,13 @@ public class RoleController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
} }
else else
{ {
@@ -673,8 +435,6 @@ public class RoleController_Tests
#endregion #endregion
#region "UPDATE" #region "UPDATE"
[TestMethod] [TestMethod]
@@ -708,12 +468,12 @@ public class RoleController_Tests
ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid)); ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(RoleDto)); Assert.IsInstanceOfType(result.Data, typeof(RoleDto));
} }
else else
@@ -752,7 +512,7 @@ public class RoleController_Tests
if (response != null) if (response != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status404NotFound); Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
} }
else else
{ {
@@ -786,13 +546,13 @@ public class RoleController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.IsTrue(result.Message == "Invalid name"); Assert.AreEqual("Invalid name", result.Message);
} }
else else
{ {
@@ -832,13 +592,13 @@ public class RoleController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.IsTrue(result.Message == "This role is not editable"); Assert.AreEqual("This role is not editable", result.Message);
} }
else else
{ {
@@ -851,96 +611,6 @@ public class RoleController_Tests
} }
} }
[TestMethod]
public async Task UpdateRoleAsync_CreateRoleRequestDataNull()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = null
};
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.UpdateRoleAsync(It.IsAny<CreateRoleRequestData>(), It.IsAny<Role>())).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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 UpdateRoleAsync_ModelInvalid()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.UpdateRoleAsync(It.IsAny<CreateRoleRequestData>(), It.IsAny<Role>())).ReturnsAsync(role);
_roleController.ModelState.AddModelError("Data", "Invalid data");
ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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] [TestMethod]
public async Task UpdateRoleAsync_Exception() public async Task UpdateRoleAsync_Exception()
{ {
@@ -971,18 +641,18 @@ public class RoleController_Tests
It.IsAny<CreateRoleRequestData>(), It.IsAny<Role>() It.IsAny<CreateRoleRequestData>(), It.IsAny<Role>()
)).ThrowsAsync(new Exception("Unexpected error")); )).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid)); ObjectResult response = (ObjectResult)await _roleController.UpdateRoleAsync(request, role.Guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult)); Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
} }
else else
{ {
@@ -996,4 +666,5 @@ public class RoleController_Tests
} }
#endregion #endregion
} }

View File

@@ -30,7 +30,7 @@ public class RootController_Test
if (result != null) if (result != null)
{ {
var data = (OkResult)result; var data = (OkResult)result;
Assert.IsTrue(data.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, data.StatusCode);
} }
else else
{ {

View File

@@ -66,6 +66,7 @@ public class UserController_Tests
} }
#region "GET"
[TestMethod] [TestMethod]
public async Task GetUserByGuidAsync_Should_Return_200_When_Successful() public async Task GetUserByGuidAsync_Should_Return_200_When_Successful()
{ {
@@ -80,12 +81,12 @@ public class UserController_Tests
ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid)); ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto)); Assert.IsInstanceOfType(result.Data, typeof(UserDto));
} }
else else
@@ -99,41 +100,6 @@ public class UserController_Tests
} }
} }
[TestMethod]
public async Task GetUserByGuidAsync_GuidIsEmpty()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = String.Empty;
DatabaseSqlServer.User? user = null;
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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] [TestMethod]
public async Task GetUserByGuidAsync_NotFound() public async Task GetUserByGuidAsync_NotFound()
{ {
@@ -151,44 +117,7 @@ public class UserController_Tests
if (response != null) if (response != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status404NotFound); Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task GetUserByGuidAsync_ModelInvalid()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User? user = null;
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).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 == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)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 else
{ {
@@ -212,13 +141,13 @@ public class UserController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
} }
else else
{ {
@@ -231,6 +160,10 @@ public class UserController_Tests
} }
} }
#endregion
#region "CREATE"
[TestMethod] [TestMethod]
public async Task CreateUserAsync_Success() public async Task CreateUserAsync_Success()
{ {
@@ -265,12 +198,12 @@ public class UserController_Tests
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status200OK); Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto)); Assert.IsInstanceOfType(result.Data, typeof(UserDto));
} }
else else
@@ -311,13 +244,13 @@ public class UserController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.IsTrue(result.Message == "Invalid email"); Assert.AreEqual("Invalid email", result.Message);
} }
else else
{ {
@@ -362,58 +295,13 @@ public class UserController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.IsTrue(result.Message == "Role not found"); Assert.AreEqual("Role not found", result.Message);
}
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<string>(), It.IsAny<string>())).ReturnsAsync(true);
_userServiceMock?.Setup(s => s.CreateUserAsync(
It.IsAny<CreateUserRequestData>(),
It.IsAny<Role>()
)).ReturnsAsync(user);
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest);
Assert.IsTrue(result.Message == "Request is not well formed");
} }
else else
{ {
@@ -462,13 +350,13 @@ public class UserController_Tests
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request)); ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status400BadRequest); Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.IsTrue(result.Message == "Not created"); Assert.AreEqual("Not created", result.Message);
} }
else else
{ {
@@ -481,59 +369,6 @@ public class UserController_Tests
} }
} }
[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<string>(), It.IsAny<string>())).ReturnsAsync(true);
_userServiceMock?.Setup(s => s.CreateUserAsync(
It.IsAny<CreateUserRequestData>(),
It.IsAny<Role>()
)).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<object>)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] [TestMethod]
public async Task CreateUserAsync_Exception() public async Task CreateUserAsync_Exception()
{ {
@@ -576,13 +411,13 @@ public class UserController_Tests
if (response != null && response.Value != null) if (response != null && response.Value != null)
{ {
Assert.IsTrue(response.StatusCode == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value; var result = (BaseResponse<object>)response.Value;
if (result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == StatusCodes.Status500InternalServerError); Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
} }
else else
{ {
@@ -594,4 +429,479 @@ public class UserController_Tests
Assert.Fail($"Response is null"); Assert.Fail($"Response is null");
} }
} }
#endregion
#region "DELETE"
[TestMethod]
public async Task DeleteRoleByGuidAsync_Success()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User user = ModelsInit.CreateUser();
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.DeleteUserByGuidAsync(guid);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_NotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User? user = null;
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.DeleteUserByGuidAsync(guid);
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.DeleteUserByGuidAsync(guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
#region "UPDATE"
[TestMethod]
public async Task UpdateUserAsync_Should_Return_200_When_Successful()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
UpdateUserRequest request = new UpdateUserRequest()
{
Data = new UpdateUserRequestData()
{
FirstName = "NewFirstName",
LastName = "NewLastName"
}
};
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserAsync(It.IsAny<UpdateUserRequestData>(), It.IsAny<User>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserAsync(request, user.Guid);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateUserAsync_UserNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User? user = null;
UpdateUserRequest request = new UpdateUserRequest()
{
Data = new UpdateUserRequestData()
{
FirstName = "NewFirstName",
LastName = "NewLastName"
}
};
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.UpdateUserAsync(request, Guid.NewGuid().ToString());
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
UpdateUserRequest request = new UpdateUserRequest()
{
Data = new UpdateUserRequestData()
{
FirstName = "NewFirstName",
LastName = "NewLastName"
}
};
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserAsync(
It.IsAny<UpdateUserRequestData>(), It.IsAny<User>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.UpdateUserAsync(request, user.Guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Should_Return_200_When_Successful()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
string newPassword = "This!s4T3stP4ssw0rd#";
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserPasswordAsync(It.IsAny<User>(), newPassword)).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserPasswordAsync(user.Guid, newPassword);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_UserNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User? user = null;
string newPassword = "This!s4T3stP4ssw0rd#";
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.UpdateUserPasswordAsync(Guid.NewGuid().ToString(), newPassword);
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
string newPassword = "This!s4T3stP4ssw0rd#";
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserPasswordAsync(
It.IsAny<User>(), It.IsAny<string>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.UpdateUserPasswordAsync(user.Guid, newPassword);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_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();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserRoleAsync(It.IsAny<User>(), It.IsAny<Role>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserRoleAsync(user.Guid, role.Guid);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_RoleNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserRoleAsync(user.Guid, Guid.NewGuid().ToString());
if (response != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
Assert.IsNotNull(response.Value);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Role not found", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_UserNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User? user = null;
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserRoleAsync(It.IsAny<User>(), It.IsAny<Role>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.UpdateUserRoleAsync(Guid.NewGuid().ToString(), role.Guid);
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserRoleAsync(
It.IsAny<User>(), It.IsAny<Role>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.UpdateUserRoleAsync(user.Guid, role.Guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
} }

View File

@@ -0,0 +1,135 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Microsoft.AspNetCore.Builder;
using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.AspNetCore.Mvc.Filters;
using BasicDotnetTemplate.MainProject.Core.Attributes;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using BasicDotnetTemplate.MainProject.Core.Filters;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject.Models.Api.Base;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class ValidationActionFilter_Tests
{
private readonly string _requestNotWellFormedMessage = "Request is not well formed";
private static ActionExecutingContext CreateContext(ModelStateDictionary modelState, object? requestBody = null)
{
var actionContext = new ActionContext(
new DefaultHttpContext(),
new Microsoft.AspNetCore.Routing.RouteData(),
new Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor(),
modelState
);
var actionArguments = new Dictionary<string, object?>();
if (requestBody != null)
{
actionArguments.Add("request", requestBody);
}
return new ActionExecutingContext(
actionContext,
[],
actionArguments,
new Mock<Controller>().Object
);
}
[TestMethod]
public void OnActionExecutionAsync_ModelStateInvalid_ReturnsBadRequestAndDoesNotCallNext()
{
// Arrange
var modelState = new ModelStateDictionary();
modelState.AddModelError("MissingProperty", "MissingProperty is required");
var context = CreateContext(modelState, new { SomeProp = "Value" });
var nextCalled = false;
ActionExecutionDelegate next = () => {
nextCalled = true;
return Task.FromResult(new ActionExecutedContext(context, [], new Mock<Controller>().Object));
};
var filter = new ValidationActionFilter();
// Act
filter.OnActionExecutionAsync(context, next).GetAwaiter().GetResult();
// Assert
Assert.IsNotNull(context.Result);
var badRequestResult = context.Result as BadRequestObjectResult;
Assert.IsNotNull(badRequestResult);
Assert.IsNotNull(badRequestResult!.Value);
ValidationError validationError = (ValidationError)badRequestResult.Value;
Assert.AreEqual(_requestNotWellFormedMessage, validationError?.Message);
Assert.IsNotNull(validationError?.Errors);
Assert.IsFalse(modelState.IsValid);
Assert.IsFalse(nextCalled);
}
[TestMethod]
public void OnActionExecutionAsync_ModelStateValid_RequestBodyNull_ReturnsBadRequestAndDoesNotCallNext()
{
var modelState = new ModelStateDictionary();
var context = CreateContext(modelState, null);
var nextCalled = false;
ActionExecutionDelegate next = () => {
nextCalled = true;
return Task.FromResult(new ActionExecutedContext(context, [], new Mock<Controller>().Object));
};
var filter = new ValidationActionFilter();
// Act
filter.OnActionExecutionAsync(context, next).GetAwaiter().GetResult();
// Assert
Assert.IsNotNull(context.Result);
var badRequestResult = context.Result as BadRequestObjectResult;
Assert.IsNotNull(badRequestResult);
Assert.IsNotNull(badRequestResult!.Value);
ValidationError validationError = (ValidationError)badRequestResult.Value;
Assert.AreEqual(_requestNotWellFormedMessage, validationError?.Message);
Assert.IsNull(validationError?.Errors);
Assert.IsTrue(modelState.IsValid);
Assert.IsFalse(nextCalled);
}
[TestMethod]
public void OnActionExecutionAsync_ModelStateValid_RequestBodyValid_CallsNextAndDoesNotSetResult()
{
// Arrange
var modelState = new ModelStateDictionary();
var requestBody = new TestRequestBody { Value = "Test" };
var context = CreateContext(modelState, requestBody);
var nextCalled = false;
ActionExecutionDelegate next = () => {
nextCalled = true;
return Task.FromResult(new ActionExecutedContext(context, [], new Mock<Controller>().Object));
};
var filter = new ValidationActionFilter();
// Act
filter.OnActionExecutionAsync(context, next).GetAwaiter().GetResult();
// Assert
Assert.IsNull(context.Result);
Assert.IsTrue(nextCalled);
}
private class TestRequestBody
{
public string? Value { get; set; }
}
}

View File

@@ -40,10 +40,10 @@ public class AutoMapperConfiguration_Tests
DatabaseSqlServer.User user = ModelsInit.CreateUser(); DatabaseSqlServer.User user = ModelsInit.CreateUser();
UserDto? data = _mapper?.Map<UserDto>(user); UserDto? data = _mapper?.Map<UserDto>(user);
Assert.IsTrue(data?.Guid == user.Guid); Assert.AreEqual(user.Guid, data?.Guid);
Assert.IsTrue(data?.FirstName == user.FirstName); Assert.AreEqual(user.FirstName, data?.FirstName);
Assert.IsTrue(data?.LastName == user.LastName); Assert.AreEqual(user.LastName, data?.LastName);
Assert.IsTrue(data?.Email == user.Email); Assert.AreEqual(user.Email, data?.Email);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -35,8 +35,9 @@
"ExpiredAfterMinsOfInactivity": 15 "ExpiredAfterMinsOfInactivity": 15
}, },
"EncryptionSettings": { "EncryptionSettings": {
"Salt": "S7VIidfXQf1tOQYX", "SaltKey": "S7VIidfXQf1tOQYX",
"Pepper": "" "Salt": "u5CZAwq9vLGysC",
"Iterations": 10
} }
} }

View File

@@ -35,8 +35,9 @@
"ExpiredAfterMinsOfInactivity": 15 "ExpiredAfterMinsOfInactivity": 15
}, },
"EncryptionSettings": { "EncryptionSettings": {
"Salt": "AAAAA", "SaltKey": "AAAAA",
"Pepper": "" "Salt": "",
"Iterations": 10
} }
} }

View File

@@ -10,12 +10,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" /> <PackageReference Include="coverlet.collector" Version="6.0.4">
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.3" /> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Moq" Version="4.20.72" /> <PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" /> <PackageReference Include="MSTest.TestAdapter" Version="3.9.3" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" /> <PackageReference Include="MSTest.TestFramework" Version="3.9.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>

View File

@@ -23,9 +23,9 @@ public class UserRole_Tests
try try
{ {
DatabaseSqlServer.Role role = ModelsInit.CreateRole(); DatabaseSqlServer.Role role = ModelsInit.CreateRole();
UserRole userRole = new UserRole(role); UserRole userRole = new(role);
Assert.IsTrue(userRole.Name == role.Name); Assert.AreEqual(role.Name, userRole.Name);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -25,9 +25,9 @@ public class AuthenticatedUser_Tests
DatabaseSqlServer.User user = ModelsInit.CreateUser(); DatabaseSqlServer.User user = ModelsInit.CreateUser();
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user); AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
Assert.IsTrue(authenticatedUser.FirstName == user.FirstName); Assert.AreEqual(user.FirstName, authenticatedUser.FirstName);
Assert.IsTrue(authenticatedUser.LastName == user.LastName); Assert.AreEqual(user.LastName, authenticatedUser.LastName);
Assert.IsTrue(authenticatedUser.Email == user.Email); Assert.AreEqual(user.Email, authenticatedUser.Email);
Assert.IsInstanceOfType(authenticatedUser.Role, typeof(UserRole)); Assert.IsInstanceOfType(authenticatedUser.Role, typeof(UserRole));
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -35,7 +35,7 @@ public class ApiResponse_Tests
try try
{ {
var baseResponse = new BaseResponse<object>(201, null, null); var baseResponse = new BaseResponse<object>(201, null, null);
Assert.IsFalse(baseResponse.Status == StatusCodes.Status200OK); Assert.AreNotEqual(StatusCodes.Status200OK, baseResponse.Status);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -39,7 +39,7 @@ public class AuthenticateResponse_Tests
try try
{ {
var authenticateResponse = new AuthenticateResponse(201, null, null); var authenticateResponse = new AuthenticateResponse(201, null, null);
Assert.IsFalse(authenticateResponse.Status == StatusCodes.Status200OK); Assert.AreNotEqual(StatusCodes.Status200OK, authenticateResponse.Status);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -54,7 +54,7 @@ public class GetRoleResponse_Tests
try try
{ {
var getRoleResponse = new GetRoleResponse(201, null, null); var getRoleResponse = new GetRoleResponse(201, null, null);
Assert.IsFalse(getRoleResponse.Status == StatusCodes.Status200OK); Assert.AreNotEqual(StatusCodes.Status200OK, getRoleResponse.Status);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -54,7 +54,7 @@ public class GetUserResponse_Tests
try try
{ {
var getUserResponse = new GetUserResponse(201, null, null); var getUserResponse = new GetUserResponse(201, null, null);
Assert.IsFalse(getUserResponse.Status == StatusCodes.Status200OK); Assert.AreNotEqual(StatusCodes.Status200OK, getUserResponse.Status);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -54,7 +54,7 @@ public class Settings_Tests
try try
{ {
var baseResponse = new BaseResponse<object>(201, null, null); var baseResponse = new BaseResponse<object>(201, null, null);
Assert.IsFalse(baseResponse.Status == StatusCodes.Status200OK); Assert.AreNotEqual(StatusCodes.Status200OK, baseResponse.Status);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -62,7 +62,7 @@ public class AuthService_Tests
if (authService != null) if (authService != null)
{ {
var authenticatedUser = await authService.AuthenticateAsync(request.Data); var authenticatedUser = await authService.AuthenticateAsync(request.Data);
Assert.IsTrue(authenticatedUser == null); Assert.IsNull(authenticatedUser);
} }
else else
{ {
@@ -93,7 +93,7 @@ public class AuthService_Tests
if (authService != null) if (authService != null)
{ {
var authenticatedUser = await authService.AuthenticateAsync(request.Data); var authenticatedUser = await authService.AuthenticateAsync(request.Data);
Assert.IsTrue(authenticatedUser == null); Assert.IsNull(authenticatedUser);
} }
else else
{ {

View File

@@ -53,7 +53,7 @@ public class JwtService_Tests
if (jwtService != null) if (jwtService != null)
{ {
var jwt = jwtService.GenerateToken(testString); var jwt = jwtService.GenerateToken(testString);
Assert.IsTrue(jwt != null); Assert.IsNotNull(jwt);
Assert.IsInstanceOfType(jwt, typeof(string)); Assert.IsInstanceOfType(jwt, typeof(string));
} }
else else

View File

@@ -94,7 +94,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionSystemByGuidAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionSystemByGuidAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -117,7 +117,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionSystemByNameAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionSystemByNameAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -139,7 +139,7 @@ public class PermissionService_Tests
var permission = await _permissionService.CreatePermissionSystemAsync(_permissionSystem.Name, true); var permission = await _permissionService.CreatePermissionSystemAsync(_permissionSystem.Name, true);
Assert.IsInstanceOfType(permission, typeof(PermissionSystem)); Assert.IsInstanceOfType(permission, typeof(PermissionSystem));
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsTrue(permission.Name == _permissionSystem.Name); Assert.AreEqual(_permissionSystem.Name, permission.Name);
Assert.IsTrue(permission.Enabled); Assert.IsTrue(permission.Enabled);
_permissionSystem = permission; _permissionSystem = permission;
@@ -189,7 +189,7 @@ public class PermissionService_Tests
{ {
var updated = await _permissionService.HandleEnabledPermissionSystemAsync(_permissionSystem, false); var updated = await _permissionService.HandleEnabledPermissionSystemAsync(_permissionSystem, false);
Assert.IsTrue(updated); Assert.IsTrue(updated);
Assert.IsTrue(!_permissionSystem.Enabled); Assert.IsFalse(_permissionSystem.Enabled);
} }
catch (Exception ex) catch (Exception ex)
@@ -210,8 +210,8 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionSystemByGuidAsync(_permissionSystem.Guid); var permission = await _permissionService.GetPermissionSystemByGuidAsync(_permissionSystem.Guid);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionSystem)); Assert.IsInstanceOfType(permission, typeof(PermissionSystem));
Assert.IsTrue(permission.Name == _permissionSystem.Name); Assert.AreEqual(_permissionSystem.Name, permission.Name);
Assert.IsTrue(permission.Enabled == _permissionSystem.Enabled); Assert.AreEqual( _permissionSystem.Enabled, permission.Enabled);
} }
else else
{ {
@@ -236,8 +236,8 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionSystemByNameAsync(_permissionSystem.Name); var permission = await _permissionService.GetPermissionSystemByNameAsync(_permissionSystem.Name);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionSystem)); Assert.IsInstanceOfType(permission, typeof(PermissionSystem));
Assert.IsTrue(permission.Guid == _permissionSystem.Guid); Assert.AreEqual(_permissionSystem.Guid, permission.Guid);
Assert.IsTrue(permission.Enabled == _permissionSystem.Enabled); Assert.AreEqual( _permissionSystem.Enabled, permission.Enabled);
} }
else else
{ {
@@ -265,7 +265,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionModuleByGuidAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionModuleByGuidAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -288,7 +288,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionModuleByNameAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionModuleByNameAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -310,7 +310,7 @@ public class PermissionService_Tests
var permission = await _permissionService.CreatePermissionModuleAsync(_permissionModule.Name, true); var permission = await _permissionService.CreatePermissionModuleAsync(_permissionModule.Name, true);
Assert.IsInstanceOfType(permission, typeof(PermissionModule)); Assert.IsInstanceOfType(permission, typeof(PermissionModule));
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsTrue(permission.Name == _permissionModule.Name); Assert.AreEqual(_permissionModule.Name, permission.Name);
Assert.IsTrue(permission.Enabled); Assert.IsTrue(permission.Enabled);
_permissionModule = permission; _permissionModule = permission;
@@ -362,7 +362,7 @@ public class PermissionService_Tests
{ {
var updated = await _permissionService.HandleEnabledPermissionModuleAsync(_permissionModule, false); var updated = await _permissionService.HandleEnabledPermissionModuleAsync(_permissionModule, false);
Assert.IsTrue(updated); Assert.IsTrue(updated);
Assert.IsTrue(!_permissionModule.Enabled); Assert.IsFalse(_permissionModule.Enabled);
} }
catch (Exception ex) catch (Exception ex)
@@ -383,8 +383,8 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionModuleByGuidAsync(_permissionModule.Guid); var permission = await _permissionService.GetPermissionModuleByGuidAsync(_permissionModule.Guid);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionModule)); Assert.IsInstanceOfType(permission, typeof(PermissionModule));
Assert.IsTrue(permission.Name == _permissionModule.Name); Assert.AreEqual(_permissionModule.Name, permission.Name);
Assert.IsTrue(permission.Enabled == _permissionModule.Enabled); Assert.AreEqual( _permissionModule.Enabled, permission.Enabled);
} }
else else
{ {
@@ -409,8 +409,8 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionModuleByNameAsync(_permissionModule.Name); var permission = await _permissionService.GetPermissionModuleByNameAsync(_permissionModule.Name);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionModule)); Assert.IsInstanceOfType(permission, typeof(PermissionModule));
Assert.IsTrue(permission.Guid == _permissionModule.Guid); Assert.AreEqual(_permissionModule.Guid, permission.Guid);
Assert.IsTrue(permission.Enabled == _permissionModule.Enabled); Assert.AreEqual( _permissionModule.Enabled, permission.Enabled);
} }
else else
{ {
@@ -438,7 +438,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionOperationByGuidAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionOperationByGuidAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -461,7 +461,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionOperationByNameAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionOperationByNameAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -483,7 +483,7 @@ public class PermissionService_Tests
var permission = await _permissionService.CreatePermissionOperationAsync(_permissionOperation.Name); var permission = await _permissionService.CreatePermissionOperationAsync(_permissionOperation.Name);
Assert.IsInstanceOfType(permission, typeof(PermissionOperation)); Assert.IsInstanceOfType(permission, typeof(PermissionOperation));
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsTrue(permission.Name == _permissionOperation.Name); Assert.AreEqual(_permissionOperation.Name, permission.Name);
_permissionOperation = permission; _permissionOperation = permission;
} }
@@ -536,7 +536,7 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionOperationByGuidAsync(_permissionOperation.Guid); var permission = await _permissionService.GetPermissionOperationByGuidAsync(_permissionOperation.Guid);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionOperation)); Assert.IsInstanceOfType(permission, typeof(PermissionOperation));
Assert.IsTrue(permission.Name == _permissionOperation.Name); Assert.AreEqual(_permissionOperation.Name, permission.Name);
} }
else else
{ {
@@ -561,7 +561,7 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionOperationByNameAsync(_permissionOperation.Name); var permission = await _permissionService.GetPermissionOperationByNameAsync(_permissionOperation.Name);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionOperation)); Assert.IsInstanceOfType(permission, typeof(PermissionOperation));
Assert.IsTrue(permission.Guid == _permissionOperation.Guid); Assert.AreEqual(_permissionOperation.Guid, permission.Guid);
} }
else else
{ {
@@ -589,7 +589,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionSystemModuleByGuidAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionSystemModuleByGuidAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -660,7 +660,7 @@ public class PermissionService_Tests
{ {
var updated = await _permissionService.HandleEnabledPermissionSystemModuleAsync(_permissionSystemModule, false); var updated = await _permissionService.HandleEnabledPermissionSystemModuleAsync(_permissionSystemModule, false);
Assert.IsTrue(updated); Assert.IsTrue(updated);
Assert.IsTrue(!_permissionSystemModule.Enabled); Assert.IsFalse(_permissionSystemModule.Enabled);
} }
catch (Exception ex) catch (Exception ex)
@@ -681,7 +681,7 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionSystemModuleByGuidAsync(_permissionSystemModule.Guid); var permission = await _permissionService.GetPermissionSystemModuleByGuidAsync(_permissionSystemModule.Guid);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionSystemModule)); Assert.IsInstanceOfType(permission, typeof(PermissionSystemModule));
Assert.IsTrue(permission.Enabled == _permissionSystemModule.Enabled); Assert.AreEqual( _permissionSystemModule.Enabled, permission.Enabled);
} }
else else
{ {
@@ -709,7 +709,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetPermissionSystemModuleOperationByGuidAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetPermissionSystemModuleOperationByGuidAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -780,7 +780,7 @@ public class PermissionService_Tests
{ {
var updated = await _permissionService.HandleEnabledPermissionSystemModuleOperationAsync(_permissionSystemModuleOperation, false); var updated = await _permissionService.HandleEnabledPermissionSystemModuleOperationAsync(_permissionSystemModuleOperation, false);
Assert.IsTrue(updated); Assert.IsTrue(updated);
Assert.IsTrue(!_permissionSystemModuleOperation.Enabled); Assert.IsFalse(_permissionSystemModuleOperation.Enabled);
} }
catch (Exception ex) catch (Exception ex)
@@ -801,7 +801,7 @@ public class PermissionService_Tests
var permission = await _permissionService.GetPermissionSystemModuleOperationByGuidAsync(_permissionSystemModuleOperation.Guid); var permission = await _permissionService.GetPermissionSystemModuleOperationByGuidAsync(_permissionSystemModuleOperation.Guid);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(PermissionSystemModuleOperation)); Assert.IsInstanceOfType(permission, typeof(PermissionSystemModuleOperation));
Assert.IsTrue(permission.Enabled == _permissionSystemModuleOperation.Enabled); Assert.AreEqual(_permissionSystemModuleOperation.Enabled, permission.Enabled);
} }
else else
{ {
@@ -829,7 +829,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
var permission = await _permissionService.GetRolePermissionSystemModuleOperationByGuidAsync(Guid.NewGuid().ToString()); var permission = await _permissionService.GetRolePermissionSystemModuleOperationByGuidAsync(Guid.NewGuid().ToString());
Assert.IsTrue(permission == null); Assert.IsNull(permission);
} }
else else
{ {
@@ -916,7 +916,7 @@ public class PermissionService_Tests
{ {
var updated = await _permissionService.HandleEnabledRolePermissionSystemModuleOperationAsync(_rolePermissionSystemModuleOperation, false); var updated = await _permissionService.HandleEnabledRolePermissionSystemModuleOperationAsync(_rolePermissionSystemModuleOperation, false);
Assert.IsTrue(updated); Assert.IsTrue(updated);
Assert.IsTrue(!_rolePermissionSystemModuleOperation.Active); Assert.IsFalse(_rolePermissionSystemModuleOperation.Active);
} }
catch (Exception ex) catch (Exception ex)
@@ -937,7 +937,7 @@ public class PermissionService_Tests
var permission = await _permissionService.GetRolePermissionSystemModuleOperationByGuidAsync(_rolePermissionSystemModuleOperation.Guid); var permission = await _permissionService.GetRolePermissionSystemModuleOperationByGuidAsync(_rolePermissionSystemModuleOperation.Guid);
Assert.IsNotNull(permission); Assert.IsNotNull(permission);
Assert.IsInstanceOfType(permission, typeof(RolePermissionSystemModuleOperation)); Assert.IsInstanceOfType(permission, typeof(RolePermissionSystemModuleOperation));
Assert.IsTrue(permission.Active == _rolePermissionSystemModuleOperation.Active); Assert.AreEqual( _rolePermissionSystemModuleOperation.Active, permission.Active);
} }
else else
{ {
@@ -1067,7 +1067,7 @@ public class PermissionService_Tests
if (_permissionService != null) if (_permissionService != null)
{ {
List<string> permissions = _permissionService.CreatePermissionsOnStartupAsync(); List<string> permissions = _permissionService.CreatePermissionsOnStartupAsync();
Assert.IsFalse(permissions == null); Assert.IsNotNull(permissions);
List<string> cleanedPermissions = new(); List<string> cleanedPermissions = new();
foreach (var permission in permissions) foreach (var permission in permissions)

View File

@@ -79,8 +79,8 @@ public class RoleService_Tests
var role = await _roleService.CreateRoleAsync(data); var role = await _roleService.CreateRoleAsync(data);
Assert.IsInstanceOfType(role, typeof(Role)); Assert.IsInstanceOfType(role, typeof(Role));
Assert.IsNotNull(role); Assert.IsNotNull(role);
Assert.IsTrue(_expectedRole?.Name == role.Name); Assert.AreEqual(_expectedRole?.Name, role.Name);
Assert.IsTrue(_expectedRole?.IsNotEditable == role.IsNotEditable); Assert.AreEqual(_expectedRole?.IsNotEditable, role.IsNotEditable);
_role = role; _role = role;
} }
else else
@@ -188,7 +188,7 @@ public class RoleService_Tests
{ {
var role = await _roleService.GetRoleByIdAsync(_role?.Id ?? 0); var role = await _roleService.GetRoleByIdAsync(_role?.Id ?? 0);
Assert.IsNotNull(role); Assert.IsNotNull(role);
Assert.IsTrue(role.Id == _role?.Id); Assert.AreEqual(_role?.Id, _role?.Id);
} }
else else
{ {
@@ -211,7 +211,7 @@ public class RoleService_Tests
{ {
var role = await _roleService.GetRoleByGuidAsync(_role?.Guid ?? String.Empty); var role = await _roleService.GetRoleByGuidAsync(_role?.Guid ?? String.Empty);
Assert.IsNotNull(role); Assert.IsNotNull(role);
Assert.IsTrue(role.Guid == _role?.Guid); Assert.AreEqual(_role?.Guid, role.Guid);
} }
else else
{ {
@@ -234,7 +234,7 @@ public class RoleService_Tests
{ {
var role = await _roleService.GetRoleForUser(_role?.Guid); var role = await _roleService.GetRoleForUser(_role?.Guid);
Assert.IsNotNull(role); Assert.IsNotNull(role);
Assert.IsTrue(role.Guid == _role?.Guid); Assert.AreEqual(_role?.Guid, role.Guid);
} }
else else
{ {
@@ -263,8 +263,8 @@ public class RoleService_Tests
var roleCreated = await _roleService.CreateRoleAsync(data); var roleCreated = await _roleService.CreateRoleAsync(data);
var role = await _roleService.GetRoleForUser(String.Empty); var role = await _roleService.GetRoleForUser(String.Empty);
Assert.IsNotNull(role); Assert.IsNotNull(role);
Assert.IsTrue(roleCreated?.Guid == role?.Guid); Assert.AreEqual(role?.Guid, roleCreated?.Guid);
Assert.IsTrue(role?.Name == "Default"); Assert.AreEqual("Default", role?.Name);
} }
else else
{ {
@@ -317,8 +317,8 @@ public class RoleService_Tests
var role = await _roleService.UpdateRoleAsync(data, _role!); var role = await _roleService.UpdateRoleAsync(data, _role!);
Assert.IsInstanceOfType(role, typeof(Role)); Assert.IsInstanceOfType(role, typeof(Role));
Assert.IsNotNull(role); Assert.IsNotNull(role);
Assert.IsTrue(data.Name == role.Name); Assert.AreEqual(data.Name, role.Name);
Assert.IsTrue(data.IsNotEditable == role.IsNotEditable); Assert.AreEqual(data.IsNotEditable, role.IsNotEditable);
_role = role; _role = role;
} }
else else
@@ -359,8 +359,8 @@ public class RoleService_Tests
var roleUpdatedRole = await _roleService.UpdateRoleAsync(updateRoleData, role!); var roleUpdatedRole = await _roleService.UpdateRoleAsync(updateRoleData, role!);
Assert.IsInstanceOfType(roleUpdatedRole, typeof(Role)); Assert.IsInstanceOfType(roleUpdatedRole, typeof(Role));
Assert.IsNotNull(roleUpdatedRole); Assert.IsNotNull(roleUpdatedRole);
Assert.IsTrue(roleUpdatedRole.Name == createRoleData.Name); Assert.AreEqual(createRoleData.Name, roleUpdatedRole.Name);
Assert.IsTrue(roleUpdatedRole.IsNotEditable == createRoleData.IsNotEditable); Assert.AreEqual(createRoleData.IsNotEditable, roleUpdatedRole.IsNotEditable);
} }
else else
{ {

View File

@@ -36,29 +36,6 @@ public class UserService_Tests
} }
} }
[TestMethod]
public async Task GetUserByUsernameAndPassword_Null()
{
try
{
var testString = "test";
if (_userService != null)
{
var user = await _userService.GetUserByUsernameAndPassword(testString, testString);
Assert.IsTrue(user == null);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod] [TestMethod]
public async Task CheckIfEmailIsValid_EmailNotExists() public async Task CheckIfEmailIsValid_EmailNotExists()
{ {
@@ -93,7 +70,8 @@ public class UserService_Tests
{ {
FirstName = expectedUser.FirstName ?? String.Empty, FirstName = expectedUser.FirstName ?? String.Empty,
LastName = expectedUser.LastName ?? String.Empty, LastName = expectedUser.LastName ?? String.Empty,
Email = expectedUser.Email ?? String.Empty Email = expectedUser.Email ?? String.Empty,
Password = "Password"
}; };
Role role = new() Role role = new()
@@ -106,10 +84,14 @@ public class UserService_Tests
var user = await _userService.CreateUserAsync(data, role); var user = await _userService.CreateUserAsync(data, role);
Assert.IsInstanceOfType(user, typeof(User)); Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user); Assert.IsNotNull(user);
Assert.IsTrue(expectedUser.FirstName == user.FirstName); Assert.AreEqual(expectedUser.FirstName, user.FirstName);
Assert.IsTrue(expectedUser.LastName == user.LastName); Assert.AreEqual(expectedUser.LastName, user.LastName);
Assert.IsTrue(expectedUser.Email == user.Email); Assert.AreEqual(expectedUser.Email, user.Email);
Assert.IsTrue(expectedUser.Role?.Name == user.Role?.Name); Assert.AreEqual(expectedUser.Role?.Name, user.Role?.Name);
Assert.AreEqual(10, user.PasswordIterations);
Assert.IsNotNull(expectedUser.PasswordSalt);
Assert.IsNotNull(expectedUser.PasswordPepper);
Assert.IsNotNull(expectedUser.Password);
_user = user; _user = user;
} }
@@ -120,6 +102,51 @@ public class UserService_Tests
} }
} }
[TestMethod]
public async Task GetUserByUsernameAndPassword_Null()
{
try
{
if (_userService != null)
{
var user = await _userService.GetUserByUsernameAndPassword(_user.Email, "WrongPassword");
Assert.IsNull(user);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetUserByUsernameAndPassword_Success()
{
try
{
var password = "Password";
if (_userService != null)
{
var user = await _userService.GetUserByUsernameAndPassword(_user.Email, password);
Assert.IsNotNull(user);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod] [TestMethod]
public async Task CreateUserAsync_Exception() public async Task CreateUserAsync_Exception()
{ {
@@ -131,7 +158,8 @@ public class UserService_Tests
{ {
FirstName = expectedUser.FirstName ?? String.Empty, FirstName = expectedUser.FirstName ?? String.Empty,
LastName = expectedUser.LastName ?? String.Empty, LastName = expectedUser.LastName ?? String.Empty,
Email = expectedUser.Email ?? String.Empty Email = expectedUser.Email ?? String.Empty,
Password = expectedUser.Password ?? String.Empty
}; };
Role role = new() Role role = new()
@@ -223,7 +251,7 @@ public class UserService_Tests
{ {
var user = await _userService.GetUserByIdAsync(_user.Id); var user = await _userService.GetUserByIdAsync(_user.Id);
Assert.IsNotNull(user); Assert.IsNotNull(user);
Assert.IsTrue(user.Id == _user?.Id); Assert.AreEqual(user.Id, _user?.Id);
} }
else else
{ {
@@ -247,7 +275,7 @@ public class UserService_Tests
{ {
var user = await _userService.GetUserByGuidAsync(_user.Guid ?? String.Empty); var user = await _userService.GetUserByGuidAsync(_user.Guid ?? String.Empty);
Assert.IsNotNull(user); Assert.IsNotNull(user);
Assert.IsTrue(user.Guid == _user?.Guid); Assert.AreEqual(user.Guid, _user?.Guid);
} }
else else
{ {
@@ -261,6 +289,186 @@ public class UserService_Tests
} }
} }
[TestMethod]
public async Task UpdateUserAsync_Success()
{
try
{
UpdateUserRequestData data = new UpdateUserRequestData()
{
FirstName = "ChangedUserFirstName",
LastName = "ChangedUserLastName"
};
if (_userService != null)
{
Assert.IsNotNull(_user);
var user = await _userService.UpdateUserAsync(data, _user!);
Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user);
Assert.AreEqual(data.FirstName, user.FirstName);
Assert.AreEqual(data.LastName, user.LastName);
_user = user;
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateUserAsync_Exception()
{
try
{
UpdateUserRequestData data = new UpdateUserRequestData()
{
FirstName = "ChangedUserFirstName",
LastName = "ChangedUserLastName"
};
var exceptionUserService = TestUtils.CreateUserServiceException();
if (exceptionUserService != null)
{
Assert.IsNotNull(_user);
var user = await exceptionUserService.UpdateUserAsync(data, _user!);
Assert.Fail($"Expected exception instead of response: {user?.Guid}");
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(Exception));
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Success()
{
try
{
if (_userService != null)
{
Assert.IsNotNull(_user);
var oldPassword = _user.Password;
var user = await _userService.UpdateUserPasswordAsync(_user!, "this-is-a-new-password");
Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user);
Assert.AreNotEqual(user.Password, oldPassword);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Exception()
{
try
{
var exceptionUserService = TestUtils.CreateUserServiceException();
if (exceptionUserService != null)
{
Assert.IsNotNull(_user);
var user = await exceptionUserService.UpdateUserPasswordAsync(_user!, "this-is-a-new-password");
Assert.Fail($"Expected exception instead of response: {user?.Guid}");
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(Exception));
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_Success()
{
try
{
if (_userService != null)
{
Assert.IsNotNull(_user);
Role role = new()
{
Name = "NewRole",
IsNotEditable = false,
Guid = Guid.NewGuid().ToString()
};
var oldRole = _user.Role;
var user = await _userService.UpdateUserRoleAsync(_user!, role);
Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user);
Assert.AreNotEqual(user.Role?.Id, oldRole?.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 UpdateUserRoleAsync_Exception()
{
try
{
var exceptionUserService = TestUtils.CreateUserServiceException();
if (exceptionUserService != null)
{
Assert.IsNotNull(_user);
Role role = new()
{
Name = "NewRole",
IsNotEditable = false,
Guid = Guid.NewGuid().ToString()
};
var user = await exceptionUserService.UpdateUserRoleAsync(_user!, role);
Assert.Fail($"Expected exception instead of response: {user?.Guid}");
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(Exception));
}
}
[TestMethod] [TestMethod]
public async Task DeleteUser() public async Task DeleteUser()
{ {

View File

@@ -13,8 +13,9 @@ public static class ModelsInit
FirstName = "FirstName", FirstName = "FirstName",
LastName = "LastName", LastName = "LastName",
Email = "test-new@email.it", Email = "test-new@email.it",
PasswordHash = "PasswordHash", PasswordPepper = "PasswordPepper",
PasswordSalt = "PasswordSalt", PasswordSalt = "PasswordSalt",
PasswordIterations = 0,
Password = "Password", Password = "Password",
Role = CreateRole(), Role = CreateRole(),
IsTestUser = true IsTestUser = true

View File

@@ -102,12 +102,12 @@ public class CryptoUtils_Tests
} }
[TestMethod] [TestMethod]
public void GenerateSalt() public void GeneratePepper()
{ {
try try
{ {
var salt = CryptUtils.GenerateSalt(); var salt = CryptUtils.GeneratePepper();
Assert.IsTrue(!String.IsNullOrEmpty(salt)); Assert.IsFalse(String.IsNullOrEmpty(salt));
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -122,14 +122,14 @@ public class CryptoUtils_Tests
try try
{ {
var password = "P4ssw0rd@1!"; var password = "P4ssw0rd@1!";
var salt = CryptUtils.GenerateSalt(); var pepper = CryptUtils.GeneratePepper();
Assert.IsTrue(!String.IsNullOrEmpty(salt)); Assert.IsFalse(String.IsNullOrEmpty(pepper));
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>()); WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData"); AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
CryptUtils cryptoUtils = new CryptUtils(appSettings); var salt = appSettings?.EncryptionSettings?.Salt ?? String.Empty;
var encryptedPassword = cryptoUtils.GeneratePassword(password, salt, 0); var encryptedPassword = CryptUtils.GeneratePassword(password, salt, 0, pepper);
Assert.IsTrue(password != encryptedPassword); Assert.AreNotEqual(encryptedPassword, password);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -147,10 +147,7 @@ public class CryptoUtils_Tests
var salt = "Afi7PQYgEL2sPbNyVzduvg=="; var salt = "Afi7PQYgEL2sPbNyVzduvg==";
var hashedPassword = "2lMeySZ9ciH1KtSg1Z7oSJRmJEjHMeDvdaNRcJcGutM="; var hashedPassword = "2lMeySZ9ciH1KtSg1Z7oSJRmJEjHMeDvdaNRcJcGutM=";
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>()); var verified = CryptUtils.VerifyPassword(hashedPassword, password, salt, 0);
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
CryptUtils cryptoUtils = new CryptUtils(appSettings);
var verified = cryptoUtils.VerifyPassword(password, salt, 0, hashedPassword);
Assert.IsTrue(verified); Assert.IsTrue(verified);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -49,7 +49,7 @@ public class FileUtils_Tests
try try
{ {
PermissionsFile? permissionsFile = FileUtils.ConvertFileToObject<PermissionsFile>(System.AppDomain.CurrentDomain.BaseDirectory + "Config/permissions.json"); PermissionsFile? permissionsFile = FileUtils.ConvertFileToObject<PermissionsFile>(System.AppDomain.CurrentDomain.BaseDirectory + "Config/permissions.json");
Assert.IsTrue(permissionsFile != null); Assert.IsNotNull(permissionsFile);
} }
catch (Exception exception) catch (Exception exception)
{ {

View File

@@ -22,7 +22,7 @@ public class JwtTokenUtils_Tests
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData"); AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings); JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings);
var jwt = jwtUtils.GenerateToken(_guid); var jwt = jwtUtils.GenerateToken(_guid);
Assert.IsTrue(!String.IsNullOrEmpty(jwt)); Assert.IsFalse(String.IsNullOrEmpty(jwt));
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -41,7 +41,7 @@ public class JwtTokenUtils_Tests
JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings); JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings);
var jwt = jwtUtils.GenerateToken(_guid); var jwt = jwtUtils.GenerateToken(_guid);
var guid = jwtUtils.ValidateToken($"Bearer {jwt}"); var guid = jwtUtils.ValidateToken($"Bearer {jwt}");
Assert.IsTrue(_guid == guid); Assert.AreEqual(_guid, guid);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -0,0 +1,62 @@
using BasicDotnetTemplate.MainProject.Utils;
using BasicDotnetTemplate.MainProject.Models.Common;
using BasicDotnetTemplate.MainProject.Enum;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class PasswordUtils_Test
{
[TestMethod]
public void PasswordValidation_Valid()
{
try
{
List<string> errors = PasswordUtils.ValidatePassword("#aBcDeFgHi01245#");
Assert.IsTrue(errors == null || errors.Count == 0);
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
[TestMethod]
public void PasswordValidation_Invalid()
{
try
{
List<string> errors = PasswordUtils.ValidatePassword("aAa1#");
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_LENGTH));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_UPPER));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_NUMBER));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_SPECIAL));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.IDENTICAL_CHARS));
Assert.IsFalse(errors.Contains(PasswordValidationEnum.MIN_LOWER));
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
[TestMethod]
public void PasswordValidation_ToLowerInvalid()
{
try
{
List<string> errors = PasswordUtils.ValidatePassword("AaBC0*TGH1#");
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_LOWER));
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
}

View File

@@ -92,7 +92,7 @@ public class ProgramUtils_Tests
AppSettings appSettings = new AppSettings(); AppSettings appSettings = new AppSettings();
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings); OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
Assert.IsTrue(realOpenApiInfo != null); Assert.IsNotNull(realOpenApiInfo);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -118,10 +118,10 @@ public class ProgramUtils_Tests
OpenApiSettings = null OpenApiSettings = null
}; };
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings); OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
Assert.IsTrue(realOpenApiInfo != null); Assert.IsNotNull(realOpenApiInfo);
Assert.IsTrue(realOpenApiInfo.Title == appSettings.Settings.Name); Assert.AreEqual(appSettings.Settings.Name, realOpenApiInfo.Title);
Assert.IsTrue(realOpenApiInfo.Description == appSettings.Settings.Description); Assert.AreEqual(appSettings.Settings.Description, realOpenApiInfo.Description);
Assert.IsTrue(realOpenApiInfo.Version == appSettings.Settings.Version); Assert.AreEqual(appSettings.Settings.Version, realOpenApiInfo.Version);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -151,11 +151,11 @@ public class ProgramUtils_Tests
} }
}; };
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings); OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
Assert.IsTrue(realOpenApiInfo != null); Assert.IsNotNull(realOpenApiInfo);
Assert.IsTrue(realOpenApiInfo.Title == appSettings.Settings.Name); Assert.AreEqual(appSettings.Settings.Name, realOpenApiInfo.Title);
Assert.IsTrue(realOpenApiInfo.Description == appSettings.Settings.Description); Assert.AreEqual(appSettings.Settings.Description, realOpenApiInfo.Description);
Assert.IsTrue(realOpenApiInfo.Version == appSettings.Settings.Version); Assert.AreEqual(appSettings.Settings.Version, realOpenApiInfo.Version);
Assert.IsTrue(realOpenApiInfo.TermsOfService == null); Assert.IsNull(realOpenApiInfo.TermsOfService);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -6,6 +6,7 @@ using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Response; using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth; using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using BasicDotnetTemplate.MainProject.Services; using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Core.Filters;
namespace BasicDotnetTemplate.MainProject.Controllers namespace BasicDotnetTemplate.MainProject.Controllers
{ {
@@ -21,30 +22,17 @@ namespace BasicDotnetTemplate.MainProject.Controllers
this._authService = authService; this._authService = authService;
} }
[ModelStateValidationHandledByFilterAttribute]
[HttpPost("authenticate")] [HttpPost("authenticate")]
[ProducesResponseType<AuthenticateResponse>(StatusCodes.Status200OK)] [ProducesResponseType<AuthenticateResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest request) public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest request) //NOSONAR
{ {
try try
{ {
if (!ModelState.IsValid) var data = await this._authService.AuthenticateAsync(request!.Data!);
{
return BadRequest(_requestNotWellFormed);
}
if (
request == null ||
request.Data == null ||
String.IsNullOrEmpty(request.Data.Email) ||
String.IsNullOrEmpty(request.Data.Password)
)
{
return BadRequest(_requestNotWellFormed);
}
var data = await this._authService.AuthenticateAsync(request.Data);
if (data == null) if (data == null)
{ {
@@ -55,12 +43,7 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
var message = this._somethingWentWrong; return InternalServerError(exception);
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
} }
} }

View File

@@ -12,7 +12,6 @@ namespace BasicDotnetTemplate.MainProject.Controllers
protected readonly IMapper? _mapper; protected readonly IMapper? _mapper;
protected readonly IConfiguration _configuration; protected readonly IConfiguration _configuration;
protected readonly AppSettings _appSettings; protected readonly AppSettings _appSettings;
protected readonly string _requestNotWellFormed = "Request is not well formed";
protected readonly string _somethingWentWrong = "Something went wrong"; protected readonly string _somethingWentWrong = "Something went wrong";
protected BaseController( protected BaseController(
@@ -67,9 +66,13 @@ namespace BasicDotnetTemplate.MainProject.Controllers
return StatusCode((int)HttpStatusCode.BadRequest, CreateResponse(HttpStatusCode.BadRequest, message, data)); return StatusCode((int)HttpStatusCode.BadRequest, CreateResponse(HttpStatusCode.BadRequest, message, data));
} }
protected IActionResult InternalServerError(string message) protected IActionResult InternalServerError(Exception exception)
{ {
message = String.IsNullOrEmpty(message) ? "Internal server error" : message; var message = this._somethingWentWrong;
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return StatusCode((int)HttpStatusCode.InternalServerError, CreateResponse(HttpStatusCode.InternalServerError, message, new object())); return StatusCode((int)HttpStatusCode.InternalServerError, CreateResponse(HttpStatusCode.InternalServerError, message, new object()));
} }

View File

@@ -7,6 +7,7 @@ using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Role; using BasicDotnetTemplate.MainProject.Models.Api.Response.Role;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role; using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using BasicDotnetTemplate.MainProject.Core.Filters;
namespace BasicDotnetTemplate.MainProject.Controllers namespace BasicDotnetTemplate.MainProject.Controllers
{ {
@@ -23,6 +24,7 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
[JwtAuthorization()] [JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpGet("get/{guid}")] [HttpGet("get/{guid}")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)] [ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
@@ -32,15 +34,6 @@ namespace BasicDotnetTemplate.MainProject.Controllers
{ {
try try
{ {
if (!ModelState.IsValid)
{
return BadRequest(_requestNotWellFormed);
}
if (String.IsNullOrEmpty(guid))
{
return BadRequest(_requestNotWellFormed);
}
var role = await this._roleService.GetRoleByGuidAsync(guid); var role = await this._roleService.GetRoleByGuidAsync(guid);
if (role == null || String.IsNullOrEmpty(role.Guid)) if (role == null || String.IsNullOrEmpty(role.Guid))
@@ -54,39 +47,24 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
var message = this._somethingWentWrong; return InternalServerError(exception);
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
} }
} }
[JwtAuthorization()] [JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPost("create")] [HttpPost("create")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status201Created)] [ProducesResponseType<GetRoleResponse>(StatusCodes.Status201Created)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> CreateRoleAsync([FromBody] CreateRoleRequest request) public async Task<IActionResult> CreateRoleAsync([FromBody] CreateRoleRequest request) //NOSONAR
{ {
try try
{ {
if (!ModelState.IsValid) if (await this._roleService.CheckIfNameIsValid(request!.Data!.Name))
{ {
return BadRequest(_requestNotWellFormed); var role = await this._roleService.CreateRoleAsync(request!.Data);
}
if (request == null || request.Data == null || String.IsNullOrEmpty(request.Data.Name)
)
{
return BadRequest(_requestNotWellFormed);
}
if (await this._roleService.CheckIfNameIsValid(request.Data.Name))
{
var role = await this._roleService.CreateRoleAsync(request.Data);
if (role == null || String.IsNullOrEmpty(role.Guid)) if (role == null || String.IsNullOrEmpty(role.Guid))
{ {
@@ -105,40 +83,21 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
var message = this._somethingWentWrong; return InternalServerError(exception);
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
} }
} }
[JwtAuthorization()] [JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}")] [HttpPut("update/{guid}")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status201Created)] [ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateRoleAsync([FromBody] CreateRoleRequest request, string guid) public async Task<IActionResult> UpdateRoleAsync([FromBody] CreateRoleRequest request, string guid) //NOSONAR
{ {
try try
{ {
if (!ModelState.IsValid)
{
return BadRequest(_requestNotWellFormed);
}
if (
request == null ||
request.Data == null ||
String.IsNullOrEmpty(request.Data.Name) ||
String.IsNullOrEmpty(guid)
)
{
return BadRequest(_requestNotWellFormed);
}
var role = await this._roleService.GetRoleByGuidAsync(guid); var role = await this._roleService.GetRoleByGuidAsync(guid);
if (role == null || String.IsNullOrEmpty(role.Guid)) if (role == null || String.IsNullOrEmpty(role.Guid))
@@ -152,8 +111,8 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
if ( if (
await this._roleService.CheckIfNameIsValid(request.Data.Name) || await this._roleService.CheckIfNameIsValid(request!.Data!.Name) ||
await this._roleService.CheckIfNameIsValid(request.Data.Name, guid) await this._roleService.CheckIfNameIsValid(request!.Data!.Name, guid)
) )
{ {
role = await this._roleService.UpdateRoleAsync(request.Data, role); role = await this._roleService.UpdateRoleAsync(request.Data, role);
@@ -170,17 +129,13 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
var message = this._somethingWentWrong; return InternalServerError(exception);
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
} }
} }
[JwtAuthorization()] [JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpDelete("{guid}")] [HttpDelete("{guid}")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)] [ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
@@ -190,15 +145,6 @@ namespace BasicDotnetTemplate.MainProject.Controllers
{ {
try try
{ {
if (!ModelState.IsValid)
{
return BadRequest(_requestNotWellFormed);
}
if (String.IsNullOrEmpty(guid))
{
return BadRequest(_requestNotWellFormed);
}
var role = await this._roleService.GetRoleByGuidAsync(guid); var role = await this._roleService.GetRoleByGuidAsync(guid);
if (role == null || String.IsNullOrEmpty(role.Guid)) if (role == null || String.IsNullOrEmpty(role.Guid))
@@ -212,12 +158,7 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
var message = this._somethingWentWrong; return InternalServerError(exception);
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
} }
} }

View File

@@ -7,6 +7,7 @@ using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Response.User; using BasicDotnetTemplate.MainProject.Models.Api.Response.User;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User; using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Core.Filters;
namespace BasicDotnetTemplate.MainProject.Controllers namespace BasicDotnetTemplate.MainProject.Controllers
{ {
@@ -25,7 +26,9 @@ namespace BasicDotnetTemplate.MainProject.Controllers
this._roleService = roleService; this._roleService = roleService;
} }
[JwtAuthorization()] [JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpGet("get/{guid}")] [HttpGet("get/{guid}")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)] [ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
@@ -35,15 +38,6 @@ namespace BasicDotnetTemplate.MainProject.Controllers
{ {
try try
{ {
if (!ModelState.IsValid)
{
return BadRequest(_requestNotWellFormed);
}
if (String.IsNullOrEmpty(guid))
{
return BadRequest(_requestNotWellFormed);
}
var user = await this._userService.GetUserByGuidAsync(guid); var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null || String.IsNullOrEmpty(user.Guid)) if (user == null || String.IsNullOrEmpty(user.Guid))
@@ -57,49 +51,30 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
var message = this._somethingWentWrong; return InternalServerError(exception);
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
} }
} }
[JwtAuthorization()] [JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPost("create")] [HttpPost("create")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status201Created)] [ProducesResponseType<GetUserResponse>(StatusCodes.Status201Created)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> CreateUserAsync([FromBody] CreateUserRequest request) public async Task<IActionResult> CreateUserAsync([FromBody] CreateUserRequest request) //NOSONAR
{ {
try try
{ {
if (!ModelState.IsValid) if (await this._userService.CheckIfEmailIsValid(request!.Data!.Email))
{ {
return BadRequest(_requestNotWellFormed); var role = await this._roleService.GetRoleForUser(request!.Data!.RoleGuid);
}
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) if (role == null)
{ {
return BadRequest("Role not found"); return BadRequest("Role not found");
} }
var user = await this._userService.CreateUserAsync(request.Data, role); var user = await this._userService.CreateUserAsync(request!.Data, role);
if (user == null || String.IsNullOrEmpty(user.Guid)) if (user == null || String.IsNullOrEmpty(user.Guid))
{ {
@@ -118,17 +93,135 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
catch (Exception exception) catch (Exception exception)
{ {
var message = this._somethingWentWrong; return InternalServerError(exception);
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
} }
} }
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUserAsync([FromBody] UpdateUserRequest request, string guid) //NOSONAR
{
try
{
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null)
{
return NotFound();
}
user = await this._userService.UpdateUserAsync(request!.Data!, user);
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}/password")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUserPasswordAsync(string guid, string newPassword)
{
try
{
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null)
{
return NotFound();
}
user = await this._userService.UpdateUserPasswordAsync(user, newPassword);
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}/role")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUserRoleAsync(string guid, string roleGuid)
{
try
{
var role = await this._roleService.GetRoleByGuidAsync(roleGuid);
if (role == null)
{
return BadRequest("Role not found");
}
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null)
{
return NotFound();
}
user = await this._userService.UpdateUserRoleAsync(user, role);
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpDelete("{guid}")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DeleteUserByGuidAsync(string guid)
{
try
{
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null || String.IsNullOrEmpty(user.Guid))
{
return NotFound();
}
await this._userService.DeleteUserAsync(user);
return Success(String.Empty);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
} }
} }

View File

@@ -11,9 +11,6 @@ namespace BasicDotnetTemplate.MainProject.Controllers
) : base(configuration) { } ) : base(configuration) { }
[HttpGet("get")] [HttpGet("get")]
public IActionResult GetVersion() public IActionResult GetVersion() => Success(String.Empty, _appSettings?.Settings?.Version);
{
return Success(String.Empty, _appSettings?.Settings?.Version);
}
} }
} }

View File

@@ -0,0 +1,12 @@
using System;
namespace BasicDotnetTemplate.MainProject.Core.Attributes
{
/// <summary>
/// Indicates that ModelState validation is handled automatically by an Action Filter.
/// Used to suppress SonarCloud warnings about missing ModelState.IsValid checks.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ModelStateValidationHandledByFilterAttribute : Attribute
{ }
}

View File

@@ -0,0 +1,43 @@
using BasicDotnetTemplate.MainProject.Models.Api.Base;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;
namespace BasicDotnetTemplate.MainProject.Core.Filters
{
public class ValidationActionFilter : IAsyncActionFilter
{
private readonly string _requestNotWellFormedMessage = "Request is not well formed";
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(new ValidationError
{
Message = _requestNotWellFormedMessage,
Errors = context.ModelState.Where(m =>
m.Value != null && m.Value.Errors.Any())
.ToDictionary(
m => m.Key,
m => m.Value!.Errors.Select(e => e.ErrorMessage).ToList()
)
});
return;
}
var requestBody = context.ActionArguments.Values.FirstOrDefault(arg => arg != null && !arg.GetType().IsPrimitive && arg is not string);
if (requestBody == null)
{
context.Result = new BadRequestObjectResult(new ValidationError
{
Message = _requestNotWellFormedMessage
});
return;
}
await next();
}
}
}

View File

@@ -0,0 +1,10 @@
namespace BasicDotnetTemplate.MainProject.Enum;
public static class PasswordValidationEnum
{
public const string MIN_LENGTH = "Password must be at least 8 characters long";
public const string MIN_UPPER = "Password must have at least 2 uppercase letters";
public const string MIN_LOWER = "Password must have at least 2 lowercase letters";
public const string MIN_NUMBER = "Password must be at least 2 numbers";
public const string MIN_SPECIAL = "Password must be at least 2 special characters";
public const string IDENTICAL_CHARS = "Password cannot have 3 or more consecutive identical characters";
}

View File

@@ -15,36 +15,36 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.AspNetCore" Version="2.3.0" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.16" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.17" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.16" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="9.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.5"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.6" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.9.2" /> <PackageReference Include="Microsoft.Identity.Web" Version="3.9.3" />
<PackageReference Include="MongoDB.Driver" Version="3.4.0" /> <PackageReference Include="MongoDB.Driver" Version="3.4.0" />
<PackageReference Include="MongoDB.EntityFrameworkCore" Version="9.0.0" /> <PackageReference Include="MongoDB.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.4.0" /> <PackageReference Include="NLog" Version="5.5.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" /> <PackageReference Include="NLog.Extensions.Logging" Version="5.5.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.2" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="8.1.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.3" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters.Abstractions" Version="8.0.3" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters.Abstractions" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="8.1.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="8.1.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="8.1.2" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.2" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="9.0.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,4 +1,4 @@
using System; using System;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,4 +1,4 @@
using System; using System;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -1,4 +1,4 @@
using System; using System;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable

View File

@@ -0,0 +1,542 @@
// <auto-generated />
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("20250617183212_AlterTableUsersForPasswordEncryption")]
partial class AlterTableUsersForPasswordEncryption
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Name" }, "IX_IsDeleted_Name");
b.ToTable("PermissionOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionSystems");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionModuleId")
.HasColumnType("int");
b.Property<int>("PermissionSystemId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionModuleId");
b.HasIndex("PermissionSystemId");
b.ToTable("PermissionSystemModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionOperationId")
.HasColumnType("int");
b.Property<int>("PermissionSystemModuleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionOperationId");
b.HasIndex("PermissionSystemModuleId");
b.HasIndex(new[] { "IsDeleted", "Enabled", "Guid" }, "IX_IsDeleted_Enabled_Guid");
b.ToTable("PermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsNotEditable")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("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.RolePermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("Active")
.HasColumnType("bit");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionSystemModuleOperationId")
.HasColumnType("int");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionSystemModuleOperationId");
b.HasIndex("RoleId");
b.ToTable("RolePermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.HasColumnType("nvarchar(max)");
b.Property<int>("PasswordIterations")
.HasColumnType("int");
b.Property<string>("PasswordPepper")
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("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.PermissionSystemModule", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", "PermissionModule")
.WithMany()
.HasForeignKey("PermissionModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", "PermissionSystem")
.WithMany()
.HasForeignKey("PermissionSystemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionModule");
b.Navigation("PermissionSystem");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", "PermissionOperation")
.WithMany()
.HasForeignKey("PermissionOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", "PermissionSystemModule")
.WithMany()
.HasForeignKey("PermissionSystemModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionOperation");
b.Navigation("PermissionSystemModule");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.RolePermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", "PermissionSystemModuleOperation")
.WithMany()
.HasForeignKey("PermissionSystemModuleOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionSystemModuleOperation");
b.Navigation("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId");
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,109 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AlterTableUsersForPasswordEncryption : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users");
migrationBuilder.DropColumn(
name: "PasswordHash",
table: "Users");
migrationBuilder.AlterColumn<int>(
name: "RoleId",
table: "Users",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<string>(
name: "Password",
table: "Users",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AddColumn<int>(
name: "PasswordIterations",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "PasswordPepper",
table: "Users",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.AddForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users",
column: "RoleId",
principalTable: "Roles",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users");
migrationBuilder.DropColumn(
name: "PasswordIterations",
table: "Users");
migrationBuilder.DropColumn(
name: "PasswordPepper",
table: "Users");
migrationBuilder.AlterColumn<int>(
name: "RoleId",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Password",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AddColumn<string>(
name: "PasswordHash",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users",
column: "RoleId",
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@@ -17,7 +17,7 @@ namespace MainProject.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("ProductVersion", "9.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128); .HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
@@ -435,18 +435,19 @@ namespace MainProject.Migrations
.HasColumnType("nvarchar(200)"); .HasColumnType("nvarchar(200)");
b.Property<string>("Password") b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash") b.Property<int>("PasswordIterations")
.IsRequired() .HasColumnType("int");
b.Property<string>("PasswordPepper")
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt") b.Property<string>("PasswordSalt")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.Property<int>("RoleId") b.Property<int?>("RoleId")
.HasColumnType("int"); .HasColumnType("int");
b.Property<DateTime?>("UpdateTime") b.Property<DateTime?>("UpdateTime")
@@ -528,9 +529,7 @@ namespace MainProject.Migrations
{ {
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role") b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany() .WithMany()
.HasForeignKey("RoleId") .HasForeignKey("RoleId");
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role"); b.Navigation("Role");
}); });

View File

@@ -0,0 +1,9 @@
using System;
namespace BasicDotnetTemplate.MainProject.Models.Api.Base;
public class ValidationError
{
public string? Message { get; set; }
public Dictionary<string, List<string>>? Errors { get; set; }
}

View File

@@ -9,7 +9,7 @@ public class UserRole
public string? Name { get; set; } public string? Name { get; set; }
#nullable disable #nullable disable
public UserRole() {} public UserRole() { }
public UserRole(DatabaseSqlServer.Role role) public UserRole(DatabaseSqlServer.Role role)
{ {

View File

@@ -19,7 +19,7 @@ public class AuthenticatedUser
FirstName = user.FirstName; FirstName = user.FirstName;
LastName = user.LastName; LastName = user.LastName;
Email = user.Email; Email = user.Email;
Role = new UserRole(); Role = new UserRole(user.Role!);
} }
} }

View File

@@ -1,11 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Auth; namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
public class AuthenticateRequestData public class AuthenticateRequestData
{ {
#nullable enable [Required(ErrorMessage = "Email is required")]
public string? Email { get; set; } public required string Email { get; set; }
public string? Password { get; set; } [Required(ErrorMessage = "Password is required")]
#nullable disable public required string Password { get; set; }
} }

View File

@@ -1,8 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Role; namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Role;
public class CreateRoleRequestData public class CreateRoleRequestData
{ {
public string Name { get; set; } = String.Empty; [Required(ErrorMessage = "Name is required")]
public required string Name { get; set; }
public required bool IsNotEditable { get; set; } public required bool IsNotEditable { get; set; }
} }

View File

@@ -1,11 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.User; namespace BasicDotnetTemplate.MainProject.Models.Api.Data.User;
public class CreateUserRequestData public class CreateUserRequestData : UpdateUserRequestData
{ {
public string FirstName { get; set; } = String.Empty; [Required(ErrorMessage = "Email is required")]
public string LastName { get; set; } = String.Empty; [StringLength(200, ErrorMessage = "Email's maxLength: 200")]
public string Email { get; set; } = String.Empty; public required string Email { get; set; }
public string Password { get; set; } = String.Empty;
[Required(ErrorMessage = "Password is required")]
public required string Password { get; set; }
public string? RoleGuid { get; set; } public string? RoleGuid { get; set; }
} }

View File

@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.User;
public class UpdateUserRequestData
{
[Required(ErrorMessage = "FirstName is required")]
[StringLength(200, ErrorMessage = "FirstName's maxLength: 200")]
public required string FirstName { get; set; }
[Required(ErrorMessage = "LastName is required")]
[StringLength(200, ErrorMessage = "LastName's maxLength: 200")]
public required string LastName { get; set; }
}

View File

@@ -1,12 +1,12 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth; using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.Auth; namespace BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
public class AuthenticateRequest public class AuthenticateRequest
{ {
#nullable enable [Required(ErrorMessage = "Data is required")]
public AuthenticateRequestData? Data { get; set; } public required AuthenticateRequestData Data { get; set; }
#nullable disable
} }

View File

@@ -1,10 +1,10 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Role; using BasicDotnetTemplate.MainProject.Models.Api.Data.Role;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.Role; namespace BasicDotnetTemplate.MainProject.Models.Api.Request.Role;
public class CreateRoleRequest public class CreateRoleRequest
{ {
#nullable enable [Required(ErrorMessage = "Data is required")]
public CreateRoleRequestData? Data { get; set; } public required CreateRoleRequestData? Data { get; set; }
#nullable disable
} }

View File

@@ -1,12 +1,12 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.User; using BasicDotnetTemplate.MainProject.Models.Api.Data.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.User; namespace BasicDotnetTemplate.MainProject.Models.Api.Request.User;
public class CreateUserRequest public class CreateUserRequest
{ {
#nullable enable [Required(ErrorMessage = "Data is required")]
public CreateUserRequestData? Data { get; set; } public required CreateUserRequestData Data { get; set; }
#nullable disable
} }

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.User;
public class UpdateUserRequest
{
[Required(ErrorMessage = "Data is required")]
public required UpdateUserRequestData Data { get; set; }
}

View File

@@ -4,6 +4,6 @@ public class OperationInfo
{ {
#nullable enable #nullable enable
public string? Operation { get; set; } public string? Operation { get; set; }
public List<string>? Roles {get; set; } public List<string>? Roles { get; set; }
#nullable disable #nullable disable
} }

View File

@@ -4,6 +4,6 @@ public class PermissionInfo
{ {
#nullable enable #nullable enable
public string? System { get; set; } public string? System { get; set; }
public List<RolePermissionModuleOperation>? RolePermissionModuleOperations {get; set; } public List<RolePermissionModuleOperation>? RolePermissionModuleOperations { get; set; }
#nullable disable #nullable disable
} }

View File

@@ -13,7 +13,10 @@ public class User : Base
[MaxLength(200)] [MaxLength(200)]
public required string Email { get; set; } public required string Email { get; set; }
public required string PasswordSalt { get; set; } public required string PasswordSalt { get; set; }
public required string PasswordHash { get; set; } #nullable enable
public string? PasswordPepper { get; set; }
#nullable disable
public required int PasswordIterations { get; set; }
public required Role Role { get; set; } public required Role Role { get; set; }
public required bool IsTestUser { get; set; } public required bool IsTestUser { get; set; }

View File

@@ -3,7 +3,8 @@ namespace BasicDotnetTemplate.MainProject.Models.Settings;
public class EncryptionSettings public class EncryptionSettings
{ {
#nullable enable #nullable enable
public string? SaltKey { get; set; }
public string? Salt { get; set; } public string? Salt { get; set; }
public string? Pepper { get; set; } public int? Iterations { get; set; }
#nullable disable #nullable disable
} }

View File

@@ -1,4 +1,4 @@
using NLog; using NLog;
using BasicDotnetTemplate.MainProject.Models.Settings; using BasicDotnetTemplate.MainProject.Models.Settings;
using System.Reflection; using System.Reflection;
using BasicDotnetTemplate.MainProject.Utils; using BasicDotnetTemplate.MainProject.Utils;

View File

@@ -4,6 +4,7 @@ using BasicDotnetTemplate.MainProject.Core.Database;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Exceptions; using BasicDotnetTemplate.MainProject.Models.Api.Common.Exceptions;
using BasicDotnetTemplate.MainProject.Models.Api.Data.User; using BasicDotnetTemplate.MainProject.Models.Api.Data.User;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace BasicDotnetTemplate.MainProject.Services; namespace BasicDotnetTemplate.MainProject.Services;
@@ -15,7 +16,10 @@ public interface IUserService
Task<User?> GetUserByUsernameAndPassword(string email, string password); Task<User?> GetUserByUsernameAndPassword(string email, string password);
Task<bool> CheckIfEmailIsValid(string email, string? guid = ""); Task<bool> CheckIfEmailIsValid(string email, string? guid = "");
Task<User?> CreateUserAsync(CreateUserRequestData data, Role role); Task<User?> CreateUserAsync(CreateUserRequestData data, Role role);
Task<User?> UpdateUserAsync(UpdateUserRequestData data, User user);
Task<bool?> DeleteUserAsync(User user); Task<bool?> DeleteUserAsync(User user);
Task<User?> UpdateUserPasswordAsync(User user, string newPassword);
Task<User?> UpdateUserRoleAsync(User user, Role newRole);
} }
public class UserService : BaseService, IUserService public class UserService : BaseService, IUserService
@@ -42,6 +46,9 @@ public class UserService : BaseService, IUserService
private User CreateUserData(CreateUserRequestData data, Role role) private User CreateUserData(CreateUserRequestData data, Role role)
{ {
var salt = _appSettings.EncryptionSettings?.Salt ?? String.Empty;
var pepper = CryptUtils.GeneratePepper();
var iterations = _appSettings.EncryptionSettings?.Iterations ?? 10;
User user = new() User user = new()
{ {
CreationTime = DateTime.UtcNow, CreationTime = DateTime.UtcNow,
@@ -51,9 +58,10 @@ public class UserService : BaseService, IUserService
FirstName = data.FirstName, FirstName = data.FirstName,
LastName = data.LastName, LastName = data.LastName,
Email = data.Email, Email = data.Email,
PasswordSalt = "", PasswordSalt = salt,
PasswordHash = "", PasswordPepper = pepper,
Password = "", PasswordIterations = iterations,
Password = CryptUtils.GeneratePassword(data.Password, salt, iterations, pepper),
Role = role, Role = role,
IsTestUser = false IsTestUser = false
}; };
@@ -77,7 +85,9 @@ public class UserService : BaseService, IUserService
User? user = await this.GetUserByEmailQueryable(email).FirstOrDefaultAsync(); User? user = await this.GetUserByEmailQueryable(email).FirstOrDefaultAsync();
if (user != null) if (user != null)
{ {
var encryptedPassword = user.PasswordHash; var valid = CryptUtils.VerifyPassword(user.Password, password, user.PasswordSalt, user.PasswordIterations, user.PasswordPepper);
if (!valid)
user = null;
} }
return user; return user;
@@ -127,6 +137,31 @@ public class UserService : BaseService, IUserService
return user; return user;
} }
public async Task<User?> UpdateUserAsync(UpdateUserRequestData data, User user)
{
using var transaction = await _sqlServerContext.Database.BeginTransactionAsync();
try
{
user.FirstName = data.FirstName ?? user.FirstName;
user.LastName = data.LastName ?? user.LastName;
user.UpdateTime = DateTime.UtcNow;
user.UpdateUserId = this.GetCurrentUserId();
_sqlServerContext.Users.Update(user);
await _sqlServerContext.SaveChangesAsync();
await transaction.CommitAsync();
}
catch (Exception exception)
{
Logger.Error(exception, $"[UserService][UpdateUserAsync] | {transaction.TransactionId}");
await transaction.RollbackAsync();
throw new UpdateException($"An error occurred while updating the user for transaction ID {transaction.TransactionId}.", exception);
}
return user;
}
public async Task<bool?> DeleteUserAsync(User user) public async Task<bool?> DeleteUserAsync(User user)
{ {
bool? deleted = false; bool? deleted = false;
@@ -144,6 +179,59 @@ public class UserService : BaseService, IUserService
return deleted; return deleted;
} }
public async Task<User?> UpdateUserPasswordAsync(User user, string newPassword)
{
using var transaction = await _sqlServerContext.Database.BeginTransactionAsync();
try
{
var salt = _appSettings.EncryptionSettings?.Salt ?? String.Empty;
var pepper = CryptUtils.GeneratePepper();
var iterations = _appSettings.EncryptionSettings?.Iterations ?? 10;
user.PasswordSalt = salt;
user.PasswordPepper = pepper;
user.PasswordIterations = iterations;
user.Password = CryptUtils.GeneratePassword(newPassword, salt, iterations, pepper);
user.UpdateTime = DateTime.UtcNow;
user.UpdateUserId = this.GetCurrentUserId();
_sqlServerContext.Users.Update(user);
await _sqlServerContext.SaveChangesAsync();
await transaction.CommitAsync();
}
catch (Exception exception)
{
Logger.Error(exception, $"[UserService][UpdateUserPasswordAsync] | {transaction.TransactionId}");
await transaction.RollbackAsync();
throw new UpdateException($"An error occurred while updating the user for transaction ID {transaction.TransactionId}.", exception);
}
return user;
}
public async Task<User?> UpdateUserRoleAsync(User user, Role newRole)
{
using var transaction = await _sqlServerContext.Database.BeginTransactionAsync();
try
{
user.Role = newRole;
user.UpdateTime = DateTime.UtcNow;
user.UpdateUserId = this.GetCurrentUserId();
_sqlServerContext.Users.Update(user);
await _sqlServerContext.SaveChangesAsync();
await transaction.CommitAsync();
}
catch (Exception exception)
{
Logger.Error(exception, $"[UserService][UpdateUserRoleAsync] | {transaction.TransactionId}");
await transaction.RollbackAsync();
throw new UpdateException($"An error occurred while updating the user for transaction ID {transaction.TransactionId}.", exception);
}
return user;
}
} }

View File

@@ -4,24 +4,17 @@ using System.Text;
using BasicDotnetTemplate.MainProject.Models.Settings; using BasicDotnetTemplate.MainProject.Models.Settings;
namespace BasicDotnetTemplate.MainProject.Utils; namespace BasicDotnetTemplate.MainProject.Utils;
public class CryptUtils public class CryptUtils(AppSettings appSettings)
{ {
private readonly string _secretKey; private readonly string _saltKey = appSettings.EncryptionSettings?.SaltKey ?? String.Empty;
private readonly string _pepper;
private const int _M = 16; private const int _M = 16;
private const int _N = 32; private const int _N = 32;
public CryptUtils(AppSettings appSettings)
{
_secretKey = appSettings.EncryptionSettings?.Salt ?? String.Empty;
_pepper = appSettings.EncryptionSettings?.Pepper ?? String.Empty;
}
public string Decrypt(string encryptedData) public string Decrypt(string encryptedData)
{ {
var decrypted = String.Empty; var decrypted = String.Empty;
if (String.IsNullOrEmpty(this._secretKey) || this._secretKey.Length < _M) if (String.IsNullOrEmpty(this._saltKey) || this._saltKey.Length < _M)
{ {
throw new ArgumentException("Unable to proceed with decryption due to invalid settings"); throw new ArgumentException("Unable to proceed with decryption due to invalid settings");
} }
@@ -35,7 +28,7 @@ public class CryptUtils
using (var aes = Aes.Create()) using (var aes = Aes.Create())
{ {
aes.Key = Encoding.UTF8.GetBytes(this._secretKey); aes.Key = Encoding.UTF8.GetBytes(this._saltKey);
aes.IV = Encoding.UTF8.GetBytes(iv); aes.IV = Encoding.UTF8.GetBytes(iv);
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
@@ -57,21 +50,21 @@ public class CryptUtils
return decrypted; return decrypted;
} }
public static string GenerateSalt() public static string GeneratePepper()
{ {
using var rng = RandomNumberGenerator.Create(); using var rng = RandomNumberGenerator.Create();
var byteSalt = new byte[16]; var bytePepper = new byte[16];
rng.GetBytes(byteSalt); rng.GetBytes(bytePepper);
var salt = Convert.ToBase64String(byteSalt); var pepper = Convert.ToBase64String(bytePepper);
return salt; return pepper;
} }
public string GeneratePassword(string password, string salt, int iteration) public static string GeneratePassword(string password, string salt, int iterations, string? pepper = "")
{ {
string hashedPassword = password; string hashedPassword = password;
for(var i = 0; i <= iteration; i++) for (var i = 0; i <= iterations; i++)
{ {
var passwordSaltPepper = $"{hashedPassword}{salt}{this._pepper}"; var passwordSaltPepper = $"{hashedPassword}{salt}{pepper}";
var byteValue = Encoding.UTF8.GetBytes(passwordSaltPepper); var byteValue = Encoding.UTF8.GetBytes(passwordSaltPepper);
var byteHash = SHA256.HashData(byteValue); var byteHash = SHA256.HashData(byteValue);
hashedPassword = Convert.ToBase64String(byteHash); hashedPassword = Convert.ToBase64String(byteHash);
@@ -80,9 +73,9 @@ public class CryptUtils
return hashedPassword; return hashedPassword;
} }
public bool VerifyPassword(string password, string salt, int iteration, string userPassword) public static bool VerifyPassword(string userPassword, string password, string salt, int iterations, string? pepper = "")
{ {
string hashedPassword = this.GeneratePassword(password, salt, iteration); string hashedPassword = GeneratePassword(password, salt, iterations, pepper);
return hashedPassword.Equals(userPassword, StringComparison.OrdinalIgnoreCase); return hashedPassword.Equals(userPassword, StringComparison.OrdinalIgnoreCase);
} }

View File

@@ -0,0 +1,64 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BasicDotnetTemplate.MainProject.Enum;
using BasicDotnetTemplate.MainProject.Models.Settings;
namespace BasicDotnetTemplate.MainProject.Utils;
public static partial class PasswordUtils
{
private const int MIN_LENGTH = 8;
private const int MIN_UPPER = 2;
private const int MIN_LOWER = 2;
private const int MIN_NUMBER = 2;
private const int MIN_SPECIAL = 2;
[GeneratedRegex("[A-Z]")]
private static partial Regex RegexUpper();
[GeneratedRegex("[a-z]")]
private static partial Regex RegexLower();
[GeneratedRegex("[0-9]")]
private static partial Regex RegexNumber();
[GeneratedRegex("[^a-zA-Z0-9]")]
private static partial Regex RegexSpecial();
private static readonly Regex RegexIdenticalChars = new(
@"(\S)\1{2,}",
RegexOptions.IgnoreCase | RegexOptions.Compiled,
TimeSpan.FromMilliseconds(100)
);
public static List<string> ValidatePassword(string password)
{
List<string> errors = [];
if (password.Length < MIN_LENGTH)
errors.Add(PasswordValidationEnum.MIN_LENGTH);
if (RegexUpper().Matches(password).Count < MIN_UPPER)
errors.Add(PasswordValidationEnum.MIN_UPPER);
if (RegexLower().Matches(password).Count < MIN_LOWER)
errors.Add(PasswordValidationEnum.MIN_LOWER);
if (RegexNumber().Matches(password).Count < MIN_NUMBER)
errors.Add(PasswordValidationEnum.MIN_NUMBER);
if (RegexSpecial().Matches(password).Count < MIN_SPECIAL)
errors.Add(PasswordValidationEnum.MIN_SPECIAL);
if (RegexIdenticalChars.IsMatch(password))
errors.Add(PasswordValidationEnum.IDENTICAL_CHARS);
return errors;
}
}

View File

@@ -8,7 +8,7 @@ using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Services; using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Role; using BasicDotnetTemplate.MainProject.Models.Api.Data.Role;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer; using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Core.Filters;
namespace BasicDotnetTemplate.MainProject.Utils; namespace BasicDotnetTemplate.MainProject.Utils;
@@ -140,7 +140,10 @@ public static class ProgramUtils
builder.Services.AddAuthentication(); builder.Services.AddAuthentication();
builder.Services.AddAuthorization(); builder.Services.AddAuthorization();
builder.Services.AddControllers(); builder.Services.AddControllers(options =>
{
options.Filters.Add<ValidationActionFilter>();
});
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
Logger.Info("[ProgramUtils][AddServices] Done services"); Logger.Info("[ProgramUtils][AddServices] Done services");

View File

@@ -35,8 +35,9 @@
"ExpiredAfterMinsOfInactivity": 15 "ExpiredAfterMinsOfInactivity": 15
}, },
"EncryptionSettings": { "EncryptionSettings": {
"Salt": "S7VIidfXQf1tOQYX", "SaltKey": "S7VIidfXQf1tOQYX",
"Pepper": "" "Salt": "u5CZAwq9vLGysC",
"Iterations": 10
}, },
"PermissionsSettings": { "PermissionsSettings": {
"FilePath": "Config/permissions.json" "FilePath": "Config/permissions.json"