### 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.
### In particular, the DattoRMM checkbox will be checked and its sub‑options will expand.
### - 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
On-Boarding
This new deployment method ensures everything is successfully deployed with greater ease!
Steph's Pick
"@
}
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"
}
}