Merge and add BTCPay external nodes configuration

This commit is contained in:
SilverLabs DevTeam
2025-09-19 12:15:52 +01:00
15 changed files with 438 additions and 32 deletions

View File

@@ -28,6 +28,7 @@ public class AccountController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(string username, string password)
{
Console.WriteLine($"Received Username: '{username}', Password: '{password}'");
@@ -68,6 +69,7 @@ public class AccountController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
public async Task<IActionResult> Logout()
{

View File

@@ -28,6 +28,7 @@ public class CategoriesController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(CreateCategoryDto model)
{
Console.WriteLine($"Received Category: Name='{model?.Name}', Description='{model?.Description}'");
@@ -66,6 +67,7 @@ public class CategoriesController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(Guid id, UpdateCategoryDto model)
{
if (!ModelState.IsValid)
@@ -84,6 +86,7 @@ public class CategoriesController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(Guid id)
{
await _categoryService.DeleteCategoryAsync(id);

View File

@@ -72,6 +72,7 @@ public class MessagesController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Reply(Guid customerId, string content, bool isUrgent = false)
{
try

View File

@@ -78,6 +78,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(CreateOrderDto model)
{
if (!ModelState.IsValid)
@@ -101,6 +102,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(Guid id, OrderDto model)
{
if (!ModelState.IsValid)
@@ -125,6 +127,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UpdateStatus(Guid id, UpdateOrderStatusDto model)
{
var success = await _orderService.UpdateOrderStatusAsync(id, model);
@@ -138,6 +141,7 @@ public class OrdersController : Controller
// Workflow action methods
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AcceptOrder(Guid id, string? notes)
{
var userName = User.Identity?.Name ?? "Unknown";
@@ -157,6 +161,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> StartPacking(Guid id, string? notes)
{
var userName = User.Identity?.Name ?? "Unknown";
@@ -176,6 +181,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DispatchOrder(Guid id, string trackingNumber, int estimatedDays = 3, string? notes = null)
{
var userName = User.Identity?.Name ?? "Unknown";
@@ -200,6 +206,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> PutOnHold(Guid id, string reason, string? notes)
{
var userName = User.Identity?.Name ?? "Unknown";
@@ -219,6 +226,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveFromHold(Guid id)
{
var userName = User.Identity?.Name ?? "Unknown";
@@ -237,6 +245,7 @@ public class OrdersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> MarkDelivered(Guid id, DateTime? actualDeliveryDate, string? notes)
{
var deliveredDto = new MarkDeliveredDto

View File

@@ -40,6 +40,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(CreateProductDto model)
{
Console.WriteLine($"Received Product: Name='{model?.Name}', Description='{model?.Description}', Price={model?.Price}, Stock={model?.StockQuantity}");
@@ -99,6 +100,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(Guid id, UpdateProductDto model)
{
if (!ModelState.IsValid)
@@ -119,6 +121,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadPhoto(Guid id, IFormFile file, string? altText)
{
if (file != null && file.Length > 0)
@@ -130,6 +133,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeletePhoto(Guid id, Guid photoId)
{
await _productService.RemoveProductPhotoAsync(id, photoId);
@@ -137,6 +141,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(Guid id)
{
await _productService.DeleteProductAsync(id);
@@ -176,6 +181,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateVariation(CreateProductVariationDto model)
{
// Debug form data
@@ -261,6 +267,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditVariation(Guid id, UpdateProductVariationDto model)
{
if (!ModelState.IsValid)
@@ -280,6 +287,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteVariation(Guid id)
{
var variation = await _productService.GetProductVariationByIdAsync(id);
@@ -297,6 +305,7 @@ public class ProductsController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Import(IFormFile file)
{
if (file == null || file.Length == 0)

View File

@@ -30,6 +30,7 @@ public class ShippingRatesController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(CreateShippingRateDto model)
{
if (!ModelState.IsValid)
@@ -69,6 +70,7 @@ public class ShippingRatesController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(Guid id, UpdateShippingRateDto model)
{
if (!ModelState.IsValid)
@@ -88,6 +90,7 @@ public class ShippingRatesController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(Guid id)
{
var success = await _shippingRateService.DeleteShippingRateAsync(id);

View File

@@ -28,6 +28,7 @@ public class UsersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(CreateUserDto model)
{
try
@@ -73,6 +74,7 @@ public class UsersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(Guid id, UpdateUserDto model)
{
try
@@ -122,6 +124,7 @@ public class UsersController : Controller
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(Guid id)
{
try

View File

@@ -142,34 +142,38 @@ builder.Services.AddSwaggerGen(c =>
// CORS - Configure for both development and production
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll",
// Development CORS policy - configured from appsettings
options.AddPolicy("DevelopmentCors",
corsBuilder =>
{
corsBuilder.SetIsOriginAllowed(origin => true) // Allow any origin
var allowedOrigins = builder.Configuration.GetSection("CORS:AllowedOrigins").Get<string[]>()
?? new[] { "http://localhost:3000", "http://localhost:5173", "http://localhost:5000" };
corsBuilder.WithOrigins(allowedOrigins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials(); // Important for cookie authentication
});
// Production CORS policy for Hostinger deployment
// Production CORS policy - strict security
options.AddPolicy("ProductionCors",
corsBuilder =>
{
corsBuilder.SetIsOriginAllowed(origin =>
{
// Allow all subdomains of thebankofdebbie.giize.com
var allowedHosts = new[]
{
"thebankofdebbie.giize.com",
"admin.thebankofdebbie.giize.com",
"localhost"
};
var allowedOrigins = builder.Configuration.GetSection("CORS:AllowedOrigins").Get<string[]>()
?? new[] { "https://littleshop.silverlabs.uk" };
var uri = new Uri(origin);
return allowedHosts.Any(host =>
uri.Host.Equals(host, StringComparison.OrdinalIgnoreCase) ||
uri.Host.EndsWith($".{host}", StringComparison.OrdinalIgnoreCase));
})
corsBuilder.WithOrigins(allowedOrigins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
// API-specific CORS policy (no credentials for public API)
options.AddPolicy("ApiCors",
corsBuilder =>
{
// Public API should have more restricted CORS
corsBuilder.WithOrigins("https://littleshop.silverlabs.uk", "https://pay.silverlabs.uk")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
@@ -183,15 +187,14 @@ var app = builder.Build();
// Add CORS early in the pipeline - before authentication
if (app.Environment.IsDevelopment())
{
app.UseCors("AllowAll");
app.UseCors("DevelopmentCors");
app.UseSwagger();
app.UseSwaggerUI();
}
else
{
// Use production CORS policy in production environment
// For now, use AllowAll to diagnose the issue
app.UseCors("AllowAll");
app.UseCors("ProductionCors");
}
// Add error handling middleware for production

View File

@@ -33,12 +33,27 @@ public class BTCPayServerService : IBTCPayServerService
_logger.LogInformation("Initializing BTCPay Server connection to {BaseUrl} with Store ID: {StoreId}", _baseUrl, _storeId);
// Create HttpClient with certificate bypass for internal networks
var httpClient = new HttpClient(new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
});
// Create HttpClient with proper SSL validation
var httpClientHandler = new HttpClientHandler();
// Only allow insecure SSL in development mode with explicit configuration
var allowInsecureSSL = _configuration.GetValue<bool>("Security:AllowInsecureSSL", false);
if (allowInsecureSSL)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (environment == "Development")
{
_logger.LogWarning("SECURITY WARNING: SSL certificate validation is disabled for development. This should NEVER be used in production!");
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
}
else
{
_logger.LogError("Attempted to disable SSL certificate validation in non-development environment. This is not allowed.");
throw new InvalidOperationException("SSL certificate validation cannot be disabled in production environments");
}
}
var httpClient = new HttpClient(httpClientHandler);
_client = new BTCPayServerClient(new Uri(_baseUrl), apiKey, httpClient);
}

View File

@@ -0,0 +1,22 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Debug",
"LittleShop": "Debug"
}
},
"Security": {
"AllowInsecureSSL": true,
"EnableDetailedErrors": true
},
"CORS": {
"AllowedOrigins": [
"http://localhost:3000",
"http://localhost:5173",
"http://localhost:5000",
"http://localhost:5001",
"https://localhost:5001"
]
}
}