Files
CouchLog/CouchLog/Components/Account/Pages/Login.razor
T

133 lines
5.1 KiB
Plaintext

@page "/Account/Login"
@layout Layout.IdentityLayout
@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Identity
@using CouchLog.Data
@using MudBlazor
@inject SignInManager<ApplicationUser> SignInManager
@inject ILogger<Login> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager
<PageTitle>Log in</PageTitle>
<MudGrid Justify="Justify.Center" Class="align-center">
@* Linke Spalte: Login-Formular *@
<MudItem xs="12" md="7">
<MudPaper Elevation="3" Class="pa-6">
<StatusMessage Message="@errorMessage" />
<EditForm Model="Input" method="post" OnValidSubmit="LoginUser" FormName="login">
<DataAnnotationsValidator />
<MudText Typo="Typo.h5" GutterBottom="true" Align="Align.Center">Login</MudText>
<MudDivider Class="mb-6" />
<ValidationSummary class="text-danger" role="alert" />
@* MudTextFields zwingend mit Name-Attribut für SSR *@
<MudTextField @bind-Value="Input.Username"
For="@(() => Input.Username)"
Name="Input.Username"
Label="Username"
Variant="Variant.Outlined"
Margin="Margin.Dense"
ShrinkLabel="true"
Class="mb-4" />
<MudTextField @bind-Value="Input.Password"
For="@(() => Input.Password)"
Name="Input.Password"
Label="Password"
InputType="InputType.Password"
Variant="Variant.Outlined"
Margin="Margin.Dense"
ShrinkLabel="true"
Class="mb-4" />
@* Standard-Checkbox mit MudBlazor-Typografie *@
<div class="d-flex align-center mb-6">
<InputCheckbox @bind-Value="Input.RememberMe" id="Input.RememberMe" style="width: 1.2rem; height: 1.2rem; accent-color: var(--mud-palette-primary);" />
<label for="Input.RememberMe" class="ml-2 mud-typography mud-typography-body1">Remember me</label>
</div>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Size="Size.Large" FullWidth="true" Class="mb-4">
Log in
</MudButton>
<div class="d-flex flex-column gap-2 mt-4">
<MudLink Href="Account/ForgotPassword" Typo="Typo.body2">Forgot your password?</MudLink>
<MudLink Href="@(NavigationManager.GetUriWithQueryParameters("Account/Register", new Dictionary<string, object?> { ["ReturnUrl"] = ReturnUrl }))" Typo="Typo.body2">Register as a new user</MudLink>
<MudLink Href="Account/ResendEmailConfirmation" Typo="Typo.body2">Resend email confirmation</MudLink>
</div>
</EditForm>
</MudPaper>
</MudItem>
</MudGrid>
@code {
private string? errorMessage;
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
[SupplyParameterFromForm]
private InputModel Input { get; set; } = new();
[SupplyParameterFromQuery]
private string? ReturnUrl { get; set; }
protected override async Task OnInitializedAsync()
{
if (HttpMethods.IsGet(HttpContext.Request.Method))
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
}
}
public async Task LoginUser()
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await SignInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
Logger.LogInformation("User logged in.");
RedirectManager.RedirectTo(ReturnUrl);
}
else if (result.RequiresTwoFactor)
{
RedirectManager.RedirectTo(
"Account/LoginWith2fa",
new() { ["returnUrl"] = ReturnUrl, ["rememberMe"] = Input.RememberMe });
}
else if (result.IsLockedOut)
{
Logger.LogWarning("User account locked out.");
RedirectManager.RedirectTo("Account/Lockout");
}
else
{
errorMessage = "Error: Invalid login attempt.";
}
}
private sealed class InputModel
{
[Required]
[DataType(DataType.Text)]
public string Username { get; set; } = "";
[Required]
[DataType(DataType.Password)]
public string Password { get; set; } = "";
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
}