diff --git a/Endpoint/Controllers/V1/SecurityController.cs b/Endpoint/Controllers/V1/SecurityController.cs index 165bd85..5889acb 100644 --- a/Endpoint/Controllers/V1/SecurityController.cs +++ b/Endpoint/Controllers/V1/SecurityController.cs @@ -14,6 +14,64 @@ 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. ///