Files
step3/api/QuestionsApi/Controllers/DynamicQuestionsController.cs
T

69 lines
2.9 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using QuestionsApi.Models;
using QuestionsApi.Services;
using System.Security.Claims;
namespace QuestionsApi.Controllers;
[ApiController, Route("api/dynamic-questions"), Authorize(Roles = "USER,SUPER")]
public sealed class DynamicQuestionsController : ControllerBase
{
private readonly DynamicQuestionService _questions;
private readonly QuestionReportStore _reports;
public DynamicQuestionsController(DynamicQuestionService questions, QuestionReportStore reports)
{
_questions = questions;
_reports = reports;
}
[HttpGet("status")]
public async Task<ActionResult<DynamicQuestionStatusResponse>> Status() =>
Ok(await _questions.StatusAsync(UserId()));
[HttpPost("next")]
public async Task<ActionResult<DynamicQuestionEnvelope>> Next([FromBody] DynamicNextRequest request)
{
try { return Ok(await _questions.NextAsync(UserId(), request.RunToken)); }
catch (ArgumentException exception) { return BadRequest(exception.Message); }
catch (InvalidOperationException exception) { return Conflict(exception.Message); }
}
[HttpPost("attempt")]
public async Task<ActionResult<DynamicAttemptResponse>> Attempt([FromBody] DynamicAttemptRequest request)
{
if (string.IsNullOrWhiteSpace(request.GenerationToken))
return BadRequest("generationToken required");
try { return Ok(await _questions.AttemptAsync(UserId(), request)); }
catch (ArgumentException exception) { return BadRequest(exception.Message); }
catch (KeyNotFoundException) { return NotFound(); }
catch (InvalidOperationException exception) { return Conflict(exception.Message); }
}
[HttpPost("report")]
public async Task<IActionResult> Report([FromBody] DynamicReportRequest request)
{
var category = request.Category.Trim().ToLowerInvariant();
var details = request.Details.Trim();
if (!QuestionReportCategory.All.Contains(category))
return BadRequest("category is invalid");
if (details.Length is < 10 or > 2000)
return BadRequest("details must be between 10 and 2000 characters");
try
{
var (claims, _) = await _questions.RegenerateAsync(UserId(), request.GenerationToken);
var report = await _reports.CreateDynamicAsync(claims, UserId(), category, details);
return StatusCode(StatusCodes.Status201Created, new { id = report.Id, questionExternalId = report.QuestionExternalId });
}
catch (ArgumentException exception) { return BadRequest(exception.Message); }
catch (KeyNotFoundException) { return NotFound(); }
}
private string UserId() =>
User.FindFirstValue(ClaimTypes.NameIdentifier)
?? User.FindFirstValue(ClaimTypes.Name)
?? User.Identity?.Name
?? "";
}