mirror of
https://github.com/chylex/Minecraft-Phantom-Panel.git
synced 2025-04-22 02:15:41 +02:00
Fix missing audit logs for user login/logout
This commit is contained in:
parent
c7b57fac97
commit
d591318340
Common/Phantom.Common.Messages.Web
Controller/Phantom.Controller.Services
Web/Phantom.Web.Services/Authentication
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user