@page "/login" @inherits LocalizableComponentBase @Localizer["Login"] @* One sign-in for both of PrivaPub's APIs: the root signs in here, then picks the persona to act as when it has more than one (CascadingState.LoadSession picks the last one used, or the only one). *@
@if (!CascadingState.IsSignedIn) {

@Localizer["Sign in to PrivaPub"]

@Localizer["One login for all of your personas: each one is signed in separately and never linked to the others."]

@if (isWorking) { } @Localizer["Login"]
} else if (CascadingState.Personas.Count == 0) {

@Localizer["No persona yet"]

@Localizer["This login has no persona to act as. Create one on PrivaPub first."]

@Localizer["Logout"]
} else {

@Localizer["Who are you today?"]

@Localizer["Each persona has its own token; PrivaPub never tells anyone they share a login."]

@foreach (var persona in CascadingState.Personas) { }
}
@code { [Inject] AuthService AuthService { get; set; } readonly LoginForm form = new(); string error; bool isWorking; [SupplyParameterFromQuery] public string ReturnUrl { get; set; } protected override void OnInitialized() => IsLoading = false; async Task SignIn() { error = default; isWorking = true; var result = await AuthService.Login(form); if (result.IsInvalid) { error = result.ErrorMessage; isWorking = false; return; } await CascadingState.LoadSession(); isWorking = false; if (CascadingState.Personas.Count == 1 && CascadingState.Persona is not null) Continue(); } async Task Choose(string personaId) { error = default; isWorking = true; var result = await CascadingState.SwitchPersona(personaId); isWorking = false; if (result.IsInvalid) { error = result.ErrorMessage; return; } Continue(); } async Task SignOut() => await CascadingState.SignOut(); /// Back where the reader was sent from, never off the app. void Continue() { var target = ReturnUrl is { Length: > 0 } url && !url.Contains("://") && !url.StartsWith("//") && !url.StartsWith("login") ? url : ""; Navigation.NavigateTo(target); } }