mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 19:54:55 +00:00
AuthSystem
This commit is contained in:
@@ -26,10 +26,10 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="IntegrationTests\Controllers\" />
|
<Folder Include="IntegrationTests\Controllers\" />
|
||||||
<Folder Include="UnitTests\Services\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Govor.API\Govor.API.csproj" />
|
||||||
<ProjectReference Include="..\Govor.Data\Govor.Data.csproj" />
|
<ProjectReference Include="..\Govor.Data\Govor.Data.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using AutoFixture;
|
||||||
|
using Govor.API.Services;
|
||||||
|
using Govor.Core.Infrastructure.Extensions;
|
||||||
|
|
||||||
|
namespace Govor.API.Tests.UnitTests.Services;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class PasswordHasherTests
|
||||||
|
{
|
||||||
|
private IPasswordHasher _passwordHasher;
|
||||||
|
private Fixture _fixture;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void StarUp()
|
||||||
|
{
|
||||||
|
_fixture = new Fixture();
|
||||||
|
_passwordHasher = new PasswordHasher();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Given_Password_When_Hash_Then_Hash_And_Verify_Then_Result_Should_Be_True()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string password = _fixture.Create<string>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string hash = _passwordHasher.Hash(password);
|
||||||
|
|
||||||
|
var result = _passwordHasher.Verify(password, hash);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(hash, Is.Not.EqualTo(password));
|
||||||
|
Assert.That(result, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Given_Password_NotPassword_When_Hash_Should_Not_Be_True_Then_Result_Should_Be_False()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string password = _fixture.Create<string>();
|
||||||
|
string notPassword = _fixture.Create<string>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string hash = _passwordHasher.Hash(password);
|
||||||
|
|
||||||
|
var result = _passwordHasher.Verify(notPassword, hash);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.That(result, Is.False);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using Govor.API.Services.Authentication;
|
||||||
|
using Govor.Core.DTOs;
|
||||||
|
using Govor.Core.Services;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Govor.API.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class AuthController : Controller
|
||||||
|
{
|
||||||
|
private IAccountService _accountService;
|
||||||
|
private ILogger<AuthController> _logger;
|
||||||
|
|
||||||
|
public AuthController(IAccountService accountService, ILogger<AuthController> logger)
|
||||||
|
{
|
||||||
|
_accountService = accountService;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("register")]
|
||||||
|
[RequireHttps]
|
||||||
|
public async Task<IActionResult> Register([FromBody] UserDto userDto)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _accountService.RegistrationAsync(userDto.Name, userDto.Password);
|
||||||
|
return Ok(new { Message = "User registered successfully" });
|
||||||
|
}
|
||||||
|
catch (UserAlreadyExistException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, $"Registration failed for user {userDto.Name}");
|
||||||
|
return BadRequest("Registration failed: user already exists.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Unexpected error during registration for user {Name}", userDto.Name);
|
||||||
|
return StatusCode(500, "An unexpected error occurred. Please try again later.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("login")]
|
||||||
|
[RequireHttps]
|
||||||
|
public async Task<IActionResult> Login([FromBody] UserDto userDto)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _accountService.LoginAsync(userDto.Name, userDto.Password);
|
||||||
|
return Ok(new { Message = "User login successfully" });
|
||||||
|
}
|
||||||
|
catch (UserNotRegisteredException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Login failed for user {Name}", userDto.Name);
|
||||||
|
return BadRequest("Login failed: user does not exist.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Unexpected error during login for user {Name}", userDto.Name);
|
||||||
|
return StatusCode(500, "An unexpected error occurred. Please try again later.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using Govor.Core.Services;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Govor.API.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("invite")]
|
||||||
|
public class InviteController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IGroupService _groupService;
|
||||||
|
|
||||||
|
public InviteController(IGroupService groupService)
|
||||||
|
{
|
||||||
|
_groupService = groupService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{code}")]
|
||||||
|
public IActionResult JoinGroup(string code)
|
||||||
|
{
|
||||||
|
var group = _groupService.GetGroupByInvite(code);
|
||||||
|
if (group == null) return NotFound();
|
||||||
|
|
||||||
|
// Вернуть инфу, которая откроется в MAUI-клиенте
|
||||||
|
return Ok(new
|
||||||
|
{
|
||||||
|
groupId = group.Id,
|
||||||
|
name = group.Name,
|
||||||
|
isChannel = group.IsChannel
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
|
||||||
@@ -21,9 +22,4 @@
|
|||||||
<ProjectReference Include="..\Govor.Data\Govor.Data.csproj" />
|
<ProjectReference Include="..\Govor.Data\Govor.Data.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Controllers\" />
|
|
||||||
<Folder Include="Services\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Govor.Core.Infrastructure.Extensions;
|
||||||
|
using Govor.Core.Repositories;
|
||||||
|
using Govor.Core.Services;
|
||||||
|
|
||||||
|
namespace Govor.API.Services.Authentication;
|
||||||
|
|
||||||
|
public class AuthService : IAccountService
|
||||||
|
{
|
||||||
|
private readonly IPasswordHasher _passwordHasher;
|
||||||
|
private readonly IUsersRepository _usersRepository;
|
||||||
|
|
||||||
|
public AuthService(IUsersRepository usersRepository, IPasswordHasher passwordHasher)
|
||||||
|
{
|
||||||
|
_usersRepository = usersRepository;
|
||||||
|
_passwordHasher = passwordHasher;
|
||||||
|
}
|
||||||
|
public Task RegistrationAsync(string name, string password)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> LoginAsync(string name, string password)
|
||||||
|
{
|
||||||
|
if (await _usersRepository.ExistsUsernameAsync(name) == false)
|
||||||
|
throw new UserNotRegisteredException(name);
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserAlreadyExistException(string username) : Exception($"{username} is already exists!") { }
|
||||||
|
|
||||||
|
public class UserNotRegisteredException(string username) : Exception($"{username} is not registered!") { }
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using Govor.Core.Infrastructure.Extensions;
|
||||||
|
|
||||||
|
namespace Govor.API.Services;
|
||||||
|
|
||||||
|
public class PasswordHasher : IPasswordHasher
|
||||||
|
{
|
||||||
|
public string Hash(string password)
|
||||||
|
{
|
||||||
|
return BCrypt.Net.BCrypt.HashPassword(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Verify(string hashedPassword, string providedPassword)
|
||||||
|
{
|
||||||
|
return BCrypt.Net.BCrypt.Verify(hashedPassword, providedPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Govor.Core.DTOs;
|
||||||
|
|
||||||
|
public record UserDto(string Password, string Name);
|
||||||
@@ -6,10 +6,6 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="DTOs\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Govor.Core.Infrastructure.Extensions;
|
||||||
|
|
||||||
|
public interface IPasswordHasher
|
||||||
|
{
|
||||||
|
string Hash(string password);
|
||||||
|
bool Verify(string hashedPassword, string providedPassword);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Govor.Core.Services;
|
||||||
|
|
||||||
|
public interface IAccountService
|
||||||
|
{
|
||||||
|
public Task RegistrationAsync(string name, string password);
|
||||||
|
public Task<string> LoginAsync(string name, string password);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using Govor.Core.Models;
|
||||||
|
|
||||||
|
namespace Govor.Core.Services;
|
||||||
|
|
||||||
|
public interface IGroupService
|
||||||
|
{
|
||||||
|
ChatGroup GetGroupByInvite(string code);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user