using Asp.Versioning; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Mirea.Api.Dto.Common; using Mirea.Api.Endpoint.Common.Attributes; using Mirea.Api.Endpoint.Common.MapperDto; using Mirea.Api.Endpoint.Configuration.Model; using QRCoder; using System; using System.Drawing; namespace Mirea.Api.Endpoint.Controllers.V1; [ApiVersion("1.0")] public class SecurityController(IOptionsSnapshot generalConfig) : BaseController { /// /// Generates an SVG QR code for TOTP setup with customizable colors and size. /// /// The TOTP secret key to embed in the QR code. /// The label to display with the QR code (usually username or email). /// Background color for the QR code in hex format (e.g., "#FFFFFF" for white). Defaults to transparent. /// Foreground color for the QR code in hex format (e.g., "#000000" for black), defaults to black. /// The pixel size of the QR code image (width and height). /// Error correction level (low, medium, high, or very high). Valid values: L, M, Q, H. /// An SVG string of the generated QR code. [HttpGet("GenerateTotpQrCode")] [Produces("image/svg+xml")] [MaintenanceModeIgnore] public IActionResult GenerateTotpQrCode( [FromQuery] string totpKey, [FromQuery] string label, [FromQuery] string? backgroundColor = null, [FromQuery] string foregroundColor = "#000000", [FromQuery] int size = 250, [FromQuery] string? errorCorrectionLevel = "M") { try { var bgColor = string.IsNullOrEmpty(backgroundColor) ? Color.Transparent : ColorTranslator.FromHtml(backgroundColor); var fgColor = ColorTranslator.FromHtml(foregroundColor); var eccLevel = errorCorrectionLevel?.ToUpper() switch { "L" => QRCodeGenerator.ECCLevel.L, "Q" => QRCodeGenerator.ECCLevel.Q, "H" => QRCodeGenerator.ECCLevel.H, _ => QRCodeGenerator.ECCLevel.M }; var issuer = Uri.EscapeDataString("Mirea Schedule"); // Generate TOTP URI (otpauth://totp/issuer:username?secret=KEY&issuer=issuer) var totpUri = $"otpauth://totp/{issuer}:{label}?secret={totpKey}&issuer={issuer}"; using var qrGenerator = new QRCodeGenerator(); var qrCodeData = qrGenerator.CreateQrCode(totpUri, eccLevel); using var qrCode = new SvgQRCode(qrCodeData); var svgImage = qrCode.GetGraphic( pixelsPerModule: size / 25, darkColorHex: $"#{fgColor.R:X2}{fgColor.G:X2}{fgColor.B:X2}", lightColorHex: $"#{bgColor.R:X2}{bgColor.G:X2}{bgColor.B:X2}" ); return Content(svgImage, "image/svg+xml"); } catch (Exception ex) { return BadRequest($"Failed to generate QR code: {ex.Message}"); } } /// /// Retrieves the current password policy for user authentication. /// /// /// The current password policy /// [HttpGet("PasswordPolicy")] public ActionResult PasswordPolicy() => Ok(generalConfig.Value.PasswordPolicy.ConvertToDto()); }