### To Modify as of January 27 2025 ### Notes: ### - This script creates a GUI with tabs (On-Boarding, Off-Boarding, Tweaks, Steph's Pick). ### - In the On-Boarding tab, if the user selects “Select All,” then all checkboxes are checked. ### - All client-side JavaScript is wrapped in a DOMContentLoaded event listener to ensure proper initialization. # --------------------------------------------------------------------------- # 1) CREATE A GLOBAL LOG CACHE # --------------------------------------------------------------------------- if (-not $Global:LogCache -or -not ($Global:LogCache -is [System.Collections.ArrayList])) { $Global:LogCache = New-Object System.Collections.ArrayList } #region Write-LogHelper if (-not (Get-Command -Name Write-Log -CommandType Function -ErrorAction SilentlyContinue)) { function Write-LogHelper { param ( [string]$Message, [ValidateSet("Info", "Warning", "Error", "Success", "General")] [string]$Level = "Info", [string]$TaskCategory = "GeneralTask", [switch]$LogToEvent = $false, [string]$EventSource = "SVSMSP_Module", [string]$EventLog = "Application", [int]$CustomEventID ) $EventID = switch ($Level) { "Info" { 1000 } "Warning" { 2000 } "Error" { 3000 } "Success" { 4000 } "General" { 1000 } } $Icon = switch ($Level) { "Info" { [System.Char]::ConvertFromUtf32(0x1F4CB) } "Warning" { ([char]0x26A0) } "Error" { ([char]0x274C) } "Success" { ([char]0x2705) } "General" { ([char]0x1F4E6) } } $Color = switch ($Level) { "Info" { "Cyan" } "Warning" { "Yellow" } "Error" { "Red" } "Success" { "Green" } "General" { "White" } } $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) if ($LogToEvent) { $EntryType = switch ($Level) { "Info" { "Information" } "Warning" { "Warning" } "Error" { "Error" } default { "Information" } } 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 } } } function Write-LogHybrid { param ( [string]$Message, [ValidateSet("Info", "Warning", "Error", "Success", "General")] [string]$Level = "Info", [string]$TaskCategory = "GeneralTask", [switch]$LogToEvent = $false, [string]$EventSource = "SVSMSP_Module", [string]$EventLog = "Application", [int]$CustomEventID ) Write-LogHelper -Message $Message -Level $Level -TaskCategory $TaskCategory ` -LogToEvent:$LogToEvent -EventSource $EventSource -EventLog $EventLog ` -CustomEventID $CustomEventID } } else { function Write-LogHybrid { param ( [string]$Message, [ValidateSet("Info", "Warning", "Error", "Success", "General")] [string]$Level = "Info", [string]$TaskCategory = "GeneralTask", [switch]$LogToEvent = $false, [string]$EventSource = "SVSMSP_Module", [string]$EventLog = "Application", [int]$CustomEventID ) Write-Log -Message $Message -Level $Level -TaskCategory $TaskCategory ` -LogToEvent:$LogToEvent -EventSource $EventSource -EventLog $EventLog ` -CustomEventID $CustomEventID } } Write-LogHybrid -Message "Starting SVS TaskGate" -Level "Info" -TaskCategory "SVSTaskGate" -LogToEvent:$true #endregion #region Install-DattoRMM-Helper function Install-DattoRMM-Helper { param ( [string]$ApiUrl, [string]$ApiKey, [string]$ApiSecretKey, [switch]$FetchSitesOnly, [string]$SiteName, [string]$SiteUID ) if (-not $ApiUrl -or -not $ApiKey -or -not $ApiSecretKey) { Write-Log -Message "Missing required parameters. Please provide ApiUrl, ApiKey, and ApiSecretKey." -Level "Error" -LogToEvent return } [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Write-Log -Message "Fetching OAuth token..." -Level "Info" try { $securePassword = ConvertTo-SecureString -String 'public' -AsPlainText -Force $apiGenToken = Invoke-WebRequest -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ('public-client', $securePassword)) ` -Uri ('{0}/auth/oauth/token' -f $ApiUrl) ` -Method 'POST' ` -ContentType 'application/x-www-form-urlencoded' ` -Body ('grant_type=password&username={0}&password={1}' -f $ApiKey, $ApiSecretKey) ` | ConvertFrom-Json $requestToken = $apiGenToken.access_token Write-Log -Message "OAuth token fetched successfully." -Level "Success" -LogToEvent } catch { Write-Log -Message "Failed to fetch OAuth token. Details: $($_.Exception.Message)" -Level "Error" -LogToEvent return } $getHeaders = @{ "Authorization" = "Bearer $requestToken" } if ($FetchSitesOnly) { Write-Host "Fetching list of sites from the Datto RMM API..." -ForegroundColor Cyan try { $getSites = Invoke-WebRequest -Uri "$ApiUrl/api/v2/account/sites" -Method Get -Headers $getHeaders -ContentType "application/json" $sitesJson = $getSites.Content | ConvertFrom-Json $siteList = $sitesJson.sites | ForEach-Object { [PSCustomObject]@{ Name = $_.name UID = $_.uid } } Write-Host "Successfully fetched list of sites." -ForegroundColor Green return $siteList } catch { Write-Host "Failed to fetch sites from the API. Details: $($_.Exception.Message)" -ForegroundColor Red return } } } #endregion #region SVS Module function Install-SVSMSP { param ( [switch]$Cleanup, [switch]$InstallToolkit, [Parameter(Mandatory = $false)] [array]$AllModules = @( @{ ModuleName = "SVS_Toolkit" }, @{ ModuleName = "SVSMSP" } ), [Parameter(Mandatory = $false)] [string]$NewModuleName = "SVSMSP", [Parameter(Mandatory = $false)] [array]$AllRepositories = @( @{ RepoName = "SVS_Repo" }, @{ RepoName = "SVS_Toolkit" } ), [Parameter(Mandatory = $false)] [string]$NewRepositoryName = "SVS_Repo", [Parameter(Mandatory = $false)] [string]$NewRepositoryURL = "http://proget.svstools.ca:8083/nuget/SVS_Repo/", [Parameter(Mandatory = $false)] [array]$CommandsToCheck = @( "Install-DattoRMM", "Install-CyberQP", "Install-RocketCyber", "Install-Splashtop", "Install-ThreatLocker", "Install-SVSHelpdesk" ), [Parameter(Mandatory = $false)] [string]$LogFilePath = "$env:SVSMSP\svstoolkit.log" ) function Perform-Cleanup { Write-LogHybrid -Message "Cleanup mode enabled. Starting cleanup process..." -Level "Info" -LogToEvent Write-LogHybrid -Message "Starting cleanup of old modules..." -Level "Info" -LogToEvent foreach ($module in $AllModules) { $ModuleName = $module.ModuleName if (Get-Module -Name $ModuleName -ListAvailable) { Write-LogHybrid -Message "Removing module '$ModuleName'..." -Level "Warning" -LogToEvent try { Get-Module -Name $ModuleName -ListAvailable | ForEach-Object { Uninstall-Module -Name $_.Name -AllVersions -Force } Write-LogHybrid -Message "Module '$ModuleName' removed successfully." -Level "Success" -LogToEvent } catch { Write-LogHybrid -Message "Failed to remove module '$ModuleName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent } } else { Write-LogHybrid -Message "Module '$ModuleName' not found. Skipping..." -Level "Info" -LogToEvent } } Write-LogHybrid -Message "Starting cleanup of old repositories..." -Level "Info" -LogToEvent foreach ($repo in $AllRepositories) { $RepoName = $repo.RepoName Write-LogHybrid -Message "Removing repository '$RepoName'..." -Level "Warning" -LogToEvent if (Get-PSRepository -Name $RepoName -ErrorAction SilentlyContinue) { try { Unregister-PSRepository -Name $RepoName -ErrorAction Stop Write-LogHybrid -Message "Repository '$RepoName' removed successfully." -Level "Success" -LogToEvent } catch { Write-LogHybrid -Message "Failed to remove repository '$RepoName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent } } else { Write-LogHybrid -Message "Repository '$RepoName' does not exist. Skipping removal." -Level "Info" -LogToEvent } } Write-LogHybrid -Message "Cleanup process completed successfully." -Level "Success" -LogToEvent } function Perform-ToolkitInstallation { Perform-Cleanup $localMachineExecutionPolicy = Get-ExecutionPolicy -Scope LocalMachine if ($localMachineExecutionPolicy -ne "RemoteSigned") { Write-LogHybrid -Message "Setting execution policy to RemoteSigned..." -Level "Warning" -LogToEvent try { Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force Write-LogHybrid -Message "Execution policy set to RemoteSigned successfully." -Level "Success" -LogToEvent } catch { Write-LogHybrid -Message "Failed to set execution policy. Error: $_" -Level "Error" -LogToEvent return } } Install-PackageProvider -Name "NuGet" -Force -Scope AllUsers -Confirm:$false Write-LogHybrid -Message "Registering the new repository '$NewRepositoryName'..." -Level "Info" -LogToEvent try { if (!(Get-PSRepository -Name $NewRepositoryName -ErrorAction SilentlyContinue)) { Register-PSRepository -Name $NewRepositoryName -SourceLocation $NewRepositoryURL -InstallationPolicy Trusted Write-LogHybrid -Message "Repository '$NewRepositoryName' registered successfully." -Level "Success" -LogToEvent } } catch { Write-LogHybrid -Message "Failed to register new repository '$NewRepositoryName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent } Write-LogHybrid -Message "Installing the new module '$NewModuleName'..." -Level "Info" -LogToEvent try { Install-Module -Name $NewModuleName -Repository $NewRepositoryName -Scope AllUsers -Force Write-LogHybrid -Message "Module '$NewModuleName' installed successfully." -Level "Success" -LogToEvent } catch { Write-LogHybrid -Message "Failed to install new module '$NewModuleName'. Error: $($_.Exception.Message)" -Level "Error" -LogToEvent } Write-LogHybrid -Message "Toolkit installation process completed successfully." -Level "Success" -LogToEvent } Write-LogHybrid -Message "Install-SVSMSP function started." -Level "Info" -LogToEvent if ($Cleanup) { Perform-Cleanup return } if ($InstallToolkit) { Perform-ToolkitInstallation return } Write-LogHybrid -Message "No specific mode specified. Defaulting to toolkit installation mode..." -Level "Info" -LogToEvent Perform-ToolkitInstallation } #endregion #region NEW: Install-StephsPick function Install-StephsPick { param ( [array]$Packages ) Write-LogHybrid -Message "Starting Steph's Pick installation" -Level "Info" foreach ($package in $Packages) { try { $cmd = "winget install --id $package --silent" Write-LogHybrid -Message "Executing: $cmd" -Level "Info" Invoke-Expression $cmd } catch { Write-LogHybrid -Message "Error installing package $package`: $($_.Exception.Message)" -Level "Error" } } Write-LogHybrid -Message "Steph's Pick installation completed" -Level "Success" } #endregion # ---------------------------------------------------------------------------------- # START THE HTTP LISTENER # ---------------------------------------------------------------------------------- try { $listener = New-Object System.Net.HttpListener if (-not $listener) { throw "Failed to initialize HttpListener." } $listener.Prefixes.Add("http://localhost:8081/") Write-LogHybrid -Message "Listener initialized with prefix http://localhost:8081/" -Level "Info" $listener.Start() Write-LogHybrid -Message "Listener started successfully." -Level "Info" } catch { Write-LogHybrid -Message "Critical error initializing listener: $($_.Exception.Message)" -Level "Error" throw $_ } function Get-N8nWebhookData { param ( [Parameter(Mandatory = $true)] [string]$AuthHeaderValue ) $url = "https://automate.svstools.ca/webhook/svsmspkit" $headers = @{ "SVSMSPKit" = $AuthHeaderValue } try { $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get Write-Host "Response received successfully:" -ForegroundColor Green $data = $response $global:Comment_SVSmodule = $data._Comment_SVSmodule $global:ModuleName = $data.ModuleName $global:RepositoryURL = $data.RepositoryURL $global:OldRepo = $data.OldRepo $global:NewRepo = $data.NewRepo $global:CommandsToCheck = $data.CommandsToCheck $global:LogFilePath = $data.LogFilePath $global:Comment_DRMM = $data._Comment_DRMM $global:ApiUrl = $data.ApiUrl $global:ApiKey = $data.ApiKey $global:ApiSecretKey = $data.ApiSecretKey } catch { Write-Host "Error making the GET request:" -ForegroundColor Red Write-Host $_.Exception.Message return $null } } function GetHtmlContent { @" SVS TaskGate
SVS Logo

On-Boarding

This new deployment method ensures everything is successfully deployed with greater ease!

SVSMSP Stack

Optional


Off-Boarding

Tweaks

System Optimizations

Additional Tweaks

Miscellaneous

Steph's Pick

Apps

Logs will appear here...

"@ } Start-Process "msedge.exe" -ArgumentList "--app=http://localhost:8081/" try { while ($listener.IsListening) { $context = $listener.GetContext() $request = $context.Request $response = $context.Response switch ($request.Url.AbsolutePath) { "/" { $htmlContent = GetHtmlContent $buffer = [System.Text.Encoding]::UTF8.GetBytes($htmlContent) $response.ContentType = "text/html" $response.ContentLength64 = $buffer.Length $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } "/getn8npw" { if ($request.HttpMethod -eq "POST") { try { $bodyStream = New-Object IO.StreamReader $request.InputStream $body = $bodyStream.ReadToEnd() $data = ConvertFrom-Json $body $password = $data.password Get-N8nWebhookData -AuthHeaderValue $password $sites = Install-DattoRMM-Helper -ApiUrl $ApiUrl -ApiKey $ApiKey -ApiSecretKey $ApiSecretKey -FetchSitesOnly if (-not $sites) { Write-Host "No sites returned. Please check the API." -ForegroundColor Red $response.StatusCode = 500 $buffer = [System.Text.Encoding]::UTF8.GetBytes("No sites found") $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() continue } $responseData = $sites | ConvertTo-Json $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseData) $response.ContentType = "application/json" $response.ContentLength64 = $buffer.Length $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } catch { Write-LogHybrid -Message "Error processing /getn8npw: $($_.Exception.Message)" -Level "Error" $response.StatusCode = 500 $buffer = [System.Text.Encoding]::UTF8.GetBytes("Error: Failed to process the request.") $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } } } "/installSVSMSPModule" { if ($request.HttpMethod -eq "GET") { try { Install-SVSMSP -InstallToolkit $responseString = "Install SVSMSP Module triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Install SVSMSP Module: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/installrmm" { if ($request.HttpMethod -eq "POST") { try { $bodyStream = New-Object IO.StreamReader $request.InputStream $body = $bodyStream.ReadToEnd() $requestData = ConvertFrom-Json $body $checkedValues = $requestData.checkedValues $UID = $requestData.UID $Name = $requestData.Name if (-not $checkedValues -or -not $UID -or -not $Name) { Write-LogHybrid -Message "Invalid input received. Missing required parameters: UID, Name, or checkbox values." -Level "Error" $response.StatusCode = 400 $responseString = "Error: Missing required input parameters." $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() return } $installRMMCommand = "Install-DattoRMM -ApiUrl '$ApiUrl' -ApiKey '$ApiKey' -ApiSecretKey '$ApiSecretKey' -SiteName $Name -SiteUID $UID " if ($checkedValues -contains 'inputVar') { $installRMMCommand += " -PushSiteVars" } if ($checkedValues -contains 'rmm') { $installRMMCommand += " -InstallRMM" } if ($checkedValues -contains 'exe') { $installRMMCommand += " -SaveCopy" } try { Invoke-Expression $installRMMCommand $responseString = "RMM installation triggered successfully for $Name." Write-LogHybrid -Message $responseString -Level "Success" $response.StatusCode = 200 } catch { $responseString = "Error triggering RMM installation: $($_.Exception.Message)" Write-LogHybrid -Message $responseString -Level "Error" $response.StatusCode = 500 } } catch { $errorString = "An error occurred while processing the /installrmm request: $($_.Exception.Message)" Write-LogHybrid -Message $errorString -Level "Error" $response.StatusCode = 500 $responseString = $errorString } $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() } else { $response.StatusCode = 405 $response.StatusDescription = "Method Not Allowed" $responseString = "Error: Only POST requests are allowed." $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } } "/setSVSPowerplan" { if ($request.HttpMethod -eq "GET") { try { Set-SVSPowerPlan $responseString = "Setting SVS PowerPlan triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Setting SVS PowerPlan: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/installCyberQP" { if ($request.HttpMethod -eq "GET") { try { Install-CyberQP $responseString = "Install CyberQP triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Install CyberQP: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/installSplashtop" { if ($request.HttpMethod -eq "GET") { try { Install-Splashtop $responseString = "Install Splashtop triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Install Splashtop: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/installRocketCyber" { if ($request.HttpMethod -eq "GET") { try { Install-RocketCyber $responseString = "Install RocketCyber triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Install RocketCyber: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/installThreatLocker" { if ($request.HttpMethod -eq "GET") { try { Install-ThreatLocker $responseString = "Install ThreatLocker triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Install ThreatLocker: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/setedgedefaultsearch" { if ($request.HttpMethod -eq "GET") { try { set-EdgeDefaultSearchProvider $responseString = "setedgedefaultsearch triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering setedgedefaultsearch: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/installSVSHelpDesk" { if ($request.HttpMethod -eq "GET") { try { Install-SVSHelpDesk $responseString = "Install SVSHelpDesk triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Install SVSHelpDesk: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/EdgeDefaultSearchEngine" { if ($request.HttpMethod -eq "GET") { try { Write-LogHybrid -Message "Setting Edge Default Search Engine started." -Level "Info" Set-EdgeDefaultSearchEngine Write-LogHybrid -Message "Edge Default Search Engine set successfully." -Level "Success" $responseString = "Edge Default Search Engine triggered successfully." $response.StatusCode = 200 } catch { Write-LogHybrid -Message "Error setting Edge Default Search Engine: $($_.Exception.Message)" -Level "Error" $responseString = "Error attempting to set Edge Default Search Engine: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } "/EnableBitLocker" { if ($request.HttpMethod -eq "GET") { try { Set-SVSBitLocker -Mode Enable -DriveLetter C -SaveToRegistry $true $responseString = "BitLocker enabled on C successfully." $response.StatusCode = 200 } catch { $responseString = "Error Attempting to set BitLocker: $_" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use GET." $response.StatusCode = 405 } $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() } # Steph's Pick Route "/installStephsPick" { if ($request.HttpMethod -eq "POST") { try { $bodyStream = New-Object IO.StreamReader $request.InputStream $body = $bodyStream.ReadToEnd() $data = ConvertFrom-Json $body $selectedPackages = $data.packages if (-not $selectedPackages -or $selectedPackages.Count -eq 0) { $selectedPackages = @("Apple.iCloud", "Obsidian.Obsidian", "Flameshot.Flameshot", "SublimeHQ.SublimeText.4") } Install-StephsPick -Packages $selectedPackages $responseString = "Steph's Pick installation triggered successfully." $response.StatusCode = 200 } catch { $responseString = "Error triggering Steph's Pick installation: $($_.Exception.Message)" $response.StatusCode = 500 } } else { $responseString = "Method not allowed. Use POST." $response.StatusCode = 405 } $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() } "/offboard" { if ($request.HttpMethod -eq "POST") { try { $bodyStream = New-Object IO.StreamReader $request.InputStream $body = $bodyStream.ReadToEnd() $requestData = ConvertFrom-Json $body $selectedTasks = $requestData.SelectedTasks Write-LogHybrid -Message "Offboarding request received with tasks: $($selectedTasks -join ', ')" -Level "Info" if (-not $selectedTasks -or $selectedTasks.Count -eq 0) { $response.StatusCode = 400 $responseString = "Error: No offboarding tasks selected." $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() return } foreach ($task in $selectedTasks) { switch ($task) { "uninstallSVSMSPModule" { Write-LogHybrid -Message "Uninstalling SVSMSP Module..." -Level "Info"; Install-SVSMSP -cleanup } "uninstallThreatLocker" { Write-LogHybrid -Message "Uninstalling Threatlocker" -Level "Info"; Uninstall-ThreatLocker } "uninstallCyberQP" { Write-LogHybrid -Message "Uninstalling CyberQP" -Level "Info"; Uninstall-CyberQP } "uninstallDattoEDR" { Uninstall-DattoEDR } "uninstallDattoRMM" { Uninstall-DattoRMM } "uninstallRocketCyber" { Uninstall-RocketCyber } "uninstallSplashtop" { Uninstall-Splashtop } "uninstallSVSHelpdesk" { Uninstall-SVSHelpdesk } "uninstallSVSWatchtower" { Uninstall-SVSWatchtower } default { Write-LogHybrid -Message "Unknown task: $task" -Level "Warning" } } } $responseString = "Offboarding tasks executed successfully." $response.StatusCode = 200 } catch { $responseString = "Error processing offboarding tasks: $($_.Exception.Message)" $response.StatusCode = 500 } $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() } else { $responseString = "Method not allowed. Use POST." $response.StatusCode = 405 $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } } "/runTweaks" { if ($request.HttpMethod -eq "POST") { try { $bodyStream = New-Object IO.StreamReader $request.InputStream $body = $bodyStream.ReadToEnd() $requestData = ConvertFrom-Json $body $tweaks = $requestData.tweaks if (-not $tweaks -or $tweaks.Count -eq 0) { $response.StatusCode = 400 $responseString = "Error: No tweaks selected." $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() return } foreach ($tweak in $tweaks) { switch ($tweak) { "enableDarkModeCheckbox" { Write-LogHybrid -Message "Running tweak: Set Edge Default Search Engine" -Level "Info" Set-EdgeDefaultSearchEngine } "disableAnimationsCheckbox" { Write-LogHybrid -Message "Running tweak: Disable Animations" -Level "Info" } "optimizePerformanceCheckbox" { Write-LogHybrid -Message "Running tweak: Optimize Performance" -Level "Info" } "increaseFontSizeCheckbox" { Write-LogHybrid -Message "Running tweak: Increase Font Size" -Level "Info" } default { Write-LogHybrid -Message "Unknown tweak: $tweak" -Level "Warning" } } } $responseString = "Selected tweaks executed successfully." $response.StatusCode = 200 } catch { $responseString = "Error processing tweaks: $($_.Exception.Message)" $response.StatusCode = 500 } $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() } else { $responseString = "Method not allowed. Use POST." $response.StatusCode = 405 $buffer = [System.Text.Encoding]::UTF8.GetBytes($responseString) $response.OutputStream.Write($buffer, 0, $buffer.Length) $response.OutputStream.Close() } } "/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") { $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 { $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() } } } } catch { Write-Host "Error: $($_.Exception.Message)" } finally { if ($listener -ne $null) { try { Write-LogHybrid -Message "Stopping the listener." -Level "Info" $listener.Stop() $listener.Close() Write-LogHybrid -Message "Listener stopped successfully." -Level "Info" } catch { Write-LogHybrid -Message "Error stopping the listener: $($_.Exception.Message)" -Level "Error" } } else { Write-LogHybrid -Message "Listener object is null; nothing to stop." -Level "Warning" } }