mirror of
				https://github.com/chylex/Minecraft-Phantom-Panel.git
				synced 2025-10-31 20:17:16 +01:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			94148add2d
			...
			d591318340
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d591318340 | |||
| c7b57fac97 | |||
| 137a2a53c3 | 
| @@ -6,7 +6,6 @@ using Phantom.Agent.Services.Instances; | ||||
| using Phantom.Common.Data.Agent; | ||||
| using Phantom.Utils.Actor; | ||||
| using Phantom.Utils.Logging; | ||||
| using Phantom.Utils.Tasks; | ||||
| using Serilog; | ||||
|  | ||||
| namespace Phantom.Agent.Services; | ||||
| @@ -18,7 +17,6 @@ public sealed class AgentServices { | ||||
|  | ||||
| 	private AgentFolders AgentFolders { get; } | ||||
| 	private AgentState AgentState { get; } | ||||
| 	private TaskManager TaskManager { get; } | ||||
| 	private BackupManager BackupManager { get; } | ||||
|  | ||||
| 	internal JavaRuntimeRepository JavaRuntimeRepository { get; } | ||||
| @@ -30,13 +28,12 @@ public sealed class AgentServices { | ||||
| 		 | ||||
| 		this.AgentFolders = agentFolders; | ||||
| 		this.AgentState = new AgentState(); | ||||
| 		this.TaskManager = new TaskManager(PhantomLogger.Create<TaskManager, AgentServices>()); | ||||
| 		this.BackupManager = new BackupManager(agentFolders, serviceConfiguration.MaxConcurrentCompressionTasks); | ||||
| 		 | ||||
| 		this.JavaRuntimeRepository = new JavaRuntimeRepository(); | ||||
| 		this.InstanceTicketManager = new InstanceTicketManager(agentInfo, controllerConnection); | ||||
| 		 | ||||
| 		var instanceManagerInit = new InstanceManagerActor.Init(controllerConnection, agentFolders, AgentState, JavaRuntimeRepository, InstanceTicketManager, TaskManager, BackupManager); | ||||
| 		var instanceManagerInit = new InstanceManagerActor.Init(controllerConnection, agentFolders, AgentState, JavaRuntimeRepository, InstanceTicketManager, BackupManager); | ||||
| 		this.InstanceManager = ActorSystem.ActorOf(InstanceManagerActor.Factory(instanceManagerInit), "InstanceManager"); | ||||
| 	} | ||||
|  | ||||
| @@ -50,7 +47,6 @@ public sealed class AgentServices { | ||||
| 		Logger.Information("Stopping services..."); | ||||
| 		 | ||||
| 		await InstanceManager.Stop(new InstanceManagerActor.ShutdownCommand()); | ||||
| 		await TaskManager.Stop(); | ||||
| 		 | ||||
| 		BackupManager.Dispose(); | ||||
| 		 | ||||
|   | ||||
| @@ -24,7 +24,7 @@ sealed class BackupScheduler : CancellableBackgroundTask { | ||||
| 	 | ||||
| 	public event EventHandler<BackupCreationResult>? BackupCompleted; | ||||
|  | ||||
| 	public BackupScheduler(InstanceContext context, InstanceProcess process, int serverPort) : base(PhantomLogger.Create<BackupScheduler>(context.ShortName), context.Services.TaskManager, "Backup scheduler for " + context.ShortName) { | ||||
| 	public BackupScheduler(InstanceContext context, InstanceProcess process, int serverPort) : base(PhantomLogger.Create<BackupScheduler>(context.ShortName)) { | ||||
| 		this.backupManager = context.Services.BackupManager; | ||||
| 		this.context = context; | ||||
| 		this.process = process; | ||||
|   | ||||
| @@ -20,7 +20,7 @@ namespace Phantom.Agent.Services.Instances; | ||||
| sealed class InstanceManagerActor : ReceiveActor<InstanceManagerActor.ICommand> { | ||||
| 	private static readonly ILogger Logger = PhantomLogger.Create<InstanceManagerActor>(); | ||||
|  | ||||
| 	public readonly record struct Init(ControllerConnection ControllerConnection, AgentFolders AgentFolders, AgentState AgentState, JavaRuntimeRepository JavaRuntimeRepository, InstanceTicketManager InstanceTicketManager, TaskManager TaskManager, BackupManager BackupManager); | ||||
| 	public readonly record struct Init(ControllerConnection ControllerConnection, AgentFolders AgentFolders, AgentState AgentState, JavaRuntimeRepository JavaRuntimeRepository, InstanceTicketManager InstanceTicketManager, BackupManager BackupManager); | ||||
|  | ||||
| 	public static Props<ICommand> Factory(Init init) { | ||||
| 		return Props<ICommand>.Create(() => new InstanceManagerActor(init), new ActorConfiguration { SupervisorStrategy = SupervisorStrategies.Resume }); | ||||
| @@ -47,7 +47,7 @@ sealed class InstanceManagerActor : ReceiveActor<InstanceManagerActor.ICommand> | ||||
| 		var minecraftServerExecutables = new MinecraftServerExecutables(init.AgentFolders.ServerExecutableFolderPath); | ||||
| 		var launchServices = new LaunchServices(minecraftServerExecutables, init.JavaRuntimeRepository); | ||||
|  | ||||
| 		this.instanceServices = new InstanceServices(init.ControllerConnection, init.TaskManager, init.BackupManager, launchServices); | ||||
| 		this.instanceServices = new InstanceServices(init.ControllerConnection, init.BackupManager, launchServices); | ||||
| 		 | ||||
| 		ReceiveAndReply<ConfigureInstanceCommand, InstanceActionResult<ConfigureInstanceResult>>(ConfigureInstance); | ||||
| 		ReceiveAndReply<LaunchInstanceCommand, InstanceActionResult<LaunchInstanceResult>>(LaunchInstance); | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| using Phantom.Agent.Minecraft.Launcher; | ||||
| using Phantom.Agent.Rpc; | ||||
| using Phantom.Agent.Services.Backups; | ||||
| using Phantom.Utils.Tasks; | ||||
|  | ||||
| namespace Phantom.Agent.Services.Instances; | ||||
|  | ||||
| sealed record InstanceServices(ControllerConnection ControllerConnection, TaskManager TaskManager, BackupManager BackupManager, LaunchServices LaunchServices); | ||||
| sealed record InstanceServices(ControllerConnection ControllerConnection, BackupManager BackupManager, LaunchServices LaunchServices); | ||||
|   | ||||
| @@ -22,7 +22,7 @@ sealed class InstanceLogSender : CancellableBackgroundTask { | ||||
| 	 | ||||
| 	private int droppedLinesSinceLastSend; | ||||
|  | ||||
| 	public InstanceLogSender(ControllerConnection controllerConnection, TaskManager taskManager, Guid instanceGuid, string loggerName) : base(PhantomLogger.Create<InstanceLogSender>(loggerName), taskManager, "Instance log sender for " + loggerName) { | ||||
| 	public InstanceLogSender(ControllerConnection controllerConnection, Guid instanceGuid, string loggerName) : base(PhantomLogger.Create<InstanceLogSender>(loggerName)) { | ||||
| 		this.controllerConnection = controllerConnection; | ||||
| 		this.instanceGuid = instanceGuid; | ||||
| 		this.outputChannel = Channel.CreateBounded<string>(BufferOptions, OnLineDropped); | ||||
|   | ||||
| @@ -31,7 +31,7 @@ sealed class InstanceRunningState : IDisposable { | ||||
| 		this.Process = process; | ||||
| 		this.cancellationToken = cancellationToken; | ||||
|  | ||||
| 		this.logSender = new InstanceLogSender(context.Services.ControllerConnection, context.Services.TaskManager, context.InstanceGuid, context.ShortName); | ||||
| 		this.logSender = new InstanceLogSender(context.Services.ControllerConnection, context.InstanceGuid, context.ShortName); | ||||
|  | ||||
| 		this.backupScheduler = new BackupScheduler(context, process, configuration.ServerPort); | ||||
| 		this.backupScheduler.BackupCompleted += OnScheduledBackupCompleted; | ||||
|   | ||||
| @@ -7,7 +7,7 @@ public enum EventLogEventType { | ||||
| 	InstanceStopped, | ||||
| 	InstanceBackupSucceeded, | ||||
| 	InstanceBackupSucceededWithWarnings, | ||||
| 	InstanceBackupFailed, | ||||
| 	InstanceBackupFailed | ||||
| } | ||||
|  | ||||
| public static class EventLogEventTypeExtensions { | ||||
| @@ -18,7 +18,7 @@ public static class EventLogEventTypeExtensions { | ||||
| 		{ EventLogEventType.InstanceStopped, EventLogSubjectType.Instance }, | ||||
| 		{ EventLogEventType.InstanceBackupSucceeded, EventLogSubjectType.Instance }, | ||||
| 		{ EventLogEventType.InstanceBackupSucceededWithWarnings, EventLogSubjectType.Instance }, | ||||
| 		{ EventLogEventType.InstanceBackupFailed, EventLogSubjectType.Instance }, | ||||
| 		{ EventLogEventType.InstanceBackupFailed, EventLogSubjectType.Instance } | ||||
| 	}; | ||||
|  | ||||
| 	static EventLogEventTypeExtensions() { | ||||
|   | ||||
| @@ -4,7 +4,7 @@ using MemoryPack; | ||||
| namespace Phantom.Common.Data.Web.Users; | ||||
|  | ||||
| [MemoryPackable(GenerateType.VersionTolerant)] | ||||
| public sealed partial record LogInSuccess ( | ||||
| public sealed partial record LogInSuccess( | ||||
| 	[property: MemoryPackOrder(0)] Guid UserGuid, | ||||
| 	[property: MemoryPackOrder(1)] PermissionSet Permissions, | ||||
| 	[property: MemoryPackOrder(2)] ImmutableArray<byte> Token | ||||
|   | ||||
| @@ -14,9 +14,7 @@ public sealed partial class AuthToken { | ||||
| 	private readonly byte[] bytes; | ||||
|  | ||||
| 	internal AuthToken(byte[]? bytes) { | ||||
| 		if (bytes == null) { | ||||
| 			throw new ArgumentNullException(nameof(bytes)); | ||||
| 		} | ||||
| 		ArgumentNullException.ThrowIfNull(bytes); | ||||
|  | ||||
| 		if (bytes.Length != Length) { | ||||
| 			throw new ArgumentOutOfRangeException(nameof(bytes), "Invalid token length: " + bytes.Length + ". Token length must be exactly " + Length + " bytes."); | ||||
|   | ||||
| @@ -0,0 +1,10 @@ | ||||
| using System.Collections.Immutable; | ||||
| using MemoryPack; | ||||
|  | ||||
| namespace Phantom.Common.Messages.Web.ToController; | ||||
|  | ||||
| [MemoryPackable(GenerateType.VersionTolerant)] | ||||
| public sealed partial record LogOutMessage( | ||||
| 	[property: MemoryPackOrder(0)] Guid UserGuid, | ||||
| 	[property: MemoryPackOrder(1)] ImmutableArray<byte> SessionToken | ||||
| ) : IMessageToController; | ||||
| @@ -24,21 +24,22 @@ public static class WebMessageRegistries { | ||||
| 		ToController.Add<RegisterWebMessage>(0); | ||||
| 		ToController.Add<UnregisterWebMessage>(1); | ||||
| 		ToController.Add<LogInMessage, LogInSuccess?>(2); | ||||
| 		ToController.Add<CreateOrUpdateAdministratorUserMessage, CreateOrUpdateAdministratorUserResult>(3); | ||||
| 		ToController.Add<CreateUserMessage, CreateUserResult>(4); | ||||
| 		ToController.Add<DeleteUserMessage, DeleteUserResult>(5); | ||||
| 		ToController.Add<GetUsersMessage, ImmutableArray<UserInfo>>(6); | ||||
| 		ToController.Add<GetRolesMessage, ImmutableArray<RoleInfo>>(7); | ||||
| 		ToController.Add<GetUserRolesMessage, ImmutableDictionary<Guid, ImmutableArray<Guid>>>(8); | ||||
| 		ToController.Add<ChangeUserRolesMessage, ChangeUserRolesResult>(9); | ||||
| 		ToController.Add<CreateOrUpdateInstanceMessage, InstanceActionResult<CreateOrUpdateInstanceResult>>(10); | ||||
| 		ToController.Add<LaunchInstanceMessage, InstanceActionResult<LaunchInstanceResult>>(11); | ||||
| 		ToController.Add<StopInstanceMessage, InstanceActionResult<StopInstanceResult>>(12); | ||||
| 		ToController.Add<SendCommandToInstanceMessage, InstanceActionResult<SendCommandToInstanceResult>>(13); | ||||
| 		ToController.Add<GetMinecraftVersionsMessage, ImmutableArray<MinecraftVersion>>(14); | ||||
| 		ToController.Add<GetAgentJavaRuntimesMessage, ImmutableDictionary<Guid, ImmutableArray<TaggedJavaRuntime>>>(15); | ||||
| 		ToController.Add<GetAuditLogMessage, ImmutableArray<AuditLogItem>>(16); | ||||
| 		ToController.Add<GetEventLogMessage, ImmutableArray<EventLogItem>>(17); | ||||
| 		ToController.Add<LogOutMessage>(3); | ||||
| 		ToController.Add<CreateOrUpdateAdministratorUserMessage, CreateOrUpdateAdministratorUserResult>(4); | ||||
| 		ToController.Add<CreateUserMessage, CreateUserResult>(5); | ||||
| 		ToController.Add<DeleteUserMessage, DeleteUserResult>(6); | ||||
| 		ToController.Add<GetUsersMessage, ImmutableArray<UserInfo>>(7); | ||||
| 		ToController.Add<GetRolesMessage, ImmutableArray<RoleInfo>>(8); | ||||
| 		ToController.Add<GetUserRolesMessage, ImmutableDictionary<Guid, ImmutableArray<Guid>>>(9); | ||||
| 		ToController.Add<ChangeUserRolesMessage, ChangeUserRolesResult>(10); | ||||
| 		ToController.Add<CreateOrUpdateInstanceMessage, InstanceActionResult<CreateOrUpdateInstanceResult>>(11); | ||||
| 		ToController.Add<LaunchInstanceMessage, InstanceActionResult<LaunchInstanceResult>>(12); | ||||
| 		ToController.Add<StopInstanceMessage, InstanceActionResult<StopInstanceResult>>(13); | ||||
| 		ToController.Add<SendCommandToInstanceMessage, InstanceActionResult<SendCommandToInstanceResult>>(14); | ||||
| 		ToController.Add<GetMinecraftVersionsMessage, ImmutableArray<MinecraftVersion>>(15); | ||||
| 		ToController.Add<GetAgentJavaRuntimesMessage, ImmutableDictionary<Guid, ImmutableArray<TaggedJavaRuntime>>>(16); | ||||
| 		ToController.Add<GetAuditLogMessage, ImmutableArray<AuditLogItem>>(17); | ||||
| 		ToController.Add<GetEventLogMessage, ImmutableArray<EventLogItem>>(18); | ||||
| 		ToController.Add<ReplyMessage>(127); | ||||
| 		 | ||||
| 		ToWeb.Add<RegisterWebResultMessage>(0); | ||||
|   | ||||
| @@ -13,18 +13,18 @@ namespace Phantom.Controller.Database; | ||||
|  | ||||
| [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")] | ||||
| public class ApplicationDbContext : DbContext { | ||||
| 	public DbSet<UserEntity> Users { get; set; } = null!; | ||||
| 	public DbSet<RoleEntity> Roles { get; set; } = null!; | ||||
| 	public DbSet<PermissionEntity> Permissions { get; set; } = null!; | ||||
| 	public DbSet<UserEntity> Users { get; init; } = null!; | ||||
| 	public DbSet<RoleEntity> Roles { get; init; } = null!; | ||||
| 	public DbSet<PermissionEntity> Permissions { get; init; } = null!; | ||||
| 	 | ||||
| 	public DbSet<UserRoleEntity> UserRoles { get; set; } = null!; | ||||
| 	public DbSet<UserPermissionEntity> UserPermissions { get; set; } = null!; | ||||
| 	public DbSet<RolePermissionEntity> RolePermissions { get; set; } = null!; | ||||
| 	public DbSet<UserRoleEntity> UserRoles { get; init; } = null!; | ||||
| 	public DbSet<UserPermissionEntity> UserPermissions { get; init; } = null!; | ||||
| 	public DbSet<RolePermissionEntity> RolePermissions { get; init; } = null!; | ||||
| 	 | ||||
| 	public DbSet<AgentEntity> Agents { get; set; } = null!; | ||||
| 	public DbSet<InstanceEntity> Instances { get; set; } = null!; | ||||
| 	public DbSet<AuditLogEntity> AuditLog { get; set; } = null!; | ||||
| 	public DbSet<EventLogEntity> EventLog { get; set; } = null!; | ||||
| 	public DbSet<AgentEntity> Agents { get; init; } = null!; | ||||
| 	public DbSet<InstanceEntity> Instances { get; init; } = null!; | ||||
| 	public DbSet<AuditLogEntity> AuditLog { get; init; } = null!; | ||||
| 	public DbSet<EventLogEntity> EventLog { get; init; } = null!; | ||||
|  | ||||
| 	public AgentEntityUpsert AgentUpsert { get; } | ||||
| 	public InstanceEntityUpsert InstanceUpsert { get; } | ||||
|   | ||||
| @@ -9,7 +9,7 @@ namespace Phantom.Controller.Database.Entities; | ||||
| [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")] | ||||
| public sealed class AgentEntity { | ||||
| 	[Key] | ||||
| 	public Guid AgentGuid { get; set; } | ||||
| 	public Guid AgentGuid { get; init; } | ||||
| 	 | ||||
| 	public string Name { get; set; } | ||||
| 	public ushort ProtocolVersion { get; set; } | ||||
|   | ||||
| @@ -13,16 +13,16 @@ public class AuditLogEntity : IDisposable { | ||||
| 	[Key] | ||||
| 	[DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||||
| 	[SuppressMessage("ReSharper", "UnusedMember.Global")] | ||||
| 	public long Id { get; set; } | ||||
| 	public long Id { get; init; } | ||||
|  | ||||
| 	public Guid? UserGuid { get; set; } | ||||
| 	public DateTime UtcTime { get; set; } // Note: Converting to UTC is not best practice, but for historical records it's good enough. | ||||
| 	public AuditLogEventType EventType { get; set; } | ||||
| 	public AuditLogSubjectType SubjectType { get; set; } | ||||
| 	public string SubjectId { get; set; } | ||||
| 	public JsonDocument? Data { get; set; } | ||||
| 	public Guid? UserGuid { get; init; } | ||||
| 	public DateTime UtcTime { get; init; } // Note: Converting to UTC is not best practice, but for historical records it's good enough. | ||||
| 	public AuditLogEventType EventType { get; init; } | ||||
| 	public AuditLogSubjectType SubjectType { get; init; } | ||||
| 	public string SubjectId { get; init; } | ||||
| 	public JsonDocument? Data { get; init; } | ||||
|  | ||||
| 	public virtual UserEntity? User { get; set; } | ||||
| 	public virtual UserEntity? User { get; init; } | ||||
| 	 | ||||
| 	[SuppressMessage("ReSharper", "UnusedMember.Global")] | ||||
| 	internal AuditLogEntity() { | ||||
|   | ||||
| @@ -11,14 +11,14 @@ namespace Phantom.Controller.Database.Entities; | ||||
| [SuppressMessage("ReSharper", "ClassWithVirtualMembersNeverInherited.Global")] | ||||
| public sealed class EventLogEntity : IDisposable { | ||||
| 	[Key] | ||||
| 	public Guid EventGuid { get; set; } | ||||
| 	public Guid EventGuid { get; init; } | ||||
|  | ||||
| 	public DateTime UtcTime { get; set; } // Note: Converting to UTC is not best practice, but for historical records it's good enough. | ||||
| 	public Guid? AgentGuid { get; set; } | ||||
| 	public EventLogEventType EventType { get; set; } | ||||
| 	public EventLogSubjectType SubjectType { get; set; } | ||||
| 	public string SubjectId { get; set; } | ||||
| 	public JsonDocument? Data { get; set; } | ||||
| 	public DateTime UtcTime { get; init; } // Note: Converting to UTC is not best practice, but for historical records it's good enough. | ||||
| 	public Guid? AgentGuid { get; init; } | ||||
| 	public EventLogEventType EventType { get; init; } | ||||
| 	public EventLogSubjectType SubjectType { get; init; } | ||||
| 	public string SubjectId { get; init; } | ||||
| 	public JsonDocument? Data { get; init; } | ||||
| 	 | ||||
| 	[SuppressMessage("ReSharper", "UnusedMember.Global")] | ||||
| 	internal EventLogEntity() { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ namespace Phantom.Controller.Database.Entities; | ||||
| [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] | ||||
| public sealed class InstanceEntity { | ||||
| 	[Key] | ||||
| 	public Guid InstanceGuid { get; set; } | ||||
| 	public Guid InstanceGuid { get; init; } | ||||
|  | ||||
| 	public Guid AgentGuid { get; set; } | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ namespace Phantom.Controller.Database.Entities; | ||||
| [Table("Permissions", Schema = "identity")] | ||||
| public sealed class PermissionEntity { | ||||
| 	[Key] | ||||
| 	public string Id { get; set; } | ||||
| 	public string Id { get; init; } | ||||
|  | ||||
| 	public PermissionEntity(string id) { | ||||
| 		Id = id; | ||||
|   | ||||
| @@ -7,9 +7,9 @@ namespace Phantom.Controller.Database.Entities; | ||||
| [Table("Roles", Schema = "identity")] | ||||
| public sealed class RoleEntity { | ||||
| 	[Key] | ||||
| 	public Guid RoleGuid { get; set; } | ||||
| 	public Guid RoleGuid { get; init; } | ||||
|  | ||||
| 	public string Name { get; set; } | ||||
| 	public string Name { get; init; } | ||||
|  | ||||
| 	public RoleEntity(Guid roleGuid, string name) { | ||||
| 		RoleGuid = roleGuid; | ||||
|   | ||||
| @@ -4,8 +4,8 @@ namespace Phantom.Controller.Database.Entities; | ||||
|  | ||||
| [Table("RolePermissions", Schema = "identity")] | ||||
| public sealed class RolePermissionEntity { | ||||
| 	public Guid RoleGuid { get; set; } | ||||
| 	public string PermissionId { get; set; } | ||||
| 	public Guid RoleGuid { get; init; } | ||||
| 	public string PermissionId { get; init; } | ||||
| 	 | ||||
| 	public RolePermissionEntity(Guid roleGuid, string permissionId) { | ||||
| 		RoleGuid = roleGuid; | ||||
|   | ||||
| @@ -7,9 +7,9 @@ namespace Phantom.Controller.Database.Entities; | ||||
| [Table("Users", Schema = "identity")] | ||||
| public sealed class UserEntity { | ||||
| 	[Key] | ||||
| 	public Guid UserGuid { get; set; } | ||||
| 	public Guid UserGuid { get; init; } | ||||
|  | ||||
| 	public string Name { get; set; } | ||||
| 	public string Name { get; init; } | ||||
| 	public string PasswordHash { get; set; } | ||||
|  | ||||
| 	public UserEntity(Guid userGuid, string name, string passwordHash) { | ||||
|   | ||||
| @@ -4,8 +4,8 @@ namespace Phantom.Controller.Database.Entities; | ||||
|  | ||||
| [Table("UserPermissions", Schema = "identity")] | ||||
| public sealed class UserPermissionEntity { | ||||
| 	public Guid UserGuid { get; set; } | ||||
| 	public string PermissionId { get; set; } | ||||
| 	public Guid UserGuid { get; init; } | ||||
| 	public string PermissionId { get; init; } | ||||
|  | ||||
| 	public UserPermissionEntity(Guid userGuid, string permissionId) { | ||||
| 		UserGuid = userGuid; | ||||
|   | ||||
| @@ -4,11 +4,11 @@ namespace Phantom.Controller.Database.Entities; | ||||
|  | ||||
| [Table("UserRoles", Schema = "identity")] | ||||
| public sealed class UserRoleEntity { | ||||
| 	public Guid UserGuid { get; set; } | ||||
| 	public Guid RoleGuid { get; set; } | ||||
| 	public Guid UserGuid { get; init; } | ||||
| 	public Guid RoleGuid { get; init; } | ||||
|  | ||||
| 	public UserEntity User { get; set; } | ||||
| 	public RoleEntity Role { get; set; } | ||||
| 	public UserEntity User { get; init; } | ||||
| 	public RoleEntity Role { get; init; } | ||||
|  | ||||
| 	public UserRoleEntity(Guid userGuid, Guid roleGuid) { | ||||
| 		UserGuid = userGuid; | ||||
|   | ||||
| @@ -59,7 +59,7 @@ public sealed class ControllerServices : IDisposable { | ||||
| 		this.PermissionManager = new PermissionManager(dbProvider); | ||||
|  | ||||
| 		this.UserRoleManager = new UserRoleManager(dbProvider); | ||||
| 		this.UserLoginManager = new UserLoginManager(UserManager, PermissionManager); | ||||
| 		this.UserLoginManager = new UserLoginManager(UserManager, PermissionManager, dbProvider); | ||||
| 		this.AuditLogManager = new AuditLogManager(dbProvider); | ||||
| 		this.EventLogManager = new EventLogManager(ActorSystem, dbProvider, shutdownCancellationToken); | ||||
| 		 | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using Akka.Actor; | ||||
| using Phantom.Common.Data.Replies; | ||||
| using Phantom.Common.Data.Replies; | ||||
| using Phantom.Common.Messages.Agent; | ||||
| using Phantom.Common.Messages.Agent.BiDirectional; | ||||
| using Phantom.Common.Messages.Agent.ToAgent; | ||||
| @@ -19,8 +18,6 @@ sealed class AgentMessageHandlerActor : ReceiveActor<IMessageToController> { | ||||
| 		return Props<IMessageToController>.Create(() => new AgentMessageHandlerActor(init), new ActorConfiguration { SupervisorStrategy = SupervisorStrategies.Resume }); | ||||
| 	} | ||||
|  | ||||
| 	public IStash Stash { get; set; } = null!; | ||||
| 	 | ||||
| 	private readonly Guid agentGuid; | ||||
| 	private readonly RpcConnectionToClient<IMessageToAgent> connection; | ||||
| 	private readonly AgentRegistrationHandler agentRegistrationHandler; | ||||
|   | ||||
| @@ -69,6 +69,8 @@ sealed class WebMessageHandlerActor : ReceiveActor<IMessageToController> { | ||||
| 		 | ||||
| 		ReceiveAsync<RegisterWebMessage>(HandleRegisterWeb); | ||||
| 		Receive<UnregisterWebMessage>(HandleUnregisterWeb); | ||||
| 		ReceiveAndReplyLater<LogInMessage, LogInSuccess?>(HandleLogIn); | ||||
| 		Receive<LogOutMessage>(HandleLogOut); | ||||
| 		ReceiveAndReplyLater<CreateOrUpdateAdministratorUserMessage, CreateOrUpdateAdministratorUserResult>(HandleCreateOrUpdateAdministratorUser); | ||||
| 		ReceiveAndReplyLater<CreateUserMessage, CreateUserResult>(HandleCreateUser); | ||||
| 		ReceiveAndReplyLater<GetUsersMessage, ImmutableArray<UserInfo>>(HandleGetUsers); | ||||
| @@ -84,7 +86,6 @@ sealed class WebMessageHandlerActor : ReceiveActor<IMessageToController> { | ||||
| 		ReceiveAndReply<GetAgentJavaRuntimesMessage, ImmutableDictionary<Guid, ImmutableArray<TaggedJavaRuntime>>>(HandleGetAgentJavaRuntimes); | ||||
| 		ReceiveAndReplyLater<GetAuditLogMessage, ImmutableArray<AuditLogItem>>(HandleGetAuditLog); | ||||
| 		ReceiveAndReplyLater<GetEventLogMessage, ImmutableArray<EventLogItem>>(HandleGetEventLog); | ||||
| 		ReceiveAndReplyLater<LogInMessage, LogInSuccess?>(HandleLogIn); | ||||
| 		Receive<ReplyMessage>(HandleReply); | ||||
| 	} | ||||
|  | ||||
| @@ -96,6 +97,14 @@ sealed class WebMessageHandlerActor : ReceiveActor<IMessageToController> { | ||||
| 		connection.Close(); | ||||
| 	} | ||||
|  | ||||
| 	private Task<LogInSuccess?> HandleLogIn(LogInMessage message) { | ||||
| 		return userLoginManager.LogIn(message.Username, message.Password); | ||||
| 	} | ||||
|  | ||||
| 	private void HandleLogOut(LogOutMessage message) { | ||||
| 		_ = userLoginManager.LogOut(message.UserGuid, message.SessionToken); | ||||
| 	} | ||||
| 	 | ||||
| 	private Task<CreateOrUpdateAdministratorUserResult> HandleCreateOrUpdateAdministratorUser(CreateOrUpdateAdministratorUserMessage message) { | ||||
| 		return userManager.CreateOrUpdateAdministrator(message.Username, message.Password); | ||||
| 	} | ||||
| @@ -156,10 +165,6 @@ sealed class WebMessageHandlerActor : ReceiveActor<IMessageToController> { | ||||
| 		return eventLogManager.GetMostRecentItems(message.Count); | ||||
| 	} | ||||
|  | ||||
| 	private Task<LogInSuccess?> HandleLogIn(LogInMessage message) { | ||||
| 		return userLoginManager.LogIn(message.Username, message.Password); | ||||
| 	} | ||||
|  | ||||
| 	private void HandleReply(ReplyMessage message) { | ||||
| 		connection.Receive(message); | ||||
| 	} | ||||
|   | ||||
| @@ -2,19 +2,23 @@ | ||||
| using System.Collections.Immutable; | ||||
| using System.Security.Cryptography; | ||||
| using Phantom.Common.Data.Web.Users; | ||||
| using Phantom.Controller.Database; | ||||
| using Phantom.Controller.Database.Repositories; | ||||
|  | ||||
| namespace Phantom.Controller.Services.Users;  | ||||
|  | ||||
| sealed class UserLoginManager { | ||||
| 	private const int SessionIdBytes = 20; | ||||
| 	private readonly ConcurrentDictionary<string, List<ImmutableArray<byte>>> sessionTokensByUsername = new (); | ||||
| 	private readonly ConcurrentDictionary<Guid, List<ImmutableArray<byte>>> sessionTokensByUserGuid = new (); | ||||
| 	 | ||||
| 	private readonly UserManager userManager; | ||||
| 	private readonly PermissionManager permissionManager; | ||||
| 	private readonly IDbContextProvider dbProvider; | ||||
| 	 | ||||
| 	public UserLoginManager(UserManager userManager, PermissionManager permissionManager) { | ||||
| 	public UserLoginManager(UserManager userManager, PermissionManager permissionManager, IDbContextProvider dbProvider) { | ||||
| 		this.userManager = userManager; | ||||
| 		this.permissionManager = permissionManager; | ||||
| 		this.dbProvider = dbProvider; | ||||
| 	} | ||||
|  | ||||
| 	public async Task<LogInSuccess?> LogIn(string username, string password) { | ||||
| @@ -24,11 +28,37 @@ sealed class UserLoginManager { | ||||
| 		} | ||||
|  | ||||
| 		var token = ImmutableArray.Create(RandomNumberGenerator.GetBytes(SessionIdBytes)); | ||||
| 		var sessionTokens = sessionTokensByUsername.GetOrAdd(username, static _ => new List<ImmutableArray<byte>>()); | ||||
| 		var sessionTokens = sessionTokensByUserGuid.GetOrAdd(user.UserGuid, static _ => new List<ImmutableArray<byte>>()); | ||||
| 		lock (sessionTokens) { | ||||
| 			sessionTokens.Add(token); | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		await using (var db = dbProvider.Lazy()) { | ||||
| 			var auditLogWriter = new AuditLogRepository(db).Writer(user.UserGuid); | ||||
| 			auditLogWriter.UserLoggedIn(user); | ||||
| 			 | ||||
| 			await db.Ctx.SaveChangesAsync(); | ||||
| 		} | ||||
|  | ||||
| 		return new LogInSuccess(user.UserGuid, await permissionManager.FetchPermissionsForUserId(user.UserGuid), token); | ||||
| 	} | ||||
|  | ||||
| 	public async Task LogOut(Guid userGuid, ImmutableArray<byte> sessionToken) { | ||||
| 		if (!sessionTokensByUserGuid.TryGetValue(userGuid, out var sessionTokens)) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		lock (sessionTokens) { | ||||
| 			if (sessionTokens.RemoveAll(token => token.SequenceEqual(sessionToken)) == 0) { | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		await using var db = dbProvider.Lazy(); | ||||
| 		 | ||||
| 		var auditLogWriter = new AuditLogRepository(db).Writer(userGuid); | ||||
| 		auditLogWriter.UserLoggedOut(userGuid); | ||||
| 			 | ||||
| 		await db.Ctx.SaveChangesAsync(); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -10,7 +10,6 @@ using Phantom.Utils.Logging; | ||||
| using Phantom.Utils.Rpc; | ||||
| using Phantom.Utils.Rpc.Runtime; | ||||
| using Phantom.Utils.Runtime; | ||||
| using Phantom.Utils.Tasks; | ||||
|  | ||||
| var shutdownCancellationTokenSource = new CancellationTokenSource(); | ||||
| var shutdownCancellationToken = shutdownCancellationTokenSource.Token; | ||||
| @@ -64,14 +63,12 @@ try { | ||||
| 		return new RpcConfiguration(serviceName, host, port, connectionKey.Certificate); | ||||
| 	} | ||||
|  | ||||
| 	var rpcTaskManager = new TaskManager(PhantomLogger.Create<TaskManager>("Rpc")); | ||||
| 	try { | ||||
| 		await Task.WhenAll( | ||||
| 			RpcServerRuntime.Launch(ConfigureRpc("Agent", agentRpcServerHost, agentRpcServerPort, agentKeyData), AgentMessageRegistries.Definitions, controllerServices.AgentRegistrationHandler, controllerServices.ActorSystem, shutdownCancellationToken), | ||||
| 			RpcServerRuntime.Launch(ConfigureRpc("Web", webRpcServerHost, webRpcServerPort, webKeyData), WebMessageRegistries.Definitions, controllerServices.WebRegistrationHandler, controllerServices.ActorSystem, shutdownCancellationToken) | ||||
| 		); | ||||
| 	} finally { | ||||
| 		await rpcTaskManager.Stop(); | ||||
| 		NetMQConfig.Cleanup(); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,12 @@ | ||||
| using Akka.Actor; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using Akka.Actor; | ||||
| using Akka.Configuration; | ||||
| using Akka.Dispatch; | ||||
| using Akka.Dispatch.MessageQueues; | ||||
|  | ||||
| namespace Phantom.Utils.Actor.Mailbox; | ||||
|  | ||||
| [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] | ||||
| public sealed class UnboundedJumpAheadMailbox : MailboxType, IProducesMessageQueue<UnboundedJumpAheadMessageQueue> { | ||||
| 	public const string Name = "unbounded-jump-ahead-mailbox"; | ||||
| 	 | ||||
|   | ||||
| @@ -9,7 +9,7 @@ public sealed class RpcConnectionToClient<TMessageBase> : RpcConnection<TMessage | ||||
| 	private readonly uint routingId; | ||||
|  | ||||
| 	internal event EventHandler<RpcClientConnectionClosedEventArgs>? Closed; | ||||
| 	public bool IsClosed { get; private set; } | ||||
| 	private bool isClosed; | ||||
|  | ||||
| 	internal RpcConnectionToClient(ServerSocket socket, uint routingId, MessageRegistry<TMessageBase> messageRegistry, MessageReplyTracker replyTracker) : base(messageRegistry, replyTracker) { | ||||
| 		this.socket = socket; | ||||
| @@ -24,8 +24,8 @@ public sealed class RpcConnectionToClient<TMessageBase> : RpcConnection<TMessage | ||||
| 		bool hasClosed = false; | ||||
| 		 | ||||
| 		lock (this) { | ||||
| 			if (!IsClosed) { | ||||
| 				IsClosed = true; | ||||
| 			if (!isClosed) { | ||||
| 				isClosed = true; | ||||
| 				hasClosed = true; | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -12,7 +12,7 @@ public class EnvironmentVariablesTests { | ||||
| 	private readonly HashSet<string> createdVariables = new (); | ||||
|  | ||||
| 	private static void Discard<T>(T value) { | ||||
| 		var _ = value; | ||||
| 		_ = value; | ||||
| 	} | ||||
|  | ||||
| 	private string CreateVariable(string value) { | ||||
|   | ||||
| @@ -1,18 +1,8 @@ | ||||
| using System.Collections.Immutable; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
|  | ||||
| namespace Phantom.Utils.Collections; | ||||
|  | ||||
| public static class EnumerableExtensions { | ||||
| 	[SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] | ||||
| 	public static IEnumerable<TSource> WhereNotNull<TSource>(this IEnumerable<TSource?> items) { | ||||
| 		foreach (var item in items) { | ||||
| 			if (item is not null) { | ||||
| 				yield return item; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static async Task<ImmutableArray<TSource>> ToImmutableArrayAsync<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default) { | ||||
| 		var builder = ImmutableArray.CreateBuilder<TSource>(); | ||||
| 		 | ||||
|   | ||||
| @@ -5,7 +5,7 @@ using System.Diagnostics.CodeAnalysis; | ||||
| namespace Phantom.Utils.Collections; | ||||
|  | ||||
| public sealed class TableData<TRow, TKey> : IReadOnlyList<TRow>, IReadOnlyDictionary<TKey, TRow> where TRow : notnull where TKey : notnull { | ||||
| 	private readonly List<TRow> rowList = new(); | ||||
| 	private readonly List<TRow> rowList = new (); | ||||
| 	private readonly Dictionary<TKey, TRow> rowDictionary = new (); | ||||
|  | ||||
| 	public TRow this[int index] => rowList[index]; | ||||
|   | ||||
| @@ -8,19 +8,13 @@ public abstract class CancellableBackgroundTask { | ||||
| 	protected ILogger Logger { get; } | ||||
| 	protected CancellationToken CancellationToken { get; } | ||||
|  | ||||
| 	private readonly TaskManager taskManager; | ||||
| 	private readonly string taskName; | ||||
| 	 | ||||
| 	protected CancellableBackgroundTask(ILogger logger, TaskManager taskManager, string taskName) { | ||||
| 	protected CancellableBackgroundTask(ILogger logger) { | ||||
| 		this.Logger = logger; | ||||
| 		this.CancellationToken = cancellationTokenSource.Token; | ||||
| 		 | ||||
| 		this.taskManager = taskManager; | ||||
| 		this.taskName = taskName; | ||||
| 	} | ||||
|  | ||||
| 	protected void Start() { | ||||
| 		taskManager.Run(taskName, Run); | ||||
| 		Task.Run(Run, CancellationToken.None); | ||||
| 	} | ||||
|  | ||||
| 	private async Task Run() { | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace Phantom.Utils.Tasks; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
|  | ||||
| namespace Phantom.Utils.Tasks; | ||||
|  | ||||
| public abstract record Result<TValue, TError> { | ||||
| 	private Result() {} | ||||
| @@ -42,7 +44,7 @@ public abstract record Result<TError> { | ||||
| 		return new Fail(error); | ||||
| 	} | ||||
|  | ||||
| 	public static implicit operator Result<TError>(Result.OkType _) { | ||||
| 	public static implicit operator Result<TError>([SuppressMessage("ReSharper", "UnusedParameter.Global")] Result.OkType _) { | ||||
| 		return new Ok(); | ||||
| 	} | ||||
| 	 | ||||
|   | ||||
| @@ -1,76 +0,0 @@ | ||||
| using System.Collections.Concurrent; | ||||
| using Phantom.Utils.Collections; | ||||
| using Serilog; | ||||
|  | ||||
| namespace Phantom.Utils.Tasks; | ||||
|  | ||||
| public sealed class TaskManager { | ||||
| 	private readonly ILogger logger; | ||||
| 	private readonly CancellationTokenSource cancellationTokenSource = new (); | ||||
| 	private readonly CancellationToken cancellationToken; | ||||
| 	 | ||||
| 	private readonly ConcurrentDictionary<Task, string> runningTasks = new (ReferenceEqualityComparer<Task>.Instance); | ||||
| 	 | ||||
| 	public TaskManager(ILogger logger) { | ||||
| 		this.logger = logger; | ||||
| 		this.cancellationToken = cancellationTokenSource.Token; | ||||
| 	} | ||||
|  | ||||
| 	private T Add<T>(string name, T task) where T : Task { | ||||
| 		cancellationToken.ThrowIfCancellationRequested(); | ||||
| 		runningTasks.TryAdd(task, name); | ||||
| 		task.ContinueWith(OnFinished, CancellationToken.None, TaskContinuationOptions.RunContinuationsAsynchronously, TaskScheduler.Default); | ||||
| 		return task; | ||||
| 	} | ||||
|  | ||||
| 	private void OnFinished(Task task) { | ||||
| 		runningTasks.TryRemove(task, out _); | ||||
| 	} | ||||
|  | ||||
| 	public Task Run(string name, Action action) { | ||||
| 		return Add(name, Task.Run(action, cancellationToken)); | ||||
| 	} | ||||
|  | ||||
| 	public Task Run(string name, Func<Task> taskFunc) { | ||||
| 		return Add(name, Task.Run(taskFunc, cancellationToken)); | ||||
| 	} | ||||
|  | ||||
| 	public Task<T> Run<T>(string name, Func<Task<T>> taskFunc) { | ||||
| 		return Add(name, Task.Run(taskFunc, cancellationToken)); | ||||
| 	} | ||||
|  | ||||
| 	public async Task Stop() { | ||||
| 		logger.Information("Stopping task manager..."); | ||||
| 		 | ||||
| 		cancellationTokenSource.Cancel(); | ||||
|  | ||||
| 		var remainingTasksAwaiterTask = WaitForRemainingTasks(); | ||||
| 		while (true) { | ||||
| 			var logStateTimeoutTask = Task.Delay(TimeSpan.FromSeconds(10), CancellationToken.None); | ||||
| 			var completedTask = await Task.WhenAny(remainingTasksAwaiterTask, logStateTimeoutTask); | ||||
| 			if (completedTask == logStateTimeoutTask) { | ||||
| 				var remainingTaskNames = runningTasks.Values.Order().ToList(); | ||||
| 				var remainingTaskNameList = string.Join('\n', remainingTaskNames.Select(static name => "- " + name)); | ||||
| 				logger.Warning("Waiting for {TaskCount} task(s) to finish:\n{TaskNames}", remainingTaskNames.Count, remainingTaskNameList); | ||||
| 			} | ||||
| 			else { | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		runningTasks.Clear(); | ||||
| 		cancellationTokenSource.Dispose(); | ||||
| 		 | ||||
| 		logger.Information("Task manager stopped."); | ||||
| 	} | ||||
|  | ||||
| 	private async Task WaitForRemainingTasks() { | ||||
| 		foreach (var task in runningTasks.Keys) { | ||||
| 			try { | ||||
| 				await task; | ||||
| 			} catch (Exception) { | ||||
| 				// ignored | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,39 +0,0 @@ | ||||
| namespace Phantom.Utils.Threading; | ||||
|  | ||||
| public sealed class ThreadSafeLinkedList<T> : IDisposable { | ||||
| 	private readonly LinkedList<T> list = new (); | ||||
| 	private readonly SemaphoreSlim semaphore = new (1, 1); | ||||
|  | ||||
| 	public async Task Add(T item, bool toFront, CancellationToken cancellationToken) { | ||||
| 		await semaphore.WaitAsync(cancellationToken); | ||||
| 		try { | ||||
| 			if (toFront) { | ||||
| 				list.AddFirst(item); | ||||
| 			} | ||||
| 			else { | ||||
| 				list.AddLast(item); | ||||
| 			} | ||||
| 		} finally { | ||||
| 			semaphore.Release(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public async Task<T?> TryTakeFromFront(CancellationToken cancellationToken) { | ||||
| 		await semaphore.WaitAsync(cancellationToken); | ||||
| 		try { | ||||
| 			var firstNode = list.First; | ||||
| 			if (firstNode == null) { | ||||
| 				return default; | ||||
| 			} | ||||
|  | ||||
| 			list.RemoveFirst(); | ||||
| 			return firstNode.Value; | ||||
| 		} finally { | ||||
| 			semaphore.Release(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public void Dispose() { | ||||
| 		semaphore.Dispose(); | ||||
| 	} | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| namespace Phantom.Utils.Threading; | ||||
|  | ||||
| public sealed class ThreadSafeStructRef<T> : IDisposable where T : struct { | ||||
| 	private T? value; | ||||
| 	private readonly SemaphoreSlim semaphore = new (1, 1); | ||||
| 	 | ||||
| 	public async Task<T?> Get(CancellationToken cancellationToken) { | ||||
| 		await semaphore.WaitAsync(cancellationToken); | ||||
| 		try { | ||||
| 			return value; | ||||
| 		} finally { | ||||
| 			semaphore.Release(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public async Task Set(T? value, CancellationToken cancellationToken) { | ||||
| 		await semaphore.WaitAsync(cancellationToken); | ||||
| 		try { | ||||
| 			this.value = value; | ||||
| 		} finally { | ||||
| 			semaphore.Release(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public void Dispose() { | ||||
| 		semaphore.Dispose(); | ||||
| 	} | ||||
| } | ||||
| @@ -53,8 +53,8 @@ public sealed class UserLoginManager { | ||||
|  | ||||
| 	public async Task LogOut() { | ||||
| 		var stored = await sessionBrowserStorage.Delete(); | ||||
| 		if (stored != null) { | ||||
| 			sessionManager.Remove(stored.UserGuid, stored.Token); | ||||
| 		if (stored != null && sessionManager.Remove(stored.UserGuid, stored.Token)) { | ||||
| 			await controllerConnection.Send(new LogOutMessage(stored.UserGuid, stored.Token)); | ||||
| 		} | ||||
|  | ||||
| 		await navigation.NavigateTo(string.Empty); | ||||
|   | ||||
| @@ -23,9 +23,13 @@ public sealed class UserSessionManager { | ||||
| 		return userSessions.TryGetValue(userGuid, out var sessions) && sessions.HasToken(token) ? sessions.UserInfo : null; | ||||
| 	} | ||||
|  | ||||
| 	internal void Remove(Guid userGuid, ImmutableArray<byte> token) { | ||||
| 	internal bool Remove(Guid userGuid, ImmutableArray<byte> token) { | ||||
| 		if (userSessions.TryGetValue(userGuid, out var sessions)) { | ||||
| 			sessions.RemoveToken(token); | ||||
| 			return true; | ||||
| 		} | ||||
| 		else { | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -9,7 +9,6 @@ using Phantom.Utils.Logging; | ||||
| using Phantom.Utils.Rpc; | ||||
| using Phantom.Utils.Rpc.Sockets; | ||||
| using Phantom.Utils.Runtime; | ||||
| using Phantom.Utils.Tasks; | ||||
| using Phantom.Web; | ||||
| using Phantom.Web.Services; | ||||
| using Phantom.Web.Services.Rpc; | ||||
| @@ -59,8 +58,7 @@ try { | ||||
| 	var rpcSocket = RpcClientSocket.Connect(rpcConfiguration, WebMessageRegistries.Definitions, new RegisterWebMessage(webToken)); | ||||
|  | ||||
| 	var webConfiguration = new WebLauncher.Configuration(PhantomLogger.Create("Web"), webServerHost, webServerPort, webBasePath, dataProtectionKeysPath, shutdownCancellationToken); | ||||
| 	var taskManager = new TaskManager(PhantomLogger.Create<TaskManager>("Web")); | ||||
| 	var webApplication = WebLauncher.CreateApplication(webConfiguration, taskManager, applicationProperties, rpcSocket.Connection); | ||||
| 	var webApplication = WebLauncher.CreateApplication(webConfiguration, applicationProperties, rpcSocket.Connection); | ||||
|  | ||||
| 	using var actorSystem = ActorSystemFactory.Create("Web"); | ||||
| 	 | ||||
| @@ -88,7 +86,6 @@ try { | ||||
| 		await WebLauncher.Launch(webConfiguration, webApplication); | ||||
| 	} finally { | ||||
| 		shutdownCancellationTokenSource.Cancel(); | ||||
| 		await taskManager.Stop(); | ||||
| 		 | ||||
| 		rpcDisconnectSemaphore.Release(); | ||||
| 		await rpcTask; | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| using Microsoft.AspNetCore.DataProtection; | ||||
| using Phantom.Common.Messages.Web; | ||||
| using Phantom.Utils.Rpc.Runtime; | ||||
| using Phantom.Utils.Tasks; | ||||
| using Phantom.Web.Services; | ||||
| using Serilog; | ||||
| using ILogger = Serilog.ILogger; | ||||
| @@ -13,7 +12,7 @@ static class WebLauncher { | ||||
| 		public string HttpUrl => "http://" + Host + ":" + Port; | ||||
| 	} | ||||
| 	 | ||||
| 	internal static WebApplication CreateApplication(Configuration config, TaskManager taskManager, ApplicationProperties applicationProperties, RpcConnectionToServer<IMessageToController> controllerConnection) { | ||||
| 	internal static WebApplication CreateApplication(Configuration config, ApplicationProperties applicationProperties, RpcConnectionToServer<IMessageToController> controllerConnection) { | ||||
| 		var assembly = typeof(WebLauncher).Assembly; | ||||
| 		var builder = WebApplication.CreateBuilder(new WebApplicationOptions { | ||||
| 			ApplicationName = assembly.GetName().Name, | ||||
| @@ -29,7 +28,6 @@ static class WebLauncher { | ||||
| 			builder.WebHost.UseStaticWebAssets(); | ||||
| 		} | ||||
|  | ||||
| 		builder.Services.AddSingleton(taskManager); | ||||
| 		builder.Services.AddSingleton(applicationProperties); | ||||
| 		builder.Services.AddSingleton(controllerConnection); | ||||
| 		builder.Services.AddPhantomServices(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user