diff --git a/dotnet/AipsCore/Application/Abstract/Query/IQueryHandler.cs b/dotnet/AipsCore/Application/Abstract/Query/IQueryHandler.cs index d3e8632..fc6002a 100644 --- a/dotnet/AipsCore/Application/Abstract/Query/IQueryHandler.cs +++ b/dotnet/AipsCore/Application/Abstract/Query/IQueryHandler.cs @@ -3,5 +3,5 @@ public interface IQueryHandler where TQuery : IQuery { - Task HandleAsync(TQuery query, CancellationToken cancellationToken = default); + Task Handle(TQuery query, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/dotnet/AipsCore/Application/Models/User/Query/GetUser/GetUserQuery.cs b/dotnet/AipsCore/Application/Models/User/Query/GetUser/GetUserQuery.cs new file mode 100644 index 0000000..48f6ad5 --- /dev/null +++ b/dotnet/AipsCore/Application/Models/User/Query/GetUser/GetUserQuery.cs @@ -0,0 +1,5 @@ +using AipsCore.Application.Abstract.Query; + +namespace AipsCore.Application.Models.User.Query.GetUser; + +public record GetUserQuery(string UserId) : IQuery; \ No newline at end of file diff --git a/dotnet/AipsCore/Application/Models/User/Query/GetUser/GetUserQueryHandler.cs b/dotnet/AipsCore/Application/Models/User/Query/GetUser/GetUserQueryHandler.cs new file mode 100644 index 0000000..7de30d1 --- /dev/null +++ b/dotnet/AipsCore/Application/Models/User/Query/GetUser/GetUserQueryHandler.cs @@ -0,0 +1,32 @@ +using AipsCore.Application.Abstract.Query; +using AipsCore.Domain.Common.Validation; +using AipsCore.Domain.Models.User.Validation; +using AipsCore.Domain.Models.User.ValueObjects; +using AipsCore.Infrastructure.Persistence.Db; +using Microsoft.EntityFrameworkCore; + +namespace AipsCore.Application.Models.User.Query.GetUser; + +public class GetUserQueryHandler : IQueryHandler +{ + private readonly AipsDbContext _context; + + public GetUserQueryHandler(AipsDbContext context) + { + _context = context; + } + + public async Task Handle(GetUserQuery query, CancellationToken cancellationToken = default) + { + var result = await _context.Users + .Where(u => u.Id.ToString() == query.UserId) + .FirstOrDefaultAsync(cancellationToken); + + if (result is null) + { + throw new ValidationException(UserErrors.NotFound(new UserId(query.UserId))); + } + + return result; + } +} \ No newline at end of file diff --git a/dotnet/AipsCore/Application/Models/Whiteboard/Query/GetRecentWhiteboards/GetRecentWhiteboardsQuery.cs b/dotnet/AipsCore/Application/Models/Whiteboard/Query/GetRecentWhiteboards/GetRecentWhiteboardsQuery.cs new file mode 100644 index 0000000..1656f2b --- /dev/null +++ b/dotnet/AipsCore/Application/Models/Whiteboard/Query/GetRecentWhiteboards/GetRecentWhiteboardsQuery.cs @@ -0,0 +1,5 @@ +using AipsCore.Application.Abstract.Query; + +namespace AipsCore.Application.Models.Whiteboard.Query.GetRecentWhiteboards; + +public record GetRecentWhiteboardsQuery(string UserId): IQuery>; \ No newline at end of file diff --git a/dotnet/AipsCore/Application/Models/Whiteboard/Query/GetRecentWhiteboards/GetRecentWhiteboardsQueryHandler.cs b/dotnet/AipsCore/Application/Models/Whiteboard/Query/GetRecentWhiteboards/GetRecentWhiteboardsQueryHandler.cs new file mode 100644 index 0000000..a58d5b5 --- /dev/null +++ b/dotnet/AipsCore/Application/Models/Whiteboard/Query/GetRecentWhiteboards/GetRecentWhiteboardsQueryHandler.cs @@ -0,0 +1,35 @@ +using AipsCore.Application.Abstract.Query; +using AipsCore.Infrastructure.Persistence.Db; +using Microsoft.EntityFrameworkCore; + +namespace AipsCore.Application.Models.Whiteboard.Query.GetRecentWhiteboards; + +public class GetRecentWhiteboardsQueryHandler : IQueryHandler> +{ + private readonly AipsDbContext _context; + + public GetRecentWhiteboardsQueryHandler(AipsDbContext context) + { + _context = context; + } + + public async Task> Handle(GetRecentWhiteboardsQuery query, CancellationToken cancellationToken = default) + { + return await GetQuery(query.UserId).ToListAsync(cancellationToken); + } + + private IQueryable GetQuery(string userId) + { + Guid userIdGuid = Guid.Parse(userId); + + return _context.WhiteboardMemberships + .Include(m => m.Whiteboard) + .Where(m => ( + m.UserId == userIdGuid && + m.IsBanned == false && + m.Whiteboard != null + )) + .OrderByDescending(m => m.LastInteractedAt) + .Select(m => m.Whiteboard!); + } +} \ No newline at end of file diff --git a/dotnet/AipsWebApi/Controllers/UserController.cs b/dotnet/AipsWebApi/Controllers/UserController.cs index f3a3f83..fe49a91 100644 --- a/dotnet/AipsWebApi/Controllers/UserController.cs +++ b/dotnet/AipsWebApi/Controllers/UserController.cs @@ -1,5 +1,6 @@ using AipsCore.Application.Abstract; using AipsCore.Application.Models.User.Command.CreateUser; +using AipsCore.Application.Models.User.Query.GetUser; using AipsCore.Domain.Common.Validation; using AipsCore.Domain.Models.User.ValueObjects; using Microsoft.AspNetCore.Mvc; @@ -10,10 +11,25 @@ namespace AipsWebApi.Controllers; [Route("[controller]")] public class UserController : ControllerBase { - [HttpPost] - public async Task> CreateUser(CreateUserCommand command, IDispatcher dispatcher, CancellationToken cancellationToken) + private readonly IDispatcher _dispatcher; + + public UserController(IDispatcher dispatcher) { - var userId = await dispatcher.Execute(command, cancellationToken); + _dispatcher = dispatcher; + } + + [HttpGet("{userId}")] + public async Task GetUser([FromRoute] string userId, CancellationToken cancellationToken) + { + var query = new GetUserQuery(userId); + var result = await _dispatcher.Execute(query, cancellationToken); + return Ok(result); + } + + [HttpPost] + public async Task> CreateUser(CreateUserCommand command, CancellationToken cancellationToken) + { + var userId = await _dispatcher.Execute(command, cancellationToken); return Ok(userId.IdValue); } } \ No newline at end of file diff --git a/dotnet/AipsWebApi/Controllers/WeatherForecastController.cs b/dotnet/AipsWebApi/Controllers/WeatherForecastController.cs deleted file mode 100644 index 77b4928..0000000 --- a/dotnet/AipsWebApi/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace AipsWebApi.Controllers; - -[ApiController] -[Route("[controller]")] -public class WeatherForecastController : ControllerBase -{ - private static readonly string[] Summaries = - [ - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - ]; - - [HttpGet(Name = "GetWeatherForecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } -} \ No newline at end of file diff --git a/dotnet/AipsWebApi/Controllers/WhiteboardController.cs b/dotnet/AipsWebApi/Controllers/WhiteboardController.cs index 036e12f..3be4f40 100644 --- a/dotnet/AipsWebApi/Controllers/WhiteboardController.cs +++ b/dotnet/AipsWebApi/Controllers/WhiteboardController.cs @@ -4,6 +4,8 @@ using AipsCore.Application.Models.Whiteboard.Command.BanUserFromWhiteboard; using AipsCore.Application.Models.Whiteboard.Command.CreateWhiteboard; using AipsCore.Application.Models.Whiteboard.Command.KickUserFromWhiteboard; using AipsCore.Application.Models.Whiteboard.Command.UnbanUserFromWhiteboard; +using AipsCore.Application.Models.Whiteboard.Query.GetRecentWhiteboards; +using AipsCore.Domain.Models.Whiteboard; using Microsoft.AspNetCore.Mvc; namespace AipsWebApi.Controllers; @@ -12,39 +14,54 @@ namespace AipsWebApi.Controllers; [Route("[controller]")] public class WhiteboardController : ControllerBase { - [HttpPost] - public async Task> CreateWhiteboard(CreateWhiteboardCommand command, IDispatcher dispatcher, CancellationToken cancellationToken) + private readonly IDispatcher _dispatcher; + + public WhiteboardController(IDispatcher dispatcher) { - var whiteboardId = await dispatcher.Execute(command, cancellationToken); + _dispatcher = dispatcher; + } + + [HttpPost] + public async Task> CreateWhiteboard(CreateWhiteboardCommand command, CancellationToken cancellationToken) + { + var whiteboardId = await _dispatcher.Execute(command, cancellationToken); return Ok(whiteboardId.IdValue); } [HttpPost("adduser")] - public async Task AddUser(AddUserToWhiteboardCommand command, IDispatcher dispatcher, + public async Task AddUser(AddUserToWhiteboardCommand command, CancellationToken cancellationToken) { - await dispatcher.Execute(command, cancellationToken); + await _dispatcher.Execute(command, cancellationToken); return Ok(); } + + [HttpGet("recent")] + public async Task>> Recent(GetRecentWhiteboardsQuery query, CancellationToken cancellationToken) + { + var result = await _dispatcher.Execute(query, cancellationToken); + + return Ok(result); + } [HttpPut("banUser")] - public async Task BanUserFromWhiteboard(BanUserFromWhiteboardCommand command, IDispatcher dispatcher, CancellationToken cancellationToken) + public async Task BanUserFromWhiteboard(BanUserFromWhiteboardCommand command, CancellationToken cancellationToken) { - await dispatcher.Execute(command, cancellationToken); + await _dispatcher.Execute(command, cancellationToken); return Ok(); } [HttpPut("unbanUser")] - public async Task UnbanUserFromWhiteboard(UnbanUserFromWhiteboardCommand command, IDispatcher dispatcher, CancellationToken cancellationToken) + public async Task UnbanUserFromWhiteboard(UnbanUserFromWhiteboardCommand command, CancellationToken cancellationToken) { - await dispatcher.Execute(command, cancellationToken); + await _dispatcher.Execute(command, cancellationToken); return Ok(); } [HttpPut("kickUser")] - public async Task KickUserFromWhiteboard(KickUserFromWhiteboardCommand command, IDispatcher dispatcher, CancellationToken cancellationToken) + public async Task KickUserFromWhiteboard(KickUserFromWhiteboardCommand command, CancellationToken cancellationToken) { - await dispatcher.Execute(command, cancellationToken); + await _dispatcher.Execute(command, cancellationToken); return Ok(); } } \ No newline at end of file diff --git a/dotnet/AipsWebApi/WeatherForecast.cs b/dotnet/AipsWebApi/WeatherForecast.cs deleted file mode 100644 index 0f4742b..0000000 --- a/dotnet/AipsWebApi/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace AipsWebApi; - -public class WeatherForecast -{ - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } -} \ No newline at end of file