78 lines
2.4 KiB
C#
78 lines
2.4 KiB
C#
using System.Security.Claims;
|
|
using Backend.Data;
|
|
using Backend.Dtos;
|
|
using Backend.Models;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Backend.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/todos")]
|
|
[Authorize]
|
|
public class TodosController(AppDbContext db) : ControllerBase
|
|
{
|
|
private Guid CurrentUserId()
|
|
{
|
|
var sub = User.FindFirstValue("sub")
|
|
?? throw new InvalidOperationException("Authenticated request missing 'sub' claim");
|
|
return Guid.Parse(sub);
|
|
}
|
|
|
|
[HttpGet]
|
|
public async Task<ActionResult<IEnumerable<TodoDto>>> List()
|
|
{
|
|
var userId = CurrentUserId();
|
|
var todos = await db.Todos
|
|
.Where(t => t.UserId == userId)
|
|
.OrderByDescending(t => t.CreatedAt)
|
|
.Select(t => new TodoDto(t.Id, t.Title, t.Completed, t.CreatedAt))
|
|
.ToListAsync();
|
|
return Ok(todos);
|
|
}
|
|
|
|
[HttpPost]
|
|
public async Task<ActionResult<TodoDto>> Create([FromBody] CreateTodoRequest body)
|
|
{
|
|
if (!ModelState.IsValid) return ValidationProblem(ModelState);
|
|
|
|
var userId = CurrentUserId();
|
|
var todo = new Todo
|
|
{
|
|
UserId = userId,
|
|
Title = body.Title,
|
|
Completed = false,
|
|
CreatedAt = DateTimeOffset.UtcNow
|
|
};
|
|
db.Todos.Add(todo);
|
|
await db.SaveChangesAsync();
|
|
|
|
var dto = new TodoDto(todo.Id, todo.Title, todo.Completed, todo.CreatedAt);
|
|
return CreatedAtAction(nameof(List), new { id = todo.Id }, dto);
|
|
}
|
|
|
|
[HttpPatch("{id:long}")]
|
|
public async Task<ActionResult<TodoDto>> Update(long id, [FromBody] UpdateTodoRequest body)
|
|
{
|
|
var userId = CurrentUserId();
|
|
var todo = await db.Todos.FirstOrDefaultAsync(t => t.Id == id && t.UserId == userId);
|
|
if (todo is null) return NotFound();
|
|
|
|
if (body.Completed.HasValue) todo.Completed = body.Completed.Value;
|
|
await db.SaveChangesAsync();
|
|
|
|
return Ok(new TodoDto(todo.Id, todo.Title, todo.Completed, todo.CreatedAt));
|
|
}
|
|
|
|
[HttpDelete("{id:long}")]
|
|
public async Task<IActionResult> Delete(long id)
|
|
{
|
|
var userId = CurrentUserId();
|
|
var affected = await db.Todos
|
|
.Where(t => t.Id == id && t.UserId == userId)
|
|
.ExecuteDeleteAsync();
|
|
return affected == 0 ? NotFound() : NoContent();
|
|
}
|
|
}
|