@using System.Timers @using BTCPayServer.Abstractions.Extensions @using BTCPayServer.Blazor @using BTCPayServer.Client @using BTCPayServer.Data @using BTCPayServer.Security @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Http @using Microsoft.AspNetCore.Identity @using Microsoft.AspNetCore.Mvc @using Microsoft.AspNetCore.Routing @using Microsoft.Extensions.Localization @inject AuthenticationStateProvider AuthenticationStateProvider @inject IAuthorizationService AuthorizationService @inject UserManager UserManager @inject UserLoginCodeService UserLoginCodeService @inject LinkGenerator LinkGenerator @inject IHttpContextAccessor HttpContextAccessor @inject IStringLocalizer StringLocalizer @implements IDisposable @if (!string.IsNullOrEmpty(_data)) {

@StringLocalizer["Valid for {0} seconds", _seconds]

} @code { [Parameter] public string RedirectUrl { get; set; } [Parameter] public int Size { get; set; } = 256; [Parameter] public string ImpersonatedUserId { get; set; } [Parameter(CaptureUnmatchedValues = true)] public Dictionary Attrs { get; set; } private static readonly double Seconds = UserLoginCodeService.ExpirationTime.TotalSeconds; private double _seconds = Seconds; private string _data; private ApplicationUser _user; private Timer _timer; protected override async Task OnParametersSetAsync() { var auth = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var userId = auth.User.Identity?.IsAuthenticated is true ? auth.User.GetIdOrNull() : null; if (userId is null) return; var loggedInUser = await UserManager.FindByIdAsync(ImpersonatedUserId ?? userId); if (loggedInUser is null) return; if (await AuthorizationService.AuthorizeAsync(auth.User, loggedInUser.Id, [new PolicyRequirement(ImpersonationPlugin.CanImpersonateUser)]) is not { Succeeded: true }) return; _user = loggedInUser; GenerateCodeAndStartTimer(); } public void Dispose() { _timer?.Dispose(); } private void GenerateCodeAndStartTimer() { var loginCode = UserLoginCodeService.Generate(_user.Id); _data = GetData(loginCode); _seconds = Seconds; _timer?.Dispose(); _timer = new Timer(1000); _timer.Elapsed += CountDownTimer; _timer.Enabled = true; } private void CountDownTimer(object source, ElapsedEventArgs e) { if (_seconds > 0) _seconds -= 1; else GenerateCodeAndStartTimer(); InvokeAsync(StateHasChanged); } private string GetData(string loginCode) { var req = HttpContextAccessor.HttpContext?.Request; if (req == null) return ""; return LinkGenerator.LoginCodeLink(loginCode, RedirectUrl, req.GetRequestBaseUrl()); } private double Percent => Math.Round(_seconds / Seconds * 100); private string CssClass => $"user-login-code d-inline-flex flex-column {(Attrs?.ContainsKey("class") is true ? Attrs["class"] : "")}".Trim(); }