Files
mealplanner/backend/Controllers/RecipeController.cs
Claude f58782774b feat: complete mealplanner app (backend + frontend + deployment)
.NET 8 backend with Zitadel JWT auth, TheMealDB integration,
weekly meal plan generation, shopping list aggregation.
Vue 3 + Tailwind 4 frontend with dark emerald theme,
manual OIDC PKCE auth, all views implemented.
Multi-stage Dockerfile with nginx reverse proxy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:10:10 +00:00

75 lines
2.1 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MealPlanner.Models;
using MealPlanner.Services;
namespace MealPlanner.Controllers;
[ApiController]
[Route("api/recipes")]
[Authorize]
public class RecipeController(RecipeService recipeService) : ControllerBase
{
private string UserId => User.FindFirst("sub")?.Value ?? throw new UnauthorizedAccessException();
[HttpGet]
public async Task<IActionResult> GetOwn()
{
var recipes = await recipeService.GetOwnRecipesAsync(UserId);
return Ok(recipes);
}
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetById(Guid id)
{
var recipe = await recipeService.GetByIdOrFetchAsync(id);
if (recipe is null) return NotFound();
return Ok(recipe);
}
[HttpPost]
public async Task<IActionResult> Create([FromBody] Recipe recipe)
{
var created = await recipeService.CreateAsync(UserId, recipe);
return CreatedAtAction(nameof(GetById), new { id = created.Id }, created);
}
[HttpPut("{id:guid}")]
public async Task<IActionResult> Update(Guid id, [FromBody] Recipe recipe)
{
try
{
var updated = await recipeService.UpdateAsync(id, UserId, recipe);
if (updated is null) return NotFound();
return Ok(updated);
}
catch (UnauthorizedAccessException)
{
return Forbid();
}
}
[HttpDelete("{id:guid}")]
public async Task<IActionResult> Delete(Guid id)
{
try
{
var deleted = await recipeService.DeleteAsync(id, UserId);
if (!deleted) return NotFound();
return NoContent();
}
catch (UnauthorizedAccessException)
{
return Forbid();
}
}
[HttpGet("search")]
public async Task<IActionResult> Search([FromQuery] string q)
{
if (string.IsNullOrWhiteSpace(q)) return BadRequest("Query parameter 'q' is required.");
var results = await recipeService.SearchAsync(q, UserId);
return Ok(results);
}
}