CreatePost.cs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. using Application.Abstractions.Messaging;
  2. using Application.Features.Api.Forum.StockBoard.CreatePost;
  3. using Web.Api.Common;
  4. using Web.Api.Extensions;
  5. using Microsoft.AspNetCore.Mvc;
  6. using System.Security.Claims;
  7. namespace Web.Api.Endpoints.Forum.StockBoard;
  8. /// <summary>종목 가상보드 글 작성 — POST /api/boards/stock/posts (JWT). 예측(선택) 동시 등록.</summary>
  9. internal sealed class CreatePost : IEndpoint
  10. {
  11. public sealed class PredictionBody
  12. {
  13. public byte Direction { get; set; }
  14. public short HorizonDays { get; set; }
  15. public decimal? TargetPrice { get; set; }
  16. }
  17. public sealed class Request
  18. {
  19. public string StockCode { get; set; } = "";
  20. public string Subject { get; set; } = "";
  21. public string Content { get; set; } = "";
  22. public PredictionBody? Prediction { get; set; }
  23. }
  24. public void MapEndpoint(IEndpointRouteBuilder app)
  25. {
  26. app.MapPost("api/boards/stock/posts", async (
  27. ClaimsPrincipal user,
  28. [FromBody] Request request,
  29. ISender sender,
  30. CancellationToken ct
  31. ) => {
  32. var memberID = user.GetMemberID();
  33. if (memberID is null)
  34. {
  35. return ApiResponse.Fail(StatusCodes.Status401Unauthorized, "Invalid token");
  36. }
  37. var prediction = request.Prediction is { } p
  38. ? new PredictionInput(p.Direction, p.HorizonDays, p.TargetPrice)
  39. : null;
  40. var command = new Command(memberID.Value, request.StockCode, request.Subject, request.Content, prediction);
  41. var result = await sender.Send(command, ct);
  42. return result.Match(
  43. postID => ApiResponse.Created(new { ID = postID }),
  44. CustomResults.Problem
  45. );
  46. })
  47. .WithTags("StockBoard")
  48. .RequireAuthorization();
  49. }
  50. }