mirror of
https://github.com/chylex/Minecraft-Phantom-Panel.git
synced 2024-11-22 08:42:44 +01:00
122 lines
3.8 KiB
Plaintext
122 lines
3.8 KiB
Plaintext
@page "/setup"
|
|
@using Phantom.Server.Services
|
|
@using Phantom.Server.Services.Audit
|
|
@using Phantom.Server.Web.Identity.Authentication
|
|
@using Microsoft.AspNetCore.Identity
|
|
@using System.ComponentModel.DataAnnotations
|
|
@using Phantom.Utils.Cryptography
|
|
@using System.Security.Cryptography
|
|
@attribute [AllowAnonymous]
|
|
@inject ServiceConfiguration ServiceConfiguration
|
|
@inject PhantomLoginManager LoginManager
|
|
@inject UserManager<IdentityUser> UserManager
|
|
@inject AuditLog AuditLog
|
|
|
|
<h1>Administrator Setup</h1>
|
|
|
|
<Form Model="form" OnSubmit="DoLogin">
|
|
<div style="max-width: 400px;">
|
|
<div class="row">
|
|
<div class="mb-3">
|
|
<FormTextInput Id="account-username" Label="Username" @bind-Value="form.Username" autocomplete="off" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="mb-3">
|
|
<FormTextInput Id="account-password" Label="Password" Type="FormTextInputType.Password" @bind-Value="form.Password" autocomplete="new-password" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="mb-3">
|
|
<FormTextInput Id="administration-token" Label="Administration Token" Type="FormTextInputType.Password" @bind-Value="form.AdministrationToken" autocomplete="off" />
|
|
</div>
|
|
</div>
|
|
|
|
<FormButtonSubmit Label="Continue" class="btn btn-primary" />
|
|
</div>
|
|
|
|
<FormSubmitError />
|
|
</Form>
|
|
|
|
@code {
|
|
|
|
private readonly CreateAdministratorAccountFormModel form = new();
|
|
|
|
private sealed class CreateAdministratorAccountFormModel : FormModel {
|
|
[Required]
|
|
public string Username { get; set; } = string.Empty;
|
|
|
|
[Required]
|
|
public string Password { get; set; } = string.Empty;
|
|
|
|
[Required]
|
|
public string AdministrationToken { get; set; } = string.Empty;
|
|
}
|
|
|
|
private async Task DoLogin(EditContext context) {
|
|
await form.SubmitModel.StartSubmitting();
|
|
|
|
if (!IsAdministratorTokenValid()) {
|
|
form.SubmitModel.StopSubmitting("Invalid administrator token.");
|
|
return;
|
|
}
|
|
|
|
var createUserResult = await CreateOrUpdateAdministrator();
|
|
if (!createUserResult.Succeeded) {
|
|
form.SubmitModel.StopSubmitting(GetErrors(createUserResult));
|
|
return;
|
|
}
|
|
|
|
var signInResult = await LoginManager.SignIn(form.Username, form.Password);
|
|
if (!signInResult.Succeeded) {
|
|
form.SubmitModel.StopSubmitting("Error logging in.");
|
|
}
|
|
}
|
|
|
|
private bool IsAdministratorTokenValid() {
|
|
byte[] formTokenBytes;
|
|
try {
|
|
formTokenBytes = TokenGenerator.GetBytesOrThrow(form.AdministrationToken);
|
|
} catch (Exception) {
|
|
return false;
|
|
}
|
|
|
|
return CryptographicOperations.FixedTimeEquals(formTokenBytes, ServiceConfiguration.AdministratorToken);
|
|
}
|
|
|
|
private async Task<IdentityResult> CreateOrUpdateAdministrator() {
|
|
var existingUser = await UserManager.FindByNameAsync(form.Username);
|
|
return existingUser == null ? await CreateAdministrator() : await UpdateAdministrator(existingUser);
|
|
}
|
|
|
|
private async Task<IdentityResult> CreateAdministrator() {
|
|
var newUser = new IdentityUser(form.Username);
|
|
var createUserResult = await UserManager.CreateAsync(newUser, form.Password);
|
|
if (!createUserResult.Succeeded) {
|
|
return createUserResult;
|
|
}
|
|
|
|
await AuditLog.AddAdministratorUserCreatedEvent(newUser);
|
|
|
|
var addToRoleResult = await UserManager.AddToRoleAsync(newUser, Role.Administrator.Name);
|
|
return addToRoleResult;
|
|
}
|
|
|
|
private async Task<IdentityResult> UpdateAdministrator(IdentityUser existingUser) {
|
|
await UserManager.RemovePasswordAsync(existingUser);
|
|
var result = await UserManager.AddPasswordAsync(existingUser, form.Password);
|
|
if (result.Succeeded) {
|
|
await AuditLog.AddAdministratorUserModifiedEvent(existingUser);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private string GetErrors(IdentityResult result) {
|
|
return string.Join("\n", result.Errors.Select(static error => error.Description));
|
|
}
|
|
|
|
}
|