WIP: working on get todo by id
This commit is contained in:
11
src/backend/server/src/Todo.Api/Controllers/ApiController.cs
Normal file
11
src/backend/server/src/Todo.Api/Controllers/ApiController.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Todo.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
public class ApiController : ControllerBase
|
||||
{
|
||||
public IMediator Mediator => HttpContext.RequestServices.GetRequiredService<IMediator>();
|
||||
}
|
@@ -14,10 +14,7 @@ public class AuthController : ControllerBase
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
|
||||
public AuthController(IUserRepository userRepository)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
}
|
||||
public AuthController(IUserRepository userRepository) => _userRepository = userRepository;
|
||||
|
||||
[HttpPost("register")]
|
||||
public async Task<IActionResult> Register(
|
||||
|
@@ -1,55 +1,54 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Todo.Core.Application.Commands.Todo;
|
||||
using Todo.Core.Application.Queries.Todos;
|
||||
using Todo.Core.Interfaces.Persistence;
|
||||
|
||||
namespace Todo.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("/api/todos")]
|
||||
public class TodosController : ControllerBase
|
||||
[Authorize]
|
||||
public class TodosController : ApiController
|
||||
{
|
||||
private readonly ITodoRepository _todoRepository;
|
||||
|
||||
public TodosController(ITodoRepository todoRepository)
|
||||
{
|
||||
_todoRepository = todoRepository;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<Core.Entities.Todo>> CreateTodo(
|
||||
[FromBody] CreateTodoRequest request)
|
||||
{
|
||||
var userId = User.FindFirstValue("sub") ??
|
||||
throw new InvalidOperationException("Could not get user, something has gone terribly wrong");
|
||||
|
||||
return Ok(
|
||||
await _todoRepository.CreateTodoAsync(
|
||||
request.Title,
|
||||
string.Empty,
|
||||
"",
|
||||
userId));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<IEnumerable<Core.Entities.Todo>>> GetTodos()
|
||||
{
|
||||
return Ok(await _todoRepository.GetTodosAsync());
|
||||
}
|
||||
|
||||
[HttpGet("not-done")]
|
||||
public async Task<ActionResult<IEnumerable<Core.Entities.Todo>>>
|
||||
GetNotDoneTodos()
|
||||
{
|
||||
return Ok(await _todoRepository.GetNotDoneTodos());
|
||||
}
|
||||
public TodosController(ITodoRepository todoRepository) => _todoRepository = todoRepository;
|
||||
|
||||
public record CreateTodoRequest
|
||||
{
|
||||
[Required]
|
||||
[JsonPropertyName("title")]
|
||||
public string Title { get; init; }
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; init; }
|
||||
|
||||
[JsonPropertyName("project")]
|
||||
public string? Project { get; init; }
|
||||
|
||||
internal CreateTodoCommand To() => new(
|
||||
Title,
|
||||
Project,
|
||||
Description);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<string>> CreateTodo(
|
||||
[FromBody] CreateTodoRequest request)
|
||||
=> Ok(await Mediator.Send(request.To()));
|
||||
|
||||
[HttpGet("{todoId}")]
|
||||
public async Task<ActionResult<TodoViewModel>> GetTodoById([FromRoute] string todoId)
|
||||
=> await Mediator.Send(new GetTodoByIdQuery(todoId));
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<IEnumerable<Core.Entities.Todo>>> GetTodos()
|
||||
=> Ok(await _todoRepository.GetTodosAsync());
|
||||
|
||||
[HttpGet("not-done")]
|
||||
public async Task<ActionResult<IEnumerable<Core.Entities.Todo>>>
|
||||
GetNotDoneTodos()
|
||||
=> Ok(await _todoRepository.GetNotDoneTodos());
|
||||
}
|
@@ -188,9 +188,7 @@ public class TodoHub : Hub
|
||||
await action(connections);
|
||||
}
|
||||
|
||||
private string GetUserId()
|
||||
{
|
||||
return _currentUserService.GetUserId() ??
|
||||
throw new InvalidOperationException("User id was invalid. Something has gone terribly wrong");
|
||||
}
|
||||
private string GetUserId() => _currentUserService.GetUserId() ??
|
||||
throw new InvalidOperationException(
|
||||
"User id was invalid. Something has gone terribly wrong");
|
||||
}
|
@@ -10,12 +10,7 @@ public class HttpContextCurrentUserService : ICurrentUserService
|
||||
|
||||
public HttpContextCurrentUserService(
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
=> _httpContextAccessor = httpContextAccessor;
|
||||
|
||||
public string? GetUserId()
|
||||
{
|
||||
return _httpContextAccessor.HttpContext?.User.FindFirstValue("sub");
|
||||
}
|
||||
public string? GetUserId() => _httpContextAccessor.HttpContext?.User.FindFirstValue("sub");
|
||||
}
|
@@ -21,10 +21,7 @@ namespace Todo.Api;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
public Startup(IConfiguration configuration) => Configuration = configuration;
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading;
|
||||
using MediatR;
|
||||
using Todo.Core.Application.Notifications.Todo;
|
||||
@@ -7,7 +8,7 @@ using Todo.Core.Interfaces.User;
|
||||
namespace Todo.Core.Application.Commands.Todo;
|
||||
|
||||
public record CreateTodoCommand(
|
||||
string TodoTitle,
|
||||
[Required] string TodoTitle,
|
||||
string? TodoProject,
|
||||
string? TodoDescription) : IRequest<string>
|
||||
{
|
||||
|
@@ -13,10 +13,7 @@ public record TodoCreated(
|
||||
{
|
||||
private readonly ITodoPublisher _todoPublisher;
|
||||
|
||||
public Handler(ITodoPublisher todoPublisher)
|
||||
{
|
||||
_todoPublisher = todoPublisher;
|
||||
}
|
||||
public Handler(ITodoPublisher todoPublisher) => _todoPublisher = todoPublisher;
|
||||
|
||||
public async Task Handle(
|
||||
TodoCreated notification,
|
||||
|
@@ -0,0 +1,33 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading;
|
||||
using MediatR;
|
||||
using Todo.Core.Interfaces.Persistence;
|
||||
using Todo.Core.Interfaces.User;
|
||||
|
||||
namespace Todo.Core.Application.Queries.Todos;
|
||||
|
||||
public record GetTodoByIdQuery([Required] string TodoId) : IRequest<TodoViewModel>
|
||||
{
|
||||
internal class Handler : IRequestHandler<GetTodoByIdQuery, TodoViewModel>
|
||||
{
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
private readonly ITodoRepository _todoRepository;
|
||||
|
||||
public Handler(ICurrentUserService currentUserService, ITodoRepository todoRepository)
|
||||
{
|
||||
_currentUserService = currentUserService;
|
||||
_todoRepository = todoRepository;
|
||||
}
|
||||
|
||||
public async Task<TodoViewModel> Handle(GetTodoByIdQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var userId = _currentUserService.GetUserId();
|
||||
var todo = await _todoRepository.GetTodoByIdAsync(request.TodoId);
|
||||
|
||||
if (todo.AuthorId != userId)
|
||||
throw new InvalidOperationException("User is not allowed to access todo");
|
||||
|
||||
return TodoViewModel.From(todo);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
namespace Todo.Core.Application.Queries.Todos;
|
||||
|
||||
public record TodoViewModel(
|
||||
string Id,
|
||||
string Title,
|
||||
bool Status,
|
||||
string AuthorId,
|
||||
string? Project,
|
||||
string? Description
|
||||
)
|
||||
{
|
||||
internal static TodoViewModel From(Entities.Todo t) => new(
|
||||
t.Id,
|
||||
t.Title,
|
||||
t.Status,
|
||||
t.AuthorId,
|
||||
t.Project,
|
||||
t.Description);
|
||||
};
|
@@ -11,7 +11,5 @@ namespace Todo.Core;
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddCore(this IServiceCollection services)
|
||||
{
|
||||
return services.AddMediatR(Assembly.GetExecutingAssembly());
|
||||
}
|
||||
=> services.AddMediatR(Assembly.GetExecutingAssembly());
|
||||
}
|
@@ -6,16 +6,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App"/>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Application\Services"/>
|
||||
<Folder Include="Application\Services" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mediatr" Version="9.0.0"/>
|
||||
<PackageReference Include="Mediatr.Extensions.Microsoft.DependencyInjection" Version="9.0.0"/>
|
||||
<PackageReference Include="Mediatr" Version="9.0.0" />
|
||||
<PackageReference Include="Mediatr.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -49,13 +49,11 @@ public static class DependencyInjection
|
||||
|
||||
public static IApplicationBuilder UseInfrastructure(
|
||||
this IApplicationBuilder app)
|
||||
{
|
||||
return app.UseCookiePolicy(
|
||||
=> app.UseCookiePolicy(
|
||||
new CookiePolicyOptions
|
||||
{
|
||||
Secure = CookieSecurePolicy.Always
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class GiteaAuthOptions
|
||||
|
@@ -9,9 +9,7 @@ public class MongoDbConnectionHandler
|
||||
|
||||
public MongoDbConnectionHandler(
|
||||
IOptionsMonitor<MongoDbOptions> optionsMonitor)
|
||||
{
|
||||
_optionsMonitor = optionsMonitor;
|
||||
}
|
||||
=> _optionsMonitor = optionsMonitor;
|
||||
|
||||
public IMongoDatabase CreateDatabaseConnection()
|
||||
{
|
||||
@@ -30,8 +28,5 @@ public class MongoDbConnectionHandler
|
||||
}
|
||||
|
||||
public static string FormatConnectionString(MongoDbOptions options)
|
||||
{
|
||||
return
|
||||
$"mongodb://{options.Username}:{options.Password}@{options.Host}:{options.Port}";
|
||||
}
|
||||
=> $"mongodb://{options.Username}:{options.Password}@{options.Host}:{options.Port}";
|
||||
}
|
Reference in New Issue
Block a user