292 lines
9.9 KiB
PowerShell
292 lines
9.9 KiB
PowerShell
# main.ps1
|
|
|
|
# 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."
|
|
}
|
|
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")
|
|
$WebsiteBox = $window.FindName("WebsiteBox")
|
|
$StreetBox = $window.FindName("StreetBox")
|
|
$CityBox = $window.FindName("CityBox")
|
|
$ProvinceBox = $window.FindName("ProvinceBox")
|
|
$PostalCodeBox = $window.FindName("PostalCodeBox")
|
|
$CountryBox = $window.FindName("CountryBox")
|
|
|
|
# Collapse until tools selected
|
|
$CompanyNameBox.Visibility = 'Collapsed'
|
|
$PhoneBox.Visibility = 'Collapsed'
|
|
$WebsiteBox.Visibility = 'Collapsed'
|
|
$StreetBox.Visibility = 'Collapsed'
|
|
$CityBox.Visibility = 'Collapsed'
|
|
$ProvinceBox.Visibility = 'Collapsed'
|
|
$PostalCodeBox.Visibility = 'Collapsed'
|
|
$CountryBox.Visibility = 'Collapsed'
|
|
$SelectAllBox.Visibility = 'Collapsed'
|
|
$SubmitBtn.Visibility = 'Collapsed'
|
|
$AutotaskBox.Visibility = 'Collapsed'
|
|
$DattoBox.Visibility = 'Collapsed'
|
|
$BackupBox.Visibility = 'Collapsed'
|
|
$ITGlueBox.Visibility = 'Collapsed'
|
|
$RocketcyberBox.Visibility = 'Collapsed'
|
|
$CyberQPBox.Visibility = 'Collapsed'
|
|
$Pax8Box.Visibility = 'Collapsed'
|
|
|
|
$BackupBox.IsEnabled = $false
|
|
$ITGlueBox.IsEnabled = $false
|
|
$RocketcyberBox.IsEnabled = $false
|
|
$CyberQPBox.IsEnabled = $false
|
|
|
|
$CountryBox.IsEnabled = $false
|
|
|
|
$AutotaskBox.Add_Checked({
|
|
$PhoneBox.Visibility = 'Visible'
|
|
$WebsiteBox.Visibility = 'Visible'
|
|
$StreetBox.Visibility = 'Visible'
|
|
$CityBox.Visibility = 'Visible'
|
|
$ProvinceBox.Visibility = 'Visible'
|
|
$PostalCodeBox.Visibility = 'Visible'
|
|
$CountryBox.Visibility = 'Visible'
|
|
})
|
|
|
|
$AutotaskBox.Add_Unchecked({
|
|
$PhoneBox.Visibility = 'Collapsed'
|
|
$WebsiteBox.Visibility = 'Collapsed'
|
|
$StreetBox.Visibility = 'Collapsed'
|
|
$CityBox.Visibility = 'Collapsed'
|
|
$ProvinceBox.Visibility = 'Collapsed'
|
|
$PostalCodeBox.Visibility = 'Collapsed'
|
|
$CountryBox.Visibility = 'Collapsed'
|
|
})
|
|
|
|
$Pax8Box.Add_Checked({
|
|
$PhoneBox.Visibility = 'Visible'
|
|
$WebsiteBox.Visibility = 'Visible'
|
|
$StreetBox.Visibility = 'Visible'
|
|
$CityBox.Visibility = 'Visible'
|
|
$ProvinceBox.Visibility = 'Visible'
|
|
$PostalCodeBox.Visibility = 'Visible'
|
|
$CountryBox.Visibility = 'Visible'
|
|
})
|
|
|
|
$Pax8Box.Add_Unchecked({
|
|
if (-not $AutotaskBox.IsChecked) {
|
|
$PhoneBox.Visibility = 'Collapsed'
|
|
$WebsiteBox.Visibility = 'Collapsed'
|
|
$StreetBox.Visibility = 'Collapsed'
|
|
$CityBox.Visibility = 'Collapsed'
|
|
$ProvinceBox.Visibility = 'Collapsed'
|
|
$PostalCodeBox.Visibility = 'Collapsed'
|
|
$CountryBox.Visibility = 'Collapsed'
|
|
}
|
|
})
|
|
|
|
# Global tool credentials
|
|
$script:toolCredentials = $null
|
|
|
|
# Select All logic
|
|
$SelectAllBox.Add_Checked({
|
|
$AutotaskBox.IsChecked = $true
|
|
$DattoBox.IsChecked = $true
|
|
})
|
|
$SelectAllBox.Add_Unchecked({
|
|
$AutotaskBox.IsChecked = $false
|
|
$DattoBox.IsChecked = $false
|
|
})
|
|
|
|
# Login handler
|
|
$LoginBtn.Add_Click({
|
|
try {
|
|
$auth = Get-MSALToken -ClientId $CLIENT_ID -TenantId $TENANT_ID -Scopes $SCOPES -Interactive
|
|
|
|
if (-not $auth.AccessToken) {
|
|
[System.Windows.MessageBox]::Show("Login failed.", "Auth")
|
|
return
|
|
}
|
|
|
|
$headers = @{ "Content-Type" = "application/json" }
|
|
$body = @{ tenant_id = $auth.TenantId } | ConvertTo-Json -Depth 2
|
|
|
|
$response = Invoke-RestMethod -Uri $WEBHOOK_URL -Method POST -Headers $headers -Body $body
|
|
|
|
if (-not $response -or $response -isnot [pscustomobject]) {
|
|
[System.Windows.MessageBox]::Show("Unauthorized or invalid response.", "Auth")
|
|
return
|
|
}
|
|
|
|
$script:toolCredentials = @{}
|
|
foreach ($p in $response.PSObject.Properties) {
|
|
$script:toolCredentials[$p.Name] = $p.Value
|
|
}
|
|
|
|
$DattoBox.Visibility = 'Visible'
|
|
$AutotaskBox.Visibility = 'Visible'
|
|
$SelectAllBox.Visibility = 'Visible'
|
|
$CompanyNameBox.Visibility = 'Visible'
|
|
$SubmitBtn.Visibility = 'Visible'
|
|
$BackupBox.Visibility = 'Visible'
|
|
$ITGlueBox.Visibility = 'Visible'
|
|
$RocketcyberBox.Visibility = 'Visible'
|
|
$CyberQPBox.Visibility = 'Visible'
|
|
$Pax8Box.Visibility = 'Visible'
|
|
$LoginBtn.Visibility = 'Collapsed'
|
|
|
|
[System.Windows.MessageBox]::Show("Login successful.", "Auth")
|
|
}
|
|
catch {
|
|
[System.Windows.MessageBox]::Show("Login error: $($_.Exception.Message)", "Error")
|
|
}
|
|
})
|
|
|
|
# Submit handler
|
|
$SubmitBtn.Add_Click({
|
|
$company = $CompanyNameBox.Text.Trim()
|
|
$phone = $PhoneBox.Text.Trim()
|
|
|
|
$website = $WebsiteBox.Text.Trim()
|
|
$street = $StreetBox.Text.Trim()
|
|
$city = $CityBox.Text.Trim()
|
|
$province = $ProvinceBox.Text.Trim()
|
|
$postalCode = $PostalCodeBox.Text.Trim()
|
|
$country = $CountryBox.Text.Trim()
|
|
|
|
$autotaskChecked = $AutotaskBox.IsChecked
|
|
$pax8Checked = $Pax8Box.IsChecked
|
|
|
|
# Always required
|
|
if (-not $company) {
|
|
[System.Windows.MessageBox]::Show("Company Name is required.", "Missing Info")
|
|
return
|
|
}
|
|
|
|
# Required if Autotask or Pax8 selected
|
|
if ($autotaskChecked -or $pax8Checked) {
|
|
if ($phone -notmatch "^[\d\s\-\+\(\)]{10,}$") {
|
|
[System.Windows.MessageBox]::Show("Valid phone number is required.", "Invalid Input")
|
|
return
|
|
}
|
|
|
|
$missing = @()
|
|
if (-not $website) { $missing += "Website" }
|
|
if (-not $street) { $missing += "Street" }
|
|
if (-not $city) { $missing += "City" }
|
|
if (-not $province) { $missing += "Province" }
|
|
if (-not $postalCode) { $missing += "Postal Code" }
|
|
if (-not $country) { $missing += "Country" }
|
|
|
|
if ($missing.Count -gt 0) {
|
|
$msg = "Please fill in the following required fields:`n" + ($missing -join "`n")
|
|
[System.Windows.MessageBox]::Show($msg, "Missing Info")
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
$StatusBlock.Text = "Provisioning in progress..."
|
|
$window.Dispatcher.Invoke("Background", [action] { $window.UpdateLayout() })
|
|
|
|
try {
|
|
if ($AutotaskBox.IsChecked) {
|
|
Invoke-AutotaskProvision -CompanyName $company `
|
|
-PhoneNumber $phone `
|
|
-Website $WebsiteBox.Text.Trim() `
|
|
-Street $StreetBox.Text.Trim() `
|
|
-City $CityBox.Text.Trim() `
|
|
-Province $ProvinceBox.Text.Trim() `
|
|
-PostalCode $PostalCodeBox.Text.Trim() `
|
|
-Country "Canada" `
|
|
-Credentials $script:toolCredentials
|
|
}
|
|
|
|
$StatusBlock.Text = "Provisioning completed successfully."
|
|
Write-Host "[SUCCESS] Provisioning complete."
|
|
|
|
# Reset fields
|
|
$CompanyNameBox.Text = ""
|
|
$PhoneBox.Text = ""
|
|
$WebsiteBox.Text = ""
|
|
$StreetBox.Text = ""
|
|
$CountryBox.Text = ""
|
|
$CityBox.Text = ""
|
|
$ProvinceBox.Text = ""
|
|
$PostalCodeBox.Text = ""
|
|
$SelectAllBox.IsChecked = $false
|
|
$AutotaskBox.IsChecked = $false
|
|
$DattoBox.IsChecked = $false
|
|
}
|
|
catch {
|
|
$StatusBlock.Text = "Provisioning failed: $($_.Exception.Message)"
|
|
}
|
|
})
|
|
|
|
# Show window
|
|
$window.ShowDialog() | Out-Null
|