diff --git a/src/Core/API/API.Core/API.Core.csproj b/src/Core/API/API.Core/API.Core.csproj
index 4ddfa09..29247b4 100644
--- a/src/Core/API/API.Core/API.Core.csproj
+++ b/src/Core/API/API.Core/API.Core.csproj
@@ -21,7 +21,8 @@
-
+
+
diff --git a/src/Core/API/API.Core/Controllers/AuthController.cs b/src/Core/API/API.Core/Controllers/AuthController.cs
index 62a9018..bccde9b 100644
--- a/src/Core/API/API.Core/Controllers/AuthController.cs
+++ b/src/Core/API/API.Core/Controllers/AuthController.cs
@@ -3,20 +3,18 @@ using API.Core.Contracts.Common;
using Domain.Entities;
using Infrastructure.Jwt;
using Microsoft.AspNetCore.Mvc;
-using Service.Core.Auth;
+using Service.Auth.Auth;
namespace API.Core.Controllers
{
[ApiController]
[Route("api/[controller]")]
- public class AuthController(IAuthService auth, IJwtService jwtService) : ControllerBase
+ public class AuthController(IRegisterService register, ILoginService login, ITokenInfrastructure tokenInfrastructure) : ControllerBase
{
-
[HttpPost("register")]
public async Task> Register([FromBody] RegisterRequest req)
{
-
- var created = await auth.RegisterAsync(new UserAccount
+ var created = await register.RegisterAsync(new UserAccount
{
UserAccountId = Guid.Empty,
Username = req.Username,
@@ -27,8 +25,7 @@ namespace API.Core.Controllers
}, req.Password);
var jwtExpiresAt = DateTime.UtcNow.AddHours(1);
- var jwt = jwtService.GenerateJwt(created.UserAccountId, created.Username, jwtExpiresAt
-
+ var jwt = tokenInfrastructure.GenerateJwt(created.UserAccountId, created.Username, jwtExpiresAt
);
var response = new ResponseBody
@@ -46,7 +43,7 @@ namespace API.Core.Controllers
[HttpPost("login")]
public async Task Login([FromBody] LoginRequest req)
{
- var userAccount = await auth.LoginAsync(req.Username, req.Password);
+ var userAccount = await login.LoginAsync(req.Username, req.Password);
if (userAccount is null)
{
return Unauthorized(new ResponseBody
@@ -58,7 +55,7 @@ namespace API.Core.Controllers
UserDTO dto = new(userAccount.UserAccountId, userAccount.Username);
var jwtExpiresAt = DateTime.UtcNow.AddHours(1);
- var jwt = jwtService.GenerateJwt(userAccount.UserAccountId, userAccount.Username, jwtExpiresAt);
+ var jwt = tokenInfrastructure.GenerateJwt(userAccount.UserAccountId, userAccount.Username, jwtExpiresAt);
return Ok(new ResponseBody
{
@@ -67,4 +64,4 @@ namespace API.Core.Controllers
});
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Core/API/API.Core/Controllers/UserController.cs b/src/Core/API/API.Core/Controllers/UserController.cs
index 6039ce6..fe98481 100644
--- a/src/Core/API/API.Core/Controllers/UserController.cs
+++ b/src/Core/API/API.Core/Controllers/UserController.cs
@@ -1,6 +1,6 @@
using Domain.Entities;
using Microsoft.AspNetCore.Mvc;
-using Service.Core.User;
+using Service.UserManagement.User;
namespace API.Core.Controllers
{
diff --git a/src/Core/API/API.Core/Program.cs b/src/Core/API/API.Core/Program.cs
index 640dbb6..82f1463 100644
--- a/src/Core/API/API.Core/Program.cs
+++ b/src/Core/API/API.Core/Program.cs
@@ -6,8 +6,9 @@ using Infrastructure.Repository.Auth;
using Infrastructure.Repository.Sql;
using Infrastructure.Repository.UserAccount;
using Microsoft.AspNetCore.Mvc;
-using Service.Core.Auth;
-using Service.Core.User;
+using Service.Auth.Auth;
+using Service.UserManagement.User;
+
var builder = WebApplication.CreateBuilder(args);
@@ -52,14 +53,20 @@ if (!builder.Environment.IsProduction())
builder.Logging.AddDebug();
}
-// Dependency Injection
+// Configure Dependency Injection -------------------------------------------------------------------------------------
+
builder.Services.AddSingleton();
+
builder.Services.AddScoped();
-builder.Services.AddScoped();
builder.Services.AddScoped();
-builder.Services.AddScoped();
-builder.Services.AddScoped();
-builder.Services.AddScoped();
+
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+
var app = builder.Build();
diff --git a/src/Core/Core.slnx b/src/Core/Core.slnx
index a9f0a9f..c48bc6c 100644
--- a/src/Core/Core.slnx
+++ b/src/Core/Core.slnx
@@ -17,6 +17,7 @@
-
+
+
diff --git a/src/Core/Infrastructure/Infrastructure.Jwt/IJwtService.cs b/src/Core/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs
similarity index 73%
rename from src/Core/Infrastructure/Infrastructure.Jwt/IJwtService.cs
rename to src/Core/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs
index b62d2e3..7929da0 100644
--- a/src/Core/Infrastructure/Infrastructure.Jwt/IJwtService.cs
+++ b/src/Core/Infrastructure/Infrastructure.Jwt/ITokenInfrastructure.cs
@@ -1,6 +1,6 @@
namespace Infrastructure.Jwt;
-public interface IJwtService
+public interface ITokenInfrastructure
{
string GenerateJwt(Guid userId, string username, DateTime expiry);
}
diff --git a/src/Core/Infrastructure/Infrastructure.Jwt/JwtService.cs b/src/Core/Infrastructure/Infrastructure.Jwt/JwtInfrastructure.cs
similarity index 96%
rename from src/Core/Infrastructure/Infrastructure.Jwt/JwtService.cs
rename to src/Core/Infrastructure/Infrastructure.Jwt/JwtInfrastructure.cs
index d0fba84..1b093c8 100644
--- a/src/Core/Infrastructure/Infrastructure.Jwt/JwtService.cs
+++ b/src/Core/Infrastructure/Infrastructure.Jwt/JwtInfrastructure.cs
@@ -6,7 +6,7 @@ using JwtRegisteredClaimNames = System.IdentityModel.Tokens.Jwt.JwtRegisteredCla
namespace Infrastructure.Jwt;
-public class JwtService : IJwtService
+public class JwtInfrastructure : ITokenInfrastructure
{
private readonly string? _secret = Environment.GetEnvironmentVariable(
"JWT_SECRET"
diff --git a/src/Core/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs b/src/Core/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs
index ff47a77..0364900 100644
--- a/src/Core/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs
+++ b/src/Core/Infrastructure/Infrastructure.PasswordHashing/Argon2Infrastructure.cs
@@ -4,7 +4,7 @@ using Konscious.Security.Cryptography;
namespace Infrastructure.PasswordHashing;
-public class Argon2Infrastructure : IPasswordInfra
+public class Argon2Infrastructure : IPasswordInfrastructure
{
private const int SaltSize = 16; // 128-bit
private const int HashSize = 32; // 256-bit
diff --git a/src/Core/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfra.cs b/src/Core/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfrastructure.cs
similarity index 77%
rename from src/Core/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfra.cs
rename to src/Core/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfrastructure.cs
index 9a2df0b..593ed73 100644
--- a/src/Core/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfra.cs
+++ b/src/Core/Infrastructure/Infrastructure.PasswordHashing/IPasswordInfrastructure.cs
@@ -1,6 +1,6 @@
namespace Infrastructure.PasswordHashing;
-public interface IPasswordInfra
+public interface IPasswordInfrastructure
{
public string Hash(string password);
public bool Verify(string password, string stored);
diff --git a/src/Core/Service/Service.Auth/Auth/ILoginService.cs b/src/Core/Service/Service.Auth/Auth/ILoginService.cs
new file mode 100644
index 0000000..667a30a
--- /dev/null
+++ b/src/Core/Service/Service.Auth/Auth/ILoginService.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+using Domain.Entities;
+
+namespace Service.Auth.Auth;
+
+public interface ILoginService
+{
+ Task LoginAsync(string username, string password);
+}
diff --git a/src/Core/Service/Service.Auth/Auth/IRegisterService.cs b/src/Core/Service/Service.Auth/Auth/IRegisterService.cs
new file mode 100644
index 0000000..0cd5743
--- /dev/null
+++ b/src/Core/Service/Service.Auth/Auth/IRegisterService.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+using Domain.Entities;
+
+namespace Service.Auth.Auth;
+
+public interface IRegisterService
+{
+ Task RegisterAsync(UserAccount userAccount, string password);
+}
diff --git a/src/Core/Service/Service.Auth/Auth/LoginService.cs b/src/Core/Service/Service.Auth/Auth/LoginService.cs
new file mode 100644
index 0000000..f931ce2
--- /dev/null
+++ b/src/Core/Service/Service.Auth/Auth/LoginService.cs
@@ -0,0 +1,28 @@
+using System.Threading.Tasks;
+using Domain.Entities;
+using Infrastructure.PasswordHashing;
+using Infrastructure.Repository.Auth;
+
+namespace Service.Auth.Auth;
+
+public class LoginService(
+ IAuthRepository authRepo,
+ IPasswordInfrastructure passwordInfrastructure
+) : ILoginService
+{
+
+ public async Task LoginAsync(string username, string password)
+ {
+ // Attempt lookup by username
+ var user = await authRepo.GetUserByUsernameAsync(username);
+
+ // the user was not found
+ if (user is null) return null;
+
+ // @todo handle expired passwords
+ var activeCred = await authRepo.GetActiveCredentialByUserAccountIdAsync(user.UserAccountId);
+
+ if (activeCred is null) return null;
+ return !passwordInfrastructure.Verify(password, activeCred.Hash) ? null : user;
+ }
+}
diff --git a/src/Core/Service/Service.Core/Auth/AuthService.cs b/src/Core/Service/Service.Auth/Auth/RegisterService.cs
similarity index 51%
rename from src/Core/Service/Service.Core/Auth/AuthService.cs
rename to src/Core/Service/Service.Auth/Auth/RegisterService.cs
index 8756dc3..5b1493b 100644
--- a/src/Core/Service/Service.Core/Auth/AuthService.cs
+++ b/src/Core/Service/Service.Auth/Auth/RegisterService.cs
@@ -1,13 +1,14 @@
+using System.Threading.Tasks;
using Domain.Entities;
using Infrastructure.PasswordHashing;
using Infrastructure.Repository.Auth;
-namespace Service.Core.Auth;
+namespace Service.Auth.Auth;
-public class AuthService(
+public class RegisterService(
IAuthRepository authRepo,
- IPasswordInfra passwordInfra
-) : IAuthService
+ IPasswordInfrastructure passwordInfrastructure
+) : IRegisterService
{
public async Task RegisterAsync(UserAccount userAccount, string password)
{
@@ -19,7 +20,7 @@ public class AuthService(
}
// password hashing
- var hashed = passwordInfra.Hash(password);
+ var hashed = passwordInfrastructure.Hash(password);
// Register user with hashed password
return await authRepo.RegisterUserAsync(
@@ -31,18 +32,5 @@ public class AuthService(
hashed);
}
- public async Task LoginAsync(string username, string password)
- {
- // Attempt lookup by username
- var user = await authRepo.GetUserByUsernameAsync(username);
-
- // the user was not found
- if (user is null) return null;
-
- // @todo handle expired passwords
- var activeCred = await authRepo.GetActiveCredentialByUserAccountIdAsync(user.UserAccountId);
-
- if (activeCred is null) return null;
- return !passwordInfra.Verify(password, activeCred.Hash) ? null : user;
- }
+
}
diff --git a/src/Core/Service/Service.Core/Service.Core.csproj b/src/Core/Service/Service.Auth/Service.Auth.csproj
similarity index 93%
rename from src/Core/Service/Service.Core/Service.Core.csproj
rename to src/Core/Service/Service.Auth/Service.Auth.csproj
index c01d95b..48566dc 100644
--- a/src/Core/Service/Service.Core/Service.Core.csproj
+++ b/src/Core/Service/Service.Auth/Service.Auth.csproj
@@ -3,7 +3,6 @@
net10.0
enable
enable
- Service.Core
diff --git a/src/Core/Service/Service.Core/Auth/IAuthService.cs b/src/Core/Service/Service.Core/Auth/IAuthService.cs
deleted file mode 100644
index 8e99efb..0000000
--- a/src/Core/Service/Service.Core/Auth/IAuthService.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Domain.Entities;
-
-namespace Service.Core.Auth;
-
-public interface IAuthService
-{
- Task RegisterAsync(UserAccount userAccount, string password);
- Task LoginAsync(string username, string password);
-}
diff --git a/src/Core/Service/Service.UserManagement/Service.UserManagement.csproj b/src/Core/Service/Service.UserManagement/Service.UserManagement.csproj
new file mode 100644
index 0000000..776d954
--- /dev/null
+++ b/src/Core/Service/Service.UserManagement/Service.UserManagement.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/src/Core/Service/Service.Core/User/IUserService.cs b/src/Core/Service/Service.UserManagement/User/IUserService.cs
similarity index 86%
rename from src/Core/Service/Service.Core/User/IUserService.cs
rename to src/Core/Service/Service.UserManagement/User/IUserService.cs
index a515cab..71dcfac 100644
--- a/src/Core/Service/Service.Core/User/IUserService.cs
+++ b/src/Core/Service/Service.UserManagement/User/IUserService.cs
@@ -1,6 +1,6 @@
using Domain.Entities;
-namespace Service.Core.User;
+namespace Service.UserManagement.User;
public interface IUserService
{
diff --git a/src/Core/Service/Service.Core/User/UserService.cs b/src/Core/Service/Service.UserManagement/User/UserService.cs
similarity index 93%
rename from src/Core/Service/Service.Core/User/UserService.cs
rename to src/Core/Service/Service.UserManagement/User/UserService.cs
index 1959553..7391ec0 100644
--- a/src/Core/Service/Service.Core/User/UserService.cs
+++ b/src/Core/Service/Service.UserManagement/User/UserService.cs
@@ -1,7 +1,7 @@
using Domain.Entities;
using Infrastructure.Repository.UserAccount;
-namespace Service.Core.User;
+namespace Service.UserManagement.User;
public class UserService(IUserAccountRepository repository) : IUserService
{