224 lines
7.7 KiB
C#
224 lines
7.7 KiB
C#
using Asp.Versioning;
|
|
using MediatR;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using MembershipService.API.Application.Commands;
|
|
using MembershipService.API.Application.Queries;
|
|
using Swashbuckle.AspNetCore.Annotations;
|
|
|
|
namespace MembershipService.API.Controllers;
|
|
|
|
/// <summary>
|
|
/// EN: Controller for managing members.
|
|
/// VI: Controller để quản lý members.
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/v{version:apiVersion}/[controller]")]
|
|
[ApiVersion("1.0")]
|
|
[Authorize]
|
|
[SwaggerTag("Member management endpoints")]
|
|
public class MembersController : ControllerBase
|
|
{
|
|
private readonly IMediator _mediator;
|
|
private readonly ILogger<MembersController> _logger;
|
|
|
|
public MembersController(IMediator mediator, ILogger<MembersController> logger)
|
|
{
|
|
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get member by ID.
|
|
/// VI: Lấy member theo ID.
|
|
/// </summary>
|
|
[HttpGet("{id:guid}")]
|
|
[SwaggerOperation(Summary = "Get member by ID", Description = "Retrieves a member by their unique identifier")]
|
|
[SwaggerResponse(200, "Member found", typeof(MemberDto))]
|
|
[SwaggerResponse(404, "Member not found")]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<MemberDto>> GetById(Guid id)
|
|
{
|
|
var member = await _mediator.Send(new GetMemberByIdQuery(id));
|
|
if (member == null)
|
|
{
|
|
return NotFound(new { message = $"Member {id} not found" });
|
|
}
|
|
return Ok(member);
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get current user's member profile.
|
|
/// VI: Lấy profile member của user hiện tại.
|
|
/// </summary>
|
|
[HttpGet("me")]
|
|
[SwaggerOperation(Summary = "Get my member profile", Description = "Retrieves the member profile for the authenticated user")]
|
|
[SwaggerResponse(200, "Member found", typeof(MemberDto))]
|
|
[SwaggerResponse(404, "Member not found")]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<MemberDto>> GetMe()
|
|
{
|
|
var userId = GetCurrentUserId();
|
|
if (userId == null)
|
|
{
|
|
return Unauthorized();
|
|
}
|
|
|
|
var member = await _mediator.Send(new GetMemberByIdQuery(userId.Value));
|
|
if (member == null)
|
|
{
|
|
return NotFound(new { message = "Member profile not found" });
|
|
}
|
|
return Ok(member);
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get paginated list of members.
|
|
/// VI: Lấy danh sách members phân trang.
|
|
/// </summary>
|
|
[HttpGet]
|
|
[SwaggerOperation(Summary = "Get members list", Description = "Retrieves a paginated list of members")]
|
|
[SwaggerResponse(200, "Members retrieved", typeof(GetMembersResult))]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<GetMembersResult>> GetAll(
|
|
[FromQuery] int pageIndex = 0,
|
|
[FromQuery] int pageSize = 10,
|
|
[FromQuery] string? search = null)
|
|
{
|
|
var result = await _mediator.Send(new GetMembersQuery
|
|
{
|
|
PageIndex = pageIndex,
|
|
PageSize = pageSize,
|
|
SearchTerm = search
|
|
});
|
|
return Ok(result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Create a new member.
|
|
/// VI: Tạo member mới.
|
|
/// </summary>
|
|
[HttpPost]
|
|
[SwaggerOperation(Summary = "Create member", Description = "Creates a new member profile")]
|
|
[SwaggerResponse(201, "Member created", typeof(CreateMemberResult))]
|
|
[SwaggerResponse(400, "Invalid request")]
|
|
[SwaggerResponse(409, "Member already exists")]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<CreateMemberResult>> Create([FromBody] CreateMemberCommand command)
|
|
{
|
|
try
|
|
{
|
|
var result = await _mediator.Send(command);
|
|
return CreatedAtAction(nameof(GetById), new { id = result.MemberId }, result);
|
|
}
|
|
catch (InvalidOperationException ex) when (ex.Message.Contains("already exists"))
|
|
{
|
|
return Conflict(new { message = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Update member profile.
|
|
/// VI: Cập nhật profile member.
|
|
/// </summary>
|
|
[HttpPut("{id:guid}")]
|
|
[SwaggerOperation(Summary = "Update member profile", Description = "Updates a member's profile information")]
|
|
[SwaggerResponse(200, "Member updated", typeof(UpdateMemberProfileResult))]
|
|
[SwaggerResponse(400, "Invalid request")]
|
|
[SwaggerResponse(404, "Member not found")]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<UpdateMemberProfileResult>> UpdateProfile(
|
|
Guid id,
|
|
[FromBody] UpdateMemberProfileCommand command)
|
|
{
|
|
command.MemberId = id;
|
|
|
|
try
|
|
{
|
|
var result = await _mediator.Send(command);
|
|
return Ok(result);
|
|
}
|
|
catch (KeyNotFoundException ex)
|
|
{
|
|
return NotFound(new { message = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Add experience points to a member.
|
|
/// VI: Thêm điểm kinh nghiệm cho member.
|
|
/// </summary>
|
|
[HttpPost("{id:guid}/experience")]
|
|
[SwaggerOperation(Summary = "Add experience points", Description = "Adds experience points to a member")]
|
|
[SwaggerResponse(200, "Experience added", typeof(AddExperienceResult))]
|
|
[SwaggerResponse(400, "Invalid request")]
|
|
[SwaggerResponse(404, "Member not found")]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<AddExperienceResult>> AddExperience(
|
|
Guid id,
|
|
[FromBody] AddExperienceCommand command)
|
|
{
|
|
command.MemberId = id;
|
|
|
|
try
|
|
{
|
|
var result = await _mediator.Send(command);
|
|
return Ok(result);
|
|
}
|
|
catch (KeyNotFoundException ex)
|
|
{
|
|
return NotFound(new { message = ex.Message });
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
return BadRequest(new { message = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get member's level progress.
|
|
/// VI: Lấy tiến độ level của member.
|
|
/// </summary>
|
|
[HttpGet("{id:guid}/progress")]
|
|
[SwaggerOperation(Summary = "Get level progress", Description = "Retrieves member's level progress")]
|
|
[SwaggerResponse(200, "Progress retrieved", typeof(MemberProgressDto))]
|
|
[SwaggerResponse(404, "Member not found")]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<MemberProgressDto>> GetProgress(Guid id)
|
|
{
|
|
var progress = await _mediator.Send(new GetMemberProgressQuery(id));
|
|
if (progress == null)
|
|
{
|
|
return NotFound(new { message = $"Member {id} not found" });
|
|
}
|
|
return Ok(progress);
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get member's experience history.
|
|
/// VI: Lấy lịch sử EXP của member.
|
|
/// </summary>
|
|
[HttpGet("{id:guid}/experience")]
|
|
[SwaggerOperation(Summary = "Get experience history", Description = "Retrieves member's experience transaction history")]
|
|
[SwaggerResponse(200, "History retrieved", typeof(ExperienceHistoryResult))]
|
|
[SwaggerResponse(401, "Unauthorized")]
|
|
public async Task<ActionResult<ExperienceHistoryResult>> GetExperienceHistory(
|
|
Guid id,
|
|
[FromQuery] int pageIndex = 0,
|
|
[FromQuery] int pageSize = 20)
|
|
{
|
|
var result = await _mediator.Send(new GetExperienceHistoryQuery(id, pageIndex, pageSize));
|
|
return Ok(result);
|
|
}
|
|
|
|
private Guid? GetCurrentUserId()
|
|
{
|
|
var userIdClaim = User.FindFirst("sub")?.Value ?? User.FindFirst("id")?.Value;
|
|
if (Guid.TryParse(userIdClaim, out var userId))
|
|
{
|
|
return userId;
|
|
}
|
|
return null;
|
|
}
|
|
}
|