Merge and add BTCPay external nodes configuration
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -72,6 +72,7 @@ public class MessagesController : Controller
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Reply(Guid customerId, string content, bool isUrgent = false)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
22
LittleShop/appsettings.Development.json
Normal file
22
LittleShop/appsettings.Development.json
Normal 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user