List.cs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using MediatR;
  2. using Web.Api.Common;
  3. using Web.Api.Extensions;
  4. namespace Web.Api.Endpoints.V1.Members;
  5. internal sealed class List : IEndpoint
  6. {
  7. public void MapEndpoint(IEndpointRouteBuilder app)
  8. {
  9. app.MapGet("v1/members", async (
  10. ISender sender,
  11. CancellationToken ct,
  12. bool? hasChannel = null,
  13. int page = 1,
  14. int size = 50
  15. ) => {
  16. var query = new Application.Features.Api.V1.Members.List.Query(hasChannel, page, size);
  17. var result = await sender.Send(query, ct);
  18. return ApiResponse.Ok(result);
  19. })
  20. .WithTags("회원")
  21. .WithGroupName("public")
  22. .WithName("ListMembers")
  23. .WithSummary("회원 조회")
  24. .WithDescription("""
  25. DPOT 회원을 페이지네이션해 반환합니다.
  26. 탈퇴/삭제된 회원은 자동 제외됩니다.
  27. ### 필수 scope
  28. - `read:members`
  29. ### 쿼리 파라미터
  30. | 이름 | 타입 | 기본 | 설명 |
  31. |---|---|---|---|
  32. | `hasChannel` | bool? | null | `true` 크리에이터만 / `false` 일반 회원만 / 생략 시 전체 |
  33. | `page` | int | 1 | 1부터 시작 |
  34. | `size` | int | 50 | 1~200 |
  35. ### 응답 필드
  36. - `emailMasked` — 이메일은 `ji***@example.com` 형식으로 마스킹
  37. - `name` — 닉네임 (null 가능)
  38. - `hasChannel` — 채널 소유 여부
  39. - `channelSID` / `channelName` — **채널 소유 회원에만** 채워짐 (그 외 `null`)
  40. - `createdAt` — 가입일 (UTC ISO 8601)
  41. ### 사용 예
  42. ```
  43. GET /v1/members # 전체
  44. GET /v1/members?hasChannel=true # 크리에이터만
  45. GET /v1/members?hasChannel=false # 일반 회원만
  46. GET /v1/members?hasChannel=true&page=2&size=100
  47. ```
  48. """)
  49. .Produces<ApiResponse>(StatusCodes.Status200OK)
  50. .ProducesProblem(StatusCodes.Status401Unauthorized)
  51. .ProducesProblem(StatusCodes.Status403Forbidden)
  52. .RequireAuthorization(policy => policy
  53. .AddAuthenticationSchemes("ApiKey", "OAuth2Bearer")
  54. .RequireAuthenticatedUser())
  55. .RequireScope("read:members");
  56. }
  57. }