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:
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PruebaGentle.Core\PruebaGentle.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.1.0" />
|
||||
<PackageReference Include="Dapper" Version="2.1.72" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Data;
|
||||
using Dapper;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using PruebaGentle.Core.Entities;
|
||||
using PruebaGentle.Core.Interfaces;
|
||||
|
||||
namespace PruebaGentle.Infrastructure.Repositories;
|
||||
|
||||
public class UserRepository : IUserRepository
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
|
||||
public UserRepository(IConfiguration configuration)
|
||||
{
|
||||
_connectionString = configuration.GetConnectionString("DefaultConnection")
|
||||
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
|
||||
}
|
||||
|
||||
private IDbConnection CreateConnection() => new SqlConnection(_connectionString);
|
||||
|
||||
public async Task<User> CreateAsync(User user)
|
||||
{
|
||||
using var connection = CreateConnection();
|
||||
var result = await connection.QuerySingleAsync<User>(
|
||||
"sp_User_Create",
|
||||
new
|
||||
{
|
||||
user.Username,
|
||||
user.PasswordHash,
|
||||
user.Email,
|
||||
user.NombreCompleto
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<User?> GetByIdAsync(int id)
|
||||
{
|
||||
using var connection = CreateConnection();
|
||||
return await connection.QuerySingleOrDefaultAsync<User>(
|
||||
"sp_User_GetById",
|
||||
new { Id = id },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<User>> GetAllAsync()
|
||||
{
|
||||
using var connection = CreateConnection();
|
||||
return await connection.QueryAsync<User>(
|
||||
"sp_User_GetAll",
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<User?> UpdateAsync(User user)
|
||||
{
|
||||
using var connection = CreateConnection();
|
||||
return await connection.QuerySingleOrDefaultAsync<User>(
|
||||
"sp_User_Update",
|
||||
new
|
||||
{
|
||||
user.Id,
|
||||
user.Username,
|
||||
user.Email,
|
||||
user.NombreCompleto
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAsync(int id)
|
||||
{
|
||||
using var connection = CreateConnection();
|
||||
var affected = await connection.ExecuteAsync(
|
||||
"sp_User_Delete",
|
||||
new { Id = id },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
return affected > 0;
|
||||
}
|
||||
|
||||
public async Task<User?> GetByUsernameAsync(string username)
|
||||
{
|
||||
using var connection = CreateConnection();
|
||||
return await connection.QuerySingleOrDefaultAsync<User>(
|
||||
"sp_User_GetByUsername",
|
||||
new { Username = username },
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using PruebaGentle.Core.Interfaces;
|
||||
|
||||
namespace PruebaGentle.Infrastructure.Services;
|
||||
|
||||
public class PasswordHasher : IPasswordHasher
|
||||
{
|
||||
public string Hash(string password)
|
||||
{
|
||||
return BCrypt.Net.BCrypt.HashPassword(password);
|
||||
}
|
||||
|
||||
public bool Verify(string password, string hash)
|
||||
{
|
||||
return BCrypt.Net.BCrypt.Verify(password, hash);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user