This commit is contained in:
Artemy
2025-07-01 13:25:55 +07:00
parent f855b91155
commit 5883f3e340
12 changed files with 70 additions and 30 deletions
@@ -48,7 +48,7 @@ public class AuthControllerTests
var invitation = _fixture.Create<Invitation>(); var invitation = _fixture.Create<Invitation>();
var token = _fixture.Create<string>(); var token = _fixture.Create<string>();
_invitesServiceMock.Setup(s => s.Validate(request.InviteLink)).Returns(invitation); _invitesServiceMock.Setup(s => s.ValidateAsync(request.InviteLink)).ReturnsAsync(invitation);
_accountServiceMock.Setup(s => s.RegistrationAsync(request.Name, request.Password, invitation)).ReturnsAsync(token); _accountServiceMock.Setup(s => s.RegistrationAsync(request.Name, request.Password, invitation)).ReturnsAsync(token);
// Act // Act
@@ -80,7 +80,7 @@ public class AuthControllerTests
{ {
// Arrange // Arrange
var request = _fixture.Create<RegistrationRequest>(); var request = _fixture.Create<RegistrationRequest>();
_invitesServiceMock.Setup(s => s.Validate(request.InviteLink)).Throws(new InviteLinkInvalidException(request.InviteLink)); _invitesServiceMock.Setup(s => s.ValidateAsync(request.InviteLink)).ThrowsAsync(new InviteLinkInvalidException(request.InviteLink));
// Act // Act
var result = await _controller.Register(request); var result = await _controller.Register(request);
@@ -97,7 +97,7 @@ public class AuthControllerTests
// Arrange // Arrange
var request = _fixture.Create<RegistrationRequest>(); var request = _fixture.Create<RegistrationRequest>();
var invitation = _fixture.Create<Invitation>(); var invitation = _fixture.Create<Invitation>();
_invitesServiceMock.Setup(s => s.Validate(request.InviteLink)).Returns(invitation); _invitesServiceMock.Setup(s => s.ValidateAsync(request.InviteLink)).ReturnsAsync(invitation);
_accountServiceMock.Setup(s => s.RegistrationAsync(request.Name, request.Password, invitation)) _accountServiceMock.Setup(s => s.RegistrationAsync(request.Name, request.Password, invitation))
.ThrowsAsync(new UserAlreadyExistException(request.Name)); .ThrowsAsync(new UserAlreadyExistException(request.Name));
@@ -116,7 +116,7 @@ public class AuthControllerTests
// Arrange // Arrange
var request = _fixture.Create<RegistrationRequest>(); var request = _fixture.Create<RegistrationRequest>();
var invitation = _fixture.Create<Invitation>(); var invitation = _fixture.Create<Invitation>();
_invitesServiceMock.Setup(s => s.Validate(request.InviteLink)).Returns(invitation); _invitesServiceMock.Setup(s => s.ValidateAsync(request.InviteLink)).ReturnsAsync(invitation);
_accountServiceMock.Setup(s => s.RegistrationAsync(request.Name, request.Password, invitation)) _accountServiceMock.Setup(s => s.RegistrationAsync(request.Name, request.Password, invitation))
.ThrowsAsync(new System.Exception("Generic error")); .ThrowsAsync(new System.Exception("Generic error"));
@@ -233,7 +233,6 @@ public class FriendsControllerTests
} }
// Tests for AcceptFriend action // Tests for AcceptFriend action
[Test] [Test]
public async Task AcceptFriend_ValidRequest_ReturnsOkResult() public async Task AcceptFriend_ValidRequest_ReturnsOkResult()
{ {
@@ -45,7 +45,7 @@ public class JwtServiceTests
// Arrange // Arrange
var user = _fixture.Create<User>(); var user = _fixture.Create<User>();
var expectedRole = "User"; var expectedRole = "User";
_invitesServiceMock.Setup(s => s.GetRole(user)).Returns(Task.FromResult(expectedRole)); _invitesServiceMock.Setup(s => s.GetRoleAsync(user)).Returns(Task.FromResult(expectedRole));
// Act // Act
var tokenString = _jwtService.GenerateJwtToken(user); var tokenString = _jwtService.GenerateJwtToken(user);
@@ -1,4 +1,6 @@
using Govor.API.Services.AdminsStuff.Interfaces; using Govor.API.Services.AdminsStuff.Interfaces;
using Govor.Contracts.Responses.Admins;
using Govor.Core.Models;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -25,7 +27,7 @@ public class UsersController : Controller
_logger.LogInformation("Getting all users by administrator"); _logger.LogInformation("Getting all users by administrator");
var read = await _users.GetAllUsersAsync(); var read = await _users.GetAllUsersAsync();
return Ok(read); return Ok(BuildUserDtos(read));
} }
[HttpGet("{id:guid}")] [HttpGet("{id:guid}")]
@@ -33,4 +35,18 @@ public class UsersController : Controller
{ {
return Ok(id); return Ok(id);
} }
private List<UserResponse> BuildUserDtos(IEnumerable<User> users) => users.Select(user => new UserResponse
{
Id = user.Id,
Username = user.Username,
Description = user.Description,
WasOnline = user.WasOnline,
IconId = user.IconId,
PasswordHash = user.PasswordHash,
InviteId = user.InviteId,
CreatedOn = user.CreatedOn,
IsAdmin = user.Invite?.IsAdmin ?? false,
}).ToList();
} }
+7 -5
View File
@@ -3,11 +3,13 @@ using Govor.Application.Exceptions.AuthService;
using Govor.Application.Exceptions.InvitesService; using Govor.Application.Exceptions.InvitesService;
using Govor.Application.Interfaces.Authentication; using Govor.Application.Interfaces.Authentication;
using Govor.Contracts.Requests; using Govor.Contracts.Requests;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Govor.API.Controllers; namespace Govor.API.Controllers;
[ApiController] [ApiController]
[AllowAnonymous]
[Route("api/[controller]")] [Route("api/[controller]")]
public class AuthController : Controller public class AuthController : Controller
{ {
@@ -23,7 +25,7 @@ public class AuthController : Controller
} }
[HttpPost("register")]// api/auth/register [HttpPost("register")]// api/auth/register
[RequireHttps] //[RequireHttps]
public async Task<IActionResult> Register([FromBody] RegistrationRequest registrationRequest) public async Task<IActionResult> Register([FromBody] RegistrationRequest registrationRequest)
{ {
try try
@@ -33,11 +35,11 @@ public class AuthController : Controller
return BadRequest(ModelState); return BadRequest(ModelState);
} }
var invite = _invitesService.Validate(registrationRequest.InviteLink); var invite = await _invitesService.ValidateAsync(registrationRequest.InviteLink);
var token = await _accountService.RegistrationAsync(registrationRequest.Name, registrationRequest.Password, var token = await _accountService.RegistrationAsync(registrationRequest.Name, registrationRequest.Password,
invite); invite);
_logger.LogInformation($"Register request for {registrationRequest.Name}"); _logger.LogInformation($"Register request for {registrationRequest.Name} processed successfully");
return Ok(new { token }); return Ok(new { token });
} }
catch (UserAlreadyExistException ex) catch (UserAlreadyExistException ex)
@@ -63,7 +65,7 @@ public class AuthController : Controller
} }
[HttpPost("login")]// api/auth/login [HttpPost("login")]// api/auth/login
[RequireHttps] //[RequireHttps]
public async Task<IActionResult> Login([FromBody] LoginRequest userRequest) public async Task<IActionResult> Login([FromBody] LoginRequest userRequest)
{ {
try try
@@ -74,7 +76,7 @@ public class AuthController : Controller
} }
var token = await _accountService.LoginAsync(userRequest.Name, userRequest.Password); var token = await _accountService.LoginAsync(userRequest.Name, userRequest.Password);
_logger.LogInformation($"Login request for {userRequest.Name}"); _logger.LogInformation($"Login request for {userRequest.Name} processed successfully");
return Ok(new { token }); return Ok(new { token });
} }
catch (UserNotRegisteredException ex) catch (UserNotRegisteredException ex)
+1 -1
View File
@@ -26,7 +26,7 @@ public class FriendsController : Controller
_currentUserService = currentUserService; _currentUserService = currentUserService;
} }
[HttpGet("search")] [HttpGet("search")] // api/friends/search?query=
public async Task<IActionResult> Search(string query) public async Task<IActionResult> Search(string query)
{ {
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
+1 -2
View File
@@ -2,12 +2,11 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" /> <PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.6" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
+5 -2
View File
@@ -17,7 +17,7 @@ builder.Services.AddCors(options =>
{ {
options.AddPolicy("AllowFrontend", policy => options.AddPolicy("AllowFrontend", policy =>
{ {
policy.WithOrigins("http://localhost:3000", "https://localhost:3000") policy.WithOrigins("http://localhost:5000", "https://localhost:5000")
.AllowAnyHeader() .AllowAnyHeader()
.AllowAnyMethod() .AllowAnyMethod()
.AllowCredentials(); .AllowCredentials();
@@ -106,7 +106,10 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI(); app.UseSwaggerUI();
} }
app.UseHttpsRedirection();
app.UseCors();
//app.UseHttpsRedirection();
app.UseRouting(); app.UseRouting();
@@ -4,6 +4,6 @@ namespace Govor.API.Services.Authentication.Interfaces;
public interface IInvitesService public interface IInvitesService
{ {
public Task<string> GetRole(User user); public Task<string> GetRoleAsync(User user);
public Invitation Validate(string inviteCode); public Task<Invitation> ValidateAsync(string inviteCode);
} }
+17 -10
View File
@@ -15,7 +15,7 @@ public class InvitesService : IInvitesService
_invitesRepository = invitesRepository; _invitesRepository = invitesRepository;
} }
public async Task<string> GetRole(User user) public async Task<string> GetRoleAsync(User user)
{ {
try try
{ {
@@ -28,21 +28,28 @@ public class InvitesService : IInvitesService
} }
} }
public Invitation Validate(string inviteCode) public async Task<Invitation> ValidateAsync(string inviteCode)
{ {
var invite = _invitesRepository.FindByCodeAsync(inviteCode).Result; try
{
if (invite.EndDate < DateTime.Now || var invite = await _invitesRepository.FindByCodeAsync(inviteCode);
invite.MaxParticipants <= invite.Users.Count)
if (invite.EndDate < DateTime.Now || invite.MaxParticipants <= invite.Users.Count)
{
invite.IsActive = false;
await _invitesRepository.UpdateAsync(invite);
throw new InviteLinkInvalidException(inviteCode);
}
return invite;
}
catch (NotFoundByKeyException<string>)
{ {
invite.IsActive = false;
_invitesRepository.UpdateAsync(invite);
throw new InviteLinkInvalidException(inviteCode); throw new InviteLinkInvalidException(inviteCode);
} }
return invite;
} }
public string GenerateInvitationLink(Invitation invitation) public string GenerateInvitationLink(Invitation invitation)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
+1 -1
View File
@@ -24,7 +24,7 @@ public class JwtService : IJwtService
var claims = new[] var claims = new[]
{ {
new Claim("userID", user.Id.ToString()), new Claim("userID", user.Id.ToString()),
new Claim(ClaimTypes.Role, _invitesService.GetRole(user).Result, ClaimValueTypes.String) new Claim(ClaimTypes.Role, _invitesService.GetRoleAsync(user).Result, ClaimValueTypes.String)
}; };
var singing = new SigningCredentials( var singing = new SigningCredentials(
@@ -0,0 +1,14 @@
namespace Govor.Contracts.Responses.Admins;
public class UserResponse
{
public Guid Id { get; set; }
public string Username { get; set; }
public string Description { get; set; }
public string PasswordHash { get; set; }
public DateTime WasOnline { get; set; }
public DateOnly CreatedOn { get; set; }
public Guid IconId {get; set;}
public Guid InviteId {get; set;}
public bool IsAdmin {get; set;}
}