mirror of
https://github.com/chylex/Minecraft-Phantom-Panel.git
synced 2025-09-14 12:32:11 +02:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
35ca896849
|
|||
30b3ba60cd
|
@@ -1,4 +1,5 @@
|
||||
using System.Text;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using Phantom.Agent.Minecraft.Instance;
|
||||
using Phantom.Agent.Minecraft.Java;
|
||||
using Phantom.Agent.Minecraft.Server;
|
||||
@@ -11,6 +12,7 @@ public abstract class BaseLauncher : IServerLauncher {
|
||||
private readonly InstanceProperties instanceProperties;
|
||||
|
||||
protected string MinecraftVersion => instanceProperties.ServerVersion;
|
||||
protected string InstanceFolder => instanceProperties.InstanceFolder;
|
||||
|
||||
private protected BaseLauncher(InstanceProperties instanceProperties) {
|
||||
this.instanceProperties = instanceProperties;
|
||||
@@ -51,16 +53,14 @@ public abstract class BaseLauncher : IServerLauncher {
|
||||
|
||||
var processConfigurator = new ProcessConfigurator {
|
||||
FileName = javaRuntimeExecutable.ExecutablePath,
|
||||
WorkingDirectory = instanceProperties.InstanceFolder,
|
||||
WorkingDirectory = InstanceFolder,
|
||||
RedirectInput = true,
|
||||
UseShellExecute = false
|
||||
};
|
||||
|
||||
var processArguments = processConfigurator.ArgumentList;
|
||||
PrepareJvmArguments(serverJar).Build(processArguments);
|
||||
processArguments.Add("-jar");
|
||||
processArguments.Add(serverJar.FilePath);
|
||||
processArguments.Add("nogui");
|
||||
PrepareJavaProcessArguments(processArguments, serverJar.FilePath);
|
||||
|
||||
var process = processConfigurator.CreateProcess();
|
||||
var instanceProcess = new InstanceProcess(instanceProperties, process);
|
||||
@@ -99,13 +99,19 @@ public abstract class BaseLauncher : IServerLauncher {
|
||||
|
||||
private protected virtual void CustomizeJvmArguments(JvmArgumentBuilder arguments) {}
|
||||
|
||||
protected virtual void PrepareJavaProcessArguments(Collection<string> processArguments, string serverJarFilePath) {
|
||||
processArguments.Add("-jar");
|
||||
processArguments.Add(serverJarFilePath);
|
||||
processArguments.Add("nogui");
|
||||
}
|
||||
|
||||
private protected virtual Task<ServerJarInfo> PrepareServerJar(ILogger logger, string serverJarPath, CancellationToken cancellationToken) {
|
||||
return Task.FromResult(new ServerJarInfo(serverJarPath));
|
||||
}
|
||||
|
||||
private static async Task AcceptEula(InstanceProperties instanceProperties) {
|
||||
var eulaFilePath = Path.Combine(instanceProperties.InstanceFolder, "eula.txt");
|
||||
await File.WriteAllLinesAsync(eulaFilePath, new[] { "# EULA", "eula=true" }, Encoding.UTF8);
|
||||
await File.WriteAllLinesAsync(eulaFilePath, new [] { "# EULA", "eula=true" }, Encoding.UTF8);
|
||||
}
|
||||
|
||||
private static async Task UpdateServerProperties(InstanceProperties instanceProperties) {
|
||||
|
@@ -0,0 +1,29 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using Phantom.Agent.Minecraft.Instance;
|
||||
using Phantom.Agent.Minecraft.Java;
|
||||
using Serilog;
|
||||
|
||||
namespace Phantom.Agent.Minecraft.Launcher.Types;
|
||||
|
||||
public sealed class ForgeLauncher : BaseLauncher {
|
||||
public ForgeLauncher(InstanceProperties instanceProperties) : base(instanceProperties) {}
|
||||
|
||||
private protected override void CustomizeJvmArguments(JvmArgumentBuilder arguments) {
|
||||
arguments.AddProperty("terminal.ansi", "true"); // TODO
|
||||
}
|
||||
|
||||
protected override void PrepareJavaProcessArguments(Collection<string> processArguments, string serverJarFilePath) {
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
processArguments.Add("@libraries/net/minecraftforge/forge/1.20.1-47.2.0/win_args.txt");
|
||||
}
|
||||
else {
|
||||
processArguments.Add("@libraries/net/minecraftforge/forge/1.20.1-47.2.0/unix_args.txt");
|
||||
}
|
||||
|
||||
processArguments.Add("nogui");
|
||||
}
|
||||
|
||||
private protected override Task<ServerJarInfo> PrepareServerJar(ILogger logger, string serverJarPath, CancellationToken cancellationToken) {
|
||||
return Task.FromResult(new ServerJarInfo(Path.Combine(InstanceFolder, "run.sh")));
|
||||
}
|
||||
}
|
@@ -25,7 +25,7 @@ sealed class BackupArchiver {
|
||||
}
|
||||
|
||||
private bool IsFolderSkipped(ImmutableList<string> relativePath) {
|
||||
return relativePath is ["cache" or "crash-reports" or "debug" or "libraries" or "logs" or "mods" or "versions"];
|
||||
return relativePath is ["cache" or "crash-reports" or "debug" or "libraries" or "logs" or "mods" or "servermods" or "versions"];
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")]
|
||||
|
@@ -102,6 +102,7 @@ sealed class InstanceManagerActor : ReceiveActor<InstanceManagerActor.ICommand>
|
||||
IServerLauncher launcher = configuration.MinecraftServerKind switch {
|
||||
MinecraftServerKind.Vanilla => new VanillaLauncher(properties),
|
||||
MinecraftServerKind.Fabric => new FabricLauncher(properties),
|
||||
MinecraftServerKind.Forge => new ForgeLauncher(properties),
|
||||
_ => InvalidLauncher.Instance
|
||||
};
|
||||
|
||||
|
@@ -5,6 +5,7 @@ using Phantom.Common.Data.Instance;
|
||||
using Phantom.Common.Data.Replies;
|
||||
using Phantom.Common.Messages.Agent.ToController;
|
||||
using Phantom.Utils.Logging;
|
||||
using Phantom.Utils.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Phantom.Agent.Services.Instances;
|
||||
|
@@ -8,7 +8,7 @@ namespace Phantom.Common.Data;
|
||||
public sealed partial class AllowedPorts {
|
||||
[MemoryPackOrder(0)]
|
||||
[MemoryPackInclude]
|
||||
private readonly ImmutableArray<PortRange> allDefinitions;
|
||||
private readonly ImmutableArray<PortRange> allDefinitions;
|
||||
|
||||
private AllowedPorts(ImmutableArray<PortRange> allDefinitions) {
|
||||
// TODO normalize and deduplicate ranges
|
||||
|
@@ -2,5 +2,6 @@
|
||||
|
||||
public enum MinecraftServerKind : ushort {
|
||||
Vanilla = 1,
|
||||
Fabric = 2
|
||||
Fabric = 2,
|
||||
Forge = 3
|
||||
}
|
||||
|
@@ -83,7 +83,7 @@ public readonly partial record struct RamAllocationUnits(
|
||||
int unitMultiplier = char.ToUpperInvariant(definition[^1]) switch {
|
||||
'M' => 1,
|
||||
'G' => 1024,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(definition), "Must end with 'M' or 'G'.")
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(definition), "Must end with 'M' or 'G'.")
|
||||
};
|
||||
|
||||
if (!int.TryParse(definition[..^1], out int size)) {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using System.Collections.Immutable;
|
||||
using Phantom.Common.Data;
|
||||
using Phantom.Common.Data.Web.Users;
|
||||
using Phantom.Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults;
|
||||
using Phantom.Controller.Database;
|
||||
using Phantom.Controller.Database.Entities;
|
||||
using Phantom.Controller.Database.Repositories;
|
||||
@@ -57,12 +56,12 @@ sealed class UserManager {
|
||||
wasCreated = true;
|
||||
}
|
||||
else {
|
||||
return new CreationFailed(result.Error);
|
||||
return new Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults.CreationFailed(result.Error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (userRepository.SetUserPassword(user, password).TryGetError(out var error)) {
|
||||
return new UpdatingFailed(error);
|
||||
return new Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults.UpdatingFailed(error);
|
||||
}
|
||||
|
||||
auditLogWriter.AdministratorUserModified(user);
|
||||
@@ -71,7 +70,7 @@ sealed class UserManager {
|
||||
|
||||
var role = await new RoleRepository(db).GetByGuid(Role.Administrator.Guid);
|
||||
if (role == null) {
|
||||
return new AddingToRoleFailed();
|
||||
return new Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults.AddingToRoleFailed();
|
||||
}
|
||||
|
||||
await new UserRoleRepository(db).Add(user, role);
|
||||
@@ -85,10 +84,10 @@ sealed class UserManager {
|
||||
Logger.Information("Updated administrator user \"{Username}\" (GUID {Guid}).", username, user.UserGuid);
|
||||
}
|
||||
|
||||
return new Success(user.ToUserInfo());
|
||||
return new Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults.Success(user.ToUserInfo());
|
||||
} catch (Exception e) {
|
||||
Logger.Error(e, "Could not create or update administrator user \"{Username}\".", username);
|
||||
return new UnknownError();
|
||||
return new Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults.UnknownError();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>13</LangVersion>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>11</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# +---------------+
|
||||
# | Prepare build |
|
||||
# +---------------+
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/nightly/sdk:9.0 AS phantom-builder
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/nightly/sdk:8.0 AS phantom-builder
|
||||
ARG TARGETARCH
|
||||
|
||||
ADD . /app
|
||||
@@ -19,7 +19,7 @@ RUN find .artifacts/publish/*/* -maxdepth 0 -execdir mv '{}' 'release' \;
|
||||
# +---------------------+
|
||||
# | Phantom Agent image |
|
||||
# +---------------------+
|
||||
FROM mcr.microsoft.com/dotnet/nightly/runtime:9.0 AS phantom-agent
|
||||
FROM mcr.microsoft.com/dotnet/nightly/runtime:8.0 AS phantom-agent
|
||||
|
||||
RUN mkdir /data && chmod 777 /data
|
||||
WORKDIR /data
|
||||
@@ -46,7 +46,7 @@ ENTRYPOINT ["dotnet", "/app/Phantom.Agent.dll"]
|
||||
# +--------------------------+
|
||||
# | Phantom Controller image |
|
||||
# +--------------------------+
|
||||
FROM mcr.microsoft.com/dotnet/nightly/runtime:9.0 AS phantom-controller
|
||||
FROM mcr.microsoft.com/dotnet/nightly/runtime:8.0 AS phantom-controller
|
||||
|
||||
RUN mkdir /data && chmod 777 /data
|
||||
WORKDIR /data
|
||||
@@ -59,7 +59,7 @@ ENTRYPOINT ["dotnet", "/app/Phantom.Controller.dll"]
|
||||
# +-------------------+
|
||||
# | Phantom Web image |
|
||||
# +-------------------+
|
||||
FROM mcr.microsoft.com/dotnet/nightly/aspnet:9.0 AS phantom-web
|
||||
FROM mcr.microsoft.com/dotnet/nightly/aspnet:8.0 AS phantom-web
|
||||
|
||||
RUN mkdir /data && chmod 777 /data
|
||||
WORKDIR /data
|
||||
|
@@ -59,25 +59,25 @@ public sealed class RingBufferTests {
|
||||
[Test]
|
||||
public void AddOneItemAndEnumerateOne() {
|
||||
var buffer = PrepareRingBuffer(10, "a");
|
||||
Assert.That(buffer.EnumerateLast(1), Is.EquivalentTo(new[] { "a" }));
|
||||
Assert.That(buffer.EnumerateLast(1), Is.EquivalentTo(new [] { "a" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddOneItemAndEnumerateMaxValue() {
|
||||
var buffer = PrepareRingBuffer(10, "a");
|
||||
Assert.That(buffer.EnumerateLast(uint.MaxValue), Is.EquivalentTo(new[] { "a" }));
|
||||
Assert.That(buffer.EnumerateLast(uint.MaxValue), Is.EquivalentTo(new [] { "a" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddMultipleItemsWithinCapacityAndEnumerateFewer() {
|
||||
var buffer = PrepareRingBuffer(10, "a", "b", "c");
|
||||
Assert.That(buffer.EnumerateLast(2), Is.EquivalentTo(new[] { "b", "c" }));
|
||||
Assert.That(buffer.EnumerateLast(2), Is.EquivalentTo(new [] { "b", "c" }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddMultipleItemsWithinCapacityAndEnumerateMaxValue() {
|
||||
var buffer = PrepareRingBuffer(10, "a", "b", "c");
|
||||
Assert.That(buffer.EnumerateLast(uint.MaxValue), Is.EquivalentTo(new[] { "a", "b", "c" }));
|
||||
Assert.That(buffer.EnumerateLast(uint.MaxValue), Is.EquivalentTo(new [] { "a", "b", "c" }));
|
||||
}
|
||||
|
||||
[TestCase(3)]
|
||||
@@ -85,12 +85,12 @@ public sealed class RingBufferTests {
|
||||
[TestCase(5)]
|
||||
public void AddMultipleItemsOverflowingCapacityAndEnumerateFewer(int capacity) {
|
||||
var buffer = PrepareRingBuffer(capacity, "a", "b", "c", "d", "e", "f");
|
||||
Assert.That(buffer.EnumerateLast(2), Is.EquivalentTo(new[] { "e", "f" }));
|
||||
Assert.That(buffer.EnumerateLast(2), Is.EquivalentTo(new [] { "e", "f" }));
|
||||
}
|
||||
|
||||
[TestCase(3, ExpectedResult = new[] { "d", "e", "f" })]
|
||||
[TestCase(4, ExpectedResult = new[] { "c", "d", "e", "f" })]
|
||||
[TestCase(5, ExpectedResult = new[] { "b", "c", "d", "e", "f" })]
|
||||
[TestCase(3, ExpectedResult = new [] { "d", "e", "f" })]
|
||||
[TestCase(4, ExpectedResult = new [] { "c", "d", "e", "f" })]
|
||||
[TestCase(5, ExpectedResult = new [] { "b", "c", "d", "e", "f" })]
|
||||
public string[] AddMultipleItemsOverflowingCapacityAndEnumerateMaxValue(int capacity) {
|
||||
var buffer = PrepareRingBuffer(capacity, "a", "b", "c", "d", "e", "f");
|
||||
return buffer.EnumerateLast(uint.MaxValue).ToArray();
|
||||
|
@@ -9,12 +9,12 @@ public abstract class FormCustomValidationAttribute<TModel, TValue> : Validation
|
||||
|
||||
protected sealed override ValidationResult? IsValid(object? value, ValidationContext validationContext) {
|
||||
if (value is not TValue typedValue) {
|
||||
return new ValidationResult(null, new[] { FieldName });
|
||||
return new ValidationResult(null, new [] { FieldName });
|
||||
}
|
||||
|
||||
var model = (TModel) validationContext.ObjectInstance;
|
||||
var result = Validate(model, typedValue);
|
||||
return result == ValidationResult.Success ? result : new ValidationResult(result?.ErrorMessage, new[] { FieldName });
|
||||
return result == ValidationResult.Success ? result : new ValidationResult(result?.ErrorMessage, new [] { FieldName });
|
||||
}
|
||||
|
||||
protected abstract string FieldName { get; }
|
||||
|
@@ -9,7 +9,7 @@ public abstract class FormValidationAttribute<TModel, TValue> : ValidationAttrib
|
||||
|
||||
protected sealed override ValidationResult? IsValid(object? value, ValidationContext validationContext) {
|
||||
var model = (TModel) validationContext.ObjectInstance;
|
||||
return value is TValue typedValue && IsValid(model, typedValue) ? ValidationResult.Success : new ValidationResult(null, new[] { FieldName });
|
||||
return value is TValue typedValue && IsValid(model, typedValue) ? ValidationResult.Success : new ValidationResult(null, new [] { FieldName });
|
||||
}
|
||||
|
||||
protected abstract string FieldName { get; }
|
||||
|
@@ -1,6 +1,6 @@
|
||||
@using Phantom.Common.Data.Web.Users
|
||||
@using Phantom.Web.Services.Authentication
|
||||
@using Phantom.Web.Services
|
||||
@using Phantom.Web.Services.Authentication
|
||||
@using Phantom.Common.Data.Web.Users
|
||||
@inject ApplicationProperties ApplicationProperties
|
||||
|
||||
<div class="navbar navbar-dark">
|
||||
|
@@ -3,8 +3,8 @@
|
||||
@using System.Collections.Immutable
|
||||
@using Phantom.Common.Data.Web.AuditLog
|
||||
@using Phantom.Common.Data.Web.Users
|
||||
@using Phantom.Web.Services.Instances
|
||||
@using Phantom.Web.Services.Users
|
||||
@using Phantom.Web.Services.Instances
|
||||
@inherits PhantomComponent
|
||||
@inject AuditLogManager AuditLogManager
|
||||
@inject InstanceManager InstanceManager
|
||||
|
@@ -6,7 +6,7 @@
|
||||
@using Phantom.Web.Services.Agents
|
||||
@using Phantom.Web.Services.Events
|
||||
@using Phantom.Web.Services.Instances
|
||||
@inherits PhantomComponent
|
||||
@inherits Phantom.Web.Components.PhantomComponent
|
||||
@inject AgentManager AgentManager
|
||||
@inject EventLogManager EventLogManager
|
||||
@inject InstanceManager InstanceManager
|
||||
|
@@ -1,10 +1,10 @@
|
||||
@page "/"
|
||||
@inherits PhantomComponent
|
||||
@inherits Phantom.Web.Components.PhantomComponent
|
||||
|
||||
<h1>Home</h1>
|
||||
|
||||
@if (username != null) {
|
||||
<p>Welcome back, @username!</p>
|
||||
<p>Welcome back, @username!</p>
|
||||
}
|
||||
|
||||
@code {
|
||||
|
@@ -43,10 +43,10 @@
|
||||
</Cell>
|
||||
<Cell class="text-center">
|
||||
@if (instance.PlayerCounts is var (online, maximum)) {
|
||||
<p class="font-monospace">@online.ToString() / @maximum.ToString()</p>
|
||||
<p class="font-monospace">@online.ToString() / @maximum.ToString()</p>
|
||||
}
|
||||
else {
|
||||
<p class="font-monospace">-</p>
|
||||
<p class="font-monospace">-</p>
|
||||
}
|
||||
</Cell>
|
||||
<Cell>@configuration.MinecraftServerKind @configuration.MinecraftVersion</Cell>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
@page "/login"
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using Phantom.Web.Services
|
||||
@using Phantom.Web.Services.Authentication
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@attribute [AllowAnonymous]
|
||||
@inject Navigation Navigation
|
||||
@inject UserLoginManager LoginManager
|
||||
|
@@ -1,6 +1,4 @@
|
||||
@page "/setup"
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using System.Security.Cryptography
|
||||
@using Phantom.Common.Data
|
||||
@using Phantom.Common.Data.Web.Users
|
||||
@using Phantom.Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults
|
||||
@@ -9,6 +7,8 @@
|
||||
@using Phantom.Web.Services
|
||||
@using Phantom.Web.Services.Authentication
|
||||
@using Phantom.Web.Services.Rpc
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using System.Security.Cryptography
|
||||
@attribute [AllowAnonymous]
|
||||
@inject ApplicationProperties ApplicationProperties
|
||||
@inject UserLoginManager LoginManager
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
@code {
|
||||
|
||||
private readonly CreateAdministratorAccountFormModel form = new ();
|
||||
private readonly CreateAdministratorAccountFormModel form = new();
|
||||
|
||||
private sealed class CreateAdministratorAccountFormModel : FormModel {
|
||||
[Required]
|
||||
@@ -91,12 +91,12 @@
|
||||
private async Task<Result<string>> CreateOrUpdateAdministrator() {
|
||||
var reply = await ControllerConnection.Send<CreateOrUpdateAdministratorUserMessage, CreateOrUpdateAdministratorUserResult>(new CreateOrUpdateAdministratorUserMessage(form.Username, form.Password), Timeout.InfiniteTimeSpan);
|
||||
return reply switch {
|
||||
Success => Result.Ok,
|
||||
CreationFailed fail => fail.Error.ToSentences("\n"),
|
||||
UpdatingFailed fail => fail.Error.ToSentences("\n"),
|
||||
AddingToRoleFailed => "Could not assign administrator role to user.",
|
||||
null => "Timed out.",
|
||||
_ => "Unknown error."
|
||||
Success => Result.Ok,
|
||||
CreationFailed fail => fail.Error.ToSentences("\n"),
|
||||
UpdatingFailed fail => fail.Error.ToSentences("\n"),
|
||||
AddingToRoleFailed => "Could not assign administrator role to user.",
|
||||
null => "Timed out.",
|
||||
_ => "Unknown error."
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
@page "/users"
|
||||
@attribute [Authorize(Permission.ViewUsersPolicy)]
|
||||
@using System.Collections.Immutable
|
||||
@using Phantom.Common.Data.Web.Users
|
||||
@using Phantom.Web.Services.Authentication
|
||||
@using Phantom.Web.Services.Authorization
|
||||
@using Phantom.Web.Services.Users
|
||||
@inherits PhantomComponent
|
||||
@using Phantom.Common.Data.Web.Users
|
||||
@inherits Phantom.Web.Components.PhantomComponent
|
||||
@inject UserManager UserManager
|
||||
@inject RoleManager RoleManager
|
||||
@inject UserRoleManager UserRoleManager
|
||||
|
@@ -1,56 +1,56 @@
|
||||
@using Phantom.Common.Data.Instance
|
||||
<nobr>
|
||||
@switch (Status) {
|
||||
case InstanceIsOffline:
|
||||
<span class="fw-semibold">Offline</span>
|
||||
break;
|
||||
@switch (Status) {
|
||||
case InstanceIsOffline:
|
||||
<span class="fw-semibold">Offline</span>
|
||||
break;
|
||||
|
||||
case InstanceIsInvalid invalid:
|
||||
<span class="fw-semibold text-danger">Invalid <sup title="@invalid.Reason">[?]</sup></span>
|
||||
break;
|
||||
case InstanceIsInvalid invalid:
|
||||
<span class="fw-semibold text-danger">Invalid <sup title="@invalid.Reason">[?]</sup></span>
|
||||
break;
|
||||
|
||||
case InstanceIsNotRunning:
|
||||
<span class="fw-semibold">Not Running</span>
|
||||
break;
|
||||
case InstanceIsNotRunning:
|
||||
<span class="fw-semibold">Not Running</span>
|
||||
break;
|
||||
|
||||
case InstanceIsDownloading downloading:
|
||||
<ProgressBar Value="@downloading.Progress" Maximum="100">
|
||||
<span class="fw-semibold">Downloading Server</span> (@downloading.Progress%)
|
||||
</ProgressBar>
|
||||
break;
|
||||
case InstanceIsDownloading downloading:
|
||||
<ProgressBar Value="@downloading.Progress" Maximum="100">
|
||||
<span class="fw-semibold">Downloading Server</span> (@downloading.Progress%)
|
||||
</ProgressBar>
|
||||
break;
|
||||
|
||||
case InstanceIsLaunching:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Launching</span>
|
||||
break;
|
||||
case InstanceIsLaunching:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Launching</span>
|
||||
break;
|
||||
|
||||
case InstanceIsRunning:
|
||||
<span class="fw-semibold text-success">Running</span>
|
||||
break;
|
||||
case InstanceIsRunning:
|
||||
<span class="fw-semibold text-success">Running</span>
|
||||
break;
|
||||
|
||||
case InstanceIsBackingUp:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Backing Up</span>
|
||||
break;
|
||||
case InstanceIsBackingUp:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Backing Up</span>
|
||||
break;
|
||||
|
||||
case InstanceIsRestarting:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Restarting</span>
|
||||
break;
|
||||
case InstanceIsRestarting:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Restarting</span>
|
||||
break;
|
||||
|
||||
case InstanceIsStopping:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Stopping</span>
|
||||
break;
|
||||
case InstanceIsStopping:
|
||||
<div class="spinner-border" role="status"></div>
|
||||
<span class="fw-semibold"> Stopping</span>
|
||||
break;
|
||||
|
||||
case InstanceIsFailed failed:
|
||||
<span class="fw-semibold text-danger">Failed <sup title="@failed.Reason.ToSentence()">[?]</sup></span>
|
||||
break;
|
||||
case InstanceIsFailed failed:
|
||||
<span class="fw-semibold text-danger">Failed <sup title="@failed.Reason.ToSentence()">[?]</sup></span>
|
||||
break;
|
||||
|
||||
default:
|
||||
<span class="fw-semibold">Unknown</span>
|
||||
break;
|
||||
}
|
||||
default:
|
||||
<span class="fw-semibold">Unknown</span>
|
||||
break;
|
||||
}
|
||||
</nobr>
|
||||
|
||||
@code {
|
||||
|
@@ -27,7 +27,7 @@
|
||||
@code {
|
||||
|
||||
private ImmutableDictionary<Guid, RoleInfo> allRolesByGuid = ImmutableDictionary<Guid, RoleInfo>.Empty;
|
||||
private List<RoleItem> items = new ();
|
||||
private List<RoleItem> items = new();
|
||||
|
||||
protected override async Task BeforeShown(UserInfo user) {
|
||||
var allRoles = await RoleManager.GetAll(CancellationToken);
|
||||
@@ -77,11 +77,11 @@
|
||||
var errors = new List<string>();
|
||||
|
||||
foreach (var roleGuid in failedToAdd) {
|
||||
errors.Add("Could not add role: " + GetRoleName(roleGuid));
|
||||
errors.Add("Could not add role: " + GetRoleName(roleGuid));
|
||||
}
|
||||
|
||||
foreach (var roleGuid in failedToRemove) {
|
||||
errors.Add("Could not remove role: " + GetRoleName(roleGuid));
|
||||
errors.Add("Could not remove role: " + GetRoleName(roleGuid));
|
||||
}
|
||||
|
||||
OnEditFailure(string.Join("\n", errors));
|
||||
|
@@ -2,27 +2,22 @@
|
||||
using Phantom.Common.Data.Replies;
|
||||
using Phantom.Common.Data.Web.Minecraft;
|
||||
using Phantom.Common.Data.Web.Users;
|
||||
using Phantom.Common.Data.Web.Users.AddUserErrors;
|
||||
using Phantom.Common.Data.Web.Users.PasswordRequirementViolations;
|
||||
using Phantom.Common.Data.Web.Users.SetUserPasswordErrors;
|
||||
using Phantom.Common.Data.Web.Users.UsernameRequirementViolations;
|
||||
using PasswordIsInvalid = Phantom.Common.Data.Web.Users.AddUserErrors.PasswordIsInvalid;
|
||||
|
||||
namespace Phantom.Web.Utils;
|
||||
|
||||
static class Messages {
|
||||
public static string ToSentences(this AddUserError error, string delimiter) {
|
||||
return error switch {
|
||||
NameIsInvalid e => e.Violation.ToSentence(),
|
||||
PasswordIsInvalid e => string.Join(delimiter, e.Violations.Select(static v => v.ToSentence())),
|
||||
NameAlreadyExists => "Username is already occupied.",
|
||||
_ => "Unknown error."
|
||||
Common.Data.Web.Users.AddUserErrors.NameIsInvalid e => e.Violation.ToSentence(),
|
||||
Common.Data.Web.Users.AddUserErrors.PasswordIsInvalid e => string.Join(delimiter, e.Violations.Select(static v => v.ToSentence())),
|
||||
Common.Data.Web.Users.AddUserErrors.NameAlreadyExists => "Username is already occupied.",
|
||||
_ => "Unknown error."
|
||||
};
|
||||
}
|
||||
|
||||
public static string ToSentences(this SetUserPasswordError error, string delimiter) {
|
||||
return error switch {
|
||||
UserNotFound => "User not found.",
|
||||
Common.Data.Web.Users.SetUserPasswordErrors.UserNotFound => "User not found.",
|
||||
Common.Data.Web.Users.SetUserPasswordErrors.PasswordIsInvalid e => string.Join(delimiter, e.Violations.Select(static v => v.ToSentence())),
|
||||
_ => "Unknown error."
|
||||
};
|
||||
@@ -30,19 +25,19 @@ static class Messages {
|
||||
|
||||
public static string ToSentence(this UsernameRequirementViolation violation) {
|
||||
return violation switch {
|
||||
IsEmpty => "Username must not be empty.",
|
||||
TooLong v => "Username must not be longer than " + v.MaxLength + " character(s).",
|
||||
_ => "Unknown error."
|
||||
Common.Data.Web.Users.UsernameRequirementViolations.IsEmpty => "Username must not be empty.",
|
||||
Common.Data.Web.Users.UsernameRequirementViolations.TooLong v => "Username must not be longer than " + v.MaxLength + " character(s).",
|
||||
_ => "Unknown error."
|
||||
};
|
||||
}
|
||||
|
||||
public static string ToSentence(this PasswordRequirementViolation violation) {
|
||||
return violation switch {
|
||||
TooShort v => "Password must be at least " + v.MinimumLength + " character(s) long.",
|
||||
MustContainLowercaseLetter => "Password must contain a lowercase letter.",
|
||||
MustContainUppercaseLetter => "Password must contain an uppercase letter.",
|
||||
MustContainDigit => "Password must contain a digit.",
|
||||
_ => "Unknown error."
|
||||
Common.Data.Web.Users.PasswordRequirementViolations.TooShort v => "Password must be at least " + v.MinimumLength + " character(s) long.",
|
||||
Common.Data.Web.Users.PasswordRequirementViolations.MustContainLowercaseLetter => "Password must contain a lowercase letter.",
|
||||
Common.Data.Web.Users.PasswordRequirementViolations.MustContainUppercaseLetter => "Password must contain an uppercase letter.",
|
||||
Common.Data.Web.Users.PasswordRequirementViolations.MustContainDigit => "Password must contain a digit.",
|
||||
_ => "Unknown error."
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "9.0.0",
|
||||
"version": "8.0.0",
|
||||
"rollForward": "latestMinor",
|
||||
"allowPrerelease": true
|
||||
}
|
||||
|
Reference in New Issue
Block a user