116 lines
4.4 KiB
C#
116 lines
4.4 KiB
C#
using System.Text.Json;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using WebClientTpos.Server.Infrastructure;
|
|
|
|
namespace WebClientTpos.Server.Controllers;
|
|
|
|
/// <summary>
|
|
/// EN: Membership controller — proxies to MembershipService for members and levels.
|
|
/// VI: Controller thành viên — proxy đến MembershipService cho thành viên và cấp bậc.
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/bff")]
|
|
public class MembershipController : ControllerBase
|
|
{
|
|
private readonly HttpClient _membership;
|
|
|
|
public MembershipController(IHttpClientFactory httpClientFactory)
|
|
{
|
|
_membership = httpClientFactory.CreateClient("MembershipService");
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get all members (customers).
|
|
/// VI: Lấy danh sách thành viên (khách hàng).
|
|
/// </summary>
|
|
[HttpGet("members")]
|
|
public Task<IActionResult> GetMembers([FromQuery] string? search = null, [FromQuery] int pageSize = 100)
|
|
{
|
|
var qs = $"?pageSize={pageSize}";
|
|
if (!string.IsNullOrWhiteSpace(search)) qs += $"&search={Uri.EscapeDataString(search)}";
|
|
return _membership.GetAsync($"/api/v1/members{qs}").ProxyAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get a member by ID.
|
|
/// VI: Lấy thành viên theo ID.
|
|
/// </summary>
|
|
[HttpGet("members/{memberId:guid}")]
|
|
public Task<IActionResult> GetMemberById(Guid memberId) =>
|
|
_membership.GetAsync($"/api/v1/members/{memberId}").ProxyAsync();
|
|
|
|
/// <summary>
|
|
/// EN: Create a member.
|
|
/// VI: Tạo thành viên.
|
|
/// </summary>
|
|
[HttpPost("members")]
|
|
public async Task<IActionResult> CreateMember([FromBody] JsonElement body)
|
|
{
|
|
// EN: Extract userId from JWT sub claim and inject into request body
|
|
// VI: Trích userId từ JWT sub claim và thêm vào request body
|
|
var rawJson = body.GetRawText();
|
|
var userId = ExtractSubFromJwt();
|
|
if (!string.IsNullOrEmpty(userId) && !rawJson.Contains("\"userId\""))
|
|
{
|
|
// EN: Insert userId field into JSON body
|
|
// VI: Chèn trường userId vào JSON body
|
|
rawJson = rawJson.TrimEnd('}') + $",\"userId\":\"{userId}\"}}";
|
|
}
|
|
var httpContent = new StringContent(rawJson, System.Text.Encoding.UTF8, "application/json");
|
|
var resp = await _membership.PostAsync("/api/v1/members", httpContent);
|
|
var respContent = await resp.Content.ReadAsStringAsync();
|
|
return new ContentResult
|
|
{
|
|
StatusCode = (int)resp.StatusCode,
|
|
Content = respContent,
|
|
ContentType = resp.Content.Headers.ContentType?.ToString() ?? "application/json"
|
|
};
|
|
}
|
|
|
|
private string? ExtractSubFromJwt()
|
|
{
|
|
var authHeader = HttpContext.Request.Headers["Authorization"].ToString();
|
|
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ")) return null;
|
|
try
|
|
{
|
|
var parts = authHeader["Bearer ".Length..].Split('.');
|
|
if (parts.Length != 3) return null;
|
|
var payload = parts[1];
|
|
switch (payload.Length % 4)
|
|
{
|
|
case 2: payload += "=="; break;
|
|
case 3: payload += "="; break;
|
|
}
|
|
payload = payload.Replace('-', '+').Replace('_', '/');
|
|
var json = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(payload));
|
|
using var doc = JsonDocument.Parse(json);
|
|
return doc.RootElement.TryGetProperty("sub", out var sub) ? sub.GetString() : null;
|
|
}
|
|
catch { return null; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Update a member.
|
|
/// VI: Cập nhật thành viên.
|
|
/// </summary>
|
|
[HttpPut("members/{memberId:guid}")]
|
|
public Task<IActionResult> UpdateMember(Guid memberId, [FromBody] JsonElement body) =>
|
|
_membership.PutAsJsonAsync($"/api/v1/members/{memberId}", body).ProxyAsync();
|
|
|
|
/// <summary>
|
|
/// EN: Soft-delete a member.
|
|
/// VI: Xóa mềm thành viên.
|
|
/// </summary>
|
|
[HttpDelete("members/{memberId:guid}")]
|
|
public Task<IActionResult> DeleteMember(Guid memberId) =>
|
|
_membership.DeleteAsync($"/api/v1/members/{memberId}").ProxyAsync();
|
|
|
|
/// <summary>
|
|
/// EN: Get membership level definitions with member counts.
|
|
/// VI: Lấy định nghĩa cấp bậc membership với số lượng thành viên.
|
|
/// </summary>
|
|
[HttpGet("membership/levels")]
|
|
public Task<IActionResult> GetMembershipLevels() =>
|
|
_membership.GetAsync("/api/v1/levels").ProxyAsync();
|
|
}
|