diff --git a/DX86/TcpServer.cs b/DX86/TcpServer.cs index e16d755..64c4445 100644 --- a/DX86/TcpServer.cs +++ b/DX86/TcpServer.cs @@ -24,6 +24,7 @@ public abstract class TcpServer optionsList = new List(); this.dx86 = new DX86(ms, ServerType.TCP); optionsList.Add("cancel"); + LoggedInClients = new Dictionary(); ms.Log("[DX86] Server Setup Complete."); _ = RunServer(); } diff --git a/Library/Employee.cs b/Library/Employee.cs index d639ba8..0965297 100644 --- a/Library/Employee.cs +++ b/Library/Employee.cs @@ -2,5 +2,44 @@ public class Employee { + private string _id; + private string _code; + private string _surname; + private string _forename; + private string _email; + private string _phone; + private string _street; + private string _city; + private string _postcode; + private string _country; + private string _department; + private string _position; + private EmployeeState _employeeState; + public Employee(string code) + { + _code = code; + } + + public string Id + { + get => _id; + } + + public string Code + { + get => _code; + } + + public string Surname + { + get => _surname; + set => _surname = value; + } + + public string Forename + { + get => _forename; + set => _forename = value; + } } \ No newline at end of file diff --git a/Library/Server.cs b/Library/Server.cs index 9f04414..f3ca0ed 100644 --- a/Library/Server.cs +++ b/Library/Server.cs @@ -12,6 +12,12 @@ public class Server private StreamReader reader; private StreamWriter writer; private Action onMessageReceived; + + public Action OnMessageReceived + { + get => onMessageReceived; + set => onMessageReceived = value ?? throw new ArgumentNullException(nameof(value), "onMessageReceived cannot be null."); + } private ConcurrentDictionary> pendingRequests = new(); @@ -41,11 +47,20 @@ public class Server string message = await reader.ReadLineAsync(); if (message != null) { - // Parse the JSON response - var response = JsonSerializer.Deserialize(message); - if (response != null && pendingRequests.TryRemove(response.Id, out var tcs)) + if (message.StartsWith("{") && message.EndsWith("}")) { - tcs.SetResult(response.Response); // Complete the task with the response + Console.WriteLine("Received: " + message); + // Parse the JSON response + var response = JsonSerializer.Deserialize(message); + Console.WriteLine("Parsed Response: " + (response != null ? $"Id={response.Id}, Response={response.Response}" : "null")); + if (response != null && pendingRequests.TryRemove(response.Id, out var tcs)) + { + tcs.SetResult(response.Response); // Complete the task with the response + } + else + { + onMessageReceived?.Invoke(message); // Handle other messages + } } else { @@ -90,13 +105,13 @@ public class Server } } - private class JsonRequest + public class JsonRequest { public string cmd { get; set; } public string cid { get; set; } } - private class JsonResponse + public class JsonResponse { public string Id { get; set; } public string Response { get; set; } @@ -147,6 +162,9 @@ public class Server } return Task.FromException(new Exception("Failed to login.")); } + + public Task HelpCommand() => ExecuteCommandAsync("help"); + public Task Logout() { @@ -159,6 +177,25 @@ public class Server return Task.FromException(new Exception("Failed to logout.")); } + public Task GetLoggedInEmployee() + { + var commandResult = ExecuteCommandAsync("getSelfUser").Result; + try + { + var employee = JsonSerializer.Deserialize(commandResult); + if (employee != null) + { + return Task.FromResult(employee); + } + return Task.FromException(new Exception("Failed to deserialize the employee data.")); + } + catch (JsonException) + { + Console.WriteLine("Failed to deserialize the command result."); + } + return Task.FromException(new Exception("Failed to get logged in employee.")); + } + public Task clockIn(Employee employee) { var commandResult = ExecuteCommandAsync("clock in").Result; diff --git a/Mitarbeiter-Verwaltung.sln b/Mitarbeiter-Verwaltung.sln index 841ed70..72ae59f 100644 --- a/Mitarbeiter-Verwaltung.sln +++ b/Mitarbeiter-Verwaltung.sln @@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DX86", "DX86\DX86.csproj", "{62C2A1CE-C82A-4588-9CE5-42E8108D8B78}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "TestClient\TestClient.csproj", "{6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -36,5 +38,9 @@ Global {62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Debug|Any CPU.Build.0 = Debug|Any CPU {62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Release|Any CPU.ActiveCfg = Release|Any CPU {62C2A1CE-C82A-4588-9CE5-42E8108D8B78}.Release|Any CPU.Build.0 = Release|Any CPU + {6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BE87DC7-392A-4B1F-8FDF-B08B6FB9B327}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Server/BackendServer.cs b/Server/BackendServer.cs index 88e8784..3a702fe 100644 --- a/Server/BackendServer.cs +++ b/Server/BackendServer.cs @@ -43,6 +43,7 @@ public class BackendServer : DX86.TcpServer JsonMessage? jsonMessage; if (message.StartsWith("{") && message.EndsWith("}")) { + this.SendMessageAsync(client, "Command received\n"); try { jsonMessage = JsonSerializer.Deserialize(message); diff --git a/Server/Commands/ClockCommand.cs b/Server/Commands/ClockCommand.cs deleted file mode 100644 index f1da70a..0000000 --- a/Server/Commands/ClockCommand.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Server.Commands; - -public class ClockCommand -{ - -} \ No newline at end of file diff --git a/Server/CommandAttribute.cs b/Server/Commands/CommandAttribute.cs similarity index 100% rename from Server/CommandAttribute.cs rename to Server/Commands/CommandAttribute.cs diff --git a/Server/CommandException.cs b/Server/Commands/CommandException.cs similarity index 100% rename from Server/CommandException.cs rename to Server/Commands/CommandException.cs diff --git a/Server/CommandLibrary.cs b/Server/Commands/CommandLibrary.cs similarity index 64% rename from Server/CommandLibrary.cs rename to Server/Commands/CommandLibrary.cs index 0f6b2c8..13e6853 100644 --- a/Server/CommandLibrary.cs +++ b/Server/Commands/CommandLibrary.cs @@ -1,6 +1,7 @@ using System.Net.Sockets; +using System.Text.Json; using DX86; -using Server.Commands; +using Library; namespace Server; @@ -26,21 +27,24 @@ public class CommandLibrary #region Client Commands - [Command("login")] - public static string LoginCommand(string[] args, TcpClient? client, TcpServer? socket) + [Command("login")] + public static string LoginCommand(string[] args, TcpClient? client, TcpServer? socket) { if (args.Length < 2) throw new CommandException("Missing arguments: usage is login "); string username = args[0]; string password = args[1]; + + if (socket?.LoggedInClients.ContainsKey(client) == true) + throw new CommandException("User already logged in."); - if (username == "test" && password == "1234") + if (username == "TEST" && password == "1234") { if (client != null) { socket?.LoggedInClients.Add(client, username); - return "Login successful"; + return "success"; } throw new CommandException("No client connection detected."); @@ -55,10 +59,26 @@ public class CommandLibrary if (client != null && socket?.LoggedInClients.ContainsKey(client) == true) { socket.LoggedInClients.Remove(client); - return "Logout successful"; + return "success"; } throw new CommandException("No client provided or not logged in"); } + + [Command("getSelfUser")] + public static string GetSelfUserCommand(TcpClient? client, TcpServer? socket) + { + if (client == null || socket == null) + throw new CommandException("No client connection detected."); + + if (socket.LoggedInClients.TryGetValue(client, out var username)) + { + Employee returnEmployee = new Employee(username); + string jsonEmployee = JsonSerializer.Serialize(returnEmployee); + return jsonEmployee; + } + + throw new CommandException("User not logged in."); + } #endregion diff --git a/Server/CommandManager.cs b/Server/Commands/CommandManager.cs similarity index 62% rename from Server/CommandManager.cs rename to Server/Commands/CommandManager.cs index f7154a8..e4d5c2c 100644 --- a/Server/CommandManager.cs +++ b/Server/Commands/CommandManager.cs @@ -2,7 +2,6 @@ using System.Reflection; using System.Text.Json; using DX86; -using Server.Commands; namespace Server; @@ -29,8 +28,15 @@ public class CommandManager Program.messageSender.Log($"[COMMANDMANAGER] Registered command: {attr.Name}"); } } - public void ExecuteCommand(string executor, TcpClient? client = null, TcpServer? clientSocket = null, string cid = "", params string[] args) +public void ExecuteCommand(string executor, + TcpClient? client = null, + TcpServer? clientSocket = null, + string cid = "", + params string[] args) { + // — ensure args is never null — + args ??= Array.Empty(); + if (_commands.TryGetValue(executor.ToLower(), out var method)) { try @@ -50,43 +56,55 @@ public class CommandManager arguments[i] = clientSocket; else { - Program.messageSender.Warn($"[COMMANDMANAGER] Unknown parameter type '{param.ParameterType.Name}' in command '{executor}'. Defaulting to null."); + Program.messageSender.Warn( + $"[COMMANDMANAGER] Unknown parameter type '{param.ParameterType.Name}' in '{executor}'. Defaulting that argument to null." + ); arguments[i] = null; } } - Program.messageSender.Debug($"[COMMANDMANAGER] Executing command '{executor}'..."); - string result = method.Invoke(null, arguments)?.ToString() ?? ""; + Program.messageSender.Debug($"[COMMANDMANAGER] Executing command '{executor}'…"); + var rawResult = method.Invoke(null, arguments); // invoke the static command method + string result = rawResult?.ToString() ?? ""; - var returnMessage = new JsonMessage + // **Log the returned string before sending** + Program.messageSender.Debug($"[COMMANDMANAGER] Command '{executor}' returned: \"{result}\""); + + var returnMessage = new Library.Server.JsonResponse { - cid = cid, - cmd = result + Id = cid, + Response = result }; var sendClientMessage = JsonSerializer.Serialize(returnMessage); clientSocket?.SendMessageAsync(client, sendClientMessage + "\n"); Program.messageSender.Debug($"[COMMANDMANAGER] Response sent to client."); } + // If your command threw a CommandException, catch it here: catch (TargetInvocationException ex) when (ex.InnerException is CommandException cmdEx) { Program.messageSender.Warn($"[COMMANDMANAGER] Command '{executor}' failed: {cmdEx.Message}"); - var returnMessage = new JsonMessage + var returnMessage = new Library.Server.JsonResponse { - cid = cid, - cmd = $"Error: {cmdEx.Message}" + Id = cid, + Response = $"Error: {cmdEx.Message}" }; - var sendClientMessage = JsonSerializer.Serialize(returnMessage); clientSocket?.SendMessageAsync(client, sendClientMessage + "\n"); } + // Any other exception inside the invoked method catch (TargetInvocationException ex) { var actualError = ex.InnerException?.Message ?? ex.Message; - Program.messageSender.Error($"[COMMANDMANAGER] Unexpected error in command '{executor}': {actualError}"); - Program.messageSender.Debug($"[COMMANDMANAGER] Stack Trace: {ex.InnerException?.StackTrace ?? ex.StackTrace}"); + Program.messageSender.Error( + $"[COMMANDMANAGER] Unexpected error in command '{executor}': {actualError}" + ); + Program.messageSender.Debug( + $"[COMMANDMANAGER] Stack Trace: {ex.InnerException?.StackTrace ?? ex.StackTrace}" + ); } + // Anything else thrown before or during Invoke() catch (Exception ex) { Program.messageSender.Error($"[COMMANDMANAGER] Failed to invoke command '{executor}': {ex.Message}"); diff --git a/Server/Commands/GetCommand.cs b/Server/Commands/GetCommand.cs deleted file mode 100644 index 58ce44d..0000000 --- a/Server/Commands/GetCommand.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Server.Commands; - -public class GetCommand -{ - -} \ No newline at end of file diff --git a/Server/Commands/HelpCommand.cs b/Server/Commands/HelpCommand.cs deleted file mode 100644 index 956e424..0000000 --- a/Server/Commands/HelpCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Net.Sockets; -using DX86; - -namespace Server.Commands; - -public class HelpCommand : ICommand -{ - public string Executor { get; } - - public HelpCommand() - { - Executor = "help"; - } - public string Exec(string[] args, TcpClient? client = null, TcpServer? clientSocket = null) - { - return - "Available commands:\n" + - "1. help - Show this help message\n" + - "2. exit - Exit the server\n" + - "3. user - User management\n" + - "4. settings - Server settings\n" + - "5. start - Start the server\n" + - "6. stop - Stop the server\n" - ; - } -} \ No newline at end of file diff --git a/Server/Commands/ICommand.cs b/Server/Commands/ICommand.cs deleted file mode 100644 index f5e3f04..0000000 --- a/Server/Commands/ICommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Net.Sockets; -using DX86; - -namespace Server.Commands; - -public interface ICommand -{ - string Executor { get; } - public string Exec(string[] args, TcpClient? client, TcpServer? clientSocket); -} \ No newline at end of file diff --git a/Server/Commands/LoginCommand.cs b/Server/Commands/LoginCommand.cs deleted file mode 100644 index daf5f62..0000000 --- a/Server/Commands/LoginCommand.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Net.Sockets; -using DX86; -using MySqlX.XDevAPI; - -namespace Server.Commands; - -public class LoginCommand : ICommand -{ - public string Executor { get; } - - public LoginCommand() - { - Executor = "login"; - } - public string Exec(string[] args, TcpClient? client, TcpServer? clientSocket) - { - - if (args[0] == "test" && args[1] == "test") - { - if (client != null) - { - //clientSocket?.SendMessageAsync(client, "Login successful"); - clientSocket?.LoggedInClients.Add(client, "test"); - return "Login successful"; - } - } - else - { - if (client != null) return "Invalid credentials"; - } - - return "No client provided or invalid credentials"; - } -} \ No newline at end of file diff --git a/Server/Commands/LogoutCommand.cs b/Server/Commands/LogoutCommand.cs deleted file mode 100644 index ae8713e..0000000 --- a/Server/Commands/LogoutCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Net.Sockets; -using DX86; - -namespace Server.Commands; - -public class LogoutCommand : ICommand -{ - public string Executor { get; } - public LogoutCommand() - { - Executor = "logout"; - } - public string Exec(string[] args, TcpClient? client = null, TcpServer? clientSocket = null) - { - if (clientSocket == null && client == null) - return "Please provide a valid client or clientSocket."; - - if (client != null && clientSocket != null && clientSocket.LoggedInClients.ContainsKey(client)) - { - clientSocket.LoggedInClients.Remove(client); - //clientSocket.SendMessageAsync(client, "Success"); - return "Logout successful."; - } - else - { - //clientSocket?.SendMessageAsync(client, "Logout failed. You are not logged in."); - return "Logout failed. You are not logged in."; - } - } -} \ No newline at end of file