Files
Logo/TGBeta.ps1
2025-01-27 21:44:06 -05:00

1740 lines
74 KiB
PowerShell

### To Modify as of January 27 2025
### let's start thinking about the write-log -TaskCategory "On-boarding" or "Off-boarding"
### need RGB color codes form john, once we picked the RGBA colors
### add the .net silent install tweaks to toolkit
### for the reg tweak need to do/undo function maybe it should have it own check box list
### added offboard check boxes for dattormm, dattodeb, rocketcyber, cyberQP, SVSHelpdesk and Splashtop
### for the offboarding button, we need to fix the uninstall-svsmsp module
### need to fix path in the uninstall-DattoEDR -
####### ❌ [Error] [GeneralTask] Uninstallation command 'C:\Program Files\Infocyte\Agent\agent.exe' not found. (Event ID: 3000) - bad path
### need to have the fetch button check if Install-DattoRMM function exist if not run the build in helpder function to fetch sites
### need to move the tweaks to the tweeks tab
#region Write-Log
# ---------------------------------------------------------------------------
# 1) CREATE A GLOBAL LOG CACHE (NEW)
# ---------------------------------------------------------------------------
if (-not $Global:LogCache -or -not ($Global:LogCache -is [System.Collections.ArrayList])) {
$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
)
# 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
}
# 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" }
}
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 {
# If Write-Log exists, define Write-LogHybrid to use Write-Log
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
}
}
# Example usage of Write-LogHybrid
Write-LogHybrid -Message "Starting SVS TaskGate" -Level "Info" -TaskCategory "SVSTaskGate" -LogToEvent:$true
#endregion
#region SVS Module
function Install-SVSMSP {
param (
# Cleanup flag
[switch]$Cleanup,
# Toolkit installation flag
[switch]$InstallToolkit,
# Module settings
[Parameter(Mandatory = $false)]
[array]$AllModules = @(
@{ ModuleName = "SVS_Toolkit" },
@{ ModuleName = "SVSMSP" }
),
[Parameter(Mandatory = $false)]
[string]$NewModuleName = "SVSMSP",
# Repository settings
[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/",
# Commands to check
[Parameter(Mandatory = $false)]
[array]$CommandsToCheck = @(
"Install-DattoRMM",
"Install-CyberQP",
"Install-RocketCyber",
"Install-Splashtop",
"Install-ThreatLocker",
"Install-SVSHelpdesk"
),
# Log file path
[Parameter(Mandatory = $false)]
[string]$LogFilePath = "$env:SVSMSP\svstoolkit.log",
# DRMM API Settings
[Parameter(Mandatory = $false)]
[string]$ApiUrl,
[Parameter(Mandatory = $false)]
[string]$ApiKey,
[Parameter(Mandatory = $false)]
[string]$ApiSecretKey
)
function Perform-Cleanup {
Write-LogHybrid -Message "Cleanup mode enabled. Starting cleanup process..." -Level "Info" -LogToEvent
# Step 1: Remove all old modules
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
}
}
# Step 2: Remove all old repositories
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
Perform-Cleanup
# Step 1: Set Execution Policy
$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
}
}
# Step 2: Ensure NuGet is Installed
#if (!(Get-PackageProvider -Name "NuGet" -ErrorAction SilentlyContinue)) {
# Write-LogHybrid -Message "NuGet package provider not found. Installing..." -Level "Warning" -LogToEvent
# try {
Install-PackageProvider -Name "NuGet" -Force -Scope AllUsers -Confirm:$false
# Write-LogHybrid -Message "NuGet package provider installed successfully." -Level "Success" -LogToEvent
# }
# catch {
# Write-LogHybrid -Message "Failed to install NuGet package provider. Error: $_" -Level "Error" -LogToEvent
# return
# }
#}
# Step 3: Register the new repository
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
}
# Step 4: Install the new module
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 SVS Module
# ----------------------------------------------------------------------------------
# START THE LISTENER
# ----------------------------------------------------------------------------------
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add("http://localhost:8081/")
$listener.Start()
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
# Map fields
$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
# return $data
}
catch {
Write-Host "Error making the GET request:" -ForegroundColor Red
Write-Host $_.Exception.Message
return $null
}
}
# Define the HTML Content with an Off-Boarding Tab
function GetHtmlContent {
@"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVS TaskGate</title>
<link rel="icon" href="https://git.svstools.com/syelle/Logo/raw/branch/main/SVS_Favicon.ico" type="image/x-icon">
<style>
:root {
/* Cool Palette */
--background-color: rgba(18, 18, 18, 1);
--border-color: rgba(255, 127, 0, 0.25);
/* Neutral Colors */
--white-color: rgba(255, 255, 255);
--gray-color: rgba(102, 102, 102);
--dark-gray-color: rgba(51, 51, 51);
--light-gray-color: rgba(187, 187, 187);
/* Sidebar Button Colors */
--btn-sidebar-light-gray: rgba(68, 68, 68); /* Sidebar button background */
--btn-sidebar-blue: rgba(30, 144, 255, 1);
--btn-hover: rgba(0, 86, 179, 1); /* Hover state (dark blue) for buttons */
--btn-hover-scale: 1.05; /* Scale effect for button hover */
/* Button Colors */
--btn-success: rgba(40, 167, 69); /* Green button background */
--btn-success-disabled: rgba(108, 117, 125); /* Disabled success button color */
--btn-danger: rgba(220, 53, 69); /* Red button background */
}
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: var(--background-color);
color: var(--white-color);
height: 100%; /* Ensure the body fills the viewport */
overflow: hidden; /* Prevent scrollbars */
}
.logo-container {
text-align: left;
padding: 20px;
background-color: var(--background-color); /* Matches the background color */
}
.logo-container img {
max-width: 300px; /* Adjust size as needed */
height: auto;
}
.subtitle {
font-size: 1.2rem;
color: var(--gray-color);
margin-top: 0.5em;
}
.container {
display: flex;
height: 100vh; /* Ensure the container is limited to the viewport height */
overflow: hidden; /* Prevent the container from exceeding the viewport height */
}
.sidebar {
width: 200px;
height: 100%; /* Ensure it doesn't exceed the container height */
background-color: var(--background-color);
padding: 10px;
}
.sidebar button {
display: block;
width: 100%;
margin-bottom: 10px;
padding: 10px;
color: var(--white-color);
background-color: var(--btn-sidebar-light-gray);
border: none;
border-radius: 5px;
cursor: pointer;
text-align: left;
transition: background-color 0.3s ease, transform 0.2s ease;
}
.sidebar button.active {
background-color: var(--btn-sidebar-blue);
}
.sidebar button:hover {
background-color: var(--btn-hover);
transform: scale(var(--btn-hover-scale));
}
.content {
flex: 1; /* Allow the content to fill available space */
padding: 20px;
overflow-y: auto; /* Add scrolling only within the content if necessary */
max-height: calc(100vh - 50px); /* Adjust the height dynamically to fit within the viewport */
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.checkbox-group label {
margin: 0;
padding: 0;
line-height: 1.5;
display: flex;
align-items: center;
}
.password-input,
.dropdown {
width: 30%;
padding: 10px;
margin-bottom: 20px;
border-radius: 5px;
border: 1px solid var(--border-color);
background-color: var(--background-color);
color: var(--white-color);
}
#n8nPasswordContainer {
display: none;
margin-top: 20px; /* Adjust the value to set the desired spacing */
}
.button-group {
margin-top: 20px;
text-align: right;
}
.button-group button {
padding: 10px 20px;
margin-left: 10px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.install-button {
background-color: var(--btn-success);
color: var(--white-color);
}
.install-button:disabled {
background-color: var(--btn-success-disabled);
cursor: not-allowed;
}
.exit-button {
background-color: var(--btn-danger);
color: var(--white-color);
}
.columns-container {
display: flex;
justify-content: center;
gap: 20px;
align-items: flex-start;
padding: 0;
}
.column {
width: 48%;
border: 2px solid var(--border-color);
border-radius: 8px;
padding: 10px;
background-color: var(--background-color);
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.3);
margin: 0;
}
.log {
width: 80%;
margin-top: 20px;
padding: 10px;
background-color: var(--dark-gray-color);
color: var(--light-gray-color);
border-radius: 5px;
max-height: 500px;
overflow-y: auto;
}
@media (max-width: 768px) {
.container {
flex-direction: column;
}
.sidebar {
width: 100%;
}
}
</style>
</head>
<body>
<div class="logo-container">
<img src="https://git.svstools.com/syelle/Logo/raw/branch/main/SVS_logo.svg" alt="SVS Logo">
</div>
<div class="container">
<div class="sidebar">
<button class="tab-button active" data-tab="onboardTab" aria-expanded="true">On-Boarding</button>
<button class="tab-button" data-tab="offboardTab" aria-expanded="false">Off-Boarding</button>
<button class="tab-button" data-tab="tweaksTab" aria-expanded="false">Tweaks</button>
</div>
<div class="content">
<!-- On-Boarding Tab -->
<div id="onboardTab" class="tab-content active">
<h2>On-Boarding</h2>
<h3 class="subtitle">This new deployment method ensures everything is successfully deployed with greater ease!</h3>
<div class="columns-container">
<!-- Left column -->
<div class="checkbox-group column" id="leftColumn">
<label>
<input type="checkbox" id="selectAllLeftCheckbox" onclick="toggleLeftColumnCheckboxes(this)">
Select All
</label>
<label>
<input type="checkbox" class="left-checkbox" name="setSVSPowerplan" id="SetSVSPowerplanCheckbox">
Set SVS Powerplan
</label>
<label>
<input type="checkbox" class="left-checkbox" name="installSVSMSPModule" id="installSVSMSPModuleCheckbox">
Install SVSMSP Module
</label>
<label>
<input type="checkbox" class="left-checkbox" name="installCyberQP" id="installCyberQPCheckbox">
Install CyberQP
</label>
<label>
<input type="checkbox" class="left-checkbox" name="installSplashtop" id="installSplashtopCheckbox">
Install Splashtop
</label>
<label>
<input type="checkbox" class="left-checkbox" name="installSVSHelpDesk" id="installSVSHelpDeskCheckbox">
Install SVSHelpDesk
</label>
<label>
<input type="checkbox" class="left-checkbox" name="installThreatLocker" id="installThreatLockerCheckbox">
Install ThreatLocker
</label>
<label>
<input type="checkbox" class="left-checkbox" name="installRocketCyber" id="installRocketCyberCheckbox">
Install RocketCyber
</label>
<label>
<input type="checkbox" class="left-checkbox" name="installDattoRMM" id="installDattoRMMCheckbox"
onclick="toggleDattoRMMOptions()">
Install DattoRMM
</label>
<div id="dattoRMMOptionsContainer" style="display:none; padding-left: 20px;">
<label>
<input type="checkbox" class="left-checkbox" name="dattoRMMOption" value="inputVar">
Copy Site Variables
</label>
<label>
<input type="checkbox" class="left-checkbox" name="dattoRMMOption" value="rmm">
Install DRMM Agent
</label>
<label>
<input type="checkbox" class="left-checkbox" name="dattoRMMOption" value="exe">
Download.exe
</label>
<br><br>
</div>
</div>
<!-- Right column -->
<div class="checkbox-group column" id="rightColumn" >
<label>
<input type="checkbox" class="right-checkbox" name="EnableBitLocker" id="EnableBitLockerCheckbox">
Enable Bitlocker
</label>
<label>
<input type="checkbox" class="right-checkbox" name="setedgedefaultsearch" id="setedgedefaultsearchCheckbox">
Set Edge Default Search Engine
</label>
<!-- Add more checkboxes here -->
</div>
</div>
<div id="n8nPasswordContainer" style="display: none;">
<label for="n8nPassword">Enter Password:</label><br>
<input type="password" id="n8nPassword" class="password-input" placeholder="Enter Password">
</div>
<br>
<div id="DattoRMMContainer" style="display: none;">
<label for="dattoRmmDropdown">Select a Datto RMM site:</label><br>
<select id="dattoRmmDropdown" class="dropdown">
<option value="">Fetching sites...</option>
$siteOptions
</select>
</div>
<div class="button-group">
<button class="install-button" id="fetchSitesButton" onclick="fetchSites()" disabled>Fetch
Sites</button>
<button class="install-button" onclick="triggerInstall()">Install</button>
</div>
</div>
<!-- Off-Boarding Tab -->
<div id="offboardTab" class="tab-content inactive">
<h2>Off-Boarding</h2>
<div class="checkbox-group">
<label>
<input type="checkbox" id="selectAllOffboardCheckbox" onclick="toggleOffboardCheckboxes(this)">
Select All
</label>
<label>
<input type="checkbox" name="uninstallSVSMSPModule" id="uninstallSVSMSPModuleCheckbox">
Uninstall SVSMSP Module
</label>
<label>
<input type="checkbox" name="uninstallThreatLocker" id="uninstallThreatLockerCheckbox">
Uninstall ThreatLocker
</label>
<label>
<input type="checkbox" name="uninstallCyberQP" id="uninstallCyberQPCheckbox">
Uninstall CyberQP
</label>
<label>
<input type="checkbox" name="uninstallDattoEDR" id="uninstallDattoEDRCheckbox">
Uninstall DattoEDR
</label>
<label>
<input type="checkbox" name="uninstallDattoRMM" id="uninstallDattoRMMCheckbox">
Uninstall DattoRMM
</label>
<label>
<input type="checkbox" name="uninstallDattoDEB" id="uninstallDattoDEBCheckbox">
Uninstall DattoDEB
</label>
<label>
<input type="checkbox" name="uninstallRocketCyber" id="uninstallRocketCyberCheckbox">
Uninstall RocketCyber
</label>
<label>
<input type="checkbox" name="uninstallSplashtop" id="uninstallSplashtopCheckbox">
Uninstall splashtop
</label>
<label>
<input type="checkbox" name="uninstallSVSHelpdesk" id="uninstallSVSHelpdeskCheckbox">
Uninstall SVSHelpdesk
</label>
<label>
<input type="checkbox" name="uninstallSVSWatchtower" id="uninstallSVSWatchtowerCheckbox">
Uninstall SVSWatchtower
</label>
<div class="button-group">
<button class="install-button" onclick="triggerOffboard()">Offboard</button>
</div>
</div>
</div>
<!-- tweaks Tab -->
<div id="tweaksTab" class="tab-content inactive">
<h2>Tweaks</h2>
<div class="checkbox-group">
<label>
<input type="checkbox" id="selectAllTweaksCheckbox" onclick="toggleTweaksCheckboxes(this)">
Select All
</label>
<label>
<input type="checkbox" name="setedgedefaultsearch" id="setedgedefaultsearchCheckbox">
Set Edge Default Search Engine
</label>
<label>
<input type="checkbox" name="disableAnimations" id="disableAnimationsCheckbox">
Disable Animations
</label>
<label>
<input type="checkbox" name="optimizePerformance" id="optimizePerformanceCheckbox">
Optimize Performance
</label>
<label>
<input type="checkbox" name="increaseFontSize" id="increaseFontSizeCheckbox">
Increase Font Size
</label>
</div>
<div class="button-group">
<button class="install-button" onclick="triggerTweaks()">Tweaks</button>
</div>
</div>
<!-- Shared Exit Button -->
<div class="button-group">
<button class="exit-button" onclick="endSession()">Exit</button>
</div>
<!-- Log Area -->
<div class="log" id="logArea">
<p>Logs will appear here...</p>
</div>
</div>
<script>
function toggleOnboardCheckboxes(selectedCheckbox) {
const checkboxes = document.querySelectorAll('#onboardTab input[type="checkbox"]');
const dattoRMMCheckbox = document.getElementById('installDattoRMMCheckbox');
const optionsContainer = document.getElementById('dattoRMMOptionsContainer');
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
const dattoRMMContainer = document.getElementById('DattoRMMContainer');
if (dattoRMMCheckbox.checked) {
optionsContainer.style.display = 'block';
n8nPasswordContainer.style.display = 'block';
dattoRMMContainer.style.display = 'block';
} else {
optionsContainer.style.display = 'none';
n8nPasswordContainer.style.display = 'none';
dattoRMMContainer.style.display = 'none';
}
}
function toggleLeftColumnCheckboxes(selectAllCheckbox) {
const leftCheckboxes = document.querySelectorAll('#leftColumn input[type="checkbox"]:not(#selectAllLeftCheckbox)');
const dattoRMMCheckbox = document.getElementById('installDattoRMMCheckbox');
const optionsContainer = document.getElementById('dattoRMMOptionsContainer');
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
const dattoRMMContainer = document.getElementById('DattoRMMContainer');
// Toggle all checkboxes
leftCheckboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
// Check if "Install DattoRMM" is selected
if (dattoRMMCheckbox.checked) {
optionsContainer.style.display = 'block';
n8nPasswordContainer.style.display = 'block';
dattoRMMContainer.style.display = 'block';
} else {
optionsContainer.style.display = 'none';
n8nPasswordContainer.style.display = 'none';
dattoRMMContainer.style.display = 'none';
}
}
function updateSelectAllonboard() {
const selectAllCheckbox = document.getElementById('selectAllOnboardCheckbox');
const checkboxes = document
.getElementById('onboardTab')
.querySelectorAll('input[type="checkbox"]:not(#selectAllOnboardCheckbox)');
// If any checkbox is unchecked, uncheck "Select All"
selectAllCheckbox.checked = Array.from(checkboxes).every(checkbox => checkbox.checked);
}
function gatherSelectedTasks() {
const selectedLeftTasks = Array.from(document.querySelectorAll('.left-checkbox:checked')).map(checkbox => checkbox.name);
const selectedRightTasks = Array.from(document.querySelectorAll('.right-checkbox:checked')).map(checkbox => checkbox.name);
return [...selectedLeftTasks, ...selectedRightTasks];
}
// Attach the updateSelectAllonboard function to all individual checkboxes
document.querySelectorAll('#onboardTab input[type="checkbox"]:not(#selectAllOnboardCheckbox)').forEach(checkbox => {
checkbox.addEventListener('change', updateSelectAllonboard);
});
function toggleOffboardCheckboxes(selectAllCheckbox) {
const checkboxes = document.querySelectorAll('#offboardTab input[type="checkbox"]:not(#selectAllOffboardCheckbox)');
checkboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
}
function updateSelectAllOffboard() {
const selectAllCheckbox = document.getElementById('selectAllOffboardCheckbox');
const checkboxes = document.querySelectorAll('#offboardTab input[type="checkbox"]:not(#selectAllOffboardCheckbox)');
selectAllCheckbox.checked = Array.from(checkboxes).every(checkbox => checkbox.checked);
}
document.querySelectorAll('#offboardTab input[type="checkbox"]:not(#selectAllOffboardCheckbox)').forEach(checkbox => {
checkbox.addEventListener('change', updateSelectAllOffboard);
});
function triggerOffboard() {
const checkboxes = document.querySelectorAll('#offboardTab input[type="checkbox"]:not(#selectAllOffboardCheckbox)');
const selectedTasks = Array.from(checkboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.name);
if (selectedTasks.length === 0) {
appendLog("Please select at least one offboarding task.", "red");
return;
}
appendLog("Starting offboarding tasks...", "yellow");
fetch('/offboard', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ SelectedTasks: selectedTasks })
})
.then(response => {
if (!response.ok) {
throw new Error('Failed to execute offboarding tasks.');
}
return response.text();
})
.then(message => {
appendLog(message, "green");
})
.catch(error => {
appendLog("Error: " + error.message, "red");
});
}
function toggleTweaksCheckboxes(selectAllCheckbox) {
// Get all checkboxes inside the tweaksTab container
const checkboxes = document
.getElementById('tweaksTab')
.querySelectorAll('input[type="checkbox"]:not(#selectAllTweaksCheckbox)');
// Set the checked state of all checkboxes to match the "Select All" checkbox
checkboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
}
function updateSelectAllTweaks() {
const selectAllCheckbox = document.getElementById('selectAllTweaksCheckbox');
const checkboxes = document
.getElementById('tweaksTab')
.querySelectorAll('input[type="checkbox"]:not(#selectAllTweaksCheckbox)');
// If any checkbox is unchecked, uncheck "Select All"
selectAllCheckbox.checked = Array.from(checkboxes).every(checkbox => checkbox.checked);
}
// Attach the updateSelectAllTweaks function to all individual checkboxes
document.querySelectorAll('#tweaksTab input[type="checkbox"]:not(#selectAllTweaksCheckbox)').forEach(checkbox => {
checkbox.addEventListener('change', updateSelectAllTweaks);
});
function triggerTweaks() {
const setedgedefaultsearch = document.querySelector('input[name="setedgedefaultsearch"]');
if (setedgedefaultsearch.checked) {
fetch('/setedgedefaultsearch', { method: 'GET' })
}
}
function toggleDattoRMMOptions() {
const checkbox = document.getElementById('installDattoRMMCheckbox');
const optionsContainer = document.getElementById('dattoRMMOptionsContainer');
const n8nPasswordContainer = document.getElementById('n8nPasswordContainer');
const DattoRMMContainer = document.getElementById('DattoRMMContainer');
optionsContainer.style.display = checkbox.checked ? 'block' : 'none';
n8nPasswordContainer.style.display = checkbox.checked ? 'block' : 'none';
DattoRMMContainer.style.display = checkbox.checked ? 'block' : 'none';
}
const tabButtons = document.querySelectorAll('.tab-button');
const tabContents = document.querySelectorAll('.tab-content');
const logArea = document.getElementById('logArea');
const fetchSitesButton = document.getElementById('fetchSitesButton');
const n8nPasswordInput = document.getElementById('n8nPassword');
tabButtons.forEach(button => {
button.addEventListener('click', () => {
tabButtons.forEach(btn => {
btn.classList.remove('active');
btn.setAttribute('aria-expanded', 'false');
});
tabContents.forEach(tab => tab.classList.remove('active'));
button.classList.add('active');
button.setAttribute('aria-expanded', 'true');
document.getElementById(button.dataset.tab).classList.add('active');
});
});
n8nPasswordInput.addEventListener('input', () => {
fetchSitesButton.disabled = n8nPasswordInput.value.length < 4;
});
// Trigger fetchSites() on Enter key press
n8nPasswordInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && n8nPasswordInput.value.length >= 4) {
fetchSites(); // Call the fetchSites function
}
});
async function fetchSites() {
const password = document.getElementById('n8nPassword').value;
const dropdown = document.getElementById('dattoRmmDropdown');
if (!password) {
appendLog("Please enter the n8n password.", "red");
return;
}
try {
appendLog("Fetching sites...", "yellow");
const response = await fetch('/getn8npw', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password })
});
if (!response.ok) {
throw new Error('Failed to fetch sites. Please try again.');
}
const sites = await response.json();
dropdown.innerHTML = '';
sites.forEach(site => {
const option = document.createElement('option');
// Adjust property names based on your actual data
option.value = site.UID;
option.textContent = site.Name;
dropdown.appendChild(option);
});
appendLog("Sites fetched successfully, please select a site!", "green");
}
catch (error) {
dropdown.innerHTML = '<option value="">Fetching sites failed</option>';
appendLog('Error:' + error.message, "red");
}
}
function triggerInstall() {
const dropdown = document.getElementById('dattoRmmDropdown');
const UID = dropdown && dropdown.options[dropdown.selectedIndex]
? dropdown.options[dropdown.selectedIndex].value
: null;
const Name = dropdown && dropdown.options[dropdown.selectedIndex]
? dropdown.options[dropdown.selectedIndex].text
: null;
(async () => {
// Priority 1: Install SVSMSP Module
if (document.querySelector('input[name="installSVSMSPModule"]').checked) {
appendLog("Installing SVSMSP Module (Priority 1)...", "cyan");
try {
await fetch('/installSVSMSPModule', { method: 'GET' });
appendLog("SVSMSP Module installation completed.", "green");
} catch (error) {
appendLog("Error installing SVSMSP Module: " + error.message, "red");
}
}
// Priority 2: Install DattoRMM
if (document.querySelector('input[name="installDattoRMM"]').checked) {
appendLog("Installing DattoRMM (Priority 2)...", "cyan");
try {
const DattoRMMCheckbox = document.querySelectorAll('input[name="dattoRMMOption"]:checked');
const checkedValues = Array.from(DattoRMMCheckbox).map(c => c.value);
const payload = {
checkedValues,
UID,
Name
};
await fetch('/installrmm', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
appendLog("DattoRMM installation completed.", "green");
} catch (error) {
appendLog("Error installing DattoRMM: " + error.message, "red");
}
}
// Priority 3: Other tasks
if (document.querySelector('input[name="setSVSPowerplan"]').checked) {
appendLog("Setting SVS Powerplan (Priority 3)...", "cyan");
try {
await fetch('/SetSVSPowerplan', { method: 'GET' });
appendLog("SVS Powerplan set successfully.", "green");
} catch (error) {
appendLog("Error setting SVS Powerplan: " + error.message, "red");
}
}
if (document.querySelector('input[name="installCyberQP"]').checked) {
appendLog("Installing CyberQP (Priority 3)...", "cyan");
try {
await fetch('/installCyberQP', { method: 'GET' });
appendLog("CyberQP installation completed.", "green");
} catch (error) {
appendLog("Error installing CyberQP: " + error.message, "red");
}
}
if (document.querySelector('input[name="installSplashtop"]').checked) {
appendLog("Installing Splashtop (Priority 3)...", "cyan");
try {
await fetch('/installSplashtop', { method: 'GET' });
appendLog("Splashtop installation completed.", "green");
} catch (error) {
appendLog("Error installing Splashtop: " + error.message, "red");
}
}
if (document.querySelector('input[name="installSVSHelpDesk"]').checked) {
appendLog("Installing SVS HelpDesk (Priority 3)...", "cyan");
try {
await fetch('/installSVSHelpDesk', { method: 'GET' });
appendLog("SVS HelpDesk installation completed.", "green");
} catch (error) {
appendLog("Error installing SVS HelpDesk: " + error.message, "red");
}
}
if (document.querySelector('input[name="installThreatLocker"]').checked) {
appendLog("Installing ThreatLocker (Priority 3)...", "cyan");
try {
await fetch('/installThreatLocker', { method: 'GET' });
appendLog("ThreatLocker installation completed.", "green");
} catch (error) {
appendLog("Error installing ThreatLocker: " + error.message, "red");
}
}
if (document.querySelector('input[name="installRocketCyber"]').checked) {
appendLog("Installing RocketCyber (Priority 3)...", "cyan");
try {
await fetch('/installRocketCyber', { method: 'GET' });
appendLog("RocketCyber installation completed.", "green");
} catch (error) {
appendLog("Error installing RocketCyber: " + error.message, "red");
}
}
// NEW: Set Edge Default Search Engine
if (document.querySelector('input[name="setedgedefaultsearch"]').checked) {
appendLog("Setting Edge Default Search Engine (Priority 3)...", "cyan");
try {
await fetch('/setedgedefaultsearch', { method: 'GET' });
appendLog("Edge Default Search Engine set successfully.", "green");
} catch (error) {
appendLog("Error setting Edge Default Search Engine: " + error.message, "red");
}
}
if (document.querySelector('input[name="EnableBitLocker"]').checked) {
appendLog("Enabling BitLocker (Priority 3)...", "cyan");
try {
await fetch('/EnableBitLocker', { method: 'GET' });
appendLog("BitLocker enabled successfully.", "green");
} catch (error) {
appendLog("Error enabling BitLocker: " + error.message, "red");
}
}
})();
}
function endSession() {
appendLog("Session ended. Closing application...", "yellow");
fetch('/quit', { method: 'GET' })
.then(response => {
if (!response.ok) {
throw new Error('Failed to end session');
}
window.close();
})
.catch(error => {
appendLog("Error ending session: " + error.message, "red");
});
}
// Intercept window close or refresh
window.addEventListener('beforeunload', (event) => {
endSession(); // Clean up on window close
});
function appendLog(message, color = "white") {
const log = document.createElement('p');
log.style.color = color;
log.textContent = message;
document.getElementById('logArea').appendChild(log);
}
// -------------------------------------------------------------------
// 3) POLL THE SERVER LOGS (NEW)
// -------------------------------------------------------------------
let lastLogCount = 0;
async function fetchLogs() {
try {
const resp = await fetch('/getLogs');
if (!resp.ok) return;
const logs = await resp.json(); // array of {Timestamp, Level, Message}
// Append only new messages
for (let i = lastLogCount; i < logs.length; i++) {
// We'll display each new line in "white" or a color of your choice
appendLog(logs[i].Message, "white");
}
lastLogCount = logs.length;
} catch (err) {
console.error("Error fetching logs:", err);
}
}
// Poll logs every 3 seconds (feel free to adjust)
setInterval(fetchLogs, 3000);
// -------------------------------------------------------------------
</script>
</body>
</html>
"@
}
# Save and launch the HTML
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") {
$bodyStream = New-Object IO.StreamReader $request.InputStream
$body = $bodyStream.ReadToEnd()
$data = ConvertFrom-Json $body
$password = $data.password
Get-N8nWebhookData -AuthHeaderValue $password
$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
$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()
}
}
"/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 {
# Step 1: Read the Request Body
$bodyStream = New-Object IO.StreamReader $request.InputStream
$body = $bodyStream.ReadToEnd()
$requestData = ConvertFrom-Json $body
# Step 2: Extract Data from the Request
$checkedValues = $requestData.checkedValues
$UID = $requestData.UID
$Name = $requestData.Name
# Step 3: Validate Input
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
}
# Step 4: Build the PowerShell Command Dynamically
$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"
}
# Step 5: Execute the Command
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 {
# Log General Errors
$errorString = "An error occurred while processing the /installrmm request: $($_.Exception.Message)"
Write-LogHybrid -Message $errorString -Level "Error"
$response.StatusCode = 500
$responseString = $errorString
}
# Step 6: Return the Response
$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 {
# Handle Invalid HTTP Methods
$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 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()
}
"/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 = " Set 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()
}
"/offboard" {
if ($request.HttpMethod -eq "POST") {
try {
# Read the Request Body
$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
}
# Process each selected task
foreach ($task in $selectedTasks) {
switch ($task) {
"uninstallSVSMSPModule" { Write-LogHybrid -Message "Uninstalling SVSMSP Module..." -Level "Info"; } #Uninstall-SVSMSP }
"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"
}
}
}
# Return Success Response
$responseString = "Offboarding tasks executed successfully."
$response.StatusCode = 200
} catch {
$responseString = "Error processing offboarding tasks: $($_.Exception.Message)"
$response.StatusCode = 500
}
# Send the Response
$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 {
# Step 1: Read the Request Body
$bodyStream = New-Object IO.StreamReader $request.InputStream
$body = $bodyStream.ReadToEnd()
$requestData = ConvertFrom-Json $body
# Step 2: Validate Input
$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
}
# Step 3: Run Selected Tweaks
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"
#Disable-Animations
}
"optimizePerformanceCheckbox" {
Write-LogHybrid -Message "Running tweak: Optimize Performance" -Level "Info"
#Optimize-Performance
}
"increaseFontSizeCheckbox" {
Write-LogHybrid -Message "Running tweak: Increase Font Size" -Level "Info"
#Increase-FontSize
}
default {
Write-LogHybrid -Message "Unknown tweak: $tweak" -Level "Warning"
}
}
}
# Step 4: Return Success Response
$responseString = "Selected tweaks executed successfully."
$response.StatusCode = 200
} catch {
$responseString = "Error processing tweaks: $($_.Exception.Message)"
$response.StatusCode = 500
}
# Send the Response
$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()
}
}
# ----------------------------------------------------------------
# 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") {
$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 {
$listener.Stop()
$listener.Close()
}