From c23091fa6e30c4a66a1fc89c90cfca3f87ed37cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Gr=C3=BCssing?= Date: Wed, 10 Jun 2026 13:31:11 +0200 Subject: [PATCH] Add: Agent v2.1.2, WebSocket Live Shell, WebRTC Remote Desktop (Beta), Announcement Push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Agent v2.1.2: WebSocket ShellService, ACK nach WS-Ankündigungen, shown_announcements Fix - Backend: shellServer.js mit WebSocket-Server (Shell + Announcement Push + RTC Signaling) - Backend: patch.controller.js Fix (command_id=0 Falsy-Bug beim Auto-Update) - Frontend: Remote Desktop Tab (WebRTC Beta) in AgentDetailPage für super_admin/admin - Frontend: PatchManagementPage auf v2.1.2 aktualisiert - WPF Notification: AllowsTransparency=False + kein DropShadowEffect (Dispatcher-Crash Fix) Co-Authored-By: Claude Sonnet 4.6 --- agent-cs/AgentWorker.cs | 12 +- agent-cs/Models/CheckinModels.cs | 1 + agent-cs/Program.cs | 29 +- agent-cs/Services/CommandExecutor.cs | 28 + agent-cs/Services/NotificationService.cs | 11 +- agent-cs/Services/ShellService.cs | 199 ++ agent-cs/UI/NotificationWindow.xaml | 11 +- agent-cs/config.template.json | 2 +- agent-cs/setup.iss | 4 +- backend/package-lock.json | 2041 ++++++++++++++++- backend/package.json | 21 +- .../controllers/announcement.controller.js | 14 +- backend/src/controllers/fidoKey.controller.js | 5 +- backend/src/controllers/patch.controller.js | 43 +- backend/src/db/seed.js | 2 + backend/src/routes/patch.routes.js | 5 + backend/src/server.js | 8 +- backend/src/services/fidoKey.service.js | 7 +- backend/src/ws/shellServer.js | 157 ++ frontend/nginx.conf | 12 + frontend/src/pages/AgentDetailPage.jsx | 333 +++ frontend/src/pages/AssetsPage.jsx | 18 +- frontend/src/pages/FidoKeysPage.jsx | 222 +- frontend/src/pages/MonitoringPage.jsx | 693 +++--- frontend/src/pages/PatchManagementPage.jsx | 2 +- frontend/src/pages/UserManagementPage.jsx | 95 +- frontend/src/styles/App.css | 62 + 27 files changed, 3481 insertions(+), 556 deletions(-) create mode 100644 agent-cs/Services/ShellService.cs create mode 100644 backend/src/ws/shellServer.js diff --git a/agent-cs/AgentWorker.cs b/agent-cs/AgentWorker.cs index f530240..e13286b 100644 --- a/agent-cs/AgentWorker.cs +++ b/agent-cs/AgentWorker.cs @@ -6,7 +6,7 @@ namespace ITNexusAgent; public class AgentWorker { - private const string Version = "2.0.0"; + private const string Version = "2.1.2"; private const string DataDir = @"C:\ProgramData\IT Nexus Agent"; private const string ConfigPath = @"C:\ProgramData\IT Nexus Agent\config.json"; private const string StatusPath = @"C:\ProgramData\IT Nexus Agent\status.json"; @@ -39,6 +39,10 @@ public class AgentWorker Log($"Agent v{Version} gestartet"); + // WebSocket Shell-Service im Hintergrund starten + var shellService = new ShellService(_config.ServerUrl, _config.AgentKey, SystemInfoService.GetHostname()); + _ = shellService.RunAsync(_ct); + while (!_ct.IsCancellationRequested) { await RunCycleAsync(); @@ -79,12 +83,16 @@ public class AgentWorker await executor.ExecuteAsync(cmd); } - // Ankündigungen anzeigen + // Ankündigungen anzeigen + sofort ACKen damit Server sie nicht mehr schickt if (response.Announcements.Count > 0) { _notifier!.ShowAnnouncements(response.Announcements); foreach (var ann in response.Announcements) + { Log($"ANNOUNCEMENT: Dialog für {SystemInfoService.GetLastUser()} gestartet - ID {ann.Id}"); + try { await _api!.AckAnnouncementAsync(ann.Id, payload.Hostname); } + catch (Exception ex) { Log($"ANNOUNCEMENT ACK Fehler: {ex.Message}"); } + } } } catch (Exception ex) diff --git a/agent-cs/Models/CheckinModels.cs b/agent-cs/Models/CheckinModels.cs index f70dcbe..c06fb84 100644 --- a/agent-cs/Models/CheckinModels.cs +++ b/agent-cs/Models/CheckinModels.cs @@ -45,6 +45,7 @@ public class PatchCommand { [JsonProperty("id")] public int Id { get; set; } [JsonProperty("command")] public string Command { get; set; } = ""; + [JsonProperty("params")] public string? Params { get; set; } } public class RunningCommand diff --git a/agent-cs/Program.cs b/agent-cs/Program.cs index bf72f42..2f4d42c 100644 --- a/agent-cs/Program.cs +++ b/agent-cs/Program.cs @@ -39,15 +39,38 @@ internal class Program static void RunNotification(string base64Json) { + const string errorLog = @"C:\ProgramData\IT Nexus Agent\notify-error.log"; try { var json = Encoding.UTF8.GetString(Convert.FromBase64String(base64Json)); + File.AppendAllText(errorLog, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} START json={json}\n"); + var ann = JsonConvert.DeserializeObject(json); - if (ann == null) return; + if (ann == null) + { + File.AppendAllText(errorLog, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ERROR: Deserialization returned null\n"); + return; + } + var app = new System.Windows.Application(); - app.Run(new NotificationWindow(ann)); + app.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose; + app.DispatcherUnhandledException += (s, e) => + { + File.AppendAllText(errorLog, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} DISPATCHER ERROR: {e.Exception}\n"); + e.Handled = true; + app.Shutdown(); + }; + + var win = new NotificationWindow(ann); + win.Topmost = true; + win.Show(); + win.Activate(); + app.Run(); + } + catch (Exception ex) + { + File.AppendAllText(errorLog, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} ERROR: {ex}\n"); } - catch { } } static void RunDashboard() diff --git a/agent-cs/Services/CommandExecutor.cs b/agent-cs/Services/CommandExecutor.cs index f26c436..780206d 100644 --- a/agent-cs/Services/CommandExecutor.cs +++ b/agent-cs/Services/CommandExecutor.cs @@ -27,6 +27,7 @@ public class CommandExecutor(ApiService api, string hostname, string dataDir, st "reboot" => await Reboot(cmd.Id), "upgrade_win11" => await UpgradeWin11(), "update_agent" => await UpdateAgent(), + "shell_exec" => await ShellExec(cmd.Params ?? ""), _ => $"Unbekannter Command: {cmd.Command}" }; } @@ -95,6 +96,33 @@ public class CommandExecutor(ApiService api, string hostname, string dataDir, st return Task.FromResult("running"); } + private Task ShellExec(string command) + { + if (string.IsNullOrWhiteSpace(command)) return Task.FromResult("Kein Befehl angegeben"); + try + { + var psi = new ProcessStartInfo("powershell.exe", + $"-NonInteractive -NoProfile -ExecutionPolicy Bypass -Command \"{command.Replace("\"", "\\\"")}\"") + { + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false + }; + var p = Process.Start(psi)!; + var stdout = p.StandardOutput.ReadToEnd(); + var stderr = p.StandardError.ReadToEnd(); + p.WaitForExit(30000); + var output = stdout; + if (!string.IsNullOrEmpty(stderr)) output += "\n[STDERR] " + stderr; + return Task.FromResult(string.IsNullOrEmpty(output) ? "(kein Output)" : output.Trim()); + } + catch (Exception ex) + { + return Task.FromResult($"Fehler: {ex.Message}"); + } + } + private async Task UpdateAgent() { var bytes = await _api.DownloadSetupAsync(); diff --git a/agent-cs/Services/NotificationService.cs b/agent-cs/Services/NotificationService.cs index 6e46b2b..ec15e11 100644 --- a/agent-cs/Services/NotificationService.cs +++ b/agent-cs/Services/NotificationService.cs @@ -35,6 +35,11 @@ public class NotificationService return []; } + public void RemoveShownId(int id) + { + if (_shownIds.Remove(id)) SaveShownIds(); + } + private void SaveShownIds() { try { File.WriteAllText(_shownIdsPath, JsonConvert.SerializeObject(_shownIds.ToList())); } @@ -84,8 +89,12 @@ public class NotificationService // Task mit Trigger weit in der Zukunft erstellen (damit er nicht abläuft vor /run) var triggerTime = DateTime.Now.AddMinutes(60).ToString("HH:mm:ss"); + // AzureAD-User (Entra/Hybrid-Join) können nicht per /ru aufgelöst werden → INTERACTIVE + var ruArg = fullUser.StartsWith("AzureAD\\", StringComparison.OrdinalIgnoreCase) + ? "/ru \"INTERACTIVE\"" + : $"/ru \"{fullUser}\""; var args = $"/create /tn \"{taskName}\" /tr \"\\\"{_exePath}\\\" --notify {json}\" " + - $"/sc ONCE /st {triggerTime} /ru \"{fullUser}\" /it /f"; + $"/sc ONCE /st {triggerTime} {ruArg} /it /f"; var p = Process.Start(new ProcessStartInfo("schtasks.exe", args) { CreateNoWindow = true, RedirectStandardError = true, UseShellExecute = false }); p?.WaitForExit(); diff --git a/agent-cs/Services/ShellService.cs b/agent-cs/Services/ShellService.cs new file mode 100644 index 0000000..1a37c52 --- /dev/null +++ b/agent-cs/Services/ShellService.cs @@ -0,0 +1,199 @@ +using System.Diagnostics; +using System.Net.Http.Json; +using System.Net.WebSockets; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace ITNexusAgent.Services; + +public class ShellService +{ + private readonly string _serverUrl; + private readonly string _agentKey; + private readonly string _hostname; + + public ShellService(string serverUrl, string agentKey, string hostname) + { + _serverUrl = serverUrl; + _agentKey = agentKey; + _hostname = hostname; + } + + public async Task RunAsync(CancellationToken ct) + { + while (!ct.IsCancellationRequested) + { + try { await ConnectAsync(ct); } + catch (Exception ex) { AgentWorker.Log($"SHELL: {ex.Message}"); } + + if (!ct.IsCancellationRequested) + await Task.Delay(TimeSpan.FromSeconds(15), ct).ContinueWith(_ => { }); + } + } + + private async Task ConnectAsync(CancellationToken ct) + { + var wsUrl = _serverUrl + .Replace("https://", "wss://") + .Replace("http://", "ws://") + + $"/ws?type=agent&key={Uri.EscapeDataString(_agentKey)}&hostname={Uri.EscapeDataString(_hostname)}"; + + using var ws = new ClientWebSocket(); + ws.Options.SetRequestHeader("User-Agent", "IT-Nexus-Agent/2.1.2"); + + await ws.ConnectAsync(new Uri(wsUrl), ct); + AgentWorker.Log("SHELL: WebSocket verbunden"); + + Process? shell = null; + CancellationTokenSource? shellCts = null; + + async Task SendText(string text) + { + if (ws.State != WebSocketState.Open) return; + var bytes = Encoding.UTF8.GetBytes(text); + await ws.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text, true, CancellationToken.None); + } + + void StartShell() + { + try { shellCts?.Cancel(); shell?.Kill(); } catch { } + + shellCts = CancellationTokenSource.CreateLinkedTokenSource(ct); + var token = shellCts.Token; + + var psi = new ProcessStartInfo("powershell.exe", "-NoExit -NoLogo -NoProfile") + { + CreateNoWindow = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + StandardOutputEncoding = Encoding.UTF8, + StandardErrorEncoding = Encoding.UTF8, + }; + + shell = Process.Start(psi)!; + AgentWorker.Log("SHELL: PowerShell gestartet"); + + // stdout streamen + _ = Task.Run(async () => + { + var buf = new char[1024]; + while (!token.IsCancellationRequested) + { + try + { + int n = await shell.StandardOutput.ReadAsync(buf, 0, buf.Length); + if (n == 0) break; + await SendText(new string(buf, 0, n)); + } + catch { break; } + } + }, token); + + // stderr streamen (rot markiert) + _ = Task.Run(async () => + { + var buf = new char[1024]; + while (!token.IsCancellationRequested) + { + try + { + int n = await shell.StandardError.ReadAsync(buf, 0, buf.Length); + if (n == 0) break; + await SendText("\x1b[31m" + new string(buf, 0, n) + "\x1b[0m"); + } + catch { break; } + } + }, token); + } + + void StopShell() + { + shellCts?.Cancel(); + try { shell?.Kill(); } catch { } + shell = null; + AgentWorker.Log("SHELL: PowerShell gestoppt"); + } + + try + { + var buffer = new byte[8192]; + while (ws.State == WebSocketState.Open && !ct.IsCancellationRequested) + { + WebSocketReceiveResult result; + try + { + result = await ws.ReceiveAsync(new ArraySegment(buffer), ct); + } + catch { break; } + + if (result.MessageType == WebSocketMessageType.Close) break; + + var msg = Encoding.UTF8.GetString(buffer, 0, result.Count); + JObject? obj; + try { obj = JObject.Parse(msg); } + catch { continue; } + + switch (obj["type"]?.ToString()) + { + case "start_shell": + StartShell(); + break; + + case "input": + if (shell != null && !shell.HasExited) + { + var data = obj["data"]?.ToString() ?? ""; + await shell.StandardInput.WriteAsync(data); + await shell.StandardInput.FlushAsync(); + } + break; + + case "stop_shell": + StopShell(); + break; + + case "announcements": + // Sofort-Push von Ankündigungen (ohne Warten auf Check-in) + var anns = obj["announcements"]?.ToObject>(); + if (anns != null && anns.Count > 0) + { + var notifier = new NotificationService( + System.Diagnostics.Process.GetCurrentProcess().MainModule!.FileName, + @"C:\ProgramData\IT Nexus Agent"); + notifier.ShowAnnouncements(anns); + AgentWorker.Log($"SHELL: {anns.Count} Ankündigung(en) via WebSocket empfangen"); + // ACK senden + shown_announcements.json bereinigen damit gelöschte+neu erstellte + // Ankündigungen mit gleicher ID nicht geblockt werden + foreach (var ann in anns) + { + try + { + await AckAnnouncementAsync(ann.Id); + notifier.RemoveShownId(ann.Id); + } + catch (Exception ex) { AgentWorker.Log($"SHELL: ACK Fehler für ID {ann.Id}: {ex.Message}"); } + } + } + break; + } + } + } + finally + { + StopShell(); + } + + AgentWorker.Log("SHELL: WebSocket getrennt"); + } + + private async Task AckAnnouncementAsync(int announcementId) + { + using var http = new HttpClient(); + http.DefaultRequestHeaders.Add("x-agent-key", _agentKey); + var body = JsonContent.Create(new { hostname = _hostname }); + await http.PostAsync($"{_serverUrl}/api/announcements/{announcementId}/ack-agent", body); + } +} diff --git a/agent-cs/UI/NotificationWindow.xaml b/agent-cs/UI/NotificationWindow.xaml index 4cf3428..d3353ee 100644 --- a/agent-cs/UI/NotificationWindow.xaml +++ b/agent-cs/UI/NotificationWindow.xaml @@ -7,8 +7,8 @@ WindowStartupLocation="CenterScreen" ResizeMode="NoResize" WindowStyle="None" - AllowsTransparency="True" - Background="Transparent" + AllowsTransparency="False" + Background="#1A1D2E" Topmost="True" FontFamily="Segoe UI"> @@ -41,12 +41,9 @@ - - + - - - diff --git a/agent-cs/config.template.json b/agent-cs/config.template.json index 4a28ced..fbffb12 100644 --- a/agent-cs/config.template.json +++ b/agent-cs/config.template.json @@ -1,4 +1,4 @@ { "server_url": "https://it-nexus.cereda-systems.de", - "agent_key": "HIER-DEN-AGENT-KEY-EINTRAGEN" + "agent_key": "itx-4CPJPTHmCfdrL9D62WacCATEvuvULXcp7ECMpSaNUjsS344F6_L4Ug" } diff --git a/agent-cs/setup.iss b/agent-cs/setup.iss index e21ba53..0da1d61 100644 --- a/agent-cs/setup.iss +++ b/agent-cs/setup.iss @@ -1,5 +1,5 @@ #define MyAppName "IT Nexus Agent" -#define MyAppVersion "2.0.0" +#define MyAppVersion "2.1.2" #define MyAppPublisher "Cereda Systems GmbH" #define MyAppURL "https://it-nexus.cereda-systems.de" #define MyAppExeName "IT-Nexus-Agent.exe" @@ -40,7 +40,7 @@ CloseApplicationsFilter=IT-Nexus-Agent.exe Name: "german"; MessagesFile: "compiler:Languages\German.isl" [Files] -Source: "bin\Publish\IT-Nexus-Agent.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "publish\IT-Nexus-Agent.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "icon.ico"; DestDir: "{app}"; Flags: ignoreversion Source: "config.template.json"; DestDir: "{commonappdata}\IT Nexus Agent"; DestName: "config.json"; Flags: onlyifdoesntexist uninsneveruninstall diff --git a/backend/package-lock.json b/backend/package-lock.json index c2630e3..8846786 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -9,8 +9,10 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@anthropic-ai/sdk": "^0.39.0", "bcrypt": "^5.1.1", "better-sqlite3": "^12.6.2", + "botbuilder": "^4.23.3", "bwip-js": "^4.8.0", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -18,15 +20,254 @@ "express-rate-limit": "^7.1.5", "express-validator": "^7.0.1", "helmet": "^7.1.0", + "imapflow": "^1.0.0", "jsonwebtoken": "^9.0.2", + "mailparser": "^3.7.1", + "mammoth": "^1.8.0", "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "net-snmp": "^3.11.0", + "node-cron": "^3.0.0", + "nodemailer": "^6.9.0", + "pdf-parse": "^1.1.1", "pdfkit": "^0.15.0", - "qrcode": "^1.5.4" + "qrcode": "^1.5.4", + "ws": "^8.21.0" }, "devDependencies": { "nodemon": "^3.0.2" } }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.39.0.tgz", + "integrity": "sha512-eMyDIPRZbt1CCLErRCi3exlAvNkBtRe+kW5vvJyef93PmNr/clstYgHhtvmkxN82nlKgzyGPCyGxrm0JQ1ZIdg==", + "license": "MIT", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.2.tgz", + "integrity": "sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-http-compat": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.4.0.tgz", + "integrity": "sha512-f1P96IB399YiN2ARYHP7EpZi3Bf3wH4SN2lGzrw7JVwm7bbsVYtf2iKSBwTywD2P62NOPZGHFSZi+6jjb75JuA==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@azure/core-client": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.24.0.tgz", + "integrity": "sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.1.tgz", + "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^5.1.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity/node_modules/@azure/msal-common": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.7.0.tgz", + "integrity": "sha512-Jb8Y7pX6KM42SIT7KWP6YbY3+vLbwB5b5m+tpiiOzMU1QeyelQzs9lO8jv1e7/Uj9r7tg7VjPvW4T0KB1jF3UQ==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/identity/node_modules/@azure/msal-node": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.2.3.tgz", + "integrity": "sha512-YYX4TchEVddVBiybKvKhV9QO/q22jgewP+BVxKG7Uh115voPcviGlypbKERDsqQdAiSTJrwi80gcWFjYKdo8+Q==", + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.7.0", + "jsonwebtoken": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.12.0.tgz", + "integrity": "sha512-eNf2aqx1C6I0yT1GEu5ukblFrmaBXGfe1bivpmlfqvK7giPZvoXLa404C8EfeHVsy6EIryfQuPRzuW1fPxWlHg==", + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.7.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-browser/node_modules/@azure/msal-common": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.7.0.tgz", + "integrity": "sha512-Jb8Y7pX6KM42SIT7KWP6YbY3+vLbwB5b5m+tpiiOzMU1QeyelQzs9lO8jv1e7/Uj9r7tg7VjPvW4T0KB1jF3UQ==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "14.16.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.16.1.tgz", + "integrity": "sha512-nyxsA6NA4SVKh5YyRpbSXiMr7oQbwark7JU9LMeg6tJYTSPyAGkdx61wPT4gyxZfxlSxMMEyAsWaubBlNyIa1w==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.16.3.tgz", + "integrity": "sha512-CO+SE4weOsfJf+C5LM8argzvotrXw252/ZU6SM2Tz63fEblhH1uuVaaO4ISYFuN4Q6BhTo7I3qIdi8ydUQCqhw==", + "license": "MIT", + "dependencies": { + "@azure/msal-common": "14.16.1", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@azure/msal-node/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", @@ -47,6 +288,28 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT" + }, + "node_modules/@selderee/plugin-htmlparser2": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.12.0.tgz", + "integrity": "sha512-oELmoyA6ML9jDRMV3kgcMQFKxUfBU0yFVn6yTctVaLT5ygXnxH52I3TZEgV9EhXJC68/uFvE5Daj1/25c0Xa/A==", + "license": "MIT", + "dependencies": { + "domelementtype": "~2.3.0", + "domhandler": "~5.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/KillyMXI" + }, + "peerDependencies": { + "selderee": "~0.12.0" + } + }, "node_modules/@swc/helpers": { "version": "0.3.17", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz", @@ -56,12 +319,140 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.4" + } + }, + "node_modules/@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.6.tgz", + "integrity": "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==", + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@typespec/ts-http-runtime/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@typespec/ts-http-runtime/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typespec/ts-http-runtime/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@typespec/ts-http-runtime/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", + "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@zone-eu/mailsplit": { + "version": "5.4.12", + "resolved": "https://registry.npmjs.org/@zone-eu/mailsplit/-/mailsplit-5.4.12.tgz", + "integrity": "sha512-w7Gy+NvjZ0MiXm8F6zfjImAqcTONKDImgWVBjDKQVFUXWuz3VFM5levNArkL2M877ajql5+bkS2pDV56injlmg==", + "license": "(MIT OR EUPL-1.1+)", + "dependencies": { + "libbase64": "1.3.0", + "libmime": "5.3.8", + "libqp": "2.1.1" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "license": "ISC" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -75,6 +466,12 @@ "node": ">= 0.6" } }, + "node_modules/adaptivecards": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/adaptivecards/-/adaptivecards-1.2.3.tgz", + "integrity": "sha512-amQ5OSW3OpIkrxVKLjxVBPk/T49yuOtnqs1z5ZPfZr0+OpTovzmiHbyoAGDIsu5SNYHwOZFp/3LGOnRaALFa/g==", + "license": "MIT" + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -110,6 +507,18 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -148,6 +557,12 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, "node_modules/aproba": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", @@ -168,6 +583,15 @@ "node": ">=10" } }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", @@ -190,6 +614,27 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asn1-ber": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/asn1-ber/-/asn1-ber-1.2.2.tgz", + "integrity": "sha512-CbNem/7hxrjSiOAOOTX4iZxu+0m3jiLqlsERQwwPM1IDR/22M8IPpA1VVndCLw5KtjRYyRODbvAEIfuTogNDng==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -214,6 +659,18 @@ "node": ">= 0.4" } }, + "node_modules/axios": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.17.0.tgz", + "integrity": "sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, "node_modules/balanced-match": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", @@ -244,6 +701,15 @@ ], "license": "MIT" }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -323,6 +789,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "1.20.4", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", @@ -347,6 +819,201 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/botbuilder": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/botbuilder/-/botbuilder-4.23.3.tgz", + "integrity": "sha512-1gDIQHHYosYBHGXMjvZEJDrcp3NGy3lzHBml5wn9PFqVuIk/cbsCDZs3KJ3g+aH/GGh4CH/ij9iQ2KbQYHAYKA==", + "license": "MIT", + "dependencies": { + "@azure/core-rest-pipeline": "^1.18.1", + "@azure/msal-node": "^2.13.1", + "axios": "^1.8.2", + "botbuilder-core": "4.23.3", + "botbuilder-stdlib": "4.23.3-internal", + "botframework-connector": "4.23.3", + "botframework-schema": "4.23.3", + "botframework-streaming": "4.23.3", + "dayjs": "^1.11.13", + "filenamify": "^6.0.0", + "fs-extra": "^11.2.0", + "htmlparser2": "^9.0.1", + "uuid": "^10.0.0", + "zod": "^3.23.8" + } + }, + "node_modules/botbuilder-core": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/botbuilder-core/-/botbuilder-core-4.23.3.tgz", + "integrity": "sha512-48iW739I24piBH683b/Unvlu1fSzjB69ViOwZ0PbTkN2yW5cTvHJWlW7bXntO8GSqJfssgPaVthKfyaCW457ig==", + "license": "MIT", + "dependencies": { + "botbuilder-dialogs-adaptive-runtime-core": "4.23.3-preview", + "botbuilder-stdlib": "4.23.3-internal", + "botframework-connector": "4.23.3", + "botframework-schema": "4.23.3", + "uuid": "^10.0.0", + "zod": "^3.23.8" + } + }, + "node_modules/botbuilder-dialogs-adaptive-runtime-core": { + "version": "4.23.3-preview", + "resolved": "https://registry.npmjs.org/botbuilder-dialogs-adaptive-runtime-core/-/botbuilder-dialogs-adaptive-runtime-core-4.23.3-preview.tgz", + "integrity": "sha512-EssyvqK9MobX3gbnUe/jjhLuxpCEeyQeQsyUFMJ236U6vzSQdrAxNH7Jc5DyZw2KKelBdK1xPBdwTYQNM5S0Qw==", + "license": "MIT", + "dependencies": { + "dependency-graph": "^1.0.0" + } + }, + "node_modules/botbuilder-stdlib": { + "version": "4.23.3-internal", + "resolved": "https://registry.npmjs.org/botbuilder-stdlib/-/botbuilder-stdlib-4.23.3-internal.tgz", + "integrity": "sha512-fwvIHnKU8sXo1gTww+m/k8wnuM5ktVBAV/3vWJ+ou40zapy1HYjWQuu6sVCRFgMUngpKwhdmoOQsTXsp58SNtA==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-http-compat": "^2.1.2", + "@azure/core-rest-pipeline": "^1.18.1", + "@azure/core-tracing": "^1.2.0" + } + }, + "node_modules/botframework-connector": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/botframework-connector/-/botframework-connector-4.23.3.tgz", + "integrity": "sha512-sChwCFJr3xhcMCYChaOxJoE8/YgdjOPWzGwz5JAxZDwhbQonwYX5O/6Z9EA+wB3TCFNEh642SGeC/rOitaTnGQ==", + "license": "MIT", + "dependencies": { + "@azure/core-rest-pipeline": "^1.18.1", + "@azure/identity": "^4.4.1", + "@azure/msal-node": "^2.13.1", + "@types/jsonwebtoken": "9.0.6", + "axios": "^1.8.2", + "base64url": "^3.0.0", + "botbuilder-stdlib": "4.23.3-internal", + "botframework-schema": "4.23.3", + "buffer": "^6.0.3", + "cross-fetch": "^4.0.0", + "https-proxy-agent": "^7.0.5", + "jsonwebtoken": "^9.0.2", + "node-fetch": "^2.7.0", + "openssl-wrapper": "^0.3.4", + "rsa-pem-from-mod-exp": "^0.8.6", + "zod": "^3.23.8" + } + }, + "node_modules/botframework-connector/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/botframework-connector/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/botframework-connector/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/botframework-connector/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/botframework-connector/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/botframework-schema": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/botframework-schema/-/botframework-schema-4.23.3.tgz", + "integrity": "sha512-/W0uWxZ3fuPLAImZRLnPTbs49Z2xMpJSIzIBxSfvwO0aqv9GsM3bTk3zlNdJ1xr40SshQ7WiH2H1hgjBALwYJw==", + "license": "MIT", + "dependencies": { + "adaptivecards": "1.2.3", + "uuid": "^10.0.0", + "zod": "^3.23.8" + } + }, + "node_modules/botframework-streaming": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/botframework-streaming/-/botframework-streaming-4.23.3.tgz", + "integrity": "sha512-GMtciQGfZXtAW6syUqFpFJQ2vDyVbpxL3T1DqFzq/GmmkAu7KTZ1zvo7PTww6+IT1kMW0lmL/XZJVq3Rhg4PQA==", + "license": "MIT", + "dependencies": { + "@types/ws": "^6.0.3", + "uuid": "^10.0.0", + "ws": "^7.5.10" + } + }, + "node_modules/botframework-streaming/node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/brace-expansion": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", @@ -412,6 +1079,38 @@ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "license": "BSD-3-Clause" }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bwip-js": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-4.8.0.tgz", @@ -567,12 +1266,75 @@ "color-support": "bin.js" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -615,6 +1377,12 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, "node_modules/cors": { "version": "2.8.6", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", @@ -632,12 +1400,27 @@ "url": "https://opencollective.com/express" } }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, "node_modules/crypto-js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", "license": "MIT" }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -712,6 +1495,43 @@ "node": ">=4.0.0" } }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -729,6 +1549,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -746,6 +1578,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -761,6 +1602,15 @@ "node": ">= 0.8" } }, + "node_modules/dependency-graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -792,6 +1642,67 @@ "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "license": "MIT" }, + "node_modules/dingbat-to-unicode": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz", + "integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==", + "license": "BSD-2-Clause" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", @@ -804,6 +1715,15 @@ "url": "https://dotenvx.com" } }, + "node_modules/duck": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/duck/-/duck-0.1.12.tgz", + "integrity": "sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==", + "license": "BSD", + "dependencies": { + "underscore": "^1.13.1" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -848,6 +1768,15 @@ "node": ">= 0.8" } }, + "node_modules/encoding-japanese": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.2.0.tgz", + "integrity": "sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A==", + "license": "MIT", + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -857,6 +1786,18 @@ "once": "^1.4.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -907,6 +1848,21 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -922,6 +1878,15 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -1011,6 +1976,33 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "license": "MIT" }, + "node_modules/filename-reserved-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", + "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/filenamify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", + "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", + "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^3.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1055,6 +2047,26 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/fontkit": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.9.0.tgz", @@ -1087,6 +2099,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "license": "MIT" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "license": "MIT", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1111,6 +2158,20 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, + "node_modules/fs-extra": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -1321,6 +2382,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -1400,6 +2467,15 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, "node_modules/helmet": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.2.0.tgz", @@ -1409,6 +2485,75 @@ "node": ">=16.0.0" } }, + "node_modules/html-to-text": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-10.0.0.tgz", + "integrity": "sha512-2OH59Gtprdczel+7Rxgpz9hGVJREaf8Lt1H4kZwWHpEn70VQKRuMNGsb2eDbwaTzrYzb0hheiOG1P7Dim0B4dQ==", + "license": "MIT", + "dependencies": { + "@selderee/plugin-htmlparser2": "~0.12.0", + "deepmerge-ts": "^7.1.5", + "dom-serializer": "^2.0.0", + "htmlparser2": "^10.1.0", + "selderee": "~0.12.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/KillyMXI" + } + }, + "node_modules/html-to-text/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/html-to-text/node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -1429,6 +2574,51 @@ "url": "https://opencollective.com/express" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -1465,6 +2655,15 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1504,6 +2703,54 @@ "dev": true, "license": "ISC" }, + "node_modules/imapflow": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/imapflow/-/imapflow-1.3.7.tgz", + "integrity": "sha512-9JGZYJyOtT8DluwPYhChOjfxtkWXWYa8JD8ylvFrlGlMvfFhGgdoza4oTVyZ78Sb//cfh0Mo7hXJLke+9cyuGg==", + "license": "MIT", + "dependencies": { + "@zone-eu/mailsplit": "5.4.12", + "encoding-japanese": "2.2.0", + "iconv-lite": "0.7.2", + "libbase64": "1.3.0", + "libmime": "5.3.8", + "libqp": "2.1.1", + "nodemailer": "8.0.10", + "pino": "10.3.1", + "socks": "2.8.9" + } + }, + "node_modules/imapflow/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/imapflow/node_modules/nodemailer": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.10.tgz", + "integrity": "sha512-BLFuSth7QtHOkBzyqTehWWyub0NTRDuK2Q2SQfnGLsrJnzyU+Yeh4WpV1eZGuARFj1xQJHIdnTuJZLP+b9R1GQ==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1541,6 +2788,15 @@ "node": ">= 0.4" } }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -1655,6 +2911,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1687,6 +2958,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -1829,6 +3118,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -1842,6 +3146,18 @@ "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "license": "MIT" }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", @@ -1870,6 +3186,60 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/jszip/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/jwa": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", @@ -1891,6 +3261,64 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/leac": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/leac/-/leac-0.7.0.tgz", + "integrity": "sha512-qMrZeyEekgdRQ9o6a4NAB2EQZrv827GJdn1vnapwSJ90hWRB4TzUSunvacPkxQ2TnNqHNI1/zSt0hlo0crG8Jw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/KillyMXI" + } + }, + "node_modules/libbase64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", + "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==", + "license": "MIT" + }, + "node_modules/libmime": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.8.tgz", + "integrity": "sha512-ZrCY+Q66mPvasAfjsQ/IgahzoBvfE1VdtGRpo1hwRB1oK3wJKxhKA3GOcd2a6j7AH5eMFccxK9fBoCpRZTf8ng==", + "license": "MIT", + "dependencies": { + "encoding-japanese": "2.2.0", + "iconv-lite": "0.7.2", + "libbase64": "1.3.0", + "libqp": "2.1.1" + } + }, + "node_modules/libmime/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/libqp": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.1.tgz", + "integrity": "sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow==", + "license": "MIT" + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/linebreak": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", @@ -1910,6 +3338,25 @@ "node": ">= 0.4" } }, + "node_modules/linkify-it": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -1970,6 +3417,60 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, + "node_modules/lop": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/lop/-/lop-0.4.2.tgz", + "integrity": "sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==", + "license": "BSD-2-Clause", + "dependencies": { + "duck": "^0.1.12", + "option": "~0.2.1", + "underscore": "^1.13.1" + } + }, + "node_modules/mailparser": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.9.9.tgz", + "integrity": "sha512-ulZi7h1eKm8WQmXibIgj8dmMQGDQCUS/g+XHkxxjcLDq4Dwn2ppo+0hz5Fi+ltvu4eN7mh3ykIp5RcpiWWav1w==", + "license": "MIT", + "dependencies": { + "@zone-eu/mailsplit": "5.4.12", + "encoding-japanese": "2.2.0", + "he": "1.2.0", + "html-to-text": "10.0.0", + "iconv-lite": "0.7.2", + "libmime": "5.3.8", + "linkify-it": "5.0.1", + "nodemailer": "8.0.10", + "punycode.js": "2.3.1", + "tlds": "1.261.0" + } + }, + "node_modules/mailparser/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mailparser/node_modules/nodemailer": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.10.tgz", + "integrity": "sha512-BLFuSth7QtHOkBzyqTehWWyub0NTRDuK2Q2SQfnGLsrJnzyU+Yeh4WpV1eZGuARFj1xQJHIdnTuJZLP+b9R1GQ==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -1994,6 +3495,30 @@ "semver": "bin/semver.js" } }, + "node_modules/mammoth": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.12.0.tgz", + "integrity": "sha512-cwnK1RIcRdDMi2HRx2EXGYlxqIEh0Oo3bLhorgnsVJi2UkbX1+jKxuBNR9PC5+JaX7EkmJxFPmo6mjLpqShI2w==", + "license": "BSD-2-Clause", + "dependencies": { + "@xmldom/xmldom": "^0.8.6", + "argparse": "~1.0.3", + "base64-js": "^1.5.1", + "bluebird": "~3.4.0", + "dingbat-to-unicode": "^1.0.1", + "jszip": "^3.7.1", + "lop": "^0.4.2", + "path-is-absolute": "^1.0.0", + "underscore": "^1.13.1", + "xmlbuilder": "^10.0.0" + }, + "bin": { + "mammoth": "bin/mammoth" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2186,6 +3711,37 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/multer": { + "version": "1.4.5-lts.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", + "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", + "deprecated": "Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version.", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/napi-build-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", @@ -2201,6 +3757,16 @@ "node": ">= 0.6" } }, + "node_modules/net-snmp": { + "version": "3.26.3", + "resolved": "https://registry.npmjs.org/net-snmp/-/net-snmp-3.26.3.tgz", + "integrity": "sha512-DTnzoz8Bk5Vz+7WWflo2VgSXMguadFMvsPmSOrknv+YTdA65lLUL1WZhYj6ZA/7pJvKscLJPOeU4LoEd6A1EZg==", + "license": "MIT", + "dependencies": { + "asn1-ber": "^1.2.1", + "smart-buffer": "^4.1.0" + } + }, "node_modules/node-abi": { "version": "3.87.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", @@ -2219,6 +3785,54 @@ "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", "license": "MIT" }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "license": "ISC", + "dependencies": { + "uuid": "8.3.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-cron/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-ensure": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", + "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw==", + "license": "MIT" + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -2239,6 +3853,15 @@ } } }, + "node_modules/nodemailer": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz", + "integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "3.1.14", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", @@ -2397,6 +4020,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -2427,6 +4059,36 @@ "wrappy": "1" } }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openssl-wrapper": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/openssl-wrapper/-/openssl-wrapper-0.3.4.tgz", + "integrity": "sha512-iITsrx6Ho8V3/2OVtmZzzX8wQaKAaFXEJQdzoPUZDtyf5jWFlqo+h+OhGT4TATQ47f9ACKHua8nw7Qoy85aeKQ==", + "license": "MIT" + }, + "node_modules/option": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/option/-/option-0.2.4.tgz", + "integrity": "sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==", + "license": "BSD-2-Clause" + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -2469,6 +4131,19 @@ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", "license": "MIT" }, + "node_modules/parseley": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.13.1.tgz", + "integrity": "sha512-uNBJZzmb60l6p6VWLTmevizNAGnE0xoSf1n0B4q3ntegDNzcS68NRCcBDZTcyXHxt2XhBChsCuqj4M+nChvE/A==", + "license": "MIT", + "dependencies": { + "leac": "^0.7.0", + "peberminta": "^0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/KillyMXI" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2502,6 +4177,22 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/pdf-parse": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-1.1.4.tgz", + "integrity": "sha512-XRIRcLgk6ZnUbsHsYXExMw+krrPE81hJ6FQPLdBNhhBefqIQKXu/WeTgNBGSwPrfU0v+UCEwn7AoAUOsVKHFvQ==", + "license": "MIT", + "dependencies": { + "node-ensure": "^0.0.0" + }, + "engines": { + "node": ">=6.8.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/mehmet-kozan" + } + }, "node_modules/pdfkit": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.15.2.tgz", @@ -2515,6 +4206,15 @@ "png-js": "^1.0.0" } }, + "node_modules/peberminta": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.10.0.tgz", + "integrity": "sha512-80B2AsU+I4Qdb0ZAPSfe9UwvGzwkM37IKIFEvdS3D/3Ndgv2bsuJ0bfG1+iEYO+l7Gfd4EUJmuRyq7efLgRMzQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/KillyMXI" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2528,6 +4228,43 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz", + "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT" + }, "node_modules/png-js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", @@ -2569,6 +4306,28 @@ "node": ">=10" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2582,6 +4341,15 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -2599,6 +4367,15 @@ "once": "^1.3.1" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qrcode": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", @@ -2631,6 +4408,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2697,6 +4480,15 @@ "node": ">=8.10.0" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -2754,6 +4546,24 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rsa-pem-from-mod-exp": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/rsa-pem-from-mod-exp/-/rsa-pem-from-mod-exp-0.8.6.tgz", + "integrity": "sha512-c5ouQkOvGHF1qomUUDJGFcXsomeSO2gbEs6hVhMAtlkE1CuaZase/WzoaKFG/EZQuNmq6pw/EMCeEnDvOgCJYQ==", + "license": "MIT" + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2791,12 +4601,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/selderee": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.12.0.tgz", + "integrity": "sha512-b1YMh3+DHZp59DLna3qVwQ5iOla/nrI6mLBNW02XxU77M3046Df6VLkoaJyFz20VsGIG5kkp+FK0kg4K4HnUFw==", + "license": "MIT", + "dependencies": { + "parseley": "~0.13.1" + }, + "funding": { + "url": "https://github.com/sponsors/KillyMXI" + } + }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", @@ -2892,6 +4723,12 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3034,6 +4871,54 @@ "node": ">=10" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -3056,6 +4941,14 @@ "node": ">= 0.4" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3165,12 +5058,39 @@ "node": ">=6" } }, + "node_modules/thread-stream": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.2.0.tgz", + "integrity": "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==", + "license": "MIT", + "dependencies": { + "real-require": "^1.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/thread-stream/node_modules/real-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-1.0.0.tgz", + "integrity": "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==", + "license": "MIT" + }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", "license": "MIT" }, + "node_modules/tlds": { + "version": "1.261.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz", + "integrity": "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==", + "license": "MIT", + "bin": { + "tlds": "bin.js" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3240,6 +5160,18 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -3247,6 +5179,18 @@ "dev": true, "license": "MIT" }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, "node_modules/unicode-properties": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", @@ -3267,6 +5211,15 @@ "tiny-inflate": "^1.0.0" } }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -3291,6 +5244,20 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/validator": { "version": "13.15.26", "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", @@ -3309,6 +5276,15 @@ "node": ">= 0.8" } }, + "node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -3418,6 +5394,60 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xmlbuilder": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", + "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -3464,6 +5494,15 @@ "engines": { "node": ">=6" } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/backend/package.json b/backend/package.json index fc3bd85..164e06c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -16,29 +16,30 @@ "author": "", "license": "ISC", "dependencies": { + "@anthropic-ai/sdk": "^0.39.0", "bcrypt": "^5.1.1", "better-sqlite3": "^12.6.2", + "botbuilder": "^4.23.3", "bwip-js": "^4.8.0", - "imapflow": "^1.0.0", - "node-cron": "^3.0.0", - "nodemailer": "^6.9.0", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "express-rate-limit": "^7.1.5", "express-validator": "^7.0.1", "helmet": "^7.1.0", + "imapflow": "^1.0.0", "jsonwebtoken": "^9.0.2", + "mailparser": "^3.7.1", + "mammoth": "^1.8.0", "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "net-snmp": "^3.11.0", + "node-cron": "^3.0.0", + "nodemailer": "^6.9.0", + "pdf-parse": "^1.1.1", "pdfkit": "^0.15.0", "qrcode": "^1.5.4", - "@anthropic-ai/sdk": "^0.39.0", - "botbuilder": "^4.23.3", - "pdf-parse": "^1.1.1", - "mammoth": "^1.8.0", - "mailparser": "^3.7.1", - "net-snmp": "^3.11.0", - "multer": "^1.4.5-lts.1" + "ws": "^8.21.0" }, "devDependencies": { "nodemon": "^3.0.2" diff --git a/backend/src/controllers/announcement.controller.js b/backend/src/controllers/announcement.controller.js index f4f18c2..ab74fbd 100644 --- a/backend/src/controllers/announcement.controller.js +++ b/backend/src/controllers/announcement.controller.js @@ -1,4 +1,5 @@ const { getDatabase } = require('../config/database'); +const { pushAnnouncementToAgent, broadcastAnnouncement, getConnectedAgents } = require('../ws/shellServer'); // Hilfsfunktion: welche Ankündigungen sind für einen Agenten relevant (nach Gruppe)? function getForAgent(agentId) { @@ -94,7 +95,18 @@ const create = (req, res) => { INSERT INTO announcements (title, message, type, target_groups, target_agent_ids, created_by_user_id, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?) `).run(title.trim(), message.trim(), type, JSON.stringify(target_groups), JSON.stringify(target_agent_ids), req.user.id, expires_at || null); - res.status(201).json(db.prepare('SELECT * FROM announcements WHERE id=?').get(result.lastInsertRowid)); + const ann = db.prepare('SELECT * FROM announcements WHERE id=?').get(result.lastInsertRowid); + + // WebSocket-Push: sofort an verbundene Agents schicken + const wsPayload = { id: ann.id, title: ann.title, message: ann.message, type: ann.type }; + const agentIds = JSON.parse(ann.target_agent_ids || '[]'); + if (agentIds.length > 0) { + agentIds.forEach(id => pushAnnouncementToAgent(id, [wsPayload])); + } else { + broadcastAnnouncement(wsPayload); + } + + res.status(201).json(ann); }; const update = (req, res) => { diff --git a/backend/src/controllers/fidoKey.controller.js b/backend/src/controllers/fidoKey.controller.js index 600bb7d..3c2105a 100644 --- a/backend/src/controllers/fidoKey.controller.js +++ b/backend/src/controllers/fidoKey.controller.js @@ -7,7 +7,10 @@ class FidoKeyController { * GET /api/fido-keys */ static getAllKeys = asyncHandler(async (req, res) => { - const keys = FidoKeyService.getAllKeys(); + const { user_id } = req.query; + const keys = user_id + ? FidoKeyService.getKeysByUser(parseInt(user_id)) + : FidoKeyService.getAllKeys(); res.json({ status: 'success', diff --git a/backend/src/controllers/patch.controller.js b/backend/src/controllers/patch.controller.js index f103d73..6f1e858 100644 --- a/backend/src/controllers/patch.controller.js +++ b/backend/src/controllers/patch.controller.js @@ -273,11 +273,14 @@ const reportCommandResult = (req, res) => { if (!agentKey || agentKey !== process.env.AGENT_API_KEY) { return res.status(401).json({ error: 'Unauthorized' }); } - const { command_id, status, result } = req.body; - if (!command_id) return res.status(400).json({ error: 'command_id erforderlich' }); + const command_id = req.body.command_id ?? req.body.CommandId; + const { status, result } = req.body; + if (command_id === undefined || command_id === null) return res.status(400).json({ error: 'command_id erforderlich' }); const db = getDatabase(); - db.prepare("UPDATE patch_commands SET status=?, result=?, completed_at=CURRENT_TIMESTAMP WHERE id=?") - .run(status || 'done', result || null, command_id); + if (command_id !== 0) { + db.prepare("UPDATE patch_commands SET status=?, result=?, completed_at=CURRENT_TIMESTAMP WHERE id=?") + .run(status || 'done', result || null, command_id); + } res.json({ success: true }); }; @@ -293,6 +296,37 @@ const getPendingCommands = (agentId) => { return { pending: cmds, running }; }; +// Remote Shell: POST /api/patch/shell/:agentId +const triggerShell = (req, res) => { + const { agentId } = req.params; + const { command } = req.body; + if (!command) return res.status(400).json({ error: 'command erforderlich' }); + const db = getDatabase(); + const result = db.prepare( + "INSERT INTO patch_commands (agent_id, command, params, triggered_by_user_id) VALUES (?,?,?,?)" + ).run(parseInt(agentId), 'shell_exec', command, req.user.id); + res.status(201).json({ id: result.lastInsertRowid }); +}; + +// Remote Shell: GET /api/patch/shell/:agentId/result/:cmdId +const getShellResult = (req, res) => { + const { cmdId } = req.params; + const db = getDatabase(); + const cmd = db.prepare("SELECT id, status, result, created_at, completed_at FROM patch_commands WHERE id=?").get(parseInt(cmdId)); + if (!cmd) return res.status(404).json({ error: 'Nicht gefunden' }); + res.json(cmd); +}; + +// Remote Shell: GET /api/patch/shell/:agentId/history +const getShellHistory = (req, res) => { + const { agentId } = req.params; + const db = getDatabase(); + const cmds = db.prepare( + "SELECT id, params, status, result, created_at, completed_at FROM patch_commands WHERE agent_id=? AND command='shell_exec' ORDER BY created_at DESC LIMIT 50" + ).all(parseInt(agentId)); + res.json(cmds); +}; + module.exports = { getGroups, createGroup, updateGroup, deleteGroup, releaseVersionToGroup, releaseVersionToAll, upsertPolicy, deletePolicy, @@ -300,4 +334,5 @@ module.exports = { getOverview, triggerCommand, triggerGroupCommand, getCommands, reportCommandResult, getPendingCommands, + triggerShell, getShellResult, getShellHistory, }; diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index 83cbfd0..582d09b 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -540,6 +540,8 @@ async function initializeDatabase() { `INSERT OR IGNORE INTO license_prices (sku_part_number, display_name, price_per_month) VALUES ('MCOPSTN1', 'Teams Domestic Calling', 8.00)`, `INSERT OR IGNORE INTO license_prices (sku_part_number, display_name, price_per_month) VALUES ('Remote_', 'Remote Desktop Services', 0.00)`, `INSERT OR IGNORE INTO license_prices (sku_part_number, display_name, price_per_month) VALUES ('SPB', 'Microsoft 365 Business Premium', 22.00)`, + // Remote Shell — params Feld für patch_commands + `ALTER TABLE patch_commands ADD COLUMN params TEXT`, ]; for (const migration of migrations) { try { diff --git a/backend/src/routes/patch.routes.js b/backend/src/routes/patch.routes.js index d029ad8..599e25b 100644 --- a/backend/src/routes/patch.routes.js +++ b/backend/src/routes/patch.routes.js @@ -26,4 +26,9 @@ router.post('/commands/trigger', requireAdmin, ctrl.triggerCommand); router.post('/commands/trigger-group', requireAdmin, ctrl.triggerGroupCommand); // (result route is before authenticateToken above) +// Remote Shell +router.post('/shell/:agentId', requireAdmin, ctrl.triggerShell); +router.get('/shell/:agentId/result/:cmdId', requireAdmin, ctrl.getShellResult); +router.get('/shell/:agentId/history', requireAdmin, ctrl.getShellHistory); + module.exports = router; diff --git a/backend/src/server.js b/backend/src/server.js index b6a31ba..933d357 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -1,4 +1,5 @@ const express = require('express'); +const http = require('http'); const cors = require('cors'); const helmet = require('helmet'); const morgan = require('morgan'); @@ -430,12 +431,17 @@ async function startServer() { } // Start server - app.listen(PORT, () => { + const { setupWebSocketServer } = require('./ws/shellServer'); + const httpServer = http.createServer(app); + setupWebSocketServer(httpServer); + + httpServer.listen(PORT, () => { console.log('═══════════════════════════════════════════'); console.log(`✅ Server running on http://localhost:${PORT}`); console.log(`📝 Environment: ${process.env.NODE_ENV || 'development'}`); console.log(`🌐 API: http://localhost:${PORT}/api`); console.log(`💚 Health: http://localhost:${PORT}/health`); + console.log(`🔌 WebSocket: ws://localhost:${PORT}/ws`); console.log('═══════════════════════════════════════════'); console.log(''); console.log('Press CTRL+C to stop the server'); diff --git a/backend/src/services/fidoKey.service.js b/backend/src/services/fidoKey.service.js index 7431377..768d90d 100644 --- a/backend/src/services/fidoKey.service.js +++ b/backend/src/services/fidoKey.service.js @@ -3,13 +3,14 @@ const AuditLog = require('../models/AuditLog'); const { AppError } = require('../middleware/errorHandler'); class FidoKeyService { - /** - * Get all FIDO keys - */ static getAllKeys() { return FidoKey.getAll(); } + static getKeysByUser(userId) { + return FidoKey.getByAssignedUser(userId); + } + /** * Get FIDO key by ID */ diff --git a/backend/src/ws/shellServer.js b/backend/src/ws/shellServer.js new file mode 100644 index 0000000..f2c5d26 --- /dev/null +++ b/backend/src/ws/shellServer.js @@ -0,0 +1,157 @@ +const WebSocket = require('ws'); +const jwt = require('jsonwebtoken'); +const { getDatabase } = require('../config/database'); + +// agentId -> WebSocket +const agentSockets = new Map(); +// agentId -> WebSocket +const browserSockets = new Map(); + +function setupWebSocketServer(httpServer) { + const wss = new WebSocket.Server({ server: httpServer, path: '/ws' }); + + wss.on('connection', (ws, req) => { + let url; + try { + url = new URL(req.url, 'http://localhost'); + } catch { + ws.close(1008, 'invalid url'); + return; + } + const type = url.searchParams.get('type'); + + if (type === 'agent') { + handleAgent(ws, url); + } else if (type === 'shell') { + handleBrowser(ws, url); + } else { + ws.close(1008, 'unknown type'); + } + }); + + console.log('[WS] WebSocket server ready at /ws'); + return wss; +} + +function handleAgent(ws, url) { + const key = url.searchParams.get('key'); + if (key !== process.env.AGENT_API_KEY) { + ws.close(1008, 'unauthorized'); + return; + } + const hostname = url.searchParams.get('hostname'); + if (!hostname) { ws.close(1008, 'hostname required'); return; } + + const db = getDatabase(); + const agent = db.prepare('SELECT id FROM monitoring_agents WHERE hostname = ?').get(hostname); + if (!agent) { ws.close(1008, 'agent not found'); return; } + + const agentId = agent.id; + // Alte Verbindung schließen falls vorhanden + const oldWs = agentSockets.get(agentId); + if (oldWs && oldWs.readyState === WebSocket.OPEN) oldWs.close(); + + agentSockets.set(agentId, ws); + console.log(`[WS] Agent verbunden: ${hostname} (id=${agentId})`); + + // Falls Browser bereits wartet → Shell starten + melden + const bws = browserSockets.get(agentId); + if (bws?.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'start_shell' })); + bws.send('\r\n\x1b[32m[Agent verbunden — Shell gestartet]\x1b[0m\r\n'); + } + + ws.on('message', (data) => { + const bws = browserSockets.get(agentId); + if (!bws || bws.readyState !== WebSocket.OPEN) return; + // RTC-Signaling (offer/answer/ice) → transparent weiterleiten + try { + const msg = JSON.parse(data.toString()); + if (msg.type?.startsWith('rtc_')) { bws.send(data.toString()); return; } + } catch { /* kein JSON → Shell-Output */ } + bws.send(data.toString()); + }); + + ws.on('close', () => { + agentSockets.delete(agentId); + const bws = browserSockets.get(agentId); + if (bws?.readyState === WebSocket.OPEN) { + bws.send('\r\n\x1b[31m[Agent getrennt]\x1b[0m\r\n'); + } + console.log(`[WS] Agent getrennt: ${hostname}`); + }); +} + +function handleBrowser(ws, url) { + const token = url.searchParams.get('token'); + try { + jwt.verify(token, process.env.JWT_SECRET); + } catch { + ws.close(1008, 'unauthorized'); + return; + } + + const agentId = parseInt(url.searchParams.get('agentId')); + if (!agentId) { ws.close(1008, 'agentId required'); return; } + + browserSockets.set(agentId, ws); + + const aws = agentSockets.get(agentId); + if (aws?.readyState === WebSocket.OPEN) { + aws.send(JSON.stringify({ type: 'start_shell' })); + ws.send('\x1b[32m[Verbunden]\x1b[0m\r\n'); + } else { + ws.send('\x1b[33m[Warte auf Agent-Verbindung...]\x1b[0m\r\n'); + } + + ws.on('message', (data) => { + const aws = agentSockets.get(agentId); + if (!aws || aws.readyState !== WebSocket.OPEN) return; + // RTC-Signaling (offer/answer/ice) → transparent weiterleiten + try { + const msg = JSON.parse(data.toString()); + if (msg.type?.startsWith('rtc_')) { aws.send(data.toString()); return; } + } catch { /* kein JSON → Tastatureingabe */ } + aws.send(JSON.stringify({ type: 'input', data: data.toString() })); + }); + + ws.on('close', () => { + browserSockets.delete(agentId); + const aws = agentSockets.get(agentId); + if (aws?.readyState === WebSocket.OPEN) { + aws.send(JSON.stringify({ type: 'stop_shell' })); + } + }); +} + +// Ankündigung an Agent pushen (für sofortige Zustellung) +function pushAnnouncementToAgent(agentId, announcements) { + const aws = agentSockets.get(agentId); + if (aws?.readyState === WebSocket.OPEN) { + aws.send(JSON.stringify({ type: 'announcements', announcements })); + return true; + } + return false; +} + +// Ankündigung an alle verbundenen Agents pushen +function broadcastAnnouncement(announcement) { + let pushed = 0; + for (const [agentId, aws] of agentSockets.entries()) { + if (aws.readyState === WebSocket.OPEN) { + aws.send(JSON.stringify({ type: 'announcements', announcements: [announcement] })); + pushed++; + } + } + return pushed; +} + +function getConnectedAgents() { + const ids = []; + for (const [agentId, ws] of agentSockets.entries()) { + if (ws.readyState === WebSocket.OPEN) ids.push(agentId); + } + return ids; +} + +module.exports = { setupWebSocketServer, pushAnnouncementToAgent, broadcastAnnouncement, getConnectedAgents }; diff --git a/frontend/nginx.conf b/frontend/nginx.conf index ac6b14e..13194b2 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -93,6 +93,18 @@ server { proxy_send_timeout 300s; } + # WebSocket Proxy (Remote Shell + Agent-Verbindungen) + location /ws { + proxy_pass http://backend:5000/ws; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + } + # API Proxy zum Backend location /api/ { proxy_pass http://backend:5000/api/; diff --git a/frontend/src/pages/AgentDetailPage.jsx b/frontend/src/pages/AgentDetailPage.jsx index 3062f43..3f9d5df 100644 --- a/frontend/src/pages/AgentDetailPage.jsx +++ b/frontend/src/pages/AgentDetailPage.jsx @@ -4,6 +4,7 @@ import monitoringService from '../services/monitoringService'; import assetService from '../services/assetService'; import api from '../services/api'; import { toast } from 'react-toastify'; +import { useAuth } from '../context/AuthContext'; // ─── CSS Variables injected inline (design from Device Detail.html) ───────────── @@ -152,11 +153,313 @@ const Btn = ({ onClick, children, variant = 'default', disabled }) => { ); }; +// ─── Remote Shell (WebSocket Live Terminal) ─────────────────────────────────── + +const API = process.env.REACT_APP_API_URL || '/api'; +const authFetch = (url, opts = {}) => { + const token = localStorage.getItem('token'); + return fetch(url, { ...opts, headers: { ...(opts.headers || {}), Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } }); +}; + +// Einfacher ANSI-Code-Stripper für die Anzeige ohne xterm.js +function stripAnsi(str) { + // eslint-disable-next-line no-control-regex + return str.replace(/\x1b\[[0-9;]*[mGKHF]/g, '').replace(/\x1b\[[0-9;]*[A-Z]/g, ''); +} + +function RemoteShell({ agentId, agentHostname }) { + const [input, setInput] = useState(''); + const [output, setOutput] = useState(''); + const [status, setStatus] = useState('disconnected'); // disconnected | connecting | connected + const outputRef = useRef(null); + const wsRef = useRef(null); + const inputRef = useRef(null); + + const getWsUrl = () => { + const token = localStorage.getItem('token'); + const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'; + const host = window.location.host; + return `${proto}://${host}/ws?type=shell&agentId=${agentId}&token=${token}`; + }; + + const connect = () => { + if (wsRef.current && wsRef.current.readyState <= 1) return; + setStatus('connecting'); + setOutput(''); + + const ws = new WebSocket(getWsUrl()); + wsRef.current = ws; + + ws.onopen = () => setStatus('connected'); + + ws.onmessage = (e) => { + setOutput(prev => prev + stripAnsi(e.data)); + setTimeout(() => { + if (outputRef.current) outputRef.current.scrollTop = outputRef.current.scrollHeight; + }, 10); + }; + + ws.onclose = () => { + setStatus('disconnected'); + setOutput(prev => prev + '\r\n[Verbindung getrennt]\r\n'); + }; + + ws.onerror = () => { + setStatus('disconnected'); + }; + }; + + const disconnect = () => { + wsRef.current?.close(); + wsRef.current = null; + }; + + // Beim Unmount trennen + useEffect(() => { return () => disconnect(); }, []); + + const send = () => { + if (!input.trim() || !wsRef.current || wsRef.current.readyState !== 1) return; + wsRef.current.send(input + '\n'); + setInput(''); + }; + + const onKey = (e) => { + if (e.key === 'Enter') { e.preventDefault(); send(); } + if (e.key === 'c' && e.ctrlKey) { + wsRef.current?.send('\x03'); // Ctrl+C + e.preventDefault(); + } + }; + + const statusColor = status === 'connected' ? '#34d399' : status === 'connecting' ? '#f59e0b' : '#6b7280'; + const statusLabel = status === 'connected' ? 'Verbunden' : status === 'connecting' ? 'Verbinde…' : 'Getrennt'; + + return ( +
+
+ 🖥️ + Remote Shell + {agentHostname} · PowerShell (SYSTEM) + + + {statusLabel} + +
+ {status === 'disconnected' ? ( + + ) : ( + + )} + +
+
+
inputRef.current?.focus()} + style={{ fontFamily: 'ui-monospace, Cascadia Code, Consolas, monospace', fontSize: 12.5, lineHeight: 1.6, padding: '16px 20px', minHeight: 240, maxHeight: 480, overflowY: 'auto', background: '#0d1117', color: '#e6edf3', cursor: 'text', whiteSpace: 'pre-wrap', wordBreak: 'break-all' }} + > + {output || {status === 'disconnected' ? 'Auf "Verbinden" klicken um eine Shell-Sitzung zu starten.' : 'Warte auf Agent…'}} +
+
+ PS> + setInput(e.target.value)} + onKeyDown={onKey} + disabled={status !== 'connected'} + placeholder={status === 'connected' ? 'Befehl eingeben… (Enter = Senden, Ctrl+C = Abbrechen)' : 'Nicht verbunden'} + style={{ flex: 1, background: 'transparent', border: 'none', outline: 'none', color: '#e6edf3', fontFamily: 'ui-monospace, monospace', fontSize: 13, opacity: status !== 'connected' ? 0.4 : 1 }} + /> + +
+
+ ); +} + +// ─── Remote Desktop (WebRTC) ───────────────────────────────────────────────────── + +function RemoteDesktop({ agentId, agentHostname }) { + const [status, setStatus] = useState('idle'); // idle | signaling | connected | error + const [error, setError] = useState(''); + const videoRef = useRef(null); + const pcRef = useRef(null); + const wsRef = useRef(null); + const dcRef = useRef(null); + const canvasRef = useRef(null); + + const getWsUrl = () => { + const token = localStorage.getItem('token'); + const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'; + return `${proto}://${window.location.host}/ws?type=shell&agentId=${agentId}&token=${token}`; + }; + + const connect = async () => { + setStatus('signaling'); + setError(''); + + const ws = new WebSocket(getWsUrl()); + wsRef.current = ws; + + const pc = new RTCPeerConnection({ + iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] + }); + pcRef.current = pc; + + // Video-Stream vom Agent empfangen + pc.ontrack = (e) => { + if (videoRef.current && e.streams[0]) { + videoRef.current.srcObject = e.streams[0]; + setStatus('connected'); + } + }; + + // ICE Candidates an Agent schicken + pc.onicecandidate = (e) => { + if (e.candidate && ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'rtc_ice', candidate: e.candidate })); + } + }; + + pc.onconnectionstatechange = () => { + if (pc.connectionState === 'disconnected' || pc.connectionState === 'failed') { + setStatus('idle'); + } + }; + + // DataChannel für Maus/Tastatur-Input + const dc = pc.createDataChannel('input'); + dcRef.current = dc; + + // Offer erstellen und an Agent senden + ws.onopen = async () => { + const offer = await pc.createOffer({ offerToReceiveVideo: true, offerToReceiveAudio: false }); + await pc.setLocalDescription(offer); + ws.send(JSON.stringify({ type: 'rtc_offer', sdp: offer.sdp })); + }; + + ws.onmessage = async (e) => { + // Shell-Output ignorieren, nur RTC-Messages verarbeiten + try { + const msg = JSON.parse(e.data); + if (msg.type === 'rtc_answer') { + await pc.setRemoteDescription({ type: 'answer', sdp: msg.sdp }); + } else if (msg.type === 'rtc_ice' && msg.candidate) { + await pc.addIceCandidate(msg.candidate); + } + } catch { /* kein JSON / Shell-Output → ignorieren */ } + }; + + ws.onerror = () => { setStatus('error'); setError('WebSocket-Fehler'); }; + ws.onclose = () => { if (status !== 'connected') setStatus('idle'); }; + }; + + const disconnect = () => { + pcRef.current?.close(); + wsRef.current?.close(); + pcRef.current = null; + wsRef.current = null; + if (videoRef.current) videoRef.current.srcObject = null; + setStatus('idle'); + }; + + useEffect(() => () => disconnect(), []); + + // Maus-Events auf Canvas → DataChannel + const sendMouseEvent = (type, e) => { + if (!dcRef.current || dcRef.current.readyState !== 'open') return; + const rect = canvasRef.current?.getBoundingClientRect(); + if (!rect) return; + const scaleX = 1920 / rect.width; + const scaleY = 1080 / rect.height; + dcRef.current.send(JSON.stringify({ + type, x: Math.round((e.clientX - rect.left) * scaleX), + y: Math.round((e.clientY - rect.top) * scaleY), button: e.button + })); + }; + + const statusColor = status === 'connected' ? '#34d399' : status === 'signaling' ? '#f59e0b' : status === 'error' ? '#ef4444' : '#6b7280'; + const statusLabel = { idle: 'Getrennt', signaling: 'Verbinde…', connected: 'Verbunden', error: 'Fehler' }[status]; + + return ( +
+
+ 🖥️ + Remote Desktop + {agentHostname} · WebRTC + + + {statusLabel} + +
+ {status === 'idle' || status === 'error' ? ( + + ) : ( + + )} +
+
+ + {status === 'idle' || status === 'error' ? ( +
+ 🖥️ +
+
Remote Desktop (Beta)
+
Direktübertragung via WebRTC — Agent muss v2.2.0+ haben
+ {error &&
{error}
} +
+
+ ) : ( +
+
+ )} +
+ ); +} + // ─── Main Page ─────────────────────────────────────────────────────────────────── export default function AgentDetailPage() { const { id, hostname } = useParams(); const navigate = useNavigate(); + const { isSuperAdmin, isAdmin } = useAuth(); const [agent, setAgent] = useState(null); const [asset, setAsset] = useState(null); const [assignedUser, setAssignedUser] = useState(null); @@ -166,6 +469,7 @@ export default function AgentDetailPage() { const [annText, setAnnText] = useState(''); const [showAnnModal, setShowAnnModal] = useState(false); const [patchHistory, setPatchHistory] = useState([]); + const [shellTab, setShellTab] = useState('shell'); // 'shell' | 'rdp' const [countdown, setCountdown] = useState(60); const agentRef = useRef(null); const refreshTimer = useRef(null); @@ -617,6 +921,35 @@ export default function AgentDetailPage() { )} + {/* ── REMOTE TOOLS ─────────────────────────────────────────────────── */} + {(isSuperAdmin || isAdmin) && ( +
+
+ {[ + { id: 'shell', label: '⌨️ Remote Shell' }, + { id: 'rdp', label: '🖥️ Remote Desktop', badge: 'Beta' }, + ].map(t => ( + + ))} +
+ {shellTab === 'shell' && } + {shellTab === 'rdp' && } +
+ )} + {!isSuperAdmin && !isAdmin && ( + + )} + {/* ── ANKÜNDIGUNG MODAL ────────────────────────────────────────────── */} {showAnnModal && (
{ ); }); - /* ── Agent lookup: by serial, IP or hostname ── */ + /* ── Agent lookup: by serial (primary) or hostname (fallback) — NOT by IP (not unique with DHCP) ── */ const getAgent = (asset) => { if (!asset || !agents.length) return null; - return agents.find(ag => - (asset.serial_number && ag.hardware_serial && ag.hardware_serial.toLowerCase() === asset.serial_number.toLowerCase()) || - (asset.ip_address && ag.ip_address && ag.ip_address === asset.ip_address) || - (asset.name && ag.hostname && ag.hostname.toLowerCase() === asset.name.toLowerCase()) - ) || null; + // Seriennummer ist eindeutig — erste Priorität + if (asset.serial_number) { + const bySerial = agents.find(ag => ag.hardware_serial && ag.hardware_serial.toLowerCase() === asset.serial_number.toLowerCase()); + if (bySerial) return bySerial; + } + // Hostname als Fallback + if (asset.name) { + const byHost = agents.find(ag => ag.hostname && ag.hostname.toLowerCase() === asset.name.toLowerCase()); + if (byHost) return byHost; + } + return null; }; /* ── PDF öffnen mit Auth-Token ── */ diff --git a/frontend/src/pages/FidoKeysPage.jsx b/frontend/src/pages/FidoKeysPage.jsx index 235040a..bf6cb0d 100644 --- a/frontend/src/pages/FidoKeysPage.jsx +++ b/frontend/src/pages/FidoKeysPage.jsx @@ -4,10 +4,17 @@ import fidoKeyService from '../services/fidoKeyService'; import LoadingSpinner from '../components/common/LoadingSpinner'; import { toast } from 'react-toastify'; +const API = process.env.REACT_APP_API_URL || '/api'; +const authFetch = (url, opts = {}) => { + const token = localStorage.getItem('token'); + return fetch(url, { ...opts, headers: { ...(opts.headers || {}), Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } }); +}; + const FidoKeysPage = () => { const { canModifyFidoKeys, isAdmin } = useAuth(); const [keys, setKeys] = useState([]); const [filteredKeys, setFilteredKeys] = useState([]); + const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); @@ -18,10 +25,15 @@ const FidoKeysPage = () => { serial_number: '', status: 'aktiv', description: '', + assigned_to_user_id: '', }); useEffect(() => { loadKeys(); + authFetch(`${API}/users`) + .then(r => r.json()) + .then(d => setUsers(d.data || d || [])) + .catch(() => {}); }, []); useEffect(() => { @@ -41,32 +53,23 @@ const FidoKeysPage = () => { const filterKeys = () => { let filtered = [...keys]; - - // Search filter if (searchTerm) { filtered = filtered.filter( (key) => key.name.toLowerCase().includes(searchTerm.toLowerCase()) || - key.serial_number.toLowerCase().includes(searchTerm.toLowerCase()) + key.serial_number.toLowerCase().includes(searchTerm.toLowerCase()) || + (key.assigned_to_username || '').toLowerCase().includes(searchTerm.toLowerCase()) ); } - - // Status filter if (statusFilter !== 'all') { filtered = filtered.filter((key) => key.status === statusFilter); } - setFilteredKeys(filtered); }; const handleCreate = () => { setEditingKey(null); - setFormData({ - name: '', - serial_number: '', - status: 'aktiv', - description: '', - }); + setFormData({ name: '', serial_number: '', status: 'aktiv', description: '', assigned_to_user_id: '' }); setShowModal(true); }; @@ -77,22 +80,25 @@ const FidoKeysPage = () => { serial_number: key.serial_number, status: key.status, description: key.description || '', + assigned_to_user_id: key.assigned_to_user_id || '', }); setShowModal(true); }; const handleSubmit = async (e) => { e.preventDefault(); - try { + const payload = { + ...formData, + assigned_to_user_id: formData.assigned_to_user_id ? parseInt(formData.assigned_to_user_id) : null, + }; if (editingKey) { - await fidoKeyService.update(editingKey.id, formData); + await fidoKeyService.update(editingKey.id, payload); toast.success('FIDO-Key erfolgreich aktualisiert'); } else { - await fidoKeyService.create(formData); + await fidoKeyService.create(payload); toast.success('FIDO-Key erfolgreich erstellt'); } - setShowModal(false); loadKeys(); } catch (error) { @@ -101,10 +107,7 @@ const FidoKeysPage = () => { }; const handleDelete = async (id) => { - if (!window.confirm('Möchten Sie diesen FIDO-Key wirklich löschen?')) { - return; - } - + if (!window.confirm('Möchten Sie diesen FIDO-Key wirklich löschen?')) return; try { await fidoKeyService.delete(id); toast.success('FIDO-Key erfolgreich gelöscht'); @@ -116,7 +119,6 @@ const FidoKeysPage = () => { const handleStatusToggle = async (key) => { const newStatus = key.status === 'aktiv' ? 'inaktiv' : 'aktiv'; - try { await fidoKeyService.updateStatus(key.id, newStatus); toast.success('Status erfolgreich geändert'); @@ -126,6 +128,16 @@ const FidoKeysPage = () => { } }; + const handleUnassign = async (key) => { + try { + await fidoKeyService.update(key.id, { ...key, assigned_to_user_id: null }); + toast.success('Zuweisung aufgehoben'); + loadKeys(); + } catch (error) { + toast.error('Fehler beim Aufheben der Zuweisung'); + } + }; + if (loading) { return (
@@ -146,44 +158,21 @@ const FidoKeysPage = () => { )}
- {/* Search and Filter */}
setSearchTerm(e.target.value)} />
- - - + + +
- {/* Table */}
@@ -191,6 +180,7 @@ const FidoKeysPage = () => { + @@ -199,19 +189,34 @@ const FidoKeysPage = () => { {filteredKeys.length === 0 ? ( - + ) : ( filteredKeys.map((key) => ( - + + @@ -219,29 +224,14 @@ const FidoKeysPage = () => {
{canModifyFidoKeys() && ( <> - - + )} {isAdmin() && ( - + )}
@@ -252,93 +242,57 @@ const FidoKeysPage = () => {
Name Seriennummer StatusZugewiesen an Beschreibung Erstellt von Aktionen
- Keine FIDO-Keys gefunden - Keine FIDO-Keys gefunden
{key.name}{key.serial_number}{key.serial_number} - - {key.status} - + {key.status} + + {key.assigned_to_username ? ( +
+
+ {(key.assigned_to_username||'?').charAt(0).toUpperCase()} +
+ {key.assigned_to_username} + {canModifyFidoKeys() && ( + + )} +
+ ) : ( + — nicht zugewiesen + )}
{key.description || '-'} {key.created_by_username}
- {/* Modal */} {showModal && (
setShowModal(false)}>
e.stopPropagation()}>
-

- {editingKey ? 'FIDO-Key bearbeiten' : 'Neuer FIDO-Key'} -

- +

{editingKey ? 'FIDO-Key bearbeiten' : 'Neuer FIDO-Key'}

+
- - setFormData({ ...formData, name: e.target.value }) - } - required - /> + setFormData({ ...formData, name: e.target.value })} required />
- - setFormData({ - ...formData, - serial_number: e.target.value, - }) - } - required - /> + setFormData({ ...formData, serial_number: e.target.value })} required />
- setFormData({ ...formData, status: e.target.value })} required>
+
+ + +
+
-