diff --git a/SVSTaskGate.ps1 b/SVSTaskGate.ps1 index 3cb2fb7..839917b 100644 --- a/SVSTaskGate.ps1 +++ b/SVSTaskGate.ps1 @@ -1,84 +1,92 @@ -### now that we have a field for user to enter N8N password we need to figure out how we can make the fetch site button refresh the downdown after ### add tweek to set default provider, add to toolkit? ### power settings in tweeks or onboarding? -### make script install the toolkit -### test the write-log in the log box and in the event viewer ### need to see if there's anything else we could take from Theo script? ### make when using select all the datto rmm pus var runs before install-splashtop +# --------------------------------------------------------------------------- +# 1) CREATE A GLOBAL LOG CACHE (NEW) +# --------------------------------------------------------------------------- +$Global:LogCache = New-Object System.Collections.ArrayList + # Check if the Write-Log function exists if (-not (Get-Command -Name Write-Log -CommandType Function -ErrorAction SilentlyContinue)) { # If the Write-Log function doesn't exist, create the Write-LogHelper function - function Write-LogHelper { - param ( - [string]$Message, - [ValidateSet("Info", "Warning", "Error", "Success", "General")] - [string]$Level = "Info", - [string]$TaskCategory = "GeneralTask", # Task Category for the log entry - [switch]$LogToEvent = $false, # Log to Windows Event Log - [string]$EventSource = "SVSMSP_Module", # Event Source - [string]$EventLog = "Application", # Event Log (default: Application) - [int]$CustomEventID # Optional custom Event ID - ) + function Write-LogHelper { + param ( + [string]$Message, + [ValidateSet("Info", "Warning", "Error", "Success", "General")] + [string]$Level = "Info", + [string]$TaskCategory = "GeneralTask", # Task Category for the log entry + [switch]$LogToEvent = $false, # Log to Windows Event Log + [string]$EventSource = "SVSMSP_Module", # Event Source + [string]$EventLog = "Application", # Event Log (default: Application) + [int]$CustomEventID # Optional custom Event ID + ) - # Simplified Event ID mapping - $EventID = switch ($Level) { - "Info" { 1000 } - "Warning" { 2000 } - "Error" { 3000 } - "Success" { 4000 } - "General" { 1000 } - } - - # Icons for each level - $Icon = switch ($Level) { - "Info" { [System.Char]::ConvertFromUtf32(0x1F4CB) } # Information icon - "Warning" { ([char]0x26A0) } # Warning icon - "Error" { ([char]0x274C) } # Error icon - "Success" { ([char]0x2705) } # Success icon - "General" { ([char]0x1F4E6) } # Package icon for generic tasks/operations - } - - # Map levels to colors - $Color = switch ($Level) { - "Info" { "Cyan" } - "Warning" { "Yellow" } - "Error" { "Red" } - "Success" { "Green" } - "General" { "White" } - } - - # Include Task Category, Icon, and Message in the console output - Write-Host "$Icon [$Level] [$TaskCategory] $Message (Event ID: $EventID)" -ForegroundColor $Color - - # Optionally log to the Windows Event Log - if ($LogToEvent) { - $EntryType = switch ($Level) { - "Info" { "Information" } - "Warning" { "Warning" } - "Error" { "Error" } - default { "Information" } + # Simplified Event ID mapping + $EventID = switch ($Level) { + "Info" { 1000 } + "Warning" { 2000 } + "Error" { 3000 } + "Success" { 4000 } + "General" { 1000 } } - try { - # Check if the event source exists, create it if necessary - if (-not (Get-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue)) { - New-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue + # Icons for each level + $Icon = switch ($Level) { + "Info" { [System.Char]::ConvertFromUtf32(0x1F4CB) } # Information icon + "Warning" { ([char]0x26A0) } # Warning icon + "Error" { ([char]0x274C) } # Error icon + "Success" { ([char]0x2705) } # Success icon + "General" { ([char]0x1F4E6) } # Package icon + } + + # Map levels to colors + $Color = switch ($Level) { + "Info" { "Cyan" } + "Warning" { "Yellow" } + "Error" { "Red" } + "Success" { "Green" } + "General" { "White" } + } + + # Write to the PowerShell console + Write-Host "$Icon [$Level] [$TaskCategory] $Message (Event ID: $EventID)" -ForegroundColor $Color + + # ------------------------------------------------------------------- + # 2) ALSO STORE THE LOG IN OUR GLOBAL LOG CACHE (NEW) + # ------------------------------------------------------------------- + $logEntry = [PSCustomObject]@{ + Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") + Level = $Level + Message = "$Icon [$Level] [$TaskCategory] $Message (Event ID: $EventID)" + } + [void]$Global:LogCache.Add($logEntry) + # ------------------------------------------------------------------- + + # Optionally log to the Windows Event Log + if ($LogToEvent) { + $EntryType = switch ($Level) { + "Info" { "Information" } + "Warning" { "Warning" } + "Error" { "Error" } + default { "Information" } } - # Include Task Category in the Event Log Message - $EventMessage = "TaskCategory: $TaskCategory | Message: $Message" - - # Write the event log - Write-EventLog -LogName $EventLog -Source $EventSource -EntryType $EntryType -EventId $EventID -Message $EventMessage - } catch { - Write-Host "([char]0x26A0) [Warning] [EventLog] Failed to write to Event Log: $($_.Exception.Message)" -ForegroundColor Yellow + try { + if (-not (Get-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue)) { + New-EventLog -LogName $EventLog -Source $EventSource -ErrorAction SilentlyContinue + } + $EventMessage = "TaskCategory: $TaskCategory | Message: $Message" + Write-EventLog -LogName $EventLog -Source $EventSource -EntryType $EntryType -EventId $EventID -Message $EventMessage + } + catch { + Write-Host "([char]0x26A0) [Warning] [EventLog] Failed to write to Event Log: $($_.Exception.Message)" -ForegroundColor Yellow + } } } -} - # Define a fallback Write-LogHybrid function that uses Write-LogHelper function Write-LogHybrid { param ( [string]$Message, @@ -90,8 +98,6 @@ if (-not (Get-Command -Name Write-Log -CommandType Function -ErrorAction Silentl [string]$EventLog = "Application", [int]$CustomEventID ) - - # Use the helper function to log Write-LogHelper -Message $Message -Level $Level -TaskCategory $TaskCategory ` -LogToEvent:$LogToEvent -EventSource $EventSource -EventLog $EventLog ` -CustomEventID $CustomEventID @@ -110,8 +116,6 @@ else { [string]$EventLog = "Application", [int]$CustomEventID ) - - # Use the existing Write-Log function Write-Log -Message $Message -Level $Level -TaskCategory $TaskCategory ` -LogToEvent:$LogToEvent -EventSource $EventSource -EventLog $EventLog ` -CustomEventID $CustomEventID @@ -120,6 +124,7 @@ else { # Example usage of Write-LogHybrid Write-LogHybrid -Message "This is a test log message. Write-log2 does exist" -Level "Info" -TaskCategory "TestCategory" -LogToEvent:$true +Write-Log -Message "This is a test log message. Write-log4444 does exist" -Level "Info" -TaskCategory "TestCategory" -LogToEvent:$true function Install-SVSMSP { @@ -178,7 +183,6 @@ function Install-SVSMSP { [string]$ApiSecretKey = "YOUR_API_SECRET_HERE" ) - # Helper function: Perform Cleanup function Perform-Cleanup { Write-LogHybrid -Message "Cleanup mode enabled. Starting cleanup process..." -Level "Info" -LogToEvent -EventID 1502 @@ -225,9 +229,8 @@ function Install-SVSMSP { Write-LogHybrid -Message "Cleanup process completed successfully." -Level "Success" -LogToEvent -EventID 1510 } - # Helper function: Perform Toolkit Installation function Perform-ToolkitInstallation { - # Perform cleanup to remove old modules and repositories + # Perform cleanup Perform-Cleanup # Step 1: Set Execution Policy @@ -282,7 +285,6 @@ function Install-SVSMSP { Write-LogHybrid -Message "Toolkit installation process completed successfully." -Level "Success" -LogToEvent -EventID 1510 } - # Main Logic Write-LogHybrid -Message "Install-SVSMSP function started." -Level "Info" -LogToEvent -EventID 1500 if ($Cleanup) { @@ -299,7 +301,7 @@ function Install-SVSMSP { Perform-ToolkitInstallation } -#Install-SVSMSP -InstallToolkit +Install-SVSMSP -InstallToolkit # ---------------------------------------------------------------------------------- @@ -316,21 +318,17 @@ function Get-N8nWebhookData { [string]$AuthHeaderValue ) - # Define the URL and headers $url = "https://automate.svstools.ca/webhook/svsmspkit" $headers = @{ "SVSMSPKit" = $AuthHeaderValue } - - # Make the GET request to the N8N webhook try { $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get Write-Host "Response received successfully:" -ForegroundColor Green - # Convert the JSON response to a PowerShell object $data = $response - # Map each field to a variable (if needed) + # Map fields $global:Comment_SVSmodule = $data._Comment_SVSmodule $global:ModuleName = $data.ModuleName $global:RepositoryURL = $data.RepositoryURL @@ -343,18 +341,8 @@ function Get-N8nWebhookData { $global:ApiKey = $data.ApiKey $global:ApiSecretKey = $data.ApiSecretKey - # Print the values - Write-Output "Module Name: $ModuleName" - Write-Output "Repository URL: $RepositoryURL" - Write-Output "Old Repo: $OldRepo" - Write-Output "New Repo: $NewRepo" - Write-Output "Commands To Check: $($CommandsToCheck -join ', ')" - Write-Output "Log File Path: $LogFilePath" - Write-Output "API URL: $ApiUrl" - Write-Output "API Key: $ApiKey" - Write-Output "API Secret Key: $ApiSecretKey" + - # Return the parsed data object return $data } catch { @@ -370,11 +358,11 @@ function GetHtmlContent { @" - - On-Boarding & Off-Boarding + SVS TaskGate + - +
+ SVS Logo +

-
@@ -591,6 +568,7 @@ function GetHtmlContent {
+ - "@ } + + # Save and launch the HTML Start-Process "msedge.exe" -ArgumentList "--app=http://localhost:8081/" - try { while ($listener.IsListening) { - # Wait for an incoming request $context = $listener.GetContext() $request = $context.Request $response = $context.Response @@ -820,7 +798,6 @@ try { switch ($request.Url.AbsolutePath) { "/" { - # Serve the main HTML $htmlContent = GetHtmlContent $buffer = [System.Text.Encoding]::UTF8.GetBytes($htmlContent) $response.ContentType = "text/html" @@ -831,17 +808,13 @@ try { "/getn8npw" { if ($request.HttpMethod -eq "POST") { - # Parse the received JSON $bodyStream = New-Object IO.StreamReader $request.InputStream $body = $bodyStream.ReadToEnd() $data = ConvertFrom-Json $body $password = $data.password Get-N8nWebhookData -AuthHeaderValue $password - - # Fetch the list of Datto RMM client sites $sites = Install-DattoRMM -ApiUrl $ApiUrl -ApiKey $ApiKey -ApiSecretKey $ApiSecretKey -FetchSitesOnly - if (-not $sites) { Write-Host "No sites returned. Please check the API." -ForegroundColor Red $response.StatusCode = 500 @@ -850,15 +823,10 @@ try { $response.OutputStream.Close() continue } - - # Convert the array (or object) in $sites to JSON $responseData = $sites | ConvertTo-Json $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseData) - - # Set the response headers $response.ContentType = "application/json" $response.ContentLength64 = $buffer.Length - $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } @@ -871,7 +839,6 @@ try { $selectedSite = ConvertFrom-Json $body Invoke-Expression $selectedSite.installRMMCommand - # Return a simple success response $responseString = "RMM install triggered." $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.ContentType = "text/plain" @@ -885,7 +852,6 @@ try { if ($request.HttpMethod -eq "GET") { Install-CyberQP } - # Return something $responseString = "Install CyberQP triggered." $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.ContentType = "text/plain" @@ -954,41 +920,50 @@ try { $response.OutputStream.Close() } - - - - + # ---------------------------------------------------------------- + # 4) NEW ROUTE: /getLogs + # Returns $Global:LogCache as JSON for the polling function + # ---------------------------------------------------------------- + "/getLogs" { + if ($request.HttpMethod -eq "GET") { + $jsonLogs = $Global:LogCache | ConvertTo-Json + $logBuffer = [System.Text.Encoding]::UTF8.GetBytes($jsonLogs) + $response.ContentType = "application/json" + $response.ContentLength64 = $logBuffer.Length + $response.OutputStream.Write($logBuffer, 0, $logBuffer.Length) + $response.OutputStream.Close() + } + } + "/quit" { if ($request.HttpMethod -eq "GET") { - # Return a "shutting down" message - $responseString = "Server shutting down." - $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) - $response.ContentType = "text/plain" - $response.ContentLength64 = $buffer.Length - $response.OutputStream.Write($buffer, 0, $buffer.Length) - $response.OutputStream.Close() - Write-Host $responseString - $listener.stop() - break # exit the while loop + $responseString = "Server shutting down." + $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) + $response.ContentType = "text/plain" + $response.ContentLength64 = $buffer.Length + $response.OutputStream.Write($buffer, 0, $buffer.Length) + $response.OutputStream.Close() + Write-Host $responseString + $listener.stop() + break } } default { - # Handle unknown routes $response.StatusCode = 404 $response.StatusDescription = "Not Found" $buffer = [System.Text.Encoding]::UTF8.GetBytes("404 - Not Found") $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } - } # end switch - } # end while + } + } } catch { Write-Host "Error: $($_.Exception.Message)" + } finally { $listener.Stop() $listener.Close() } -