Adding user CRUD methods and controller + automapper

This commit is contained in:
2025-03-13 00:19:29 +01:00
parent 0b354988fd
commit 61b9c732bc
21 changed files with 639 additions and 90 deletions

View File

@@ -53,31 +53,31 @@ public class AuthController_Tests
var authServiceMock = new Mock<IAuthService>(); var authServiceMock = new Mock<IAuthService>();
var controller = new AuthController(configuration, authServiceMock.Object); var controller = new AuthController(configuration, authServiceMock.Object);
DatabaseSqlServer.User user = new DatabaseSqlServer.User() DatabaseSqlServer.User user = new DatabaseSqlServer.User()
{
Username = "test",
FirstName = "test",
LastName = "test",
Email = "test",
PasswordHash = "test",
PasswordSalt = "test",
Password = "test",
Role = new DatabaseSqlServer.Role()
{ {
Username = "test", Name = "test"
FirstName = "test", },
LastName = "test", IsTestUser = true
Email = "test", };
PasswordHash = "test",
PasswordSalt = "test",
Password = "test",
Role = new DatabaseSqlServer.Role()
{
Name = "test"
},
IsTestUser = true
};
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user); AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
var request = new AuthenticateRequest { Data = new AuthenticateRequestData { Username = "user", Password = "pass" } }; var request = new AuthenticateRequest { Data = new AuthenticateRequestData { Username = "user", Password = "pass" } };
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser); authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
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 == 200); Assert.IsTrue(response.StatusCode == 200);
var result = (BaseResponse)response.Value; var result = (BaseResponse<object>)response.Value;
if(result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == 200); Assert.IsTrue(result.Status == 200);
Assert.IsInstanceOfType(result.Data, typeof(AuthenticatedUser)); Assert.IsInstanceOfType(result.Data, typeof(AuthenticatedUser));
@@ -86,7 +86,7 @@ public class AuthController_Tests
{ {
Assert.Fail($"Result value is null"); Assert.Fail($"Result value is null");
} }
} }
else else
{ {
@@ -106,15 +106,15 @@ public class AuthController_Tests
Data = null Data = null
}; };
AuthenticatedUser? authenticatedUser = null; AuthenticatedUser? authenticatedUser = null;
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser); authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
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 == 400); Assert.IsTrue(response.StatusCode == 400);
var result = (BaseResponse)response.Value; var result = (BaseResponse<object>)response.Value;
if(result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == 400); Assert.IsTrue(result.Status == 400);
Assert.IsTrue(result.Message == "Request is not well formed"); Assert.IsTrue(result.Message == "Request is not well formed");
@@ -122,7 +122,7 @@ public class AuthController_Tests
else else
{ {
Assert.Fail($"Result value is null"); Assert.Fail($"Result value is null");
} }
} }
else else
{ {
@@ -139,21 +139,21 @@ public class AuthController_Tests
var request = new AuthenticateRequest var request = new AuthenticateRequest
{ {
Data = new AuthenticateRequestData() Data = new AuthenticateRequestData()
{ {
Username = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7", Username = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7",
Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7" Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7"
} }
}; };
AuthenticatedUser? authenticatedUser = null; AuthenticatedUser? authenticatedUser = null;
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser); authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
NotFoundResult response = (NotFoundResult)(await controller.AuthenticateAsync(request)); NotFoundResult response = (NotFoundResult)(await controller.AuthenticateAsync(request));
Assert.IsInstanceOfType(response, typeof(NotFoundResult)); Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if(response != null) if (response != null)
{ {
Assert.IsTrue(response.StatusCode == 404); Assert.IsTrue(response.StatusCode == 404);
} }
else else
{ {
@@ -173,18 +173,18 @@ public class AuthController_Tests
Data = null Data = null
}; };
AuthenticatedUser? authenticatedUser = null; AuthenticatedUser? authenticatedUser = null;
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser); authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
controller.ModelState.AddModelError("Data", "Invalid data"); controller.ModelState.AddModelError("Data", "Invalid data");
ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request)); ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request));
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 == 400); Assert.IsTrue(response.StatusCode == 400);
var result = (BaseResponse)response.Value; var result = (BaseResponse<object>)response.Value;
if(result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == 400); Assert.IsTrue(result.Status == 400);
Assert.IsTrue(result.Message == "Request is not well formed"); Assert.IsTrue(result.Message == "Request is not well formed");
@@ -192,7 +192,7 @@ public class AuthController_Tests
else else
{ {
Assert.Fail($"Result value is null"); Assert.Fail($"Result value is null");
} }
} }
else else
{ {
@@ -209,21 +209,21 @@ public class AuthController_Tests
var request = new AuthenticateRequest var request = new AuthenticateRequest
{ {
Data = new AuthenticateRequestData { Username = "user", Password = "pass" } Data = new AuthenticateRequestData { Username = "user", Password = "pass" }
}; };
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ThrowsAsync(new Exception("Unexpected error")); authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request)); ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request));
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 == 500); Assert.IsTrue(response.StatusCode == 500);
var result = (BaseResponse)response.Value; var result = (BaseResponse<object>)response.Value;
if(result != null) if (result != null)
{ {
Assert.IsTrue(result.Status == 500); Assert.IsTrue(result.Status == 500);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error"); Assert.IsTrue(result.Message == "Something went wrong. Unexpected error");
@@ -231,7 +231,7 @@ public class AuthController_Tests
else else
{ {
Assert.Fail($"Result value is null"); Assert.Fail($"Result value is null");
} }
} }
else else
{ {

View File

@@ -0,0 +1,240 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Configuration;
using Moq;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Controllers;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using AutoMapper;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class UserControllerTests
{
private IMapper _mapper;
[TestInitialize]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperConfiguration>();
});
_mapper = config.CreateMapper();
}
[TestMethod]
public void UserController_NullConfiguration()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
var exception = true;
try
{
var userServiceMock = new Mock<IUserService>();
_ = new UserController(null, userServiceMock.Object);
exception = false;
Assert.Fail($"This test should not pass as configuration is null");
}
catch (Exception)
{
Assert.IsTrue(exception);
}
}
[TestMethod]
public async Task GetUserByGuidAsync_Should_Return_200_When_Successful()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var userServiceMock = new Mock<IUserService>();
var controller = new UserController(configuration, userServiceMock.Object);
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User user = new DatabaseSqlServer.User()
{
Guid = guid,
Username = "Username",
FirstName = "FirstName",
LastName = "LastName",
Email = "Email",
PasswordHash = "PasswordHash",
PasswordSalt = "PasswordSalt",
Password = "Password",
Role = new DatabaseSqlServer.Role()
{
Name = "Role.Name"
},
IsTestUser = true
};
userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == 200);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.IsTrue(result.Status == 200);
Assert.IsInstanceOfType(result.Data, typeof(DatabaseSqlServer.User));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task GetUserByGuidAsync_AuthenticateRequestDataNull()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var userServiceMock = new Mock<IUserService>();
var controller = new UserController(configuration, userServiceMock.Object);
var guid = String.Empty;
DatabaseSqlServer.User? user = null;
userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == 400);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.IsTrue(result.Status == 400);
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 GetUserByGuidAsync_NotFound()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var userServiceMock = new Mock<IUserService>();
var controller = new UserController(configuration, userServiceMock.Object);
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User? user = null;
userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)(await controller.GetUserByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if (response != null)
{
Assert.IsTrue(response.StatusCode == 404);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task GetUserByGuidAsync_ModelInvalid()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var userServiceMock = new Mock<IUserService>();
var controller = new UserController(configuration, userServiceMock.Object);
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User? user = null;
userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
controller.ModelState.AddModelError("Data", "Invalid data");
ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == 400);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.IsTrue(result.Status == 400);
Assert.IsTrue(result.Message == "Request is not well formed");
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task GetUserByGuidAsync_Exception()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var userServiceMock = new Mock<IUserService>();
var controller = new UserController(configuration, userServiceMock.Object);
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User? user = null;
userServiceMock.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await controller.GetUserByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.IsTrue(response.StatusCode == 500);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.IsTrue(result.Status == 500);
Assert.IsTrue(result.Message == "Something went wrong. Unexpected error");
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
}

View File

@@ -47,7 +47,7 @@ public class VersionController_Tests
var objectResult = ((ObjectResult)result).Value; var objectResult = ((ObjectResult)result).Value;
if (objectResult != null) if (objectResult != null)
{ {
var data = (BaseResponse)objectResult; var data = (BaseResponse<object>)objectResult;
if (data.Data != null) if (data.Data != null)
{ {
AppSettings appSettings = new AppSettings(); AppSettings appSettings = new AppSettings();
@@ -86,7 +86,7 @@ public class VersionController_Tests
var objectResult = ((ObjectResult)result).Value; var objectResult = ((ObjectResult)result).Value;
if (objectResult != null) if (objectResult != null)
{ {
var data = (BaseResponse)objectResult; var data = (BaseResponse<object>)objectResult;
Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == 200) && String.IsNullOrEmpty(data.Data)); Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == 200) && String.IsNullOrEmpty(data.Data));
} }
else else

View File

@@ -0,0 +1,75 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Response.User;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
using AutoMapper;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class AutoMapperConfiguration_Tests
{
private IMapper _mapper;
[TestInitialize]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperConfiguration>();
});
_mapper = config.CreateMapper();
}
[TestMethod]
public void Mapper_UserDto()
{
try
{
DatabaseSqlServer.User user = new DatabaseSqlServer.User()
{
Guid = Guid.NewGuid().ToString(),
Username = "Username",
FirstName = "FirstName",
LastName = "LastName",
Email = "Email",
PasswordHash = "PasswordHash",
PasswordSalt = "PasswordSalt",
Password = "Password",
Role = new DatabaseSqlServer.Role()
{
Name = "Role.Name"
},
IsTestUser = true
};
UserDto data = _mapper.Map<UserDto>(user);
Assert.IsTrue(data.Guid == user.Guid);
Assert.IsTrue(data.Username == user.Username);
Assert.IsTrue(data.FirstName == user.FirstName);
Assert.IsTrue(data.LastName == user.LastName);
Assert.IsTrue(data.Email == user.Email);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex.Message}");
}
}
}

View File

@@ -18,7 +18,7 @@ public class ApiResponse_Tests
{ {
try try
{ {
var baseResponse = new BaseResponse(200, null, null); var baseResponse = new BaseResponse<object>(200, null, null);
Assert.IsTrue(baseResponse.Status == 200 && String.IsNullOrEmpty(baseResponse.Message) && baseResponse.Data == null); Assert.IsTrue(baseResponse.Status == 200 && String.IsNullOrEmpty(baseResponse.Message) && baseResponse.Data == null);
} }
catch (Exception ex) catch (Exception ex)
@@ -33,7 +33,7 @@ public class ApiResponse_Tests
{ {
try try
{ {
var baseResponse = new BaseResponse(201, null, null); var baseResponse = new BaseResponse<object>(201, null, null);
Assert.IsFalse(baseResponse.Status == 200); Assert.IsFalse(baseResponse.Status == 200);
} }
catch (Exception ex) catch (Exception ex)
@@ -48,7 +48,7 @@ public class ApiResponse_Tests
{ {
try try
{ {
var baseResponse = new BaseResponse(200, "This is a test message", null); var baseResponse = new BaseResponse<object>(200, "This is a test message", null);
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null); Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null);
} }
catch (Exception ex) catch (Exception ex)
@@ -64,7 +64,7 @@ public class ApiResponse_Tests
try try
{ {
string[] data = { "Volvo", "BMW", "Ford", "Mazda" }; string[] data = { "Volvo", "BMW", "Ford", "Mazda" };
var baseResponse = new BaseResponse(200, "This is a test message", data); var baseResponse = new BaseResponse<string[]>(200, "This is a test message", data);
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data); Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -0,0 +1,115 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Response.User;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
using AutoMapper;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class GetUserResponse_Tests
{
private IMapper _mapper;
[TestInitialize]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperConfiguration>();
});
_mapper = config.CreateMapper();
}
[TestMethod]
public void IstantiateGetUserResponse_OnlyStatus_Valid()
{
try
{
var getUserResponse = new GetUserResponse(200, null, null);
Assert.IsTrue(getUserResponse.Status == 200 && String.IsNullOrEmpty(getUserResponse.Message) && getUserResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex.Message}");
}
}
[TestMethod]
public void IstantiateGetUserResponse_OnlyStatus_IsInvalid()
{
try
{
var getUserResponse = new GetUserResponse(201, null, null);
Assert.IsFalse(getUserResponse.Status == 200);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex.Message}");
}
}
[TestMethod]
public void IstantiateGetUserResponse_StatusAndMessage_Valid()
{
try
{
var getUserResponse = new GetUserResponse(200, "This is a test message", null);
Assert.IsTrue(getUserResponse.Status == 200 && getUserResponse.Message == "This is a test message" && getUserResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex.Message}");
}
}
[TestMethod]
public void IstantiateGetUserResponse_AllFields_Valid()
{
try
{
DatabaseSqlServer.User user = new DatabaseSqlServer.User()
{
Username = "test",
FirstName = "test",
LastName = "test",
Email = "test",
PasswordHash = "test",
PasswordSalt = "test",
Password = "test",
Role = new DatabaseSqlServer.Role()
{
Name = "test"
},
IsTestUser = true
};
UserDto data = _mapper.Map<UserDto>(user);
var getUserResponse = new GetUserResponse(200, "This is a test message", data);
Assert.IsTrue(getUserResponse.Status == 200 && getUserResponse.Message == "This is a test message" && getUserResponse.Data == data);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex.Message}");
}
}
}

View File

@@ -25,7 +25,8 @@ public class Settings_Tests
var privateSettings = new PrivateSettings() var privateSettings = new PrivateSettings()
{ {
DatabaseConnection = new DatabaseConnection() { DatabaseConnection = new DatabaseConnection()
{
SqlServer = sqlServer, SqlServer = sqlServer,
Mongodb = mongodb, Mongodb = mongodb,
Postgres = postgres, Postgres = postgres,
@@ -33,9 +34,9 @@ public class Settings_Tests
}; };
Assert.IsTrue( Assert.IsTrue(
privateSettings.DatabaseConnection != null && privateSettings.DatabaseConnection != null &&
privateSettings.DatabaseConnection.SqlServer == sqlServer && privateSettings.DatabaseConnection.SqlServer == sqlServer &&
privateSettings.DatabaseConnection.Mongodb == mongodb && privateSettings.DatabaseConnection.Mongodb == mongodb &&
privateSettings.DatabaseConnection.Postgres == postgres privateSettings.DatabaseConnection.Postgres == postgres
); );
} }
@@ -51,7 +52,7 @@ public class Settings_Tests
{ {
try try
{ {
var baseResponse = new BaseResponse(201, null, null); var baseResponse = new BaseResponse<object>(201, null, null);
Assert.IsFalse(baseResponse.Status == 200); Assert.IsFalse(baseResponse.Status == 200);
} }
catch (Exception ex) catch (Exception ex)
@@ -66,7 +67,7 @@ public class Settings_Tests
{ {
try try
{ {
var baseResponse = new BaseResponse(200, "This is a test message", null); var baseResponse = new BaseResponse<object>(200, "This is a test message", null);
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null); Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == null);
} }
catch (Exception ex) catch (Exception ex)
@@ -82,7 +83,7 @@ public class Settings_Tests
try try
{ {
string[] data = { "Volvo", "BMW", "Ford", "Mazda" }; string[] data = { "Volvo", "BMW", "Ford", "Mazda" };
var baseResponse = new BaseResponse(200, "This is a test message", data); var baseResponse = new BaseResponse<string[]>(200, "This is a test message", data);
Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data); Assert.IsTrue(baseResponse.Status == 200 && baseResponse.Message == "This is a test message" && baseResponse.Data == data);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -23,9 +23,9 @@ namespace BasicDotnetTemplate.MainProject.Controllers
[HttpPost("authenticate")] [HttpPost("authenticate")]
[ProducesResponseType<AuthenticateResponse>(StatusCodes.Status200OK)] [ProducesResponseType<AuthenticateResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse>(StatusCodes.Status404NotFound)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse>(StatusCodes.Status400BadRequest)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse>(StatusCodes.Status500InternalServerError)] [ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest request) public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest request)
{ {
try try
@@ -34,7 +34,7 @@ namespace BasicDotnetTemplate.MainProject.Controllers
{ {
return BadRequest("Request is not well formed"); return BadRequest("Request is not well formed");
} }
if ( if (
request == null || request == null ||
request.Data == null || request.Data == null ||

View File

@@ -20,9 +20,9 @@ namespace BasicDotnetTemplate.MainProject.Controllers
} }
#nullable enable #nullable enable
private static BaseResponse CreateResponse(HttpStatusCode status, string message, object? data = null) private static BaseResponse<T> CreateResponse<T>(HttpStatusCode status, string message, T? data)
{ {
return new BaseResponse((int)status, message, data); return new BaseResponse<T>((int)status, message, data);
} }
protected new IActionResult Created(string message, object? data = null) protected new IActionResult Created(string message, object? data = null)
@@ -58,7 +58,7 @@ namespace BasicDotnetTemplate.MainProject.Controllers
protected IActionResult InternalServerError(string message) protected IActionResult InternalServerError(string message)
{ {
message = String.IsNullOrEmpty(message) ? "Internal server error" : message; message = String.IsNullOrEmpty(message) ? "Internal server error" : message;
return StatusCode((int)HttpStatusCode.InternalServerError, CreateResponse(HttpStatusCode.InternalServerError, message)); return StatusCode((int)HttpStatusCode.InternalServerError, CreateResponse(HttpStatusCode.InternalServerError, message, new object()));
} }
#nullable disable #nullable disable

View File

@@ -0,0 +1,62 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using BasicDotnetTemplate.MainProject.Core.Attributes;
using BasicDotnetTemplate.MainProject.Services;
//using BasicDotnetTemplate.MainProject.Models.Api.Request.User;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Response.User;
namespace BasicDotnetTemplate.MainProject.Controllers
{
[Route("[controller]")]
public class UserController : BaseController
{
private readonly IUserService _userService;
public UserController(
IConfiguration configuration,
IUserService userService
) : base(configuration)
{
this._userService = userService;
}
[HttpGet("get/{guid}")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> GetUserByGuidAsync(string guid)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest("Request is not well formed");
}
if (String.IsNullOrEmpty(guid))
{
return BadRequest("Request is not well formed");
}
var data = await this._userService.GetUserByGuidAsync(guid);
if (data == null || String.IsNullOrEmpty(data.Guid))
{
return NotFound();
}
return Success(String.Empty, data);
}
catch (Exception exception)
{
var message = "Something went wrong";
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return InternalServerError(message);
}
}
}
}

View File

@@ -0,0 +1,14 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using SqlServerDatabase = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using AutoMapper;
namespace BasicDotnetTemplate.MainProject.Core.Middlewares;
public class AutoMapperConfiguration : Profile
{
public AutoMapperConfiguration()
{
CreateMap<SqlServerDatabase.User, UserDto>();
}
}

View File

@@ -9,6 +9,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="coverlet.msbuild" Version="6.0.2"> <PackageReference Include="coverlet.msbuild" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@@ -0,0 +1,19 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Models.Api.Common.User;
public class UserDto
{
#nullable enable
public string? Guid { get; set; }
public string? Username { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
#nullable disable
}

View File

@@ -1,9 +1,8 @@
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User; using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Response.Auth; namespace BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
public class AuthenticateResponse: BaseResponse public class AuthenticateResponse : BaseResponse<AuthenticatedUser>
{ {
public AuthenticateResponse(int status, string? message, AuthenticatedUser? data) : base(status, message, data) {} public AuthenticateResponse(int status, string? message, AuthenticatedUser? data) : base(status, message, data) { }
} }

View File

@@ -1,9 +1,9 @@
namespace BasicDotnetTemplate.MainProject.Models.Api.Response; namespace BasicDotnetTemplate.MainProject.Models.Api.Response;
public class BaseResponse public class BaseResponse<T>
{ {
#nullable enable #nullable enable
public BaseResponse(int status, string? message, dynamic? data) public BaseResponse(int status, string? message, T? data)
{ {
this.Status = status; this.Status = status;
this.Message = message; this.Message = message;

View File

@@ -0,0 +1,8 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Response.User;
public class GetUserResponse : BaseResponse<UserDto>
{
public GetUserResponse(int status, string? message, UserDto? data) : base(status, message, data) { }
}

View File

@@ -1,22 +1,22 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
{
public class User : Base
{
public required string Username { get; set; }
public required string FirstName { get; set; }
public required string LastName { get; set; }
public required string Email { get; set; }
public required string PasswordSalt { get; set; }
public required string PasswordHash { get; set; }
public required Role Role { get; set; }
public required bool IsTestUser { get; set; }
[JsonIgnore] public class User : Base
public required string Password { get; set; } {
} public required string Username { get; set; }
public required string FirstName { get; set; }
public required string LastName { get; set; }
public required string Email { get; set; }
public required string PasswordSalt { get; set; }
public required string PasswordHash { get; set; }
public required Role Role { get; set; }
public required bool IsTestUser { get; set; }
[JsonIgnore]
public required string Password { get; set; }
} }

View File

@@ -44,7 +44,8 @@ public class JwtService : BaseService, IJwtService
string? guid = _jwtTokenUtils.ValidateToken(headerAuthorization); string? guid = _jwtTokenUtils.ValidateToken(headerAuthorization);
if(!String.IsNullOrEmpty(guid)) if(!String.IsNullOrEmpty(guid))
{ {
user = this._userService.GetUserByGuid(guid); var userTask = Task.Run(() => this._userService.GetUserByGuidAsync(guid));
user = userTask.Result;
} }
return user; return user;
} }

View File

@@ -8,8 +8,8 @@ namespace BasicDotnetTemplate.MainProject.Services;
public interface IUserService public interface IUserService
{ {
User? GetUserById(int id); Task<User?> GetUserByIdAsync(int id);
User? GetUserByGuid(string guid); Task<User?> GetUserByGuidAsync(string guid);
Task<User?> GetUserByUsernameAndPassword(string username, string password); Task<User?> GetUserByUsernameAndPassword(string username, string password);
} }
@@ -34,14 +34,14 @@ public class UserService : BaseService, IUserService
); );
} }
public User? GetUserById(int id) public async Task<User?> GetUserByIdAsync(int id)
{ {
return this.GetUsers().Where(x => x.Id == id).FirstOrDefault(); return await this.GetUsers().Where(x => x.Id == id).FirstOrDefaultAsync();
} }
public User? GetUserByGuid(string guid) public async Task<User?> GetUserByGuidAsync(string guid)
{ {
return this.GetUsers().Where(x => x.Guid == guid).FirstOrDefault(); return await this.GetUsers().Where(x => x.Guid == guid).FirstOrDefaultAsync();
} }
public async Task<User?> GetUserByUsernameAndPassword(string username, string password) public async Task<User?> GetUserByUsernameAndPassword(string username, string password)
@@ -64,5 +64,12 @@ public class UserService : BaseService, IUserService
return user; return user;
} }
// public async Task<User?> CreateUser(CreateUserRequestData data)
// {
// }
} }

View File

@@ -71,10 +71,9 @@ public class CryptUtils
string hashedPassword = password; string hashedPassword = password;
for(var i = 0; i <= iteration; i++) for(var i = 0; i <= iteration; i++)
{ {
using var sha256 = SHA256.Create();
var passwordSaltPepper = $"{hashedPassword}{salt}{this._pepper}"; var passwordSaltPepper = $"{hashedPassword}{salt}{this._pepper}";
var byteValue = Encoding.UTF8.GetBytes(passwordSaltPepper); var byteValue = Encoding.UTF8.GetBytes(passwordSaltPepper);
var byteHash = sha256.ComputeHash(byteValue); var byteHash = SHA256.HashData(byteValue);
hashedPassword = Convert.ToBase64String(byteHash); hashedPassword = Convert.ToBase64String(byteHash);
} }

View File

@@ -3,6 +3,7 @@ using Microsoft.OpenApi.Models;
using MongoDB.Driver; using MongoDB.Driver;
using NLog; using NLog;
using BasicDotnetTemplate.MainProject.Core.Database; using BasicDotnetTemplate.MainProject.Core.Database;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
using BasicDotnetTemplate.MainProject.Models.Settings; using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Services; using BasicDotnetTemplate.MainProject.Services;
@@ -218,4 +219,11 @@ public static class ProgramUtils
Logger.Info("[ProgramUtils][AddScopes] Done scopes"); Logger.Info("[ProgramUtils][AddScopes] Done scopes");
} }
public static void AddAutoMapper(ref WebApplicationBuilder builder)
{
Logger.Info("[ProgramUtils][AddAutoMapper] Adding AutoMapperConfiguration");
builder.Services.AddAutoMapper(typeof(AutoMapperConfiguration));
Logger.Info("[ProgramUtils][AddScopes] Done AutoMapperConfiguration");
}
} }