mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 19:54:55 +00:00
Created SessionController and UserSessionReader
+ tests for UserSessionReader
This commit is contained in:
@@ -87,6 +87,8 @@ public static class ConfigurationProgramExtensions
|
||||
services.AddAutoMapper(typeof(MappingProfile));
|
||||
|
||||
services.AddScoped<IHubUserAccessor, HubUserAccessor>();
|
||||
|
||||
services.AddScoped<IUserSessionReader, UserSessionReader>();
|
||||
}
|
||||
|
||||
public static void AddRepositories(this IServiceCollection services)
|
||||
|
||||
@@ -21,5 +21,7 @@ public class MappingProfile : Profile
|
||||
.AfterMap<UserToUserDtoMappingAction>();
|
||||
|
||||
CreateMap<Friendship, FriendshipDto>();
|
||||
|
||||
CreateMap<UserSession, SessionDto>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using AutoMapper;
|
||||
using Govor.Application.Interfaces.Infrastructure.Extensions;
|
||||
using Govor.Application.Interfaces.UserSession;
|
||||
using Govor.Contracts.DTOs;
|
||||
using Govor.Data.Repositories.Exceptions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Govor.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize(Roles = "Admin,User")]
|
||||
[Route("api/[controller]")]
|
||||
public class SessionController : Controller
|
||||
{
|
||||
private readonly ILogger<SessionController> _logger;
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
private readonly IUserSessionReader _userSessionReader;
|
||||
private readonly IUserSessionRevoker _userSessionRevoker;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public SessionController(
|
||||
ILogger<SessionController> logger,
|
||||
ICurrentUserService currentUserService,
|
||||
IUserSessionReader userSessionReader,
|
||||
IUserSessionRevoker userSessionRevoker,
|
||||
IMapper mapper)
|
||||
{
|
||||
_logger = logger;
|
||||
_currentUserService = currentUserService;
|
||||
_userSessionReader = userSessionReader;
|
||||
_userSessionRevoker = userSessionRevoker;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
[HttpGet("all")]
|
||||
public async Task<IActionResult> GetAllSessions()
|
||||
{
|
||||
try
|
||||
{
|
||||
var sessions = await _userSessionReader.GetAllSessionsAsync(_currentUserService.GetCurrentUserId());
|
||||
return Ok(_mapper.Map<List<SessionDto>>(sessions));
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, ex.Message);
|
||||
return Forbid(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, ex.Message);
|
||||
return StatusCode(500, "Unexpected Error! Please try again later.");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("close/{sessionId}")]
|
||||
public async Task<IActionResult> CloseSession(Guid sessionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sessionId == Guid.Empty)
|
||||
return BadRequest("Invalid sessionId.");
|
||||
|
||||
await _userSessionRevoker.CloseSessionByIdAsync(sessionId,
|
||||
_currentUserService.GetCurrentUserId());
|
||||
return Ok();
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
_logger.LogError(ex, ex.Message);
|
||||
return BadRequest(ex.Message);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, ex.Message);
|
||||
return Forbid(ex.Message);
|
||||
}
|
||||
catch (NotFoundException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, ex.Message);
|
||||
return NotFound(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, ex.Message);
|
||||
return StatusCode(500, "Unexpected Error! Please try again later.");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("close/all")]
|
||||
public async Task<IActionResult> CloseAllSessions()
|
||||
{
|
||||
try
|
||||
{
|
||||
await _userSessionRevoker.CloseAllSessionsAsync(_currentUserService.GetCurrentUserId());
|
||||
return Ok();
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, ex.Message);
|
||||
return Forbid(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, ex.Message);
|
||||
return StatusCode(500, "Unexpected Error! Please try again later.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using AutoFixture;
|
||||
using Govor.Application.Interfaces.UserSession;
|
||||
using Govor.Application.Services.UserSessions;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Repositories.UserSessionsRepository;
|
||||
using Govor.Data.Repositories.Exceptions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace Govor.Application.Tests.Services.UserSessions;
|
||||
|
||||
[TestFixture]
|
||||
[TestOf(typeof(UserSessionReader))]
|
||||
public class UserSessionReaderTests
|
||||
{
|
||||
private Mock<IUserSessionsRepository> _mockUserSessionsRepository;
|
||||
private Mock<ILogger<UserSessionReader>> _mockLogger;
|
||||
private Fixture _fixture;
|
||||
private IUserSessionReader _userSessionReader;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
|
||||
_mockUserSessionsRepository = new Mock<IUserSessionsRepository>();
|
||||
_mockLogger = new Mock<ILogger<UserSessionReader>>();
|
||||
|
||||
_userSessionReader = new UserSessionReader(_mockUserSessionsRepository.Object,
|
||||
_mockLogger.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetAllUserSessionsAsync_ShouldReturnAllUserSessions()
|
||||
{
|
||||
// Arrange
|
||||
var sessios = _fixture.CreateMany<UserSession>().ToList();
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
_mockUserSessionsRepository.Setup(f => f.GetByUserIdAsync(userId))
|
||||
.ReturnsAsync(sessios);
|
||||
// Act
|
||||
var result = await _userSessionReader.GetAllSessionsAsync(userId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.EquivalentTo(sessios));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetAllUserSessionsAsync_ThrowsNotFoundByKeyException_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
_mockUserSessionsRepository.Setup(f => f.GetByUserIdAsync(userId))
|
||||
.ThrowsAsync(new NotFoundByKeyException<Guid>(userId));
|
||||
|
||||
// Act
|
||||
var result = await _userSessionReader.GetAllSessionsAsync(userId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.Not.Null);
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,6 @@ namespace Govor.Application.Interfaces.UserSession;
|
||||
|
||||
public interface IUserSessionRevoker
|
||||
{
|
||||
Task CloseSessionByRefreshTokenAsync(string refreshToken);
|
||||
Task CloseSessionByIdAsync(Guid sessionId, Guid userId);
|
||||
Task CloseAllSessionsAsync(Guid userId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Govor.Application.Interfaces.UserSession;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Repositories.UserSessionsRepository;
|
||||
using Govor.Data.Repositories.Exceptions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Govor.Application.Services.UserSessions;
|
||||
|
||||
public class UserSessionReader : IUserSessionReader
|
||||
{
|
||||
private readonly IUserSessionsRepository _repository;
|
||||
private readonly ILogger<UserSessionReader> _logger;
|
||||
|
||||
public UserSessionReader(IUserSessionsRepository repository, ILogger<UserSessionReader> logger)
|
||||
{
|
||||
_repository = repository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<List<UserSession>> GetAllSessionsAsync(Guid userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation($"Getting all sessions for user {userId}");
|
||||
var sessions = await _repository.GetByUserIdAsync(userId);
|
||||
return sessions;
|
||||
}
|
||||
catch (NotFoundByKeyException<Guid> ex)
|
||||
{
|
||||
_logger.LogWarning("The user has no active sessions.");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Govor.Contracts.DTOs;
|
||||
|
||||
public record SessionDto
|
||||
{
|
||||
public Guid Id { get; init; }
|
||||
public string DeviceInfo { get; init; } = string.Empty;
|
||||
public DateTime CreatedAt { get; init; }
|
||||
public DateTime ExpiresAt { get; init; }
|
||||
public bool IsRevoked { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user