@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). A server without an administrator offers its setup (Setup); anyone else joins through a group's invitation (Join). A forgotten password is recovered through the login's verified address (PasswordRecovery). *@
@if (!CascadingState.IsSignedIn) {
@if (setupPending) { @Localizer["This server has no administrator yet"] @Localizer["Set it up: the first login made becomes its administrator."] }

@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"] @Localizer["Forgot your password?"]

@Localizer["Have an invitation?"] @Localizer["Join with an invitation"]

} else if (CascadingState.Personas.Count == 0) {

@Localizer["No persona yet"]

@Localizer["This login has no persona to act as yet: make one in Settings."]

@Localizer["Settings"] @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; bool setupPending; [SupplyParameterFromQuery] public string ReturnUrl { get; set; } protected override async Task OnInitializedAsync() { if (CascadingState.IsOffline) { WhenOnline(LoadData); StartOnlinePolling(); IsLoading = false; return; } await LoadData(); IsLoading = false; } async Task LoadData() => setupPending = !CascadingState.IsSignedIn && await AuthService.SetupPending(); async Task SignIn() { error = default; isWorking = true; var result = await AuthService.Login(form); if (result.IsInvalid) { error = result.ErrorMessage; isWorking = false; return; } await CascadingState.SignedIn(result.Data as JwtUser); 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); } }