Add interactive CCS case practice
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using QuestionsApi.Models;
|
||||
using QuestionsApi.Services;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace QuestionsApi.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/ccs")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public sealed class CcsController(CcsStore store) : ControllerBase
|
||||
{
|
||||
[HttpGet("cases")]
|
||||
public async Task<IActionResult> Cases() => Ok(await store.ListCasesAsync());
|
||||
|
||||
[HttpGet("orders/search")]
|
||||
public async Task<IActionResult> SearchOrders([FromQuery] string q, [FromQuery] int limit = 20) =>
|
||||
Ok(await store.SearchOrdersAsync(q ?? "", limit));
|
||||
|
||||
[HttpPost("attempts")]
|
||||
public async Task<IActionResult> CreateAttempt(CreateCcsAttemptRequest request)
|
||||
{
|
||||
try { return Ok(await store.ToResponseAsync(await store.CreateAttemptAsync(UserId(), request))); }
|
||||
catch (ArgumentException exception) { return BadRequest(exception.Message); }
|
||||
catch (KeyNotFoundException) { return NotFound(); }
|
||||
catch (InvalidOperationException exception) { return Conflict(exception.Message); }
|
||||
}
|
||||
|
||||
[HttpGet("attempts/{id}")]
|
||||
public async Task<IActionResult> Attempt(string id)
|
||||
{
|
||||
var attempt = await store.GetOwnedAsync(id, UserId());
|
||||
return attempt is null ? NotFound() : Ok(await store.ToResponseAsync(attempt));
|
||||
}
|
||||
|
||||
[HttpPost("attempts/{id}/commands")]
|
||||
public async Task<IActionResult> Command(string id, CcsCommandRequest request)
|
||||
{
|
||||
var attempt = await store.GetOwnedAsync(id, UserId());
|
||||
if (attempt is null) return NotFound();
|
||||
try { return Ok(await store.ToResponseAsync(await store.ApplyCommandAsync(attempt, request))); }
|
||||
catch (ArgumentException exception) { return BadRequest(exception.Message); }
|
||||
catch (InvalidOperationException exception) { return Conflict(exception.Message); }
|
||||
}
|
||||
|
||||
[HttpPost("attempts/{id}/abandon")]
|
||||
public async Task<IActionResult> Abandon(string id)
|
||||
{
|
||||
var attempt = await store.GetOwnedAsync(id, UserId());
|
||||
if (attempt is null) return NotFound();
|
||||
await store.AbandonAsync(attempt);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpGet("history")]
|
||||
public async Task<IActionResult> History([FromQuery] int limit = 50) => Ok(await store.HistoryAsync(UserId(), limit));
|
||||
|
||||
[HttpGet("prediction")]
|
||||
public async Task<IActionResult> Prediction() => Ok(await store.PredictionAsync(UserId()));
|
||||
|
||||
[HttpPost("admin/import")]
|
||||
[Authorize(Roles = "SUPER")]
|
||||
public async Task<IActionResult> Import(CcsImportRequest request)
|
||||
{
|
||||
var response = await store.ImportAsync(request);
|
||||
return response.Errors.Count > 0 ? BadRequest(response) : Ok(response);
|
||||
}
|
||||
|
||||
private string UserId() => User.FindFirstValue(ClaimTypes.NameIdentifier)
|
||||
?? User.FindFirstValue(ClaimTypes.Name)
|
||||
?? User.Identity?.Name
|
||||
?? throw new UnauthorizedAccessException();
|
||||
}
|
||||
Reference in New Issue
Block a user