using Microsoft.AspNetCore.Mvc;
using QRRapidoApp.Data;
using QRRapidoApp.Models;
using MongoDB.Driver;
namespace QRRapidoApp.Controllers
{
///
/// Admin controller - ONLY accessible from localhost for security
///
[ApiController]
[Route("api/[controller]")]
public class AdminController : ControllerBase
{
private readonly MongoDbContext _context;
private readonly ILogger _logger;
public AdminController(MongoDbContext context, ILogger logger)
{
_context = context;
_logger = logger;
}
///
/// Seed/Update MongoDB Plans collection
/// Only accessible from localhost (127.0.0.1 or ::1)
///
[HttpPost("SeedPlans")]
public async Task SeedPlans([FromBody] List plans)
{
// SECURITY: Only allow from localhost
var remoteIp = HttpContext.Connection.RemoteIpAddress;
var isLocalhost = remoteIp != null &&
(remoteIp.ToString() == "127.0.0.1" ||
remoteIp.ToString() == "::1" ||
remoteIp.ToString() == "localhost");
if (!isLocalhost)
{
_logger.LogWarning($"Unauthorized admin access attempt from {remoteIp}");
return Forbid("This endpoint is only accessible from localhost");
}
try
{
_logger.LogInformation($"SeedPlans called from localhost - Upserting {plans.Count} plans");
foreach (var plan in plans)
{
// Upsert based on interval (month/year)
var filter = Builders.Filter.Eq(p => p.Interval, plan.Interval);
var options = new ReplaceOptions { IsUpsert = true };
await _context.Plans.ReplaceOneAsync(filter, plan, options);
_logger.LogInformation($"Upserted plan: {plan.Interval}");
}
return Ok(new {
success = true,
message = $"{plans.Count} plans seeded successfully",
plans = plans.Select(p => new {
interval = p.Interval,
priceIds = p.PricesByCountry.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.StripePriceId
)
})
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error seeding plans");
return StatusCode(500, new { success = false, error = ex.Message });
}
}
///
/// Get all plans from MongoDB
/// Only accessible from localhost
///
[HttpGet("Plans")]
public async Task GetPlans()
{
// SECURITY: Only allow from localhost
var remoteIp = HttpContext.Connection.RemoteIpAddress;
var isLocalhost = remoteIp != null &&
(remoteIp.ToString() == "127.0.0.1" ||
remoteIp.ToString() == "::1" ||
remoteIp.ToString() == "localhost");
if (!isLocalhost)
{
_logger.LogWarning($"Unauthorized admin access attempt from {remoteIp}");
return Forbid("This endpoint is only accessible from localhost");
}
try
{
var plans = await _context.Plans.Find(_ => true).ToListAsync();
return Ok(new { success = true, count = plans.Count, plans });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving plans");
return StatusCode(500, new { success = false, error = ex.Message });
}
}
///
/// Delete all plans from MongoDB
/// Only accessible from localhost
///
[HttpDelete("Plans")]
public async Task DeleteAllPlans()
{
// SECURITY: Only allow from localhost
var remoteIp = HttpContext.Connection.RemoteIpAddress;
var isLocalhost = remoteIp != null &&
(remoteIp.ToString() == "127.0.0.1" ||
remoteIp.ToString() == "::1" ||
remoteIp.ToString() == "localhost");
if (!isLocalhost)
{
_logger.LogWarning($"Unauthorized admin access attempt from {remoteIp}");
return Forbid("This endpoint is only accessible from localhost");
}
try
{
var result = await _context.Plans.DeleteManyAsync(_ => true);
_logger.LogInformation($"Deleted {result.DeletedCount} plans");
return Ok(new { success = true, deletedCount = result.DeletedCount });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting plans");
return StatusCode(500, new { success = false, error = ex.Message });
}
}
}
}