# 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' }) function Update-SharedFieldVisibility { $visible = ($AutotaskBox.IsChecked -or $Pax8Box.IsChecked) $visibility = if ($visible) { 'Visible' } else { 'Collapsed' } $PhoneBox.Visibility = $visibility $WebsiteBox.Visibility = $visibility $StreetBox.Visibility = $visibility $CityBox.Visibility = $visibility $ProvinceBox.Visibility = $visibility $PostalCodeBox.Visibility = $visibility $CountryBox.Visibility = $visibility } $AutotaskBox.Add_Checked( { Update-SharedFieldVisibility }) $AutotaskBox.Add_Unchecked( { Update-SharedFieldVisibility }) $Pax8Box.Add_Checked( { Update-SharedFieldVisibility }) $Pax8Box.Add_Unchecked( { Update-SharedFieldVisibility }) # 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