feat: Sistema de Usuarios - Backend CRUD + JWT Auth (Issue #1)

Implementación fundacional del proyecto PruebaGentle:
- Arquitectura Clean/Hexagonal: Core, Infrastructure, API
- 6 Stored Procedures para CRUD + autenticación
- JWT authentication con BCrypt password hashing
- Docker Compose (SQL Server + Backend)
- Solución .NET 10 con Dapper + SqlClient

Closes #1
This commit is contained in:
2026-03-31 17:36:04 -03:00
commit 21e7e7b044
34 changed files with 795 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
namespace PruebaGentle.Core.Config;
public class JwtSettings
{
public string Secret { get; set; } = string.Empty;
public int ExpirationHours { get; set; } = 24;
}

View File

@@ -0,0 +1,9 @@
namespace PruebaGentle.Core.DTOs;
public class CreateUserDto
{
public string Username { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string NombreCompleto { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,7 @@
namespace PruebaGentle.Core.DTOs;
public class LoginDto
{
public string Username { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,7 @@
namespace PruebaGentle.Core.DTOs;
public class LoginResponseDto
{
public string Token { get; set; } = string.Empty;
public DateTime ExpiresAt { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace PruebaGentle.Core.DTOs;
public class UpdateUserDto
{
public string Username { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string NombreCompleto { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,10 @@
namespace PruebaGentle.Core.DTOs;
public class UserResponseDto
{
public int Id { get; set; }
public string Username { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string NombreCompleto { get; set; } = string.Empty;
public DateTime FechaCreacion { get; set; }
}

View File

@@ -0,0 +1,11 @@
namespace PruebaGentle.Core.Entities;
public class User
{
public int Id { get; set; }
public string Username { get; set; } = string.Empty;
public string PasswordHash { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string NombreCompleto { get; set; } = string.Empty;
public DateTime FechaCreacion { get; set; }
}

View File

@@ -0,0 +1,7 @@
namespace PruebaGentle.Core.Interfaces;
public interface IPasswordHasher
{
string Hash(string password);
bool Verify(string password, string hash);
}

View File

@@ -0,0 +1,13 @@
using PruebaGentle.Core.Entities;
namespace PruebaGentle.Core.Interfaces;
public interface IUserRepository
{
Task<User> CreateAsync(User user);
Task<User?> GetByIdAsync(int id);
Task<IEnumerable<User>> GetAllAsync();
Task<User?> UpdateAsync(User user);
Task<bool> DeleteAsync(int id);
Task<User?> GetByUsernameAsync(string username);
}

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>