dramaling-vocab-learning/backend/DramaLing.Api/Controllers/BaseController.cs

157 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.AspNetCore.Mvc;
using DramaLing.Api.Models.DTOs;
using DramaLing.Api.Services;
using System.Security.Claims;
namespace DramaLing.Api.Controllers;
[ApiController]
public abstract class BaseController : ControllerBase
{
protected readonly ILogger _logger;
protected readonly IAuthService? _authService;
protected BaseController(ILogger logger, IAuthService? authService = null)
{
_logger = logger;
_authService = authService;
}
/// <summary>
/// 統一的成功響應格式
/// </summary>
protected IActionResult SuccessResponse<T>(T data, string? message = null)
{
return Ok(new ApiResponse<T>
{
Success = true,
Data = data,
Message = message,
Timestamp = DateTime.UtcNow
});
}
/// <summary>
/// 統一的錯誤響應格式
/// </summary>
protected IActionResult ErrorResponse(string code, string message, object? details = null, int statusCode = 500)
{
var response = new ApiErrorResponse
{
Success = false,
Error = new ApiError
{
Code = code,
Message = message,
Details = details,
Suggestions = GetSuggestionsForError(code)
},
RequestId = Guid.NewGuid().ToString(),
Timestamp = DateTime.UtcNow
};
return StatusCode(statusCode, response);
}
/// <summary>
/// 獲取當前用戶ID統一處理認證
/// </summary>
protected async Task<Guid> GetCurrentUserIdAsync()
{
if (_authService != null)
{
// 使用AuthService進行JWT解析適用於已實現認證的Controller
var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
if (userId.HasValue)
return userId.Value;
}
// Fallback: 從Claims直接解析
var userIdString = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ??
User.FindFirst("sub")?.Value;
if (Guid.TryParse(userIdString, out var parsedUserId))
return parsedUserId;
// 開發階段使用固定測試用戶ID
if (IsTestEnvironment())
{
return Guid.Parse("00000000-0000-0000-0000-000000000001");
}
throw new UnauthorizedAccessException("Invalid or missing user authentication");
}
/// <summary>
/// 檢查是否為測試環境
/// </summary>
protected bool IsTestEnvironment()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
return environment == "Development" || environment == "Testing";
}
/// <summary>
/// 統一的模型驗證錯誤處理
/// </summary>
protected IActionResult HandleModelStateErrors()
{
var errors = ModelState
.Where(x => x.Value?.Errors.Count > 0)
.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value?.Errors.Select(e => e.ErrorMessage).ToArray() ?? Array.Empty<string>()
);
return ErrorResponse("VALIDATION_ERROR", "輸入資料驗證失敗", errors, 400);
}
/// <summary>
/// 根據錯誤代碼獲取建議
/// </summary>
private List<string> GetSuggestionsForError(string errorCode)
{
return errorCode switch
{
"VALIDATION_ERROR" => new List<string> { "請檢查輸入格式", "確保所有必填欄位已填寫" },
"INVALID_INPUT" => new List<string> { "請檢查輸入格式", "確保文本長度在限制內" },
"RATE_LIMIT_EXCEEDED" => new List<string> { "升級到Premium帳戶以獲得無限使用", "明天重新嘗試" },
"AI_SERVICE_ERROR" => new List<string> { "請稍後重試", "如果問題持續,請聯繫客服" },
"UNAUTHORIZED" => new List<string> { "請檢查登入狀態", "確認Token是否有效" },
"NOT_FOUND" => new List<string> { "請檢查資源ID是否正確", "確認資源是否存在" },
_ => new List<string> { "請稍後重試", "如果問題持續,請聯繫客服" }
};
}
}
/// <summary>
/// 統一API響應格式
/// </summary>
public class ApiResponse<T>
{
public bool Success { get; set; } = true;
public T? Data { get; set; }
public string? Message { get; set; }
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}
/// <summary>
/// 分頁響應格式
/// </summary>
public class PagedApiResponse<T> : ApiResponse<List<T>>
{
public PaginationMetadata Pagination { get; set; } = new();
}
/// <summary>
/// 分頁元數據
/// </summary>
public class PaginationMetadata
{
public int CurrentPage { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPages { get; set; }
public bool HasNext { get; set; }
public bool HasPrevious { get; set; }
}