littleshop/LittleShop.Client/Services/CatalogService.cs
SysAdmin 622bdcf111 🔒 SECURITY: Emergency fixes and hardening
EMERGENCY FIXES:
 DELETE MockSilverPayService.cs - removed fake payment system
 REMOVE mock service registration - no fake payments possible
 GENERATE new JWT secret - replaced hardcoded key
 FIX HttpClient disposal - proper resource management

SECURITY HARDENING:
 ADD production guards - prevent mock services in production
 CREATE environment configs - separate dev/prod settings
 ADD config validation - fail fast on misconfiguration

IMPACT:
- Mock payment system completely eliminated
- JWT authentication now uses secure keys
- Production deployment now validated on startup
- Resource leaks fixed in TeleBot currency API

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-22 05:45:49 +01:00

162 lines
5.7 KiB
C#

using System.Net.Http.Json;
using LittleShop.Client.Models;
using Microsoft.Extensions.Logging;
namespace LittleShop.Client.Services;
public class CatalogService : ICatalogService
{
private readonly HttpClient _httpClient;
private readonly ILogger<CatalogService> _logger;
public CatalogService(HttpClient httpClient, ILogger<CatalogService> logger)
{
_httpClient = httpClient;
_logger = logger;
}
public async Task<ApiResponse<List<Category>>> GetCategoriesAsync()
{
try
{
var response = await _httpClient.GetAsync("api/catalog/categories");
if (response.IsSuccessStatusCode)
{
var categories = await response.Content.ReadFromJsonAsync<List<Category>>();
return ApiResponse<List<Category>>.Success(categories ?? new List<Category>());
}
var error = await response.Content.ReadAsStringAsync();
return ApiResponse<List<Category>>.Failure(error, response.StatusCode);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get categories");
return ApiResponse<List<Category>>.Failure(
ex.Message,
System.Net.HttpStatusCode.InternalServerError);
}
}
public async Task<ApiResponse<Category>> GetCategoryByIdAsync(Guid id)
{
try
{
var response = await _httpClient.GetAsync($"api/catalog/categories/{id}");
if (response.IsSuccessStatusCode)
{
var category = await response.Content.ReadFromJsonAsync<Category>();
if (category != null)
return ApiResponse<Category>.Success(category);
}
var error = await response.Content.ReadAsStringAsync();
return ApiResponse<Category>.Failure(error, response.StatusCode);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get category {CategoryId}", id);
return ApiResponse<Category>.Failure(
ex.Message,
System.Net.HttpStatusCode.InternalServerError);
}
}
public async Task<ApiResponse<PagedResult<Product>>> GetProductsAsync(
int pageNumber = 1,
int pageSize = 20,
Guid? categoryId = null,
string? searchTerm = null,
decimal? minPrice = null,
decimal? maxPrice = null)
{
try
{
var queryParams = new List<string>
{
$"pageNumber={pageNumber}",
$"pageSize={pageSize}"
};
if (categoryId.HasValue)
queryParams.Add($"categoryId={categoryId.Value}");
if (!string.IsNullOrEmpty(searchTerm))
queryParams.Add($"search={Uri.EscapeDataString(searchTerm)}");
if (minPrice.HasValue)
queryParams.Add($"minPrice={minPrice.Value}");
if (maxPrice.HasValue)
queryParams.Add($"maxPrice={maxPrice.Value}");
var queryString = string.Join("&", queryParams);
var response = await _httpClient.GetAsync($"api/catalog/products?{queryString}");
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadFromJsonAsync<PagedResult<Product>>();
if (result != null)
return ApiResponse<PagedResult<Product>>.Success(result);
}
var error = await response.Content.ReadAsStringAsync();
return ApiResponse<PagedResult<Product>>.Failure(error, response.StatusCode);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get products");
return ApiResponse<PagedResult<Product>>.Failure(
ex.Message,
System.Net.HttpStatusCode.InternalServerError);
}
}
public async Task<ApiResponse<Product>> GetProductByIdAsync(Guid id)
{
try
{
var response = await _httpClient.GetAsync($"api/catalog/products/{id}");
if (response.IsSuccessStatusCode)
{
var product = await response.Content.ReadFromJsonAsync<Product>();
if (product != null)
return ApiResponse<Product>.Success(product);
}
var error = await response.Content.ReadAsStringAsync();
return ApiResponse<Product>.Failure(error, response.StatusCode);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get product {ProductId}", id);
return ApiResponse<Product>.Failure(
ex.Message,
System.Net.HttpStatusCode.InternalServerError);
}
}
public async Task<ApiResponse<List<string>>> GetAvailableCurrenciesAsync()
{
try
{
var response = await _httpClient.GetAsync("api/currency/available");
if (response.IsSuccessStatusCode)
{
var currencies = await response.Content.ReadFromJsonAsync<List<string>>();
return ApiResponse<List<string>>.Success(currencies ?? new List<string>());
}
var error = await response.Content.ReadAsStringAsync();
return ApiResponse<List<string>>.Failure(error, response.StatusCode);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get available currencies");
return ApiResponse<List<string>>.Failure(
ex.Message,
System.Net.HttpStatusCode.InternalServerError);
}
}
}