Files
InstaClientPS/main.ps1
Chris Payne df968a5461 Fix naming
2025-07-08 20:36:47 -04:00

305 lines
11 KiB
PowerShell

# main.ps1 (clean, gated execution)
# Ensure MSAL.PS is installed
if (-not (Get-Module -ListAvailable -Name MSAL.PS)) {
try {
Write-Host "[INFO] Installing MSAL.PS..."
Install-Module -Name MSAL.PS -Scope CurrentUser -Force -AllowClobber
} catch {
[System.Windows.MessageBox]::Show("MSAL.PS install failed: $($_.Exception.Message)", "Error")
exit 1
}
}
Import-Module MSAL.PS
Write-Host "[INFO] MSAL.PS module loaded."
# Load config and tool modules
$urls = @{
autotask = "https://git.svstools.com/cpayne/InstaClientPS/raw/branch/main/tools/autotask.ps1"
datto = "https://git.svstools.com/cpayne/InstaClientPS/raw/branch/main/tools/dattormm.ps1"
pax8 = "https://git.svstools.com/cpayne/InstaClientPS/raw/branch/main/tools/pax8.ps1"
config = "https://git.svstools.com/cpayne/InstaClientPS/raw/branch/main/config.ps1"
}
$xamlUrl = "https://git.svstools.com/cpayne/InstaClientPS/raw/branch/main/layout.xaml"
try {
$xamlContent = Invoke-WebRequest -Uri $xamlUrl -UseBasicParsing -ErrorAction Stop
[xml]$xaml = $xamlContent.Content
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
$window = [Windows.Markup.XamlReader]::Load($reader)
if (-not $window) {
Write-Host "[ERROR] Failed to load XAML window."
exit 1
}
Write-Host "[INFO] WPF window loaded."
Write-Host "[INFO] XAML loaded from remote URL."
} catch {
Write-Host ("[ERROR] Failed to load XAML from {0}: {1}" -f $xamlUrl, $_.Exception.Message)
exit 1
}
foreach ($name in $urls.Keys) {
try {
$scriptText = Invoke-WebRequest -Uri $urls[$name] -UseBasicParsing
Invoke-Expression $scriptText.Content
Write-Host "[INFO] Loaded $name.ps1 from URL."
} catch {
Write-Host "[ERROR] Failed to load $name.ps1: $($_.Exception.Message)"
exit 1
}
}
Write-Host "[INFO] Config and tool modules loaded."
# Load WPF assemblies
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
Add-Type -AssemblyName WindowsBase
Add-Type -AssemblyName System.Xaml
# Map named UI controls
$CompanyNameBox = $window.FindName("CompanyNameBox")
$PhoneBox = $window.FindName("PhoneBox")
$SelectAllBox = $window.FindName("SelectAllBox")
$AutotaskBox = $window.FindName("AutotaskBox")
$DattoBox = $window.FindName("DattoBox")
$BackupBox = $window.FindName("BackupBox")
$ITGlueBox = $window.FindName("ITGlueBox")
$RocketcyberBox = $window.FindName("RocketcyberBox")
$CyberQPBox = $window.FindName("CyberQPBox")
$Pax8Box = $window.FindName("Pax8Box")
$LoginBtn = $window.FindName("LoginBtn")
$SubmitBtn = $window.FindName("SubmitBtn")
$StatusBlock = $window.FindName("StatusBlock")
$phoneLabel = $window.FindName("PhoneLabel")
$companyLabel = $window.FindName("CompanyLabel")
$websiteBox = $window.FindName("WebsiteBox")
$streetBox = $window.FindName("StreetBox")
$cityBox = $window.FindName("CityBox")
$provinceBox = $window.FindName("ProvinceBox")
$postalCodeBox = $window.FindName("PostalCodeBox")
$countryBox = $window.FindName("CountyBox")
$websiteLabel = $window.FindName("WebsiteLabel")
$streetLabel = $window.FindName("StreetLabel")
$cityLabel = $window.FindName("CityLabel")
$provinceLabel = $window.FindName("ProvinceLabel")
$postalCodeLabel = $window.FindName("PostalCodeLabel")
$countryLabel = $window.FindName("CountyLabel")
$PhoneBox.Visibility = 'Collapsed'
$phoneLabel.Visibility = 'Collapsed'
$SubmitBtn.Visibility = 'Collapsed'
$DattoBox.Visibility = 'Collapsed'
$AutotaskBox.Visibility = 'Collapsed'
$BackupBox.Visibility = 'Collapsed'
$ITGlueBox.Visibility = 'Collapsed'
$RocketcyberBox.Visibility = 'Collapsed'
$CyberQPBox.Visibility = 'Collapsed'
$Pax8Box.Visibility = 'Collapsed'
$SelectAllBox.Visibility = 'Collapsed'
$CompanyNameBox.Visibility = 'Collapsed'
$companyLabel.Visibility = 'Collapsed'
$websiteBox.Visibility = 'Collapsed'
$websiteLabel.Visibility = 'Collapsed'
$streetBox.Visibility = 'Collapsed'
$streetLabel.Visibility = 'Collapsed'
$cityBox.Visibility = 'Collapsed'
$cityLabel.Visibility = 'Collapsed'
$provinceBox.Visibility = 'Collapsed'
$provinceLabel.Visibility = 'Collapsed'
$postalCodeBox.Visibility = 'Collapsed'
$postalCodeLabel.Visibility = 'Collapsed'
$countryBox.Visibility = 'Collapsed'
$countryLabel.Visibility = 'Collapsed'
$BackupBox.IsEnabled = $false
$ITGlueBox.IsEnabled = $false
$RocketcyberBox.IsEnabled = $false
$CyberQPBox.IsEnabled = $false
$AutotaskBox.Add_Checked({
$PhoneBox.Visibility = 'Visible'
$phoneLabel.Visibility = 'Visible'
})
$AutotaskBox.Add_Unchecked({
$PhoneBox.Visibility = 'Collapsed'
$phoneLabel.Visibility = 'Collapsed'
})
$Pax8Box.Add_Checked({
$PhoneBox.Visibility = 'Visible'
$phoneLabel.Visibility = 'Visible'
$websiteBox.Visibility = 'Visible'
$websiteLabel.Visibility = 'Visible'
$streetBox.Visibility = 'Visible'
$streetLabel.Visibility = 'Visible'
$cityBox.Visibility = 'Visible'
$cityLabel.Visibility = 'Visible'
$provinceBox.Visibility = 'Visible'
$provinceLabel.Visibility = 'Visible'
$postalCodeBox.Visibility = 'Visible'
$postalLabel.Visibility = 'Visible'
$countryBox.Visibility = 'Visible'
$countryLabel.Visibility = 'Visible'
})
$Pax8Box.Add_Unchecked({
$PhoneBox.Visibility = 'Collapsed'
$phoneLabel.Visibility = 'Collapsed'
$websiteBox.Visibility = 'Collapsed'
$websiteLabel.Visibility = 'Collapsed'
$streetBox.Visibility = 'Collapsed'
$streetLabel.Visibility = 'Collapsed'
$cityBox.Visibility = 'Collapsed'
$cityLabel.Visibility = 'Collapsed'
$provinceBox.Visibility = 'Collapsed'
$provinceLabel.Visibility = 'Collapsed'
$postalCodeBox.Visibility = 'Collapsed'
$postalLabel.Visibility = 'Collapsed'
$countryBox.Visibility = 'Collapsed'
$countryLabel.Visibility = 'Collapsed'
})
Write-Host "[INFO] UI control references assigned."
# Global tool credentials
$script:toolCredentials = $null
# Select All logic
$SelectAllBox.Add_Checked({
$AutotaskBox.IsChecked = $true
$DattoBox.IsChecked = $true
Write-Host "[UI] Select All: Checked"
})
$SelectAllBox.Add_Unchecked({
$AutotaskBox.IsChecked = $false
$DattoBox.IsChecked = $false
Write-Host "[UI] Select All: Unchecked"
})
# Login logic
$LoginBtn.Add_Click({
Write-Host "[LOGIN] Initiating login..."
try {
$auth = Get-MSALToken -ClientId $CLIENT_ID -TenantId $TENANT_ID -Scopes $SCOPES -Interactive
Write-Host "[LOGIN] Token acquired."
if (-not $auth.AccessToken) {
Write-Host "[ERROR] No access token returned."
[System.Windows.MessageBox]::Show("Login failed.", "Auth")
return
}
$tenantId = $auth.TenantId
Write-Host "[DEBUG] Tenant ID: $tenantId"
if (-not $tenantId) {
[System.Windows.MessageBox]::Show("Tenant ID missing from login result.", "Auth Error")
return
}
$headers = @{ "Content-Type" = "application/json" }
$body = @{ tenant_id = $tenantId } | ConvertTo-Json -Depth 2
Write-Host "[DEBUG] Webhook payload: $body"
$response = Invoke-RestMethod -Uri $WEBHOOK_URL -Method POST -Headers $headers -Body $body
if (-not $response) {
Write-Host "[ERROR] Webhook returned no data."
[System.Windows.MessageBox]::Show("Unauthorized tenant or empty webhook response.", "Auth")
return
}
if ($response -is [pscustomobject]) {
$script:toolCredentials = @{}
foreach ($property in $response.PSObject.Properties) {
$script:toolCredentials[$property.Name] = $property.Value
}
} else {
Write-Host "[ERROR] Webhook returned non-object data: $response"
[System.Windows.MessageBox]::Show("Invalid webhook response.", "Auth")
return
}
$DattoBox.Visibility = 'Visible'
$AutotaskBox.Visibility = 'Visible'
$SelectAllBox.Visibility = 'Visible'
$CompanyNameBox.Visibility = 'Visible'
$companyLabel.Visibility = 'Visible'
$SubmitBtn.Visibility = 'Visible'
$BackupBox.Visibility = 'Visible'
$ITGlueBox.Visibility = 'Visible'
$RocketcyberBox.Visibility = 'Visible'
$CyberQPBox.Visibility = 'Visible'
$Pax8Box.Visibility = 'Visible'
$LoginBtn.Visibility = 'Collapsed'
Write-Host "[INFO] Login and webhook successful."
[System.Windows.MessageBox]::Show("Login successful.", "Auth")
}
catch {
Write-Host "[ERROR] Login/Webhook exception: $($_.Exception.Message)"
[System.Windows.MessageBox]::Show("Login/Webhook error: $($_.Exception.Message)", "Error")
}
})
# Submit logic
$SubmitBtn.Add_Click({
$company = $CompanyNameBox.Text.Trim()
$phone = $PhoneBox.Text.Trim()
$StatusBlock.Text = ""
Write-Host "[SUBMIT] Provisioning start"
Write-Host "[DEBUG] Company: $company"
Write-Host "[DEBUG] Phone: $phone"
Write-Host "[DEBUG] Autotask selected: $($AutotaskBox.IsChecked)"
Write-Host "[DEBUG] Datto selected: $($DattoBox.IsChecked)"
Write-Host "[DEBUG] Tool Credentials: $($script:toolCredentials | ConvertTo-Json -Depth 4)"
if (-not $company) {
[System.Windows.MessageBox]::Show("Please enter a company name.", "Missing Info")
return
}
if ($AutotaskBox.IsChecked -and ($phone -notmatch "^[\d\s\-\+\(\)]{10,}$")) {
[System.Windows.MessageBox]::Show("Valid phone number required for Autotask.", "Invalid Input")
return
}
$StatusBlock.Text = "Provisioning in progress..."
$window.Dispatcher.Invoke("Background", [action]{ $window.UpdateLayout() })
try {
if ($AutotaskBox.IsChecked) {
Write-Host "[INFO] Provisioning Autotask..."
Invoke-AutotaskProvision -CompanyName $company -PhoneNumber $phone -Credentials $script:toolCredentials
}
if ($DattoBox.IsChecked) {
Write-Host "[INFO] Provisioning Datto RMM..."
Invoke-DattoProvision -CompanyName $company -Credentials $script:toolCredentials
}
if ($Pax8Box.IsChecked) {
Write-Host "[INFO] Provisioning Pax8..."
Invoke-Pax8Provision -CompanyName $company -Phone $phone -Website $WebsiteBox.Text.Trim() -Street $StreetBox.Text.Trim() -City $CityBox.Text.Trim() -Province $ProvinceBox.Text.Trim() -PostalCode $PostalCodeBox.Text.Trim() -Country $CountryBox.Text.Trim() -Credentials $script:toolCredentials
}
$StatusBlock.Text = "Provisioning completed successfully."
Write-Host "[SUCCESS] Provisioning complete."
$CompanyNameBox.Text = ""
$PhoneBox.Text = ""
$SelectAllBox.IsChecked = $false
}
catch {
Write-Host "[ERROR] Provisioning failed: $($_.Exception.Message)"
$StatusBlock.Text = "Provisioning failed: $($_.Exception.Message)"
}
})
# Show the window
$window.ShowDialog() | Out-Null