Files
CouchLog/CouchLog/Components/Account/Pages/Register.razor

154 lines
5.5 KiB
Plaintext

@page "/Account/Register"
@using System.ComponentModel.DataAnnotations
@using System.Text
@using System.Text.Encodings.Web
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.WebUtilities
@using CouchLog.Data
@inject UserManager<ApplicationUser> UserManager
@inject IUserStore<ApplicationUser> UserStore
@inject SignInManager<ApplicationUser> SignInManager
@inject ILogger<Register> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager
@inject ApplicationDbContext CouchLogDB
<PageTitle>Register</PageTitle>
<h1>Register</h1>
<div class="row">
<div class="col-lg-6">
<StatusMessage Message="@Message" />
<EditForm Model="Input" asp-route-returnUrl="@ReturnUrl" method="post" OnValidSubmit="RegisterUser" FormName="register">
<DataAnnotationsValidator />
<h2>Create a new account.</h2>
<hr />
<ValidationSummary class="text-danger" role="alert" />
<div class="form-floating mb-3">
<InputText @bind-Value="Input.Username" id="Input.Username" class="form-control" autocomplete="username" aria-required="true" placeholder="NewUsername" />
<label for="Input.Username">Username</label>
<ValidationMessage For="() => Input.Username" class="text-danger" />
</div>
<div class="form-floating mb-3">
<InputText type="password" @bind-Value="Input.Password" id="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
<label for="Input.Password">Password</label>
<ValidationMessage For="() => Input.Password" class="text-danger" />
</div>
<div class="form-floating mb-3">
<InputText type="password" @bind-Value="Input.ConfirmPassword" id="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
<label for="Input.ConfirmPassword">Confirm Password</label>
<ValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
</div>
<button type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
</EditForm>
</div>
<div class="col-lg-4 col-lg-offset-2">
<section>
<h3>Use another service to register.</h3>
<hr />
<ExternalLoginPicker />
</section>
</div>
</div>
@code {
private IEnumerable<IdentityError>? identityErrors;
[SupplyParameterFromForm]
private InputModel Input { get; set; } = new();
[SupplyParameterFromQuery]
private string? ReturnUrl { get; set; }
private string? Message => identityErrors is null ? null : $"Error: {string.Join(", ", identityErrors.Select(error => error.Description))}";
public async Task RegisterUser(EditContext editContext)
{
if(!CouchLogDB.AccountsSettings.First().IsRegistrationAllowed)
{
identityErrors = new[]
{
new IdentityError { Description = "Registration is deactivated" }
};
return;
}
var user = CreateUser();
await UserStore.SetUserNameAsync(user, Input.Username, CancellationToken.None);
user.EmailConfirmed = true;
var result = await UserManager.CreateAsync(user, Input.Password);
if (!result.Succeeded)
{
identityErrors = result.Errors;
return;
}
if(CouchLogDB.CouchLogState.Count() == 0)
{
await UserManager.AddToRoleAsync(user, "Admin");
await CouchLogDB.CouchLogState.AddAsync(new CouchLogState
{
Id = 1,
InitializationDate = DateTime.Now,
IsInitialized = true
});
}
else
{
await UserManager.AddToRoleAsync(user, "User");
}
await CouchLogDB.SaveChangesAsync();
Logger.LogInformation("User created a new account with password.");
await SignInManager.SignInAsync(user, isPersistent: false);
RedirectManager.RedirectTo(ReturnUrl);
}
private ApplicationUser CreateUser()
{
try
{
return Activator.CreateInstance<ApplicationUser>();
}
catch
{
throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
$"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor.");
}
}
private IUserEmailStore<ApplicationUser> GetEmailStore()
{
if (!UserManager.SupportsUserEmail)
{
throw new NotSupportedException("The default UI requires a user store with email support.");
}
return (IUserEmailStore<ApplicationUser>)UserStore;
}
private sealed class InputModel
{
[Required]
[Display(Name = "Username")]
public string Username { get; set; } = "";
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; } = "";
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; } = "";
}
}