🔒 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>
This commit is contained in:
2025-09-22 05:45:49 +01:00
parent 5138242a99
commit 622bdcf111
41 changed files with 6797 additions and 341 deletions

View File

@@ -0,0 +1,75 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using LittleShop.Services;
using LittleShop.Enums;
namespace LittleShop.Areas.Admin.Controllers;
[Area("Admin")]
[Authorize(Policy = "AdminOnly")]
public class SystemSettingsController : Controller
{
private readonly ISystemSettingsService _systemSettingsService;
private readonly ILogger<SystemSettingsController> _logger;
public SystemSettingsController(
ISystemSettingsService systemSettingsService,
ILogger<SystemSettingsController> logger)
{
_systemSettingsService = systemSettingsService;
_logger = logger;
}
public async Task<IActionResult> Index()
{
try
{
var viewModel = new SystemSettingsViewModel
{
TestCurrencies = new Dictionary<string, bool>
{
{ "TBTC", await _systemSettingsService.IsTestCurrencyEnabledAsync("TBTC") },
{ "TLTC", await _systemSettingsService.IsTestCurrencyEnabledAsync("TLTC") }
}
};
return View(viewModel);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error loading system settings");
ViewBag.Error = "Failed to load system settings";
return View(new SystemSettingsViewModel());
}
}
[HttpPost]
public async Task<IActionResult> UpdateTestCurrencies(SystemSettingsViewModel model)
{
try
{
if (model.TestCurrencies != null)
{
foreach (var currency in model.TestCurrencies)
{
await _systemSettingsService.SetTestCurrencyEnabledAsync(currency.Key, currency.Value);
_logger.LogInformation("Updated test currency {Currency} to {Enabled}", currency.Key, currency.Value);
}
}
ViewBag.Success = "Test currency settings updated successfully";
return View("Index", model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating test currency settings");
ViewBag.Error = "Failed to update test currency settings";
return View("Index", model);
}
}
}
public class SystemSettingsViewModel
{
public Dictionary<string, bool> TestCurrencies { get; set; } = new();
}

View File

@@ -92,6 +92,11 @@
<i class="fas fa-robot"></i> Bots
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="@Url.Action("Index", "SystemSettings", new { area = "Admin" })">
<i class="fas fa-cog"></i> Settings
</a>
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item dropdown">

View File

@@ -0,0 +1,104 @@
@model LittleShop.Areas.Admin.Controllers.SystemSettingsViewModel
@{
ViewData["Title"] = "System Settings";
}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">System Settings</h3>
</div>
<div class="card-body">
@if (!string.IsNullOrEmpty(ViewBag.Success))
{
<div class="alert alert-success alert-dismissible fade show" role="alert">
@ViewBag.Success
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}
@if (!string.IsNullOrEmpty(ViewBag.Error))
{
<div class="alert alert-danger alert-dismissible fade show" role="alert">
@ViewBag.Error
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
}
<form asp-controller="SystemSettings" asp-action="UpdateTestCurrencies" method="post">
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title">Test Currencies</h5>
<p class="card-subtitle text-muted">
Enable test currencies for development and testing purposes.
These currencies are only available when enabled here.
</p>
</div>
<div class="card-body">
@foreach (var currency in Model.TestCurrencies)
{
<div class="form-check mb-3">
<input class="form-check-input"
type="checkbox"
name="TestCurrencies[@currency.Key]"
value="true"
@(currency.Value ? "checked" : "")
id="currency-@currency.Key">
<input type="hidden" name="TestCurrencies[@currency.Key]" value="false">
<label class="form-check-label" for="currency-@currency.Key">
<strong>@currency.Key</strong>
@{
string description = currency.Key switch
{
"TBTC" => "Test Bitcoin - Bitcoin testnet currency for development",
"TLTC" => "Test Litecoin - Litecoin testnet currency for development",
_ => "Test cryptocurrency"
};
}
<br><small class="text-muted">@description</small>
</label>
</div>
}
<div class="mt-3">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> Update Test Currencies
</button>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title">Production Currencies</h5>
<p class="card-subtitle text-muted">
Production currencies are always available based on SilverPay support.
</p>
</div>
<div class="card-body">
<div class="alert alert-info">
<h6>Always Enabled:</h6>
<ul class="mb-0">
<li><strong>BTC</strong> - Bitcoin (Production)</li>
<li><strong>ETH</strong> - Ethereum (Production)</li>
</ul>
<p class="mt-2 mb-0">
<small>These currencies are automatically available in the TeleBot based on SilverPay API support.</small>
</p>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>