69 lines
2.9 KiB
C#
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
|
|
?? "";
|
|
}
|