Attempt to add more data for autotask

This commit is contained in:
Chris Payne
2025-07-08 21:06:00 -04:00
parent 9e21feb741
commit 8cb90b71db
2 changed files with 219 additions and 217 deletions

224
main.ps1
View File

@@ -1,11 +1,12 @@
# main.ps1 (clean, gated execution) # main.ps1
# Ensure MSAL.PS is installed # Ensure MSAL.PS is installed
if (-not (Get-Module -ListAvailable -Name MSAL.PS)) { if (-not (Get-Module -ListAvailable -Name MSAL.PS)) {
try { try {
Write-Host "[INFO] Installing MSAL.PS..." Write-Host "[INFO] Installing MSAL.PS..."
Install-Module -Name MSAL.PS -Scope CurrentUser -Force -AllowClobber Install-Module -Name MSAL.PS -Scope CurrentUser -Force -AllowClobber
} catch { }
catch {
[System.Windows.MessageBox]::Show("MSAL.PS install failed: $($_.Exception.Message)", "Error") [System.Windows.MessageBox]::Show("MSAL.PS install failed: $($_.Exception.Message)", "Error")
exit 1 exit 1
} }
@@ -31,21 +32,21 @@ try {
if (-not $window) { if (-not $window) {
Write-Host "[ERROR] Failed to load XAML window." Write-Host "[ERROR] Failed to load XAML window."
exit 1 exit 1
}
Write-Host "[INFO] WPF window loaded."
} }
Write-Host "[INFO] WPF window loaded." catch {
Write-Host "[INFO] XAML loaded from remote URL."
} catch {
Write-Host ("[ERROR] Failed to load XAML from {0}: {1}" -f $xamlUrl, $_.Exception.Message) Write-Host ("[ERROR] Failed to load XAML from {0}: {1}" -f $xamlUrl, $_.Exception.Message)
exit 1 exit 1
} }
foreach ($name in $urls.Keys) { foreach ($name in $urls.Keys) {
try { try {
$scriptText = Invoke-WebRequest -Uri $urls[$name] -UseBasicParsing $scriptText = Invoke-WebRequest -Uri $urls[$name] -UseBasicParsing
Invoke-Expression $scriptText.Content Invoke-Expression $scriptText.Content
Write-Host "[INFO] Loaded $name.ps1 from URL." Write-Host "[INFO] Loaded $name.ps1 from URL."
} catch { }
catch {
Write-Host "[ERROR] Failed to load $name.ps1: $($_.Exception.Message)" Write-Host "[ERROR] Failed to load $name.ps1: $($_.Exception.Message)"
exit 1 exit 1
} }
@@ -73,31 +74,31 @@ $Pax8Box = $window.FindName("Pax8Box")
$LoginBtn = $window.FindName("LoginBtn") $LoginBtn = $window.FindName("LoginBtn")
$SubmitBtn = $window.FindName("SubmitBtn") $SubmitBtn = $window.FindName("SubmitBtn")
$StatusBlock = $window.FindName("StatusBlock") $StatusBlock = $window.FindName("StatusBlock")
$websiteBox = $window.FindName("WebsiteBox") $WebsiteBox = $window.FindName("WebsiteBox")
$streetBox = $window.FindName("StreetBox") $StreetBox = $window.FindName("StreetBox")
$cityBox = $window.FindName("CityBox") $CityBox = $window.FindName("CityBox")
$provinceBox = $window.FindName("ProvinceBox") $ProvinceBox = $window.FindName("ProvinceBox")
$postalCodeBox = $window.FindName("PostalCodeBox") $PostalCodeBox = $window.FindName("PostalCodeBox")
$countryBox = $window.FindName("CountryBox") $CountryBox = $window.FindName("CountryBox")
# Collapse until tools selected
$CompanyNameBox.Visibility = 'Collapsed'
$PhoneBox.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' $SubmitBtn.Visibility = 'Collapsed'
$DattoBox.Visibility = 'Collapsed'
$AutotaskBox.Visibility = 'Collapsed' $AutotaskBox.Visibility = 'Collapsed'
$DattoBox.Visibility = 'Collapsed'
$BackupBox.Visibility = 'Collapsed' $BackupBox.Visibility = 'Collapsed'
$ITGlueBox.Visibility = 'Collapsed' $ITGlueBox.Visibility = 'Collapsed'
$RocketcyberBox.Visibility = 'Collapsed' $RocketcyberBox.Visibility = 'Collapsed'
$CyberQPBox.Visibility = 'Collapsed' $CyberQPBox.Visibility = 'Collapsed'
$Pax8Box.Visibility = 'Collapsed' $Pax8Box.Visibility = 'Collapsed'
$SelectAllBox.Visibility = 'Collapsed'
$CompanyNameBox.Visibility = 'Collapsed'
$websiteBox.Visibility = 'Collapsed'
$streetBox.Visibility = 'Collapsed'
$cityBox.Visibility = 'Collapsed'
$provinceBox.Visibility = 'Collapsed'
$postalCodeBox.Visibility = 'Collapsed'
$countryBox.Visibility = 'Collapsed'
$BackupBox.IsEnabled = $false $BackupBox.IsEnabled = $false
$ITGlueBox.IsEnabled = $false $ITGlueBox.IsEnabled = $false
@@ -106,45 +107,45 @@ $CyberQPBox.IsEnabled = $false
$AutotaskBox.Add_Checked({ $AutotaskBox.Add_Checked({
$PhoneBox.Visibility = 'Visible' $PhoneBox.Visibility = 'Visible'
$websiteBox.Visibility = 'Visible' $WebsiteBox.Visibility = 'Visible'
$streetBox.Visibility = 'Visible' $StreetBox.Visibility = 'Visible'
$cityBox.Visibility = 'Visible' $CityBox.Visibility = 'Visible'
$provinceBox.Visibility = 'Visible' $ProvinceBox.Visibility = 'Visible'
$postalCodeBox.Visibility = 'Visible' $PostalCodeBox.Visibility = 'Visible'
$countryBox.Visibility = 'Visible' $CountryBox.Visibility = 'Visible'
}) })
$AutotaskBox.Add_Unchecked({ $AutotaskBox.Add_Unchecked({
$PhoneBox.Visibility = 'Collapsed' $PhoneBox.Visibility = 'Collapsed'
$websiteBox.Visibility = 'Collapsed' $WebsiteBox.Visibility = 'Collapsed'
$streetBox.Visibility = 'Collapsed' $StreetBox.Visibility = 'Collapsed'
$cityBox.Visibility = 'Collapsed' $CityBox.Visibility = 'Collapsed'
$provinceBox.Visibility = 'Collapsed' $ProvinceBox.Visibility = 'Collapsed'
$postalCodeBox.Visibility = 'Collapsed' $PostalCodeBox.Visibility = 'Collapsed'
$countryBox.Visibility = 'Collapsed' $CountryBox.Visibility = 'Collapsed'
}) })
$Pax8Box.Add_Checked({ $Pax8Box.Add_Checked({
$PhoneBox.Visibility = 'Visible' $PhoneBox.Visibility = 'Visible'
$websiteBox.Visibility = 'Visible' $WebsiteBox.Visibility = 'Visible'
$streetBox.Visibility = 'Visible' $StreetBox.Visibility = 'Visible'
$cityBox.Visibility = 'Visible' $CityBox.Visibility = 'Visible'
$provinceBox.Visibility = 'Visible' $ProvinceBox.Visibility = 'Visible'
$postalCodeBox.Visibility = 'Visible' $PostalCodeBox.Visibility = 'Visible'
$countryBox.Visibility = 'Visible' $CountryBox.Visibility = 'Visible'
}) })
$Pax8Box.Add_Unchecked({ $Pax8Box.Add_Unchecked({
if (-not $AutotaskBox.IsChecked) {
$PhoneBox.Visibility = 'Collapsed' $PhoneBox.Visibility = 'Collapsed'
$websiteBox.Visibility = 'Collapsed' $WebsiteBox.Visibility = 'Collapsed'
$streetBox.Visibility = 'Collapsed' $StreetBox.Visibility = 'Collapsed'
$cityBox.Visibility = 'Collapsed' $CityBox.Visibility = 'Collapsed'
$provinceBox.Visibility = 'Collapsed' $ProvinceBox.Visibility = 'Collapsed'
$postalCodeBox.Visibility = 'Collapsed' $PostalCodeBox.Visibility = 'Collapsed'
$countryBox.Visibility = 'Collapsed' $CountryBox.Visibility = 'Collapsed'
}) }
})
Write-Host "[INFO] UI control references assigned."
# Global tool credentials # Global tool credentials
$script:toolCredentials = $null $script:toolCredentials = $null
@@ -153,55 +154,35 @@ $script:toolCredentials = $null
$SelectAllBox.Add_Checked({ $SelectAllBox.Add_Checked({
$AutotaskBox.IsChecked = $true $AutotaskBox.IsChecked = $true
$DattoBox.IsChecked = $true $DattoBox.IsChecked = $true
Write-Host "[UI] Select All: Checked" })
})
$SelectAllBox.Add_Unchecked({ $SelectAllBox.Add_Unchecked({
$AutotaskBox.IsChecked = $false $AutotaskBox.IsChecked = $false
$DattoBox.IsChecked = $false $DattoBox.IsChecked = $false
Write-Host "[UI] Select All: Unchecked" })
})
# Login logic # Login handler
$LoginBtn.Add_Click({ $LoginBtn.Add_Click({
Write-Host "[LOGIN] Initiating login..."
try { try {
$auth = Get-MSALToken -ClientId $CLIENT_ID -TenantId $TENANT_ID -Scopes $SCOPES -Interactive $auth = Get-MSALToken -ClientId $CLIENT_ID -TenantId $TENANT_ID -Scopes $SCOPES -Interactive
Write-Host "[LOGIN] Token acquired."
if (-not $auth.AccessToken) { if (-not $auth.AccessToken) {
Write-Host "[ERROR] No access token returned."
[System.Windows.MessageBox]::Show("Login failed.", "Auth") [System.Windows.MessageBox]::Show("Login failed.", "Auth")
return 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" } $headers = @{ "Content-Type" = "application/json" }
$body = @{ tenant_id = $tenantId } | ConvertTo-Json -Depth 2 $body = @{ tenant_id = $auth.TenantId } | ConvertTo-Json -Depth 2
Write-Host "[DEBUG] Webhook payload: $body"
$response = Invoke-RestMethod -Uri $WEBHOOK_URL -Method POST -Headers $headers -Body $body $response = Invoke-RestMethod -Uri $WEBHOOK_URL -Method POST -Headers $headers -Body $body
if (-not $response) { if (-not $response -or $response -isnot [pscustomobject]) {
Write-Host "[ERROR] Webhook returned no data." [System.Windows.MessageBox]::Show("Unauthorized or invalid response.", "Auth")
[System.Windows.MessageBox]::Show("Unauthorized tenant or empty webhook response.", "Auth")
return return
} }
if ($response -is [pscustomobject]) {
$script:toolCredentials = @{} $script:toolCredentials = @{}
foreach ($property in $response.PSObject.Properties) { foreach ($p in $response.PSObject.Properties) {
$script:toolCredentials[$property.Name] = $property.Value $script:toolCredentials[$p.Name] = $p.Value
}
} else {
Write-Host "[ERROR] Webhook returned non-object data: $response"
[System.Windows.MessageBox]::Show("Invalid webhook response.", "Auth")
return
} }
$DattoBox.Visibility = 'Visible' $DattoBox.Visibility = 'Visible'
@@ -216,55 +197,77 @@ $LoginBtn.Add_Click({
$Pax8Box.Visibility = 'Visible' $Pax8Box.Visibility = 'Visible'
$LoginBtn.Visibility = 'Collapsed' $LoginBtn.Visibility = 'Collapsed'
Write-Host "[INFO] Login and webhook successful."
[System.Windows.MessageBox]::Show("Login successful.", "Auth") [System.Windows.MessageBox]::Show("Login successful.", "Auth")
} }
catch { catch {
Write-Host "[ERROR] Login/Webhook exception: $($_.Exception.Message)" [System.Windows.MessageBox]::Show("Login error: $($_.Exception.Message)", "Error")
[System.Windows.MessageBox]::Show("Login/Webhook error: $($_.Exception.Message)", "Error")
} }
}) })
# Submit logic # Submit handler
$SubmitBtn.Add_Click({ $SubmitBtn.Add_Click({
$company = $CompanyNameBox.Text.Trim() $company = $CompanyNameBox.Text.Trim()
$phone = $PhoneBox.Text.Trim() $phone = $PhoneBox.Text.Trim()
$StatusBlock.Text = ""
Write-Host "[SUBMIT] Provisioning start" $website = $WebsiteBox.Text.Trim()
Write-Host "[DEBUG] Tool Credentials: $($script:toolCredentials | ConvertTo-Json -Depth 4)" $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) { if (-not $company) {
[System.Windows.MessageBox]::Show("Please enter a company name.", "Missing Info") [System.Windows.MessageBox]::Show("Company Name is required.", "Missing Info")
return return
} }
if ($AutotaskBox.IsChecked -and ($phone -notmatch "^[\d\s\-\+\(\)]{10,}$")) { # Required if Autotask or Pax8 selected
[System.Windows.MessageBox]::Show("Valid phone number required for Autotask.", "Invalid Input") if ($autotaskChecked -or $pax8Checked) {
if ($phone -notmatch "^[\d\s\-\+\(\)]{10,}$") {
[System.Windows.MessageBox]::Show("Valid phone number is required.", "Invalid Input")
return 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..." $StatusBlock.Text = "Provisioning in progress..."
$window.Dispatcher.Invoke("Background", [action]{ $window.UpdateLayout() }) $window.Dispatcher.Invoke("Background", [action] { $window.UpdateLayout() })
try { try {
if ($AutotaskBox.IsChecked) { if ($AutotaskBox.IsChecked) {
Write-Host "[INFO] Provisioning Autotask..." Invoke-AutotaskProvision -CompanyName $company `
Invoke-AutotaskProvision -CompanyName $company -PhoneNumber $phone -Credentials $script:toolCredentials -PhoneNumber $phone `
} -Website $WebsiteBox.Text.Trim() `
-Street $StreetBox.Text.Trim() `
if ($DattoBox.IsChecked) { -City $CityBox.Text.Trim() `
Write-Host "[INFO] Provisioning Datto RMM..." -Province $ProvinceBox.Text.Trim() `
Invoke-DattoProvision -CompanyName $company -Credentials $script:toolCredentials -PostalCode $PostalCodeBox.Text.Trim() `
} -Country "Canada" `
-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." $StatusBlock.Text = "Provisioning completed successfully."
Write-Host "[SUCCESS] Provisioning complete." Write-Host "[SUCCESS] Provisioning complete."
# Reset fields
$CompanyNameBox.Text = "" $CompanyNameBox.Text = ""
$PhoneBox.Text = "" $PhoneBox.Text = ""
$WebsiteBox.Text = "" $WebsiteBox.Text = ""
@@ -273,21 +276,14 @@ $SubmitBtn.Add_Click({
$CityBox.Text = "" $CityBox.Text = ""
$ProvinceBox.Text = "" $ProvinceBox.Text = ""
$PostalCodeBox.Text = "" $PostalCodeBox.Text = ""
$SelectAllBox.IsChecked = $false $SelectAllBox.IsChecked = $false
$AutotaskBox.IsChecked = $false $AutotaskBox.IsChecked = $false
$DattoBox.IsChecked = $false $DattoBox.IsChecked = $false
$ITGlueBox.IsChecked = $false
$BackupBox.IsChecked = $false
$RocketcyberBox.IsChecked = $false
$CyberQPBox.IsChecked = $false
$Pax8Box.IsChecked = $false
} }
catch { catch {
Write-Host "[ERROR] Provisioning failed: $($_.Exception.Message)"
$StatusBlock.Text = "Provisioning failed: $($_.Exception.Message)" $StatusBlock.Text = "Provisioning failed: $($_.Exception.Message)"
} }
}) })
# Show the window # Show window
$window.ShowDialog() | Out-Null $window.ShowDialog() | Out-Null

View File

@@ -1,21 +1,21 @@
function Invoke-AutotaskProvision { function Invoke-AutotaskProvision {
param ( param (
[Parameter(Mandatory)] [Parameter(Mandatory)][string]$CompanyName,
[string]$CompanyName, [Parameter(Mandatory)][string]$PhoneNumber,
[string]$Website,
[Parameter(Mandatory)] [string]$Street,
[string]$PhoneNumber, [string]$City,
[string]$Province,
[Parameter(Mandatory)] [string]$PostalCode,
[hashtable]$Credentials [string]$Country,
[Parameter(Mandatory)][hashtable]$Credentials
) )
if (-not $Credentials["AutotaskURL"] -or -not $Credentials["AutotaskIntCode"] -or -not $Credentials["AutotaskUsername"] -or -not $Credentials["AutotaskSecret"]) { if (-not $Credentials["AutotaskURL"] -or -not $Credentials["AutotaskIntCode"] -or -not $Credentials["AutotaskUsername"] -or -not $Credentials["AutotaskSecret"]) {
throw "Missing Autotask credentials in hashtable." throw "Missing Autotask credentials in hashtable."
} }
$BaseURL = $Credentials["AutotaskURL"] $Url = "https://$($Credentials["AutotaskURL"])/atservicesrest/v1.0/companies"
$Url = "https://$BaseURL/atservicesrest/v1.0/companies"
$Headers = @{ $Headers = @{
"ApiIntegrationcode" = $Credentials["AutotaskIntCode"] "ApiIntegrationcode" = $Credentials["AutotaskIntCode"]
@@ -28,12 +28,18 @@ function Invoke-AutotaskProvision {
companyName = $CompanyName companyName = $CompanyName
companyType = 1 companyType = 1
phone = $PhoneNumber phone = $PhoneNumber
website = $Website
address1 = $Street
city = $City
state = $Province
postalCode = $PostalCode
countryID = 38 # Statically set to Canada
ownerResourceID = 4 ownerResourceID = 4
} | ConvertTo-Json -Depth 3 } | ConvertTo-Json -Depth 3
try { try {
$Response = Invoke-RestMethod -Uri $Url -Method Post -Headers $Headers -Body $Body $Response = Invoke-RestMethod -Uri $Url -Method Post -Headers $Headers -Body $Body
$Response.itemId, $Response.id, $Response.companyID, $Response.item.id | Where-Object { $_ } | Select-Object -First 1 return $Response.itemId, $Response.id, $Response.companyID, $Response.item.id | Where-Object { $_ } | Select-Object -First 1
} catch { } catch {
throw "[Autotask] Provisioning failed: $($_.Exception.Message)" throw "[Autotask] Provisioning failed: $($_.Exception.Message)"
} }