Files
pos-system/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/MembershipController.cs
Ho Ngoc Hai 629fed8a55 commit
2026-03-05 01:39:40 +07:00

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();
}