diff --git a/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1 b/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1 index 9543e90..e99512f 100644 --- a/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1 +++ b/output/PSOPNSenseAPI/PSOPNSenseAPI.psd1 @@ -3,7 +3,7 @@ RootModule = 'lib\PSOPNSenseAPI.dll' # Version number of this module. - ModuleVersion = '2025.04.15.1143' + ModuleVersion = '2025.04.15.1216' # Supported PSEditions CompatiblePSEditions = @('Desktop', 'Core') diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/LICENSE b/release/PSOPNSenseAPI-2025.04.15.1543/LICENSE new file mode 100644 index 0000000..2a38299 --- /dev/null +++ b/release/PSOPNSenseAPI-2025.04.15.1543/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 PSOPNSenseAPI Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/PSOPNSenseAPI.psd1 b/release/PSOPNSenseAPI-2025.04.15.1543/PSOPNSenseAPI.psd1 new file mode 100644 index 0000000..5bce804 --- /dev/null +++ b/release/PSOPNSenseAPI-2025.04.15.1543/PSOPNSenseAPI.psd1 @@ -0,0 +1,213 @@ +@{ + # Script module or binary module file associated with this manifest. + RootModule = 'lib\PSOPNSenseAPI.dll' + + # Version number of this module. + ModuleVersion = '2025.04.15.1543' + + # Supported PSEditions + CompatiblePSEditions = @('Desktop', 'Core') + + # ID used to uniquely identify this module + GUID = '9a3b4c55-5f9a-4b8c-87d9-9a7a5cdd5c9f' + + # Author of this module + Author = 'PSOPNSenseAPI Contributors' + + # Company or vendor of this module + CompanyName = 'PSOPNSenseAPI' + + # Copyright statement for this module + Copyright = '(c) 2025 PSOPNSenseAPI Contributors. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'PowerShell module for interacting with the OPNSense API to configure firewalls' + + # Minimum version of the PowerShell engine required by this module + PowerShellVersion = '5.1' + + # Name of the PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '4.7.2' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + ClrVersion = '4.0' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = @() + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = @( + 'Apply-OPNSenseFirewallChanges', + 'Connect-OPNSense', + 'Connect-OPNSenseTailscale', + 'ConvertTo-OPNSenseNetworkNotation', + 'Disable-OPNSenseCronJob', + 'Disable-OPNSenseFirewallRule', + 'Disable-OPNSensePlugin', + 'Disable-OPNSenseTailscale', + 'Disconnect-OPNSense', + 'Disconnect-OPNSenseTailscale', + 'Enable-OPNSenseCronJob', + 'Enable-OPNSenseFirewallRule', + 'Enable-OPNSensePlugin', + 'Enable-OPNSenseTailscale', + 'Export-OPNSenseConfig', + 'Get-OPNSenseAlias', + 'Get-OPNSenseConfig', + 'Get-OPNSenseConfigBackup', + 'Get-OPNSenseConnection', + 'Get-OPNSenseCronJob', + 'Get-OPNSenseDHCPLease', + 'Get-OPNSenseDHCPOption', + 'Get-OPNSenseDHCPServer', + 'Get-OPNSenseDHCPStaticMapping', + 'Get-OPNSenseDNSForwarding', + 'Get-OPNSenseDNSForwardingHost', + 'Get-OPNSenseDNSOverride', + 'Get-OPNSenseDNSServer', + 'Get-OPNSenseFirewallRule', + 'Get-OPNSenseFirmware', + 'Get-OPNSenseGateway', + 'Get-OPNSenseInterface', + 'Get-OPNSenseInterfaceStatistics', + 'Get-OPNSensePlugin', + 'Get-OPNSensePortForwardingRule', + 'Get-OPNSenseRoute', + 'Get-OPNSenseSystemDNS', + 'Get-OPNSenseTailscaleStatus', + 'Get-OPNSenseUser', + 'Get-OPNSenseVLAN', + 'Import-OPNSenseConfig', + 'Install-OPNSensePlugin', + 'Invoke-OPNSenseNetworkCalculation', + 'New-OPNSenseAlias', + 'New-OPNSenseCronJob', + 'New-OPNSenseDHCPOption', + 'New-OPNSenseDHCPStaticMapping', + 'New-OPNSenseDNSForwardingHost', + 'New-OPNSenseDNSOverride', + 'New-OPNSenseFirewallRule', + 'New-OPNSenseGateway', + 'New-OPNSensePortForwardingRule', + 'New-OPNSenseRoute', + 'New-OPNSenseSubnetVLANs', + 'New-OPNSenseUser', + 'New-OPNSenseVLAN', + 'Remove-OPNSenseAlias', + 'Remove-OPNSenseCronJob', + 'Remove-OPNSenseDHCPLease', + 'Remove-OPNSenseDHCPOption', + 'Remove-OPNSenseDHCPStaticMapping', + 'Remove-OPNSenseDNSForwardingHost', + 'Remove-OPNSenseDNSOverride', + 'Remove-OPNSenseFirewallRule', + 'Remove-OPNSenseGateway', + 'Remove-OPNSensePortForwardingRule', + 'Remove-OPNSenseRoute', + 'Remove-OPNSenseUser', + 'Remove-OPNSenseVLAN', + 'Restart-OPNSenseFirewall', + 'Restart-OPNSenseInterface', + 'Restore-OPNSenseConfig', + 'Set-OPNSenseAlias', + 'Set-OPNSenseCronJob', + 'Set-OPNSenseDHCPOption', + 'Set-OPNSenseDHCPServer', + 'Set-OPNSenseDHCPStaticMapping', + 'Set-OPNSenseDNSForwarding', + 'Set-OPNSenseDNSForwardingHost', + 'Set-OPNSenseDNSServer', + 'Set-OPNSenseFirewallRule', + 'Set-OPNSenseGateway', + 'Set-OPNSenseInterface', + 'Set-OPNSensePortForwardingRule', + 'Set-OPNSenseRoute', + 'Set-OPNSenseSystemDNS', + 'Set-OPNSenseUser', + 'Set-OPNSenseVLAN', + 'Uninstall-OPNSensePlugin', + 'Update-OPNSenseFirmware', + 'Start-OPNSenseFirmwareUpgrade' + ) + + # Variables to export from this module + VariablesToExport = @() + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = @() + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = @('PowerShell', 'OPNSense', 'Firewall', 'API') + + # A URL to the license for this module. + LicenseUri = 'https://github.com/freedbygrace/PSOPNSenseAPI/blob/main/LICENSE' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/freedbygrace/PSOPNSenseAPI' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + ReleaseNotes = 'https://github.com/freedbygrace/PSOPNSenseAPI/blob/main/CHANGELOG.md' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfoURI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' +} diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/README.md b/release/PSOPNSenseAPI-2025.04.15.1543/README.md new file mode 100644 index 0000000..e4e97b5 --- /dev/null +++ b/release/PSOPNSenseAPI-2025.04.15.1543/README.md @@ -0,0 +1,202 @@ +# PSOPNSenseAPI + +PowerShell module for interacting with the OPNSense API to configure firewalls. + +## Overview + +PSOPNSenseAPI is a PowerShell module that provides cmdlets for managing OPNSense firewalls through their API. The module is built as a binary module in C# and is compatible with both PowerShell 5.1 and PowerShell 7. + +## Features + +- Connect to OPNSense firewalls using API credentials +- Manage firewall rules (create, read, update, delete) +- Configure NAT rules and port forwarding +- Manage aliases (host, network, port, URL, etc.) +- Manage network interfaces and VLANs +- Configure DNS settings, overrides, and forwarding +- Configure system DNS servers +- Backup, restore, export, and import configurations +- Manage plugins (install, uninstall, enable, disable) +- Manage users and permissions +- Update and upgrade firmware +- Reboot firewall with wait for reconnection +- Create VLANs from subnet divisions +- Configure DHCP servers, static mappings, leases, and options +- Manage cron jobs +- Configure and manage Tailscale VPN (with auto-installation) +- Manage gateways and static routes +- Network calculation utilities (subnet, supernet, CIDR conversion) +- Apply and revert configuration changes +- Extensive logging and error handling +- Compatible with both PowerShell 5.1 and PowerShell 7 + +## Requirements + +- PowerShell 5.1 or PowerShell 7+ +- .NET Framework 4.7.2+ (for PowerShell 5.1) +- .NET Core 3.1+ (for PowerShell 7) + +## Installation + +```powershell +# Install from PowerShell Gallery (when published) +Install-Module -Name PSOPNSenseAPI + +# Or install manually +# 1. Download the module +# 2. Extract to a directory in your PSModulePath +# 3. Import the module +Import-Module PSOPNSenseAPI +``` + +## Quick Start + +```powershell +# Connect to an OPNSense firewall +Connect-OPNSense -Server "https://firewall.example.com" -ApiKey "your_api_key" -ApiSecret "your_api_secret" -SkipCertificateCheck + +# Get all firewall rules +Get-OPNSenseFirewallRule + +# Create a new firewall rule +New-OPNSenseFirewallRule -Description "Allow HTTP" -Protocol TCP -SourceNet "192.168.1.0/24" -DestinationPort 80 -Action Pass + +# Apply changes +Apply-OPNSenseFirewallChanges + +# Manage aliases +Get-OPNSenseAlias +New-OPNSenseAlias -Name "WebServers" -Type host -Content "192.168.1.10,192.168.1.11" -Description "Web Servers" -Apply +New-OPNSenseAlias -Name "WebPorts" -Type port -Content "80,443" -Protocol TCP -Description "Web Ports" -Apply +Set-OPNSenseAlias -Uuid "9e4ec4f0-9dd1-4fa3-8c1d-8a8e9d772b0f" -Content "192.168.1.10,192.168.1.11,192.168.1.12" -Apply + +# Manage interfaces +Get-OPNSenseInterface +Set-OPNSenseInterface -Name "lan" -Description "Local Network" -IpAddress "192.168.1.1" -SubnetMask "24" + +# Create VLANs from subnet divisions +New-OPNSenseSubnetVLANs -ParentInterface "em0" -Network "192.168.0.0/24" -SubnetMaskBits 27 -StartingVlanId 10 -VlanIdIncrement 10 -EnableDHCP + +# Configure DNS +Set-OPNSenseDNSServer -Forwarding -Forwarders "8.8.8.8","8.8.4.4" -Apply +New-OPNSenseDNSOverride -Hostname "server" -Domain "local" -IpAddress "192.168.1.10" + +# Manage plugins +Get-OPNSensePlugin -Installed +Install-OPNSensePlugin -Name "os-acme-client" -Wait + +# Manage users +New-OPNSenseUser -Username "john" -Password "P@ssw0rd" -FullName "John Doe" -Groups "admins" + +# Configure DHCP +Get-OPNSenseDHCPServer +Set-OPNSenseDHCPServer -Interface "lan" -RangeFrom "192.168.1.100" -RangeTo "192.168.1.200" -Apply +New-OPNSenseDHCPStaticMapping -Interface "lan" -MacAddress "00:11:22:33:44:55" -IpAddress "192.168.1.50" -Hostname "printer" +Get-OPNSenseDHCPLease +Remove-OPNSenseDHCPLease -MacAddress "00:11:22:33:44:55" -Apply +Get-OPNSenseDHCPOption -Interface "lan" +New-OPNSenseDHCPOption -Interface "lan" -Number 66 -Value "192.168.1.10" -Description "TFTP Server" -Apply + +# Manage cron jobs +Get-OPNSenseCronJob +New-OPNSenseCronJob -Description "Daily backup" -Command "/usr/local/bin/backup.sh" -Minutes "0" -Hours "2" -Apply + +# Configure and manage Tailscale +Get-OPNSenseTailscaleStatus -IncludeInterfaces +Enable-OPNSenseTailscale -AcceptDns -AcceptRoutes -Force +# Advertise subnet routes to Tailscale network +Enable-OPNSenseTailscale -AdvertiseRoutes -SubnetRoutes "192.168.1.0/24","10.0.0.0/8" -Force +Connect-OPNSenseTailscale -AuthKey "tskey-auth-abcdef123456" -InstallIfMissing -Force + +# Manage DNS forwarding +Get-OPNSenseDNSForwarding +Set-OPNSenseDNSForwarding -Enabled -DnsServers "8.8.8.8","8.8.4.4" -Apply +New-OPNSenseDNSForwardingHost -Domain "example.com" -Server "192.168.1.10" -Apply + +# Configure system DNS +Get-OPNSenseSystemDNS +Set-OPNSenseSystemDNS -Hostname "firewall" -Domain "example.com" -DnsServers "1.1.1.1","1.0.0.1" -Apply + +# Manage gateways and routes +Get-OPNSenseGateway -IncludeStatus +New-OPNSenseGateway -Name "WAN2_GW" -Interface "opt1" -IpAddress "203.0.113.1" -Description "Secondary WAN" -Apply +Get-OPNSenseRoute +New-OPNSenseRoute -Network "192.168.100.0/24" -Gateway "WAN2_GW" -Description "Remote Office" -Apply + +# Network utilities +Invoke-OPNSenseNetworkCalculation -Network "192.168.1.0/24" -Operation Info +Invoke-OPNSenseNetworkCalculation -Network "10.0.0.0/16" -Operation Subnet -PrefixLength 24 +ConvertTo-OPNSenseNetworkNotation -CIDR 24 # Returns "255.255.255.0" + +# Advanced supernetting +Invoke-OPNSenseNetworkCalculation -Network "192.168.1.0/24" -Operation Supernet -AdditionalNetworks "192.168.2.0/24" +Invoke-OPNSenseNetworkCalculation -Network "10.0.0.0/24" -Operation SupernetSummarize -AdditionalNetworks "10.0.1.0/24","10.0.2.0/24" + +# Firmware management +Update-OPNSenseFirmware -Wait + +# Major firmware upgrade +Start-OPNSenseFirmwareUpgrade -Wait -Timeout 1200 + +# Reboot firewall +Restart-OPNSenseFirewall -Wait -Timeout 300 + +# Configuration management +Get-OPNSenseConfig | Restore-OPNSenseConfig -Force # Get and restore configuration in one line +$config = Get-OPNSenseConfig # Get configuration as XML document +Export-OPNSenseConfig -Path (New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml") +Import-OPNSenseConfig -Path (New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml") -Force +``` + +## Documentation + +For detailed documentation, see the [docs](./docs) directory or use PowerShell's built-in help: + +```powershell +Get-Help Connect-OPNSense -Full +``` + +## Development + +### Build and Test + +To build and test the module locally: + +```powershell +# Run tests +.\build\test.ps1 + +# Build the module +.\build\build.ps1 + +# Build a release version with automatic versioning +.\build\build-release.ps1 -Clean -Test -Package +``` + +### Versioning + +The module uses a versioning scheme of `yyyy.MM.dd.HHmm` for releases, which is automatically generated during the build process. + +### CI/CD + +The project uses GitHub Actions for continuous integration and deployment: + +- Builds and tests are run on every push to the main branch +- Release packages are automatically created with the versioning scheme +- Release artifacts are uploaded to GitHub Releases + +## Contributing + +Contributions are welcome! Please follow these steps: + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Make your changes +4. Run tests to ensure they pass +5. Commit your changes (`git commit -m 'Add some amazing feature'`) +6. Push to the branch (`git push origin feature/amazing-feature`) +7. Open a Pull Request + +## License + +This project is licensed under the MIT License - see the LICENSE file for details. diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/Newtonsoft.Json.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/Newtonsoft.Json.dll new file mode 100644 index 0000000..341d08f Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/Newtonsoft.Json.dll differ diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/PSOPNSenseAPI.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/PSOPNSenseAPI.dll new file mode 100644 index 0000000..5eac19a Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/PSOPNSenseAPI.dll differ diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Buffers.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Buffers.dll new file mode 100644 index 0000000..f2d83c5 Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Buffers.dll differ diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Management.Automation.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Management.Automation.dll new file mode 100644 index 0000000..3dfa7d8 Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Management.Automation.dll differ diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Memory.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Memory.dll new file mode 100644 index 0000000..4617199 Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Memory.dll differ diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Net.IPNetwork.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Net.IPNetwork.dll new file mode 100644 index 0000000..ce68dd5 Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Net.IPNetwork.dll differ diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Numerics.Vectors.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Numerics.Vectors.dll new file mode 100644 index 0000000..0865972 Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Numerics.Vectors.dll differ diff --git a/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Runtime.CompilerServices.Unsafe.dll b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Runtime.CompilerServices.Unsafe.dll new file mode 100644 index 0000000..de9e124 Binary files /dev/null and b/release/PSOPNSenseAPI-2025.04.15.1543/lib/System.Runtime.CompilerServices.Unsafe.dll differ diff --git a/src/PSOPNSenseAPI/Cmdlets/ApplyOPNSenseFirewallChangesCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/ApplyOPNSenseFirewallChangesCmdlet.cs index d71d211..6a33676 100644 --- a/src/PSOPNSenseAPI/Cmdlets/ApplyOPNSenseFirewallChangesCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/ApplyOPNSenseFirewallChangesCmdlet.cs @@ -46,55 +46,70 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var firewallService = new FirewallService(ApiClient, Logger); + var firewallService = new FirewallService(ApiClient, Logger); - if (NoRollback.IsPresent) + if (NoRollback.IsPresent) + { + WriteVerbose("Applying firewall changes without rollback protection"); + var applyResult = ExecuteAsyncTask(() => firewallService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { - WriteVerbose("Applying firewall changes without rollback protection"); - var applyTask = Task.Run(async () => await firewallService.ApplyChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - WriteVerbose($"Firewall changes applied: {applyResult.Status}"); + return; + } + + WriteVerbose($"Firewall changes applied: {applyResult.Status}"); + } + else + { + WriteVerbose("Creating savepoint for rollback protection"); + var savepointResult = ExecuteAsyncTask(() => firewallService.CreateSavepointAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || savepointResult == null) + { + return; + } + + var revision = savepointResult.Revision; + + WriteVerbose($"Created savepoint with revision {revision}"); + WriteVerbose("Applying firewall changes with rollback protection"); + + var applyResult = ExecuteAsyncTask(() => firewallService.ApplyChangesAsync(revision)); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"Firewall changes applied: {applyResult.Status}"); + + if (CancelRollback.IsPresent) + { + WriteVerbose($"Waiting {Timeout} seconds before cancelling rollback"); + System.Threading.Thread.Sleep(Timeout * 1000); + + WriteVerbose("Cancelling automatic rollback"); + var cancelResult = ExecuteAsyncTask(() => firewallService.CancelRollbackAsync(revision)); + + // Only continue if no exception occurred + if (ProcessingException != null || cancelResult == null) + { + return; + } + + WriteVerbose($"Rollback cancelled: {cancelResult.Status}"); } else { - WriteVerbose("Creating savepoint for rollback protection"); - var savepointTask = Task.Run(async () => await firewallService.CreateSavepointAsync()); - var savepointResult = savepointTask.GetAwaiter().GetResult(); - var revision = savepointResult.Revision; - - WriteVerbose($"Created savepoint with revision {revision}"); - WriteVerbose("Applying firewall changes with rollback protection"); - - var applyTask = Task.Run(async () => await firewallService.ApplyChangesAsync(revision)); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"Firewall changes applied: {applyResult.Status}"); - - if (CancelRollback.IsPresent) - { - WriteVerbose($"Waiting {Timeout} seconds before cancelling rollback"); - System.Threading.Thread.Sleep(Timeout * 1000); - - WriteVerbose("Cancelling automatic rollback"); - var cancelTask = Task.Run(async () => await firewallService.CancelRollbackAsync(revision)); - var cancelResult = cancelTask.GetAwaiter().GetResult(); - - WriteVerbose($"Rollback cancelled: {cancelResult.Status}"); - } - else - { - WriteVerbose($"Automatic rollback will occur in 60 seconds if connectivity is lost"); - } + WriteVerbose($"Automatic rollback will occur in 60 seconds if connectivity is lost"); } } - catch (Exception ex) - { - HandleException(ex); - } } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/ConvertToOPNSenseNetworkNotationCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/ConvertToOPNSenseNetworkNotationCmdlet.cs index 35401be..404a7e3 100644 --- a/src/PSOPNSenseAPI/Cmdlets/ConvertToOPNSenseNetworkNotationCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/ConvertToOPNSenseNetworkNotationCmdlet.cs @@ -57,6 +57,14 @@ namespace PSOPNSenseAPI.Cmdlets [Parameter(Mandatory = false, ParameterSetName = "FromIPWithSubnetMask")] public string IPWithSubnetMask { get; set; } + /// + /// Begins the processing of the cmdlet + /// + protected override void BeginProcessing() + { + base.BeginProcessing(); + } + /// /// Processes the cmdlet /// @@ -88,22 +96,16 @@ namespace PSOPNSenseAPI.Cmdlets string[] parts = IPWithCIDR.Split('/'); if (parts.Length != 2) { - WriteError(new ErrorRecord( - new ArgumentException($"Invalid IP with CIDR: {IPWithCIDR}. Expected format: 192.168.1.0/24"), - "InvalidIPWithCIDR", - ErrorCategory.InvalidArgument, - null)); + // Use WriteWarning instead of WriteError to avoid threading issues + WriteWarning($"Invalid IP with CIDR: {IPWithCIDR}. Expected format: 192.168.1.0/24"); return; } string ip = parts[0]; if (!int.TryParse(parts[1], out int cidr)) { - WriteError(new ErrorRecord( - new ArgumentException($"Invalid CIDR: {parts[1]}"), - "InvalidCIDR", - ErrorCategory.InvalidArgument, - null)); + // Use WriteWarning instead of WriteError to avoid threading issues + WriteWarning($"Invalid CIDR: {parts[1]}"); return; } @@ -118,11 +120,8 @@ namespace PSOPNSenseAPI.Cmdlets string[] parts = IPWithSubnetMask.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 2) { - WriteError(new ErrorRecord( - new ArgumentException($"Invalid IP with subnet mask: {IPWithSubnetMask}. Expected format: 192.168.1.0 255.255.255.0"), - "InvalidIPWithSubnetMask", - ErrorCategory.InvalidArgument, - null)); + // Use WriteWarning instead of WriteError to avoid threading issues + WriteWarning($"Invalid IP with subnet mask: {IPWithSubnetMask}. Expected format: 192.168.1.0 255.255.255.0"); return; } @@ -136,12 +135,17 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - WriteError(new ErrorRecord( - ex, - "ConversionError", - ErrorCategory.InvalidOperation, - null)); + // Use WriteWarning instead of WriteError to avoid threading issues + WriteWarning($"Conversion error: {ex.Message}"); } } + + /// + /// Ends the processing of the cmdlet + /// + protected override void EndProcessing() + { + base.EndProcessing(); + } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseFirewallRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseFirewallRuleCmdlet.cs index 2f84dd3..b075fb9 100644 --- a/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseFirewallRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseFirewallRuleCmdlet.cs @@ -28,21 +28,20 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var firewallService = new FirewallService(ApiClient, Logger); + var firewallService = new FirewallService(ApiClient, Logger); - var task = Task.Run(async () => await firewallService.ToggleRuleAsync(Uuid, false)); - var result = task.GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => firewallService.ToggleRuleAsync(Uuid, false)); - WriteVerbose($"Firewall rule {Uuid} disabled: {result.Result}"); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteVerbose($"Firewall rule {Uuid} disabled: {result.Result}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/DisableOPNSensePluginCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/DisableOPNSensePluginCmdlet.cs index 057a82f..dcd348a 100644 --- a/src/PSOPNSenseAPI/Cmdlets/DisableOPNSensePluginCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/DisableOPNSensePluginCmdlet.cs @@ -28,22 +28,21 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var pluginService = new PluginService(ApiClient, Logger); + var pluginService = new PluginService(ApiClient, Logger); - var task = Task.Run(async () => await pluginService.DisablePluginAsync(Name)); - var result = task.GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => pluginService.DisablePluginAsync(Name)); - WriteVerbose($"Plugin {Name} disabled: {result.Status}"); - WriteObject($"Plugin {Name} disabled: {result.Status}"); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteVerbose($"Plugin {Name} disabled: {result.Status}"); + WriteObject($"Plugin {Name} disabled: {result.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseTailscaleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseTailscaleCmdlet.cs index 222ecb4..4bb2e2f 100644 --- a/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseTailscaleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/DisableOPNSenseTailscaleCmdlet.cs @@ -38,79 +38,100 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var tailscaleService = new TailscaleService(ApiClient, Logger); + + // Check if the plugin is installed + var isInstalled = ExecuteAsyncTask(() => tailscaleService.IsPluginInstalledAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null) { - var tailscaleService = new TailscaleService(ApiClient, Logger); + return; + } - // Check if the plugin is installed - var isInstalledTask = Task.Run(async () => await tailscaleService.IsPluginInstalledAsync()); - var isInstalled = isInstalledTask.GetAwaiter().GetResult(); + if (!isInstalled) + { + WriteWarning("Tailscale plugin is not installed on the OPNSense firewall."); + return; + } - if (!isInstalled) - { - WriteWarning("Tailscale plugin is not installed on the OPNSense firewall."); - return; - } + // Get current settings + var settingsResult = ExecuteAsyncTask(() => tailscaleService.GetSettingsAsync()); - // Get current settings - var settingsTask = Task.Run(async () => await tailscaleService.GetSettingsAsync()); - var currentSettings = settingsTask.GetAwaiter().GetResult().General; + // Only continue if no exception occurred + if (ProcessingException != null || settingsResult == null) + { + return; + } - // Create new settings with disabled flag - var settings = new TailscaleSettings - { - Enabled = "0", - AcceptDns = currentSettings.AcceptDns, - AcceptRoutes = currentSettings.AcceptRoutes, - AdvertiseExitNode = currentSettings.AdvertiseExitNode, - AdvertiseRoutes = currentSettings.AdvertiseRoutes, - RoutesToAdvertise = currentSettings.RoutesToAdvertise, - Hostname = currentSettings.Hostname, - LoginServer = currentSettings.LoginServer, - Ssh = currentSettings.Ssh, - Ephemeral = currentSettings.Ephemeral, - ResetOnStart = currentSettings.ResetOnStart - }; + var currentSettings = settingsResult.General; - if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Disable Tailscale")) + // Create new settings with disabled flag + var settings = new TailscaleSettings + { + Enabled = "0", + AcceptDns = currentSettings.AcceptDns, + AcceptRoutes = currentSettings.AcceptRoutes, + AdvertiseExitNode = currentSettings.AdvertiseExitNode, + AdvertiseRoutes = currentSettings.AdvertiseRoutes, + RoutesToAdvertise = currentSettings.RoutesToAdvertise, + Hostname = currentSettings.Hostname, + LoginServer = currentSettings.LoginServer, + Ssh = currentSettings.Ssh, + Ephemeral = currentSettings.Ephemeral, + ResetOnStart = currentSettings.ResetOnStart + }; + + if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Disable Tailscale")) + { + return; + } + + // Update settings + var updateResult = ExecuteAsyncTask(() => tailscaleService.UpdateSettingsAsync(settings)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"Tailscale settings updated: {updateResult.Result}"); + + // Stop the service if requested + if (Stop.IsPresent) + { + WriteVerbose("Stopping Tailscale service..."); + var stopResult = ExecuteAsyncTask(() => tailscaleService.StopServiceAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || stopResult == null) { return; } - // Update settings - var updateTask = Task.Run(async () => await tailscaleService.UpdateSettingsAsync(settings)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"Tailscale settings updated: {updateResult.Result}"); - - // Stop the service if requested - if (Stop.IsPresent) - { - WriteVerbose("Stopping Tailscale service..."); - var stopTask = Task.Run(async () => await tailscaleService.StopServiceAsync()); - var stopResult = stopTask.GetAwaiter().GetResult(); - WriteVerbose($"Tailscale service stopped: {stopResult.Status}"); - } - - // Get updated status - var statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync()); - var status = statusTask.GetAwaiter().GetResult(); - - // Create result object - var result = new PSObject(); - result.Properties.Add(new PSNoteProperty("PluginInstalled", true)); - result.Properties.Add(new PSNoteProperty("Enabled", status.Enabled)); - result.Properties.Add(new PSNoteProperty("Running", status.Running)); - result.Properties.Add(new PSNoteProperty("Status", status.Status)); - - WriteObject(result); + WriteVerbose($"Tailscale service stopped: {stopResult.Status}"); } - catch (Exception ex) + + // Get updated status + var status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || status == null) { - HandleException(ex); + return; } + + // Create result object + var result = new PSObject(); + result.Properties.Add(new PSNoteProperty("PluginInstalled", true)); + result.Properties.Add(new PSNoteProperty("Enabled", status.Enabled)); + result.Properties.Add(new PSNoteProperty("Running", status.Running)); + result.Properties.Add(new PSNoteProperty("Status", status.Status)); + + WriteObject(result); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/DisconnectOPNSenseCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/DisconnectOPNSenseCmdlet.cs index 6ee411f..8c7b6bd 100644 --- a/src/PSOPNSenseAPI/Cmdlets/DisconnectOPNSenseCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/DisconnectOPNSenseCmdlet.cs @@ -17,6 +17,14 @@ namespace PSOPNSenseAPI.Cmdlets [OutputType(typeof(void))] public class DisconnectOPNSenseCmdlet : PSCmdlet { + /// + /// Begins the processing of the cmdlet + /// + protected override void BeginProcessing() + { + base.BeginProcessing(); + } + /// /// Processes the cmdlet /// @@ -38,12 +46,17 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - WriteError(new ErrorRecord( - ex, - "DisconnectionFailed", - ErrorCategory.ConnectionError, - null)); + // Use WriteWarning instead of WriteError to avoid threading issues + WriteWarning($"Failed to disconnect: {ex.Message}"); } } + + /// + /// Ends the processing of the cmdlet + /// + protected override void EndProcessing() + { + base.EndProcessing(); + } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/EnableOPNSenseFirewallRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/EnableOPNSenseFirewallRuleCmdlet.cs index 7290d90..48dc069 100644 --- a/src/PSOPNSenseAPI/Cmdlets/EnableOPNSenseFirewallRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/EnableOPNSenseFirewallRuleCmdlet.cs @@ -28,21 +28,20 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var firewallService = new FirewallService(ApiClient, Logger); + var firewallService = new FirewallService(ApiClient, Logger); - var task = Task.Run(async () => await firewallService.ToggleRuleAsync(Uuid, true)); - var result = task.GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => firewallService.ToggleRuleAsync(Uuid, true)); - WriteVerbose($"Firewall rule {Uuid} enabled: {result.Result}"); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteVerbose($"Firewall rule {Uuid} enabled: {result.Result}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/EnableOPNSensePluginCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/EnableOPNSensePluginCmdlet.cs index f1bf3b2..463c451 100644 --- a/src/PSOPNSenseAPI/Cmdlets/EnableOPNSensePluginCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/EnableOPNSensePluginCmdlet.cs @@ -28,22 +28,21 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var pluginService = new PluginService(ApiClient, Logger); + var pluginService = new PluginService(ApiClient, Logger); - var task = Task.Run(async () => await pluginService.EnablePluginAsync(Name)); - var result = task.GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => pluginService.EnablePluginAsync(Name)); - WriteVerbose($"Plugin {Name} enabled: {result.Status}"); - WriteObject($"Plugin {Name} enabled: {result.Status}"); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteVerbose($"Plugin {Name} enabled: {result.Status}"); + WriteObject($"Plugin {Name} enabled: {result.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/ExportOPNSenseConfigCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/ExportOPNSenseConfigCmdlet.cs index 2f529c8..e1920f9 100644 --- a/src/PSOPNSenseAPI/Cmdlets/ExportOPNSenseConfigCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/ExportOPNSenseConfigCmdlet.cs @@ -35,28 +35,31 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { + string fullPath = Path.FullName; + + // Check if the file exists + if (File.Exists(fullPath) && !Force.IsPresent) + { + ProcessingException = new IOException($"The file '{fullPath}' already exists. Use -Force to overwrite."); + WriteWarning($"The file '{fullPath}' already exists. Use -Force to overwrite."); + return; + } + + var configService = new ConfigService(ApiClient, Logger); + + // Use our safe execution method + var configContent = ExecuteAsyncTask(() => configService.ExportConfigAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || configContent == null) + { + return; + } + try { - string fullPath = Path.FullName; - - // Check if the file exists - if (File.Exists(fullPath) && !Force.IsPresent) - { - WriteError(new ErrorRecord( - new IOException($"The file '{fullPath}' already exists. Use -Force to overwrite."), - "FileExists", - ErrorCategory.ResourceExists, - fullPath)); - return; - } - - var configService = new ConfigService(ApiClient, Logger); - - // Execute the async method synchronously on the main thread - var configContent = configService.ExportConfigAsync().GetAwaiter().GetResult(); - // Create the directory if it doesn't exist var directory = System.IO.Path.GetDirectoryName(fullPath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) @@ -71,7 +74,8 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - HandleException(ex); + ProcessingException = ex; + WriteWarning($"Failed to write configuration to file: {ex.Message}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseAliasCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseAliasCmdlet.cs index 50ef56a..4a820a7 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseAliasCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseAliasCmdlet.cs @@ -52,54 +52,60 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var aliasService = new AliasService(ApiClient, Logger); + + if (ParameterSetName == "ByUuid") { - var aliasService = new AliasService(ApiClient, Logger); + // Use our safe execution method + var result = ExecuteAsyncTask(() => aliasService.GetAliasAsync(Uuid)); - if (ParameterSetName == "ByUuid") + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - var task = Task.Run(async () => await aliasService.GetAliasAsync(Uuid)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Alias); + return; } - else - { - var task = Task.Run(async () => await aliasService.GetAliasesAsync()); - var result = task.GetAwaiter().GetResult(); - // Filter by name if specified - if (ParameterSetName == "ByName") + WriteObject(result.Alias); + } + else + { + // Use our safe execution method + var result = ExecuteAsyncTask(() => aliasService.GetAliasesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + // Filter by name if specified + if (ParameterSetName == "ByName") + { + var filteredByName = result.Rows.FindAll(a => a.Name.Equals(Name, StringComparison.OrdinalIgnoreCase)); + + // Further filter by type if specified + if (!string.IsNullOrEmpty(Type)) { - var filteredByName = result.Rows.FindAll(a => a.Name.Equals(Name, StringComparison.OrdinalIgnoreCase)); - - // Further filter by type if specified - if (!string.IsNullOrEmpty(Type)) - { - var filteredByType = filteredByName.FindAll(a => a.Type.Equals(Type, StringComparison.OrdinalIgnoreCase)); - WriteObject(filteredByType, true); - } - else - { - WriteObject(filteredByName, true); - } - } - // Filter by type if specified - else if (!string.IsNullOrEmpty(Type)) - { - var filteredByType = result.Rows.FindAll(a => a.Type.Equals(Type, StringComparison.OrdinalIgnoreCase)); + var filteredByType = filteredByName.FindAll(a => a.Type.Equals(Type, StringComparison.OrdinalIgnoreCase)); WriteObject(filteredByType, true); } else { - WriteObject(result.Rows, true); + WriteObject(filteredByName, true); } } - } - catch (Exception ex) - { - HandleException(ex); + // Filter by type if specified + else if (!string.IsNullOrEmpty(Type)) + { + var filteredByType = result.Rows.FindAll(a => a.Type.Equals(Type, StringComparison.OrdinalIgnoreCase)); + WriteObject(filteredByType, true); + } + else + { + WriteObject(result.Rows, true); + } } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigBackupCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigBackupCmdlet.cs index 4beb35f..7251055 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigBackupCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigBackupCmdlet.cs @@ -21,21 +21,20 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var configService = new ConfigService(ApiClient, Logger); + var configService = new ConfigService(ApiClient, Logger); - var task = Task.Run(async () => await configService.GetConfigBackupsAsync()); - var result = task.GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => configService.GetConfigBackupsAsync()); - WriteObject(result.Backups, true); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteObject(result.Backups, true); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigCmdlet.cs index 98b8b3d..3bad039 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConfigCmdlet.cs @@ -28,17 +28,23 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { + var configService = new ConfigService(ApiClient, Logger); + + // Use our safe execution method + var configContent = ExecuteAsyncTask(() => configService.ExportConfigAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || configContent == null) + { + return; + } + + // Convert the byte array to an XML document + var xmlDoc = new XmlDocument(); try { - var configService = new ConfigService(ApiClient, Logger); - - // Execute the async method synchronously on the main thread - var configContent = configService.ExportConfigAsync().GetAwaiter().GetResult(); - - // Convert the byte array to an XML document - var xmlDoc = new XmlDocument(); using (var memoryStream = new MemoryStream(configContent)) { xmlDoc.Load(memoryStream); @@ -49,7 +55,8 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - HandleException(ex); + ProcessingException = ex; + WriteWarning($"Failed to parse XML configuration: {ex.Message}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPOptionCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPOptionCmdlet.cs index 0bf7ee5..b9d4232 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPOptionCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPOptionCmdlet.cs @@ -40,28 +40,35 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var dhcpService = new DHCPService(ApiClient, Logger); + var dhcpService = new DHCPService(ApiClient, Logger); - if (ParameterSetName == "ByUuid") - { - var task = Task.Run(async () => await dhcpService.GetOptionAsync(Interface, Uuid)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Option); - } - else - { - var task = Task.Run(async () => await dhcpService.GetOptionsAsync(Interface)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Rows, true); - } - } - catch (Exception ex) + if (ParameterSetName == "ByUuid") { - HandleException(ex); + // Use our safe execution method + var result = ExecuteAsyncTask(() => dhcpService.GetOptionAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Option); + } + else + { + // Use our safe execution method + var result = ExecuteAsyncTask(() => dhcpService.GetOptionsAsync(Interface)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Rows, true); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPServerCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPServerCmdlet.cs index 7a74e27..d3975e0 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPServerCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPServerCmdlet.cs @@ -33,43 +33,49 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dhcpService = new DHCPService(ApiClient, Logger); + + if (ParameterSetName == "ByInterface") { - var dhcpService = new DHCPService(ApiClient, Logger); + // Use our safe execution method + var result = ExecuteAsyncTask(() => dhcpService.GetServerAsync(Interface)); - if (ParameterSetName == "ByInterface") + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - var task = Task.Run(async () => await dhcpService.GetServerAsync(Interface)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Server); + return; } - else - { - var task = Task.Run(async () => await dhcpService.GetServersAsync()); - var result = task.GetAwaiter().GetResult(); - foreach (var kvp in result.Servers.Interfaces) - { - var server = new PSObject(); - server.Properties.Add(new PSNoteProperty("Interface", kvp.Key)); - server.Properties.Add(new PSNoteProperty("Enabled", kvp.Value.Enabled == "1")); - server.Properties.Add(new PSNoteProperty("RangeFrom", kvp.Value.RangeFrom)); - server.Properties.Add(new PSNoteProperty("RangeTo", kvp.Value.RangeTo)); - server.Properties.Add(new PSNoteProperty("DefaultLeaseTime", kvp.Value.DefaultLeaseTime)); - server.Properties.Add(new PSNoteProperty("MaxLeaseTime", kvp.Value.MaxLeaseTime)); - server.Properties.Add(new PSNoteProperty("Domain", kvp.Value.Domain)); - server.Properties.Add(new PSNoteProperty("DnsServers", kvp.Value.DnsServers)); - server.Properties.Add(new PSNoteProperty("Gateway", kvp.Value.Gateway)); - - WriteObject(server); - } - } + WriteObject(result.Server); } - catch (Exception ex) + else { - HandleException(ex); + // Use our safe execution method + var result = ExecuteAsyncTask(() => dhcpService.GetServersAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + foreach (var kvp in result.Servers.Interfaces) + { + var server = new PSObject(); + server.Properties.Add(new PSNoteProperty("Interface", kvp.Key)); + server.Properties.Add(new PSNoteProperty("Enabled", kvp.Value.Enabled == "1")); + server.Properties.Add(new PSNoteProperty("RangeFrom", kvp.Value.RangeFrom)); + server.Properties.Add(new PSNoteProperty("RangeTo", kvp.Value.RangeTo)); + server.Properties.Add(new PSNoteProperty("DefaultLeaseTime", kvp.Value.DefaultLeaseTime)); + server.Properties.Add(new PSNoteProperty("MaxLeaseTime", kvp.Value.MaxLeaseTime)); + server.Properties.Add(new PSNoteProperty("Domain", kvp.Value.Domain)); + server.Properties.Add(new PSNoteProperty("DnsServers", kvp.Value.DnsServers)); + server.Properties.Add(new PSNoteProperty("Gateway", kvp.Value.Gateway)); + + WriteObject(server); + } } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPStaticMappingCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPStaticMappingCmdlet.cs index 6604dea..88d5bdc 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPStaticMappingCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDHCPStaticMappingCmdlet.cs @@ -40,28 +40,35 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var dhcpService = new DHCPService(ApiClient, Logger); + var dhcpService = new DHCPService(ApiClient, Logger); - if (ParameterSetName == "ByUuid") - { - var task = Task.Run(async () => await dhcpService.GetStaticMappingAsync(Interface, Uuid)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Mapping); - } - else - { - var task = Task.Run(async () => await dhcpService.GetStaticMappingsAsync(Interface)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Rows, true); - } - } - catch (Exception ex) + if (ParameterSetName == "ByUuid") { - HandleException(ex); + // Use our safe execution method + var result = ExecuteAsyncTask(() => dhcpService.GetStaticMappingAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Mapping); + } + else + { + // Use our safe execution method + var result = ExecuteAsyncTask(() => dhcpService.GetStaticMappingsAsync(Interface)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Rows, true); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSForwardingCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSForwardingCmdlet.cs index 630d147..5b755a1 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSForwardingCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSForwardingCmdlet.cs @@ -21,21 +21,20 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var dnsService = new DNSService(ApiClient, Logger); + var dnsService = new DNSService(ApiClient, Logger); - var task = Task.Run(async () => await dnsService.GetDNSForwardingAsync()); - var result = task.GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => dnsService.GetDNSForwardingAsync()); - WriteObject(result.Forward); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteObject(result.Forward); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSServerCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSServerCmdlet.cs index 8fd7b71..2b19e2b 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSServerCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseDNSServerCmdlet.cs @@ -21,32 +21,31 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dnsService = new DNSService(ApiClient, Logger); + + // Use our safe execution method + var result = ExecuteAsyncTask(() => dnsService.GetDNSConfigAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - var dnsService = new DNSService(ApiClient, Logger); - - var task = Task.Run(async () => await dnsService.GetDNSConfigAsync()); - var result = task.GetAwaiter().GetResult(); - - var dnsConfig = new PSObject(); - dnsConfig.Properties.Add(new PSNoteProperty("Enabled", result.Unbound.Enabled == "1")); - dnsConfig.Properties.Add(new PSNoteProperty("Port", result.Unbound.Port)); - dnsConfig.Properties.Add(new PSNoteProperty("Interfaces", result.Unbound.Interfaces)); - dnsConfig.Properties.Add(new PSNoteProperty("Forwarding", result.Unbound.Forwarding == "1")); - dnsConfig.Properties.Add(new PSNoteProperty("Forwarders", result.Unbound.Forwarders)); - dnsConfig.Properties.Add(new PSNoteProperty("RegisterDhcp", result.Unbound.RegisterDhcp == "1")); - dnsConfig.Properties.Add(new PSNoteProperty("RegisterDhcpDomain", result.Unbound.RegisterDhcpDomain)); - dnsConfig.Properties.Add(new PSNoteProperty("RegisterDhcpStatic", result.Unbound.RegisterDhcpStatic == "1")); - dnsConfig.Properties.Add(new PSNoteProperty("ActiveInterfaces", result.Unbound.ActiveInterfaces)); - - WriteObject(dnsConfig); - } - catch (Exception ex) - { - HandleException(ex); + return; } + + var dnsConfig = new PSObject(); + dnsConfig.Properties.Add(new PSNoteProperty("Enabled", result.Unbound.Enabled == "1")); + dnsConfig.Properties.Add(new PSNoteProperty("Port", result.Unbound.Port)); + dnsConfig.Properties.Add(new PSNoteProperty("Interfaces", result.Unbound.Interfaces)); + dnsConfig.Properties.Add(new PSNoteProperty("Forwarding", result.Unbound.Forwarding == "1")); + dnsConfig.Properties.Add(new PSNoteProperty("Forwarders", result.Unbound.Forwarders)); + dnsConfig.Properties.Add(new PSNoteProperty("RegisterDhcp", result.Unbound.RegisterDhcp == "1")); + dnsConfig.Properties.Add(new PSNoteProperty("RegisterDhcpDomain", result.Unbound.RegisterDhcpDomain)); + dnsConfig.Properties.Add(new PSNoteProperty("RegisterDhcpStatic", result.Unbound.RegisterDhcpStatic == "1")); + dnsConfig.Properties.Add(new PSNoteProperty("ActiveInterfaces", result.Unbound.ActiveInterfaces)); + + WriteObject(dnsConfig); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseFirewallRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseFirewallRuleCmdlet.cs index 4c1d89b..f6d6d4e 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseFirewallRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseFirewallRuleCmdlet.cs @@ -58,28 +58,35 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var firewallService = new FirewallService(ApiClient, Logger); + var firewallService = new FirewallService(ApiClient, Logger); - if (ParameterSetName == "ByUuid") - { - var task = Task.Run(async () => await firewallService.GetRuleAsync(Uuid)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Rule); - } - else - { - var task = Task.Run(async () => await firewallService.GetRulesAsync(SearchPhrase, Page, RowCount)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Rows, true); - } - } - catch (Exception ex) + if (ParameterSetName == "ByUuid") { - HandleException(ex); + // Use our safe execution method + var result = ExecuteAsyncTask(() => firewallService.GetRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Rule); + } + else + { + // Use our safe execution method + var result = ExecuteAsyncTask(() => firewallService.GetRulesAsync(SearchPhrase, Page, RowCount)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Rows, true); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseInterfaceStatisticsCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseInterfaceStatisticsCmdlet.cs index 0145249..ba3343c 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseInterfaceStatisticsCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseInterfaceStatisticsCmdlet.cs @@ -26,33 +26,32 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var interfaceService = new InterfaceService(ApiClient, Logger); + + // Use our safe execution method + var result = ExecuteAsyncTask(() => interfaceService.GetInterfaceStatisticsAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - var interfaceService = new InterfaceService(ApiClient, Logger); - - var task = Task.Run(async () => await interfaceService.GetInterfaceStatisticsAsync()); - var result = task.GetAwaiter().GetResult(); - - foreach (var kvp in result.Statistics) - { - var stats = new PSObject(); - stats.Properties.Add(new PSNoteProperty("Name", kvp.Key)); - stats.Properties.Add(new PSNoteProperty("InPackets", kvp.Value.InPackets)); - stats.Properties.Add(new PSNoteProperty("InBytes", kvp.Value.InBytes)); - stats.Properties.Add(new PSNoteProperty("InErrors", 0)); - stats.Properties.Add(new PSNoteProperty("OutPackets", kvp.Value.OutPackets)); - stats.Properties.Add(new PSNoteProperty("OutBytes", kvp.Value.OutBytes)); - stats.Properties.Add(new PSNoteProperty("OutErrors", 0)); - stats.Properties.Add(new PSNoteProperty("Collisions", 0)); - - WriteObject(stats); - } + return; } - catch (Exception ex) + + foreach (var kvp in result.Statistics) { - HandleException(ex); + var stats = new PSObject(); + stats.Properties.Add(new PSNoteProperty("Name", kvp.Key)); + stats.Properties.Add(new PSNoteProperty("InPackets", kvp.Value.InPackets)); + stats.Properties.Add(new PSNoteProperty("InBytes", kvp.Value.InBytes)); + stats.Properties.Add(new PSNoteProperty("InErrors", 0)); + stats.Properties.Add(new PSNoteProperty("OutPackets", kvp.Value.OutPackets)); + stats.Properties.Add(new PSNoteProperty("OutBytes", kvp.Value.OutBytes)); + stats.Properties.Add(new PSNoteProperty("OutErrors", 0)); + stats.Properties.Add(new PSNoteProperty("Collisions", 0)); + + WriteObject(stats); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePluginCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePluginCmdlet.cs index a6e8b0e..3af74b4 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePluginCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePluginCmdlet.cs @@ -43,60 +43,59 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var pluginService = new PluginService(ApiClient, Logger); + + // Use our safe execution method + var result = ExecuteAsyncTask(() => pluginService.GetPluginsAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - var pluginService = new PluginService(ApiClient, Logger); + return; + } - var task = Task.Run(async () => await pluginService.GetPluginsAsync()); - var result = task.GetAwaiter().GetResult(); - - if (ParameterSetName == "Installed" || ParameterSetName == "") + if (ParameterSetName == "Installed" || ParameterSetName == "") + { + foreach (var kvp in result.Installed) { - foreach (var kvp in result.Installed) - { - var plugin = new PSObject(); - plugin.Properties.Add(new PSNoteProperty("Name", kvp.Key)); - plugin.Properties.Add(new PSNoteProperty("Version", kvp.Value.Version)); - plugin.Properties.Add(new PSNoteProperty("Comment", kvp.Value.Comment)); - plugin.Properties.Add(new PSNoteProperty("Repository", kvp.Value.Repository)); - plugin.Properties.Add(new PSNoteProperty("Origin", kvp.Value.Origin)); - plugin.Properties.Add(new PSNoteProperty("License", kvp.Value.License)); - plugin.Properties.Add(new PSNoteProperty("FlatSize", kvp.Value.FlatSize)); - plugin.Properties.Add(new PSNoteProperty("Locked", kvp.Value.Locked == "1")); - plugin.Properties.Add(new PSNoteProperty("Enabled", kvp.Value.Enabled == "1")); - plugin.Properties.Add(new PSNoteProperty("Status", "Installed")); - - WriteObject(plugin); - } - } + var plugin = new PSObject(); + plugin.Properties.Add(new PSNoteProperty("Name", kvp.Key)); + plugin.Properties.Add(new PSNoteProperty("Version", kvp.Value.Version)); + plugin.Properties.Add(new PSNoteProperty("Comment", kvp.Value.Comment)); + plugin.Properties.Add(new PSNoteProperty("Repository", kvp.Value.Repository)); + plugin.Properties.Add(new PSNoteProperty("Origin", kvp.Value.Origin)); + plugin.Properties.Add(new PSNoteProperty("License", kvp.Value.License)); + plugin.Properties.Add(new PSNoteProperty("FlatSize", kvp.Value.FlatSize)); + plugin.Properties.Add(new PSNoteProperty("Locked", kvp.Value.Locked == "1")); + plugin.Properties.Add(new PSNoteProperty("Enabled", kvp.Value.Enabled == "1")); + plugin.Properties.Add(new PSNoteProperty("Status", "Installed")); - if (ParameterSetName == "Available" || ParameterSetName == "") - { - foreach (var kvp in result.Available) - { - // Skip if the plugin is already installed - if (result.Installed.ContainsKey(kvp.Key)) - continue; - - var plugin = new PSObject(); - plugin.Properties.Add(new PSNoteProperty("Name", kvp.Key)); - plugin.Properties.Add(new PSNoteProperty("Version", kvp.Value.Version)); - plugin.Properties.Add(new PSNoteProperty("Comment", kvp.Value.Comment)); - plugin.Properties.Add(new PSNoteProperty("Repository", kvp.Value.Repository)); - plugin.Properties.Add(new PSNoteProperty("Origin", kvp.Value.Origin)); - plugin.Properties.Add(new PSNoteProperty("License", kvp.Value.License)); - plugin.Properties.Add(new PSNoteProperty("FlatSize", kvp.Value.FlatSize)); - plugin.Properties.Add(new PSNoteProperty("Status", "Available")); - - WriteObject(plugin); - } + WriteObject(plugin); } } - catch (Exception ex) + + if (ParameterSetName == "Available" || ParameterSetName == "") { - HandleException(ex); + foreach (var kvp in result.Available) + { + // Skip if the plugin is already installed + if (result.Installed.ContainsKey(kvp.Key)) + continue; + + var plugin = new PSObject(); + plugin.Properties.Add(new PSNoteProperty("Name", kvp.Key)); + plugin.Properties.Add(new PSNoteProperty("Version", kvp.Value.Version)); + plugin.Properties.Add(new PSNoteProperty("Comment", kvp.Value.Comment)); + plugin.Properties.Add(new PSNoteProperty("Repository", kvp.Value.Repository)); + plugin.Properties.Add(new PSNoteProperty("Origin", kvp.Value.Origin)); + plugin.Properties.Add(new PSNoteProperty("License", kvp.Value.License)); + plugin.Properties.Add(new PSNoteProperty("FlatSize", kvp.Value.FlatSize)); + plugin.Properties.Add(new PSNoteProperty("Status", "Available")); + + WriteObject(plugin); + } } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePortForwardingRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePortForwardingRuleCmdlet.cs index 5eedb00..c37afb9 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePortForwardingRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSensePortForwardingRuleCmdlet.cs @@ -19,7 +19,7 @@ namespace PSOPNSenseAPI.Cmdlets /// [Cmdlet(VerbsCommon.Get, "OPNSensePortForwardingRule")] [OutputType(typeof(PortForwardingRule))] - public class GetOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet + public class GetOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet { /// /// The UUID of the port forwarding rule to get. If not specified, all rules are returned. @@ -30,14 +30,21 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - var portForwardingService = new PortForwardingService(SessionState.ApiClient); + var portForwardingService = new PortForwardingService(ApiClient); if (!string.IsNullOrEmpty(Uuid)) { - // Get a specific rule - var rule = Task.Run(async () => await portForwardingService.GetPortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); + // Use our safe execution method + var rule = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } + if (rule != null) { WriteObject(rule); @@ -49,8 +56,15 @@ namespace PSOPNSenseAPI.Cmdlets } else { - // Get all rules - var rules = Task.Run(async () => await portForwardingService.GetPortForwardingRulesAsync()).GetAwaiter().GetResult(); + // Use our safe execution method + var rules = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRulesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || rules == null) + { + return; + } + WriteObject(rules, true); } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseSystemDNSCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseSystemDNSCmdlet.cs index 23f730d..b41006d 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseSystemDNSCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseSystemDNSCmdlet.cs @@ -21,21 +21,20 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var systemDNSService = new SystemDNSService(ApiClient, Logger); + var systemDNSService = new SystemDNSService(ApiClient, Logger); - var task = Task.Run(async () => await systemDNSService.GetSystemDNSAsync()); - var result = task.GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => systemDNSService.GetSystemDNSAsync()); - WriteObject(result.System); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteObject(result.System); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseVLANCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseVLANCmdlet.cs index 6006e2a..2cb86e4 100644 --- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseVLANCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseVLANCmdlet.cs @@ -33,28 +33,35 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var interfaceService = new InterfaceService(ApiClient, Logger); + var interfaceService = new InterfaceService(ApiClient, Logger); - if (ParameterSetName == "ByUuid") - { - var task = Task.Run(async () => await interfaceService.GetVLANAsync(Uuid)); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Vlan); - } - else - { - var task = Task.Run(async () => await interfaceService.GetVLANsAsync()); - var result = task.GetAwaiter().GetResult(); - WriteObject(result.Rows, true); - } - } - catch (Exception ex) + if (ParameterSetName == "ByUuid") { - HandleException(ex); + // Use our safe execution method + var result = ExecuteAsyncTask(() => interfaceService.GetVLANAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Vlan); + } + else + { + // Use our safe execution method + var result = ExecuteAsyncTask(() => interfaceService.GetVLANsAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + + WriteObject(result.Rows, true); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/ImportOPNSenseConfigCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/ImportOPNSenseConfigCmdlet.cs index 00667a2..bde36d2 100644 --- a/src/PSOPNSenseAPI/Cmdlets/ImportOPNSenseConfigCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/ImportOPNSenseConfigCmdlet.cs @@ -35,42 +35,46 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { + string fullPath = Path.FullName; + + // Check if the file exists + if (!File.Exists(fullPath)) + { + ProcessingException = new FileNotFoundException($"The file '{fullPath}' does not exist."); + WriteWarning($"The file '{fullPath}' does not exist."); + return; + } + + if (!Force.IsPresent && !ShouldProcess(fullPath, "Import configuration")) + { + return; + } + + var configService = new ConfigService(ApiClient, Logger); + try { - string fullPath = Path.FullName; - - // Check if the file exists - if (!File.Exists(fullPath)) - { - WriteError(new ErrorRecord( - new FileNotFoundException($"The file '{fullPath}' does not exist."), - "FileNotFound", - ErrorCategory.ObjectNotFound, - fullPath)); - return; - } - - if (!Force.IsPresent && !ShouldProcess(fullPath, "Import configuration")) - { - return; - } - - var configService = new ConfigService(ApiClient, Logger); - // Read the configuration file var configContent = File.ReadAllBytes(fullPath); - // Execute the async method synchronously on the main thread - var result = configService.ImportConfigAsync(configContent).GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => configService.ImportConfigAsync(configContent)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } WriteVerbose($"Imported configuration from {fullPath}: {result.Status}"); WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online."); } catch (Exception ex) { - HandleException(ex); + ProcessingException = ex; + WriteWarning($"Failed to read or process configuration file: {ex.Message}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs index 8cb1d69..0bf59cb 100644 --- a/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs @@ -185,11 +185,7 @@ namespace PSOPNSenseAPI.Cmdlets { if (prefixLength <= network.Cidr) { - WriteError(new ErrorRecord( - new ArgumentException($"Prefix length ({prefixLength}) must be greater than the network CIDR ({network.Cidr})."), - "InvalidPrefixLength", - ErrorCategory.InvalidArgument, - null)); + ProcessingException = new ArgumentException($"Prefix length ({prefixLength}) must be greater than the network CIDR ({network.Cidr})."); return; } @@ -206,11 +202,7 @@ namespace PSOPNSenseAPI.Cmdlets } catch (ArgumentException ex) { - WriteError(new ErrorRecord( - ex, - "InvalidSubnetCount", - ErrorCategory.InvalidArgument, - null)); + ProcessingException = ex; } } @@ -236,11 +228,7 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - WriteError(new ErrorRecord( - ex, - "InvalidIPAddress", - ErrorCategory.InvalidArgument, - null)); + ProcessingException = ex; } } @@ -267,11 +255,7 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - WriteError(new ErrorRecord( - ex, - "InvalidAdditionalNetwork", - ErrorCategory.InvalidArgument, - null)); + ProcessingException = ex; } } @@ -292,11 +276,7 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - WriteError(new ErrorRecord( - ex, - "SupernetError", - ErrorCategory.InvalidOperation, - null)); + ProcessingException = ex; } } @@ -317,11 +297,7 @@ namespace PSOPNSenseAPI.Cmdlets } catch (Exception ex) { - WriteError(new ErrorRecord( - ex, - "SupernetSummarizeError", - ErrorCategory.InvalidOperation, - null)); + ProcessingException = ex; } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseFirewallRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseFirewallRuleCmdlet.cs index 58dea0a..c96e900 100644 --- a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseFirewallRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseFirewallRuleCmdlet.cs @@ -83,35 +83,34 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var firewallService = new FirewallService(ApiClient, Logger); + + var rule = new FirewallRuleCreate { - var firewallService = new FirewallService(ApiClient, Logger); + Description = Description, + Protocol = Protocol, + SourceNet = SourceNet, + SourcePort = SourcePort, + DestinationNet = DestinationNet, + DestinationPort = DestinationPort, + Action = Action, + Sequence = Sequence, + Enabled = Enabled.IsPresent ? "1" : "0" + }; - var rule = new FirewallRuleCreate - { - Description = Description, - Protocol = Protocol, - SourceNet = SourceNet, - SourcePort = SourcePort, - DestinationNet = DestinationNet, - DestinationPort = DestinationPort, - Action = Action, - Sequence = Sequence, - Enabled = Enabled.IsPresent ? "1" : "0" - }; + // Use our safe execution method + var result = ExecuteAsyncTask(() => firewallService.CreateRuleAsync(rule)); - var task = Task.Run(async () => await firewallService.CreateRuleAsync(rule)); - var result = task.GetAwaiter().GetResult(); - - WriteVerbose($"Created firewall rule with UUID {result.Uuid}"); - WriteObject(result.Uuid); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteVerbose($"Created firewall rule with UUID {result.Uuid}"); + WriteObject(result.Uuid); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/NewOPNSensePortForwardingRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/NewOPNSensePortForwardingRuleCmdlet.cs index df4e61f..4f41432 100644 --- a/src/PSOPNSenseAPI/Cmdlets/NewOPNSensePortForwardingRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/NewOPNSensePortForwardingRuleCmdlet.cs @@ -15,7 +15,7 @@ namespace PSOPNSenseAPI.Cmdlets /// [Cmdlet(VerbsCommon.New, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)] [OutputType(typeof(PortForwardingRule))] - public class NewOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet + public class NewOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet { /// /// Whether the rule is enabled. @@ -106,7 +106,7 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { var rule = new PortForwardingRule { @@ -127,8 +127,16 @@ namespace PSOPNSenseAPI.Cmdlets if (Force || ShouldProcess($"OPNSense firewall", $"Create port forwarding rule from {Destination}:{DestinationPort} to {TargetIP}:{TargetPort}")) { - var portForwardingService = new PortForwardingService(SessionState.ApiClient); - var uuid = Task.Run(async () => await portForwardingService.CreatePortForwardingRuleAsync(rule)).GetAwaiter().GetResult(); + var portForwardingService = new PortForwardingService(ApiClient); + + // Use our safe execution method + var uuid = ExecuteAsyncTask(() => portForwardingService.CreatePortForwardingRuleAsync(rule)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } if (!string.IsNullOrEmpty(uuid)) { @@ -138,11 +146,8 @@ namespace PSOPNSenseAPI.Cmdlets } else { - WriteError(new ErrorRecord( - new PSInvalidOperationException("Failed to create port forwarding rule."), - "PortForwardingRuleCreationFailed", - ErrorCategory.InvalidOperation, - null)); + ProcessingException = new PSInvalidOperationException("Failed to create port forwarding rule."); + WriteWarning("Failed to create port forwarding rule."); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseSubnetVLANsCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseSubnetVLANsCmdlet.cs index c4f4c80..60a303e 100644 --- a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseSubnetVLANsCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseSubnetVLANsCmdlet.cs @@ -99,199 +99,219 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + // Parse the network CIDR + var ipNetwork = IPNetwork2.Parse(Network); + + // Validate subnet mask bits + if (SubnetMaskBits <= ipNetwork.Cidr) { - // Parse the network CIDR - var ipNetwork = IPNetwork2.Parse(Network); + ProcessingException = new ArgumentException($"Subnet mask bits ({SubnetMaskBits}) must be greater than the network CIDR ({ipNetwork.Cidr})."); + WriteWarning($"Subnet mask bits ({SubnetMaskBits}) must be greater than the network CIDR ({ipNetwork.Cidr})."); + return; + } - // Validate subnet mask bits - if (SubnetMaskBits <= ipNetwork.Cidr) + // Calculate the number of subnets + int numSubnets = (int)Math.Pow(2, SubnetMaskBits - ipNetwork.Cidr); + + // Calculate the maximum VLAN ID + int maxVlanId = StartingVlanId + (numSubnets - 1) * VlanIdIncrement; + + // Validate the maximum VLAN ID + if (maxVlanId > 4094) + { + ProcessingException = new ArgumentException($"The maximum VLAN ID ({maxVlanId}) exceeds the maximum allowed value (4094)."); + WriteWarning($"The maximum VLAN ID ({maxVlanId}) exceeds the maximum allowed value (4094)."); + return; + } + + // Get confirmation + if (!Force.IsPresent && !ShouldProcess($"Create {numSubnets} VLANs for subnets of {Network} with VLAN IDs {StartingVlanId}-{maxVlanId}", "New-OPNSenseSubnetVLANs")) + { + return; + } + + // Get the interface service + var interfaceService = new InterfaceService(ApiClient, Logger); + + // Verify the parent interface exists + var interfaceDetail = ExecuteAsyncTask(() => interfaceService.GetInterfaceDetailAsync(ParentInterface)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } + + // Get existing VLANs + var vlansResult = ExecuteAsyncTask(() => interfaceService.GetVLANsAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || vlansResult == null) + { + return; + } + + var existingVlans = vlansResult.Rows; + + // Create a list to store the created VLANs + var createdVlans = new List(); + + // Get DHCP service if needed + DHCPService dhcpService = null; + if (EnableDHCP.IsPresent) + { + dhcpService = new DHCPService(ApiClient, Logger); + } + + // Divide the network into subnets + var subnets = ipNetwork.Subnet((byte)SubnetMaskBits); + int vlanId = StartingVlanId; + int subnetIndex = 0; + + foreach (var subnet in subnets) + { + // Calculate the gateway IP (first host address) + var gatewayIp = GetFirstHostAddress(subnet); + + // Calculate the DHCP range (second host address to last host address) + var dhcpStart = GetSecondHostAddress(subnet); + var dhcpEnd = GetLastHostAddress(subnet); + + // Create a description for the VLAN + string description = $"{DescriptionPrefix} {vlanId} - {subnet}"; + + // Check if the VLAN already exists + var existingVlan = existingVlans.FirstOrDefault(v => + v.Interface == ParentInterface && + int.Parse(v.Tag) == vlanId); + + if (existingVlan != null) { - WriteError(new ErrorRecord( - new ArgumentException($"Subnet mask bits ({SubnetMaskBits}) must be greater than the network CIDR ({ipNetwork.Cidr})."), - "InvalidSubnetMaskBits", - ErrorCategory.InvalidArgument, - SubnetMaskBits)); - return; + WriteVerbose($"VLAN {vlanId} already exists on interface {ParentInterface}"); + + // Add the existing VLAN to the list + var vlanInfo = new PSObject(); + vlanInfo.Properties.Add(new PSNoteProperty("VlanId", vlanId)); + vlanInfo.Properties.Add(new PSNoteProperty("Subnet", subnet.ToString())); + vlanInfo.Properties.Add(new PSNoteProperty("Gateway", gatewayIp.ToString())); + vlanInfo.Properties.Add(new PSNoteProperty("Uuid", existingVlan.Uuid)); + vlanInfo.Properties.Add(new PSNoteProperty("Status", "Existing")); + + createdVlans.Add(vlanInfo); } - - // Calculate the number of subnets - int numSubnets = (int)Math.Pow(2, SubnetMaskBits - ipNetwork.Cidr); - - // Calculate the maximum VLAN ID - int maxVlanId = StartingVlanId + (numSubnets - 1) * VlanIdIncrement; - - // Validate the maximum VLAN ID - if (maxVlanId > 4094) + else { - WriteError(new ErrorRecord( - new ArgumentException($"The maximum VLAN ID ({maxVlanId}) exceeds the maximum allowed value (4094)."), - "InvalidVlanIdRange", - ErrorCategory.InvalidArgument, - maxVlanId)); - return; - } - - // Get confirmation - if (!Force.IsPresent && !ShouldProcess($"Create {numSubnets} VLANs for subnets of {Network} with VLAN IDs {StartingVlanId}-{maxVlanId}", "New-OPNSenseSubnetVLANs")) - { - return; - } - - // Get the interface service - var interfaceService = new InterfaceService(ApiClient, Logger); - - // Verify the parent interface exists - var getInterfaceTask = Task.Run(async () => await interfaceService.GetInterfaceDetailAsync(ParentInterface)); - getInterfaceTask.GetAwaiter().GetResult(); - - // Get existing VLANs - var getVlansTask = Task.Run(async () => await interfaceService.GetVLANsAsync()); - var existingVlans = getVlansTask.GetAwaiter().GetResult().Rows; - - // Create a list to store the created VLANs - var createdVlans = new List(); - - // Get DHCP service if needed - DHCPService dhcpService = null; - if (EnableDHCP.IsPresent) - { - dhcpService = new DHCPService(ApiClient, Logger); - } - - // Divide the network into subnets - var subnets = ipNetwork.Subnet((byte)SubnetMaskBits); - int vlanId = StartingVlanId; - int subnetIndex = 0; - - foreach (var subnet in subnets) - { - // Calculate the gateway IP (first host address) - var gatewayIp = GetFirstHostAddress(subnet); - - // Calculate the DHCP range (second host address to last host address) - var dhcpStart = GetSecondHostAddress(subnet); - var dhcpEnd = GetLastHostAddress(subnet); - - // Create a description for the VLAN - string description = $"{DescriptionPrefix} {vlanId} - {subnet}"; - - // Check if the VLAN already exists - var existingVlan = existingVlans.FirstOrDefault(v => - v.Interface == ParentInterface && - int.Parse(v.Tag) == vlanId); - - if (existingVlan != null) + // Create the VLAN + var vlanConfig = new VLANConfig { - WriteVerbose($"VLAN {vlanId} already exists on interface {ParentInterface}"); + Interface = ParentInterface, + Tag = vlanId.ToString(), + Priority = "0", + Description = description + }; - // Add the existing VLAN to the list - var vlanInfo = new PSObject(); - vlanInfo.Properties.Add(new PSNoteProperty("VlanId", vlanId)); - vlanInfo.Properties.Add(new PSNoteProperty("Subnet", subnet.ToString())); - vlanInfo.Properties.Add(new PSNoteProperty("Gateway", gatewayIp.ToString())); - vlanInfo.Properties.Add(new PSNoteProperty("Uuid", existingVlan.Uuid)); - vlanInfo.Properties.Add(new PSNoteProperty("Status", "Existing")); + var createVlanResult = ExecuteAsyncTask(() => interfaceService.CreateVLANAsync(vlanConfig)); - createdVlans.Add(vlanInfo); - } - else + // Only continue if no exception occurred + if (ProcessingException != null || createVlanResult == null) { - // Create the VLAN - var vlanConfig = new VLANConfig - { - Interface = ParentInterface, - Tag = vlanId.ToString(), - Priority = "0", - Description = description - }; - - var createVlanTask = Task.Run(async () => await interfaceService.CreateVLANAsync(vlanConfig)); - var createVlanResult = createVlanTask.GetAwaiter().GetResult(); - - WriteVerbose($"Created VLAN {vlanId} on interface {ParentInterface} with UUID {createVlanResult.Uuid}"); - - // Configure the VLAN interface - string vlanInterfaceName = $"{ParentInterface}.{vlanId}"; - - var interfaceConfig = new InterfaceConfig - { - Description = description, - IpAddress = gatewayIp.ToString(), - SubnetMask = SubnetMaskBits.ToString(), - Enabled = "1" - }; - - var updateInterfaceTask = Task.Run(async () => await interfaceService.UpdateInterfaceAsync(vlanInterfaceName, interfaceConfig)); - updateInterfaceTask.GetAwaiter().GetResult(); - - WriteVerbose($"Configured interface {vlanInterfaceName} with IP {gatewayIp}/{SubnetMaskBits}"); - - // If EnableDHCP is specified, configure DHCP for the interface - if (EnableDHCP.IsPresent && dhcpService != null) - { - // Configure DHCP server for the interface - var dhcpConfig = new DHCPServerConfig - { - Enabled = "1", - RangeFrom = dhcpStart.ToString(), - RangeTo = dhcpEnd.ToString(), - DefaultLeaseTime = "7200", - MaxLeaseTime = "86400", - Domain = Domain, - Gateway = gatewayIp.ToString(), - DnsServers = DnsServers != null ? new List(DnsServers) : new List { gatewayIp.ToString() } - }; - - var updateDhcpTask = Task.Run(async () => await dhcpService.UpdateServerAsync(vlanInterfaceName, dhcpConfig)); - updateDhcpTask.GetAwaiter().GetResult(); - - WriteVerbose($"Configured DHCP server for interface {vlanInterfaceName} with range {dhcpStart} - {dhcpEnd}"); - } - - // Add the created VLAN to the list - var vlanInfo = new PSObject(); - vlanInfo.Properties.Add(new PSNoteProperty("VlanId", vlanId)); - vlanInfo.Properties.Add(new PSNoteProperty("Subnet", subnet.ToString())); - vlanInfo.Properties.Add(new PSNoteProperty("Gateway", gatewayIp.ToString())); - vlanInfo.Properties.Add(new PSNoteProperty("Uuid", createVlanResult.Uuid)); - vlanInfo.Properties.Add(new PSNoteProperty("Status", "Created")); - if (EnableDHCP.IsPresent) - { - vlanInfo.Properties.Add(new PSNoteProperty("DHCPRange", $"{dhcpStart} - {dhcpEnd}")); - } - - createdVlans.Add(vlanInfo); + return; } - // Increment the VLAN ID - vlanId += VlanIdIncrement; - subnetIndex++; + WriteVerbose($"Created VLAN {vlanId} on interface {ParentInterface} with UUID {createVlanResult.Uuid}"); + + // Configure the VLAN interface + string vlanInterfaceName = $"{ParentInterface}.{vlanId}"; + + var interfaceConfig = new InterfaceConfig + { + Description = description, + IpAddress = gatewayIp.ToString(), + SubnetMask = SubnetMaskBits.ToString(), + Enabled = "1" + }; + + var updateInterfaceResult = ExecuteAsyncTask(() => interfaceService.UpdateInterfaceAsync(vlanInterfaceName, interfaceConfig)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } + + WriteVerbose($"Configured interface {vlanInterfaceName} with IP {gatewayIp}/{SubnetMaskBits}"); + + // If EnableDHCP is specified, configure DHCP for the interface + if (EnableDHCP.IsPresent && dhcpService != null) + { + // Configure DHCP server for the interface + var dhcpConfig = new DHCPServerConfig + { + Enabled = "1", + RangeFrom = dhcpStart.ToString(), + RangeTo = dhcpEnd.ToString(), + DefaultLeaseTime = "7200", + MaxLeaseTime = "86400", + Domain = Domain, + Gateway = gatewayIp.ToString(), + DnsServers = DnsServers != null ? new List(DnsServers) : new List { gatewayIp.ToString() } + }; + + var updateDhcpResult = ExecuteAsyncTask(() => dhcpService.UpdateServerAsync(vlanInterfaceName, dhcpConfig)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } + + WriteVerbose($"Configured DHCP server for interface {vlanInterfaceName} with range {dhcpStart} - {dhcpEnd}"); + } + + // Add the created VLAN to the list + var vlanInfo = new PSObject(); + vlanInfo.Properties.Add(new PSNoteProperty("VlanId", vlanId)); + vlanInfo.Properties.Add(new PSNoteProperty("Subnet", subnet.ToString())); + vlanInfo.Properties.Add(new PSNoteProperty("Gateway", gatewayIp.ToString())); + vlanInfo.Properties.Add(new PSNoteProperty("Uuid", createVlanResult.Uuid)); + vlanInfo.Properties.Add(new PSNoteProperty("Status", "Created")); + if (EnableDHCP.IsPresent) + { + vlanInfo.Properties.Add(new PSNoteProperty("DHCPRange", $"{dhcpStart} - {dhcpEnd}")); + } + + createdVlans.Add(vlanInfo); } - // Apply DHCP changes if needed - if (EnableDHCP.IsPresent && dhcpService != null) - { - var applyDhcpTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); - var applyDhcpResult = applyDhcpTask.GetAwaiter().GetResult(); - WriteVerbose($"Applied DHCP changes: {applyDhcpResult.Status}"); - } - - // Create a result object - var result = new PSObject(); - result.Properties.Add(new PSNoteProperty("ParentInterface", ParentInterface)); - result.Properties.Add(new PSNoteProperty("Network", Network)); - result.Properties.Add(new PSNoteProperty("SubnetMaskBits", SubnetMaskBits)); - result.Properties.Add(new PSNoteProperty("VLANs", createdVlans)); - - WriteObject(result); + // Increment the VLAN ID + vlanId += VlanIdIncrement; + subnetIndex++; } - catch (Exception ex) + + // Apply DHCP changes if needed + if (EnableDHCP.IsPresent && dhcpService != null) { - HandleException(ex); + var applyDhcpResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyDhcpResult == null) + { + return; + } + + WriteVerbose($"Applied DHCP changes: {applyDhcpResult.Status}"); } + + // Create a result object + var result = new PSObject(); + result.Properties.Add(new PSNoteProperty("ParentInterface", ParentInterface)); + result.Properties.Add(new PSNoteProperty("Network", Network)); + result.Properties.Add(new PSNoteProperty("SubnetMaskBits", SubnetMaskBits)); + result.Properties.Add(new PSNoteProperty("VLANs", createdVlans)); + + WriteObject(result); } /// diff --git a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseVLANCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseVLANCmdlet.cs index 0e1f514..bd3b7c6 100644 --- a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseVLANCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseVLANCmdlet.cs @@ -48,30 +48,29 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var interfaceService = new InterfaceService(ApiClient, Logger); + + var vlan = new VLANConfig { - var interfaceService = new InterfaceService(ApiClient, Logger); + Interface = Interface, + Tag = Tag.ToString(), + Priority = Priority.ToString(), + Description = Description + }; - var vlan = new VLANConfig - { - Interface = Interface, - Tag = Tag.ToString(), - Priority = Priority.ToString(), - Description = Description - }; + // Use our safe execution method + var result = ExecuteAsyncTask(() => interfaceService.CreateVLANAsync(vlan)); - var task = Task.Run(async () => await interfaceService.CreateVLANAsync(vlan)); - var result = task.GetAwaiter().GetResult(); - - WriteVerbose($"Created VLAN with UUID {result.Uuid}"); - WriteObject(result.Uuid); - } - catch (Exception ex) + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { - HandleException(ex); + return; } + + WriteVerbose($"Created VLAN with UUID {result.Uuid}"); + WriteObject(result.Uuid); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseAliasCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseAliasCmdlet.cs index dbd21fb..97bb633 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseAliasCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseAliasCmdlet.cs @@ -50,44 +50,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var aliasService = new AliasService(ApiClient, Logger); + + // Get the alias details for the confirmation message + var getResult = ExecuteAsyncTask(() => aliasService.GetAliasAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var aliasService = new AliasService(ApiClient, Logger); + return; + } - // Get the alias details for the confirmation message - var getTask = Task.Run(async () => await aliasService.GetAliasAsync(Uuid)); - var alias = getTask.GetAwaiter().GetResult().Alias; + var alias = getResult.Alias; - string confirmMessage = $"Alias: {alias.Name} ({alias.Type})"; - if (!string.IsNullOrEmpty(alias.Description)) - { - confirmMessage += $" - {alias.Description}"; - } + string confirmMessage = $"Alias: {alias.Name} ({alias.Type})"; + if (!string.IsNullOrEmpty(alias.Description)) + { + confirmMessage += $" - {alias.Description}"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => aliasService.DeleteAliasAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"Alias {Uuid} removed: {deleteResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => aliasService.ReconfigureAliasesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await aliasService.DeleteAliasAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"Alias {Uuid} removed: {deleteResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await aliasService.ReconfigureAliasesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"Alias changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"Alias changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPLeaseCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPLeaseCmdlet.cs index 7ea15bb..1a9eeee 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPLeaseCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPLeaseCmdlet.cs @@ -45,44 +45,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dhcpService = new DHCPService(ApiClient, Logger); + + // Get the lease details for the confirmation message + var getResult = ExecuteAsyncTask(() => dhcpService.GetLeaseByMacAsync(MacAddress)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dhcpService = new DHCPService(ApiClient, Logger); + return; + } - // Get the lease details for the confirmation message - var getTask = Task.Run(async () => await dhcpService.GetLeaseByMacAsync(MacAddress)); - var lease = getTask.GetAwaiter().GetResult().Lease; + var lease = getResult.Lease; - string confirmMessage = $"DHCP lease: {lease.MacAddress} -> {lease.IpAddress}"; - if (!string.IsNullOrEmpty(lease.Hostname)) - { - confirmMessage += $" ({lease.Hostname})"; - } + string confirmMessage = $"DHCP lease: {lease.MacAddress} -> {lease.IpAddress}"; + if (!string.IsNullOrEmpty(lease.Hostname)) + { + confirmMessage += $" ({lease.Hostname})"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => dhcpService.DeleteLeaseAsync(MacAddress)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"DHCP lease {MacAddress} removed: {deleteResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await dhcpService.DeleteLeaseAsync(MacAddress)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP lease {MacAddress} removed: {deleteResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"DHCP changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPOptionCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPOptionCmdlet.cs index 441b9dd..d3eab4e 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPOptionCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPOptionCmdlet.cs @@ -52,44 +52,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dhcpService = new DHCPService(ApiClient, Logger); + + // Get the option details for the confirmation message + var getResult = ExecuteAsyncTask(() => dhcpService.GetOptionAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dhcpService = new DHCPService(ApiClient, Logger); + return; + } - // Get the option details for the confirmation message - var getTask = Task.Run(async () => await dhcpService.GetOptionAsync(Interface, Uuid)); - var option = getTask.GetAwaiter().GetResult().Option; + var option = getResult.Option; - string confirmMessage = $"DHCP option: {option.Number} = {option.Value}"; - if (!string.IsNullOrEmpty(option.Description)) - { - confirmMessage += $" ({option.Description})"; - } + string confirmMessage = $"DHCP option: {option.Number} = {option.Value}"; + if (!string.IsNullOrEmpty(option.Description)) + { + confirmMessage += $" ({option.Description})"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => dhcpService.DeleteOptionAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"DHCP option {Uuid} removed: {deleteResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await dhcpService.DeleteOptionAsync(Interface, Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP option {Uuid} removed: {deleteResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"DHCP changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPStaticMappingCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPStaticMappingCmdlet.cs index 3676511..5dc8c5f 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPStaticMappingCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDHCPStaticMappingCmdlet.cs @@ -52,44 +52,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dhcpService = new DHCPService(ApiClient, Logger); + + // Get the mapping details for the confirmation message + var getResult = ExecuteAsyncTask(() => dhcpService.GetStaticMappingAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dhcpService = new DHCPService(ApiClient, Logger); + return; + } - // Get the mapping details for the confirmation message - var getTask = Task.Run(async () => await dhcpService.GetStaticMappingAsync(Interface, Uuid)); - var mapping = getTask.GetAwaiter().GetResult().Mapping; + var mapping = getResult.Mapping; - string confirmMessage = $"Static mapping: {mapping.MacAddress} -> {mapping.IpAddress}"; - if (!string.IsNullOrEmpty(mapping.Hostname)) - { - confirmMessage += $" ({mapping.Hostname})"; - } + string confirmMessage = $"Static mapping: {mapping.MacAddress} -> {mapping.IpAddress}"; + if (!string.IsNullOrEmpty(mapping.Hostname)) + { + confirmMessage += $" ({mapping.Hostname})"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => dhcpService.DeleteStaticMappingAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"Static mapping {Uuid} removed: {deleteResult.Result}"); + + // Apply the changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await dhcpService.DeleteStaticMappingAsync(Interface, Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"Static mapping {Uuid} removed: {deleteResult.Result}"); - - // Apply the changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"DHCP changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSForwardingHostCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSForwardingHostCmdlet.cs index 52c7f6e..c1bc7c7 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSForwardingHostCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSForwardingHostCmdlet.cs @@ -45,44 +45,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dnsService = new DNSService(ApiClient, Logger); + + // Get the host details for the confirmation message + var getResult = ExecuteAsyncTask(() => dnsService.GetDNSForwardingHostAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dnsService = new DNSService(ApiClient, Logger); + return; + } - // Get the host details for the confirmation message - var getTask = Task.Run(async () => await dnsService.GetDNSForwardingHostAsync(Uuid)); - var host = getTask.GetAwaiter().GetResult().Host; + var host = getResult.Host; - string confirmMessage = $"DNS forwarding host: {host.Domain} -> {host.Server}"; - if (!string.IsNullOrEmpty(host.Description)) - { - confirmMessage += $" ({host.Description})"; - } + string confirmMessage = $"DNS forwarding host: {host.Domain} -> {host.Server}"; + if (!string.IsNullOrEmpty(host.Description)) + { + confirmMessage += $" ({host.Description})"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => dnsService.DeleteDNSForwardingHostAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"DNS forwarding host {Uuid} removed: {deleteResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await dnsService.DeleteDNSForwardingHostAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS forwarding host {Uuid} removed: {deleteResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"DNS changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSOverrideCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSOverrideCmdlet.cs index 0777b50..c9fa2c5 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSOverrideCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseDNSOverrideCmdlet.cs @@ -45,44 +45,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dnsService = new DNSService(ApiClient, Logger); + + // Get the DNS override details for the confirmation message + var getResult = ExecuteAsyncTask(() => dnsService.GetDNSOverrideAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dnsService = new DNSService(ApiClient, Logger); + return; + } - // Get the DNS override details for the confirmation message - var getTask = Task.Run(async () => await dnsService.GetDNSOverrideAsync(Uuid)); - var dnsOverride = getTask.GetAwaiter().GetResult().Host; + var dnsOverride = getResult.Host; - string confirmMessage = $"DNS override {dnsOverride.Hostname}.{dnsOverride.Domain} -> {dnsOverride.IpAddress}"; - if (!string.IsNullOrEmpty(dnsOverride.Description)) - { - confirmMessage += $" ({dnsOverride.Description})"; - } + string confirmMessage = $"DNS override {dnsOverride.Hostname}.{dnsOverride.Domain} -> {dnsOverride.IpAddress}"; + if (!string.IsNullOrEmpty(dnsOverride.Description)) + { + confirmMessage += $" ({dnsOverride.Description})"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => dnsService.DeleteDNSOverrideAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"DNS override {Uuid} removed: {deleteResult.Result}"); + + // Apply the changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await dnsService.DeleteDNSOverrideAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS override {Uuid} removed: {deleteResult.Result}"); - - // Apply the changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"DNS changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseFirewallRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseFirewallRuleCmdlet.cs index 1a75381..235420e 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseFirewallRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseFirewallRuleCmdlet.cs @@ -39,36 +39,41 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var firewallService = new FirewallService(ApiClient, Logger); + + // Get the rule details for the confirmation message + var getResult = ExecuteAsyncTask(() => firewallService.GetRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var firewallService = new FirewallService(ApiClient, Logger); - - // Get the rule details for the confirmation message - var getTask = Task.Run(async () => await firewallService.GetRuleAsync(Uuid)); - var rule = getTask.GetAwaiter().GetResult().Rule; - - string confirmMessage = $"Firewall rule: {rule.Description}"; - if (!string.IsNullOrEmpty(rule.Protocol) && rule.Protocol != "any") - { - confirmMessage += $" ({rule.Protocol})"; - } - - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) - { - return; - } - - var deleteTask = Task.Run(async () => await firewallService.DeleteRuleAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"Firewall rule {Uuid} removed: {deleteResult.Result}"); + return; } - catch (Exception ex) + + var rule = getResult.Rule; + + string confirmMessage = $"Firewall rule: {rule.Description}"; + if (!string.IsNullOrEmpty(rule.Protocol) && rule.Protocol != "any") { - HandleException(ex); + confirmMessage += $" ({rule.Protocol})"; } + + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => firewallService.DeleteRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"Firewall rule {Uuid} removed: {deleteResult.Result}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseGatewayCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseGatewayCmdlet.cs index 7e10376..ff12f70 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseGatewayCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseGatewayCmdlet.cs @@ -45,44 +45,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var gatewayService = new GatewayService(ApiClient, Logger); + + // Get the gateway details for the confirmation message + var getResult = ExecuteAsyncTask(() => gatewayService.GetGatewayAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var gatewayService = new GatewayService(ApiClient, Logger); + return; + } - // Get the gateway details for the confirmation message - var getTask = Task.Run(async () => await gatewayService.GetGatewayAsync(Uuid)); - var gateway = getTask.GetAwaiter().GetResult().Gateway; + var gateway = getResult.Gateway; - string confirmMessage = $"Gateway: {gateway.Name} ({gateway.IpAddress})"; - if (!string.IsNullOrEmpty(gateway.Description)) - { - confirmMessage += $" - {gateway.Description}"; - } + string confirmMessage = $"Gateway: {gateway.Name} ({gateway.IpAddress})"; + if (!string.IsNullOrEmpty(gateway.Description)) + { + confirmMessage += $" - {gateway.Description}"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => gatewayService.DeleteGatewayAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"Gateway {Uuid} removed: {deleteResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => gatewayService.ApplyGatewayChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await gatewayService.DeleteGatewayAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"Gateway {Uuid} removed: {deleteResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await gatewayService.ApplyGatewayChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"Gateway changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"Gateway changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSensePortForwardingRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSensePortForwardingRuleCmdlet.cs index a3ec126..53918c3 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSensePortForwardingRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSensePortForwardingRuleCmdlet.cs @@ -13,7 +13,7 @@ namespace PSOPNSenseAPI.Cmdlets /// /// [Cmdlet(VerbsCommon.Remove, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)] - public class RemoveOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet + public class RemoveOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet { /// /// The UUID of the port forwarding rule to remove. @@ -30,12 +30,18 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - var portForwardingService = new PortForwardingService(SessionState.ApiClient); + var portForwardingService = new PortForwardingService(ApiClient); // Get the rule to display information in the confirmation message - var rule = Task.Run(async () => await portForwardingService.GetPortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); + var rule = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } if (rule == null) { @@ -52,7 +58,13 @@ namespace PSOPNSenseAPI.Cmdlets if (Force || ShouldProcess($"OPNSense firewall", confirmationMessage)) { - var success = Task.Run(async () => await portForwardingService.DeletePortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); + var success = ExecuteAsyncTask(() => portForwardingService.DeletePortForwardingRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } if (success) { @@ -60,11 +72,8 @@ namespace PSOPNSenseAPI.Cmdlets } else { - WriteError(new ErrorRecord( - new PSInvalidOperationException($"Failed to remove port forwarding rule with UUID '{Uuid}'."), - "PortForwardingRuleRemovalFailed", - ErrorCategory.InvalidOperation, - Uuid)); + ProcessingException = new PSInvalidOperationException($"Failed to remove port forwarding rule with UUID '{Uuid}'."); + WriteWarning($"Failed to remove port forwarding rule with UUID '{Uuid}'."); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseRouteCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseRouteCmdlet.cs index 502c19f..e0c1ece 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseRouteCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseRouteCmdlet.cs @@ -45,44 +45,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var routeService = new RouteService(ApiClient, Logger); + + // Get the route details for the confirmation message + var getResult = ExecuteAsyncTask(() => routeService.GetRouteAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var routeService = new RouteService(ApiClient, Logger); + return; + } - // Get the route details for the confirmation message - var getTask = Task.Run(async () => await routeService.GetRouteAsync(Uuid)); - var route = getTask.GetAwaiter().GetResult().Route; + var route = getResult.Route; - string confirmMessage = $"Route: {route.Network} via {route.Gateway}"; - if (!string.IsNullOrEmpty(route.Description)) - { - confirmMessage += $" ({route.Description})"; - } + string confirmMessage = $"Route: {route.Network} via {route.Gateway}"; + if (!string.IsNullOrEmpty(route.Description)) + { + confirmMessage += $" ({route.Description})"; + } - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => routeService.DeleteRouteAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"Route {Uuid} removed: {deleteResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => routeService.ApplyRouteChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) { return; } - var deleteTask = Task.Run(async () => await routeService.DeleteRouteAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"Route {Uuid} removed: {deleteResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await routeService.ApplyRouteChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"Route changes applied: {applyResult.Status}"); - } - } - catch (Exception ex) - { - HandleException(ex); + WriteVerbose($"Route changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseUserCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseUserCmdlet.cs index d92c844..1039bed 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseUserCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseUserCmdlet.cs @@ -39,36 +39,41 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var userService = new UserService(ApiClient, Logger); + + // Get the user details for the confirmation message + var getResult = ExecuteAsyncTask(() => userService.GetUserAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var userService = new UserService(ApiClient, Logger); - - // Get the user details for the confirmation message - var getTask = Task.Run(async () => await userService.GetUserAsync(Uuid)); - var user = getTask.GetAwaiter().GetResult().User; - - string confirmMessage = $"User: {user.Username}"; - if (!string.IsNullOrEmpty(user.FullName)) - { - confirmMessage += $" ({user.FullName})"; - } - - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) - { - return; - } - - var deleteTask = Task.Run(async () => await userService.DeleteUserAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"User {Uuid} removed: {deleteResult.Result}"); + return; } - catch (Exception ex) + + var user = getResult.User; + + string confirmMessage = $"User: {user.Username}"; + if (!string.IsNullOrEmpty(user.FullName)) { - HandleException(ex); + confirmMessage += $" ({user.FullName})"; } + + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => userService.DeleteUserAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"User {Uuid} removed: {deleteResult.Result}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseVLANCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseVLANCmdlet.cs index 752846d..ebc15e6 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseVLANCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RemoveOPNSenseVLANCmdlet.cs @@ -39,36 +39,41 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var interfaceService = new InterfaceService(ApiClient, Logger); + + // Get the VLAN details for the confirmation message + var getResult = ExecuteAsyncTask(() => interfaceService.GetVLANAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var interfaceService = new InterfaceService(ApiClient, Logger); - - // Get the VLAN details for the confirmation message - var getTask = Task.Run(async () => await interfaceService.GetVLANAsync(Uuid)); - var vlan = getTask.GetAwaiter().GetResult().Vlan; - - string confirmMessage = $"VLAN {vlan.Tag} on interface {vlan.Interface}"; - if (!string.IsNullOrEmpty(vlan.Description)) - { - confirmMessage += $" ({vlan.Description})"; - } - - if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) - { - return; - } - - var deleteTask = Task.Run(async () => await interfaceService.DeleteVLANAsync(Uuid)); - var deleteResult = deleteTask.GetAwaiter().GetResult(); - - WriteVerbose($"VLAN {Uuid} removed: {deleteResult.Result}"); + return; } - catch (Exception ex) + + var vlan = getResult.Vlan; + + string confirmMessage = $"VLAN {vlan.Tag} on interface {vlan.Interface}"; + if (!string.IsNullOrEmpty(vlan.Description)) { - HandleException(ex); + confirmMessage += $" ({vlan.Description})"; } + + if (!Force.IsPresent && !ShouldProcess(confirmMessage, "Remove")) + { + return; + } + + var deleteResult = ExecuteAsyncTask(() => interfaceService.DeleteVLANAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || deleteResult == null) + { + return; + } + + WriteVerbose($"VLAN {Uuid} removed: {deleteResult.Result}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/RestartOPNSenseFirewallCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RestartOPNSenseFirewallCmdlet.cs index e06872a..5357cf6 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RestartOPNSenseFirewallCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RestartOPNSenseFirewallCmdlet.cs @@ -130,14 +130,23 @@ namespace PSOPNSenseAPI.Cmdlets // Try to get the system status var statusService = new SystemService(newClient, logger); - // We need to use Task.Run here because we're creating a new client + // We need to handle this specially because we're using a new client // and can't use ExecuteAsyncTask which uses the existing client - var statusTask = Task.Run(async () => await statusService.GetStatusAsync()); - var statusResult = statusTask.GetAwaiter().GetResult(); + try + { + // Use ConfigureAwait(false) to avoid deadlocks + var statusResult = statusService.GetStatusAsync().ConfigureAwait(false).GetAwaiter().GetResult(); - // If we get here, the firewall is back online - WriteVerbose("Successfully reconnected to the firewall"); - WriteObject($"Firewall is back online. Uptime: {statusResult.Uptime}"); + // If we get here, the firewall is back online + WriteVerbose("Successfully reconnected to the firewall"); + WriteObject($"Firewall is back online. Uptime: {statusResult.Uptime}"); + } + catch (Exception innerEx) + { + // Just log and continue the retry loop + WriteVerbose($"Status check failed: {innerEx.Message}"); + throw; // Re-throw to be caught by the outer catch + } // Set the new session OPNSenseSession.Current = newClient; diff --git a/src/PSOPNSenseAPI/Cmdlets/RestoreOPNSenseConfigCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/RestoreOPNSenseConfigCmdlet.cs index eff9bc8..77def24 100644 --- a/src/PSOPNSenseAPI/Cmdlets/RestoreOPNSenseConfigCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/RestoreOPNSenseConfigCmdlet.cs @@ -53,26 +53,33 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try - { - var configService = new ConfigService(ApiClient, Logger); - string actionDescription = "Restore configuration"; - string targetName = ParameterSetName == "Filename" ? Filename : "from XML document"; + var configService = new ConfigService(ApiClient, Logger); + string actionDescription = "Restore configuration"; + string targetName = ParameterSetName == "Filename" ? Filename : "from XML document"; - if (!Force.IsPresent && !ShouldProcess(targetName, actionDescription)) + if (!Force.IsPresent && !ShouldProcess(targetName, actionDescription)) + { + return; + } + + if (ParameterSetName == "Filename") + { + // Use our safe execution method + var result = ExecuteAsyncTask(() => configService.RestoreConfigBackupAsync(Filename)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) { return; } - if (ParameterSetName == "Filename") - { - // Restore from backup file - execute synchronously on the main thread - var result = configService.RestoreConfigBackupAsync(Filename).GetAwaiter().GetResult(); - WriteVerbose($"Restored configuration from backup: {result.Status}"); - } - else + WriteVerbose($"Restored configuration from backup: {result.Status}"); + } + else + { + try { // Restore from XML document byte[] configContent; @@ -82,17 +89,26 @@ namespace PSOPNSenseAPI.Cmdlets configContent = memoryStream.ToArray(); } - // Execute synchronously on the main thread - var result = configService.ImportConfigAsync(configContent).GetAwaiter().GetResult(); + // Use our safe execution method + var result = ExecuteAsyncTask(() => configService.ImportConfigAsync(configContent)); + + // Only continue if no exception occurred + if (ProcessingException != null || result == null) + { + return; + } + WriteVerbose($"Restored configuration from XML document: {result.Status}"); } + catch (Exception ex) + { + ProcessingException = ex; + WriteWarning($"Failed to process XML document: {ex.Message}"); + return; + } + } - WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online."); - } - catch (Exception ex) - { - HandleException(ex); - } + WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online."); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseAliasCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseAliasCmdlet.cs index 6d2dd5e..5621938 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseAliasCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseAliasCmdlet.cs @@ -94,83 +94,93 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var aliasService = new AliasService(ApiClient, Logger); + + // Get current alias + var getResult = ExecuteAsyncTask(() => aliasService.GetAliasAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var aliasService = new AliasService(ApiClient, Logger); - - // Get current alias - var getTask = Task.Run(async () => await aliasService.GetAliasAsync(Uuid)); - var currentAlias = getTask.GetAwaiter().GetResult().Alias; - - // Create updated alias - var alias = new AliasConfig - { - Name = currentAlias.Name, - Type = currentAlias.Type, - Content = Content ?? currentAlias.Content, - Description = Description ?? currentAlias.Description, - Protocol = Protocol?.ToUpper() ?? currentAlias.Protocol, - UpdateFrequency = UpdateFrequency?.ToString() ?? currentAlias.UpdateFrequency, - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - alias.Enabled = "1"; - } - else if (Enabled.IsPresent) - { - alias.Enabled = "1"; - } - else if (Disabled.IsPresent) - { - alias.Enabled = "0"; - } - else - { - alias.Enabled = currentAlias.Enabled; - } - - // Handle counters - if (EnableCounters.IsPresent && DisableCounters.IsPresent) - { - WriteWarning("Both -EnableCounters and -DisableCounters parameters were specified. Using -EnableCounters."); - alias.Counters = "1"; - } - else if (EnableCounters.IsPresent) - { - alias.Counters = "1"; - } - else if (DisableCounters.IsPresent) - { - alias.Counters = "0"; - } - else - { - alias.Counters = currentAlias.Counters; - } - - // Update alias - var updateTask = Task.Run(async () => await aliasService.UpdateAliasAsync(Uuid, alias)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"Alias {Uuid} updated: {updateResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await aliasService.ReconfigureAliasesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"Alias changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentAlias = getResult.Alias; + + // Create updated alias + var alias = new AliasConfig { - HandleException(ex); + Name = currentAlias.Name, + Type = currentAlias.Type, + Content = Content ?? currentAlias.Content, + Description = Description ?? currentAlias.Description, + Protocol = Protocol?.ToUpper() ?? currentAlias.Protocol, + UpdateFrequency = UpdateFrequency?.ToString() ?? currentAlias.UpdateFrequency, + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + alias.Enabled = "1"; + } + else if (Enabled.IsPresent) + { + alias.Enabled = "1"; + } + else if (Disabled.IsPresent) + { + alias.Enabled = "0"; + } + else + { + alias.Enabled = currentAlias.Enabled; + } + + // Handle counters + if (EnableCounters.IsPresent && DisableCounters.IsPresent) + { + WriteWarning("Both -EnableCounters and -DisableCounters parameters were specified. Using -EnableCounters."); + alias.Counters = "1"; + } + else if (EnableCounters.IsPresent) + { + alias.Counters = "1"; + } + else if (DisableCounters.IsPresent) + { + alias.Counters = "0"; + } + else + { + alias.Counters = currentAlias.Counters; + } + + // Update alias + var updateResult = ExecuteAsyncTask(() => aliasService.UpdateAliasAsync(Uuid, alias)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"Alias {Uuid} updated: {updateResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => aliasService.ReconfigureAliasesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"Alias changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPOptionCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPOptionCmdlet.cs index f150502..610a649 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPOptionCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPOptionCmdlet.cs @@ -66,43 +66,53 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dhcpService = new DHCPService(ApiClient, Logger); + + // Get current option + var getResult = ExecuteAsyncTask(() => dhcpService.GetOptionAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dhcpService = new DHCPService(ApiClient, Logger); - - // Get current option - var getTask = Task.Run(async () => await dhcpService.GetOptionAsync(Interface, Uuid)); - var currentOption = getTask.GetAwaiter().GetResult().Option; - - // Create updated option - var option = new DHCPOptionConfig - { - Number = Number ?? currentOption.Number, - Value = Value ?? currentOption.Value, - Type = Type ?? currentOption.Type, - Description = Description ?? currentOption.Description - }; - - // Update option - var updateTask = Task.Run(async () => await dhcpService.UpdateOptionAsync(Interface, Uuid, option)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP option {Uuid} updated: {updateResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentOption = getResult.Option; + + // Create updated option + var option = new DHCPOptionConfig { - HandleException(ex); + Number = Number ?? currentOption.Number, + Value = Value ?? currentOption.Value, + Type = Type ?? currentOption.Type, + Description = Description ?? currentOption.Description + }; + + // Update option + var updateResult = ExecuteAsyncTask(() => dhcpService.UpdateOptionAsync(Interface, Uuid, option)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"DHCP option {Uuid} updated: {updateResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"DHCP changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPServerCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPServerCmdlet.cs index 229bd2a..6b8a928 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPServerCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPServerCmdlet.cs @@ -94,65 +94,75 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dhcpService = new DHCPService(ApiClient, Logger); + + // First, get the current server configuration + var getResult = ExecuteAsyncTask(() => dhcpService.GetServerAsync(Interface)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dhcpService = new DHCPService(ApiClient, Logger); - - // First, get the current server configuration - var getTask = Task.Run(async () => await dhcpService.GetServerAsync(Interface)); - var currentServer = getTask.GetAwaiter().GetResult().Server; - - // Create the updated configuration - var server = new DHCPServerConfig - { - RangeFrom = RangeFrom ?? currentServer.RangeFrom, - RangeTo = RangeTo ?? currentServer.RangeTo, - DefaultLeaseTime = DefaultLeaseTime?.ToString() ?? currentServer.DefaultLeaseTime, - MaxLeaseTime = MaxLeaseTime?.ToString() ?? currentServer.MaxLeaseTime, - Domain = Domain ?? currentServer.Domain, - DnsServers = DnsServers != null ? new List(DnsServers) : currentServer.DnsServers, - Gateway = Gateway ?? currentServer.Gateway - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - server.Enabled = "1"; - } - else if (Enabled.IsPresent) - { - server.Enabled = "1"; - } - else if (Disabled.IsPresent) - { - server.Enabled = "0"; - } - else - { - server.Enabled = currentServer.Enabled; - } - - // Update the server - var updateTask = Task.Run(async () => await dhcpService.UpdateServerAsync(Interface, server)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP server for interface {Interface} updated: {updateResult.Result}"); - - // Apply the changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentServer = getResult.Server; + + // Create the updated configuration + var server = new DHCPServerConfig { - HandleException(ex); + RangeFrom = RangeFrom ?? currentServer.RangeFrom, + RangeTo = RangeTo ?? currentServer.RangeTo, + DefaultLeaseTime = DefaultLeaseTime?.ToString() ?? currentServer.DefaultLeaseTime, + MaxLeaseTime = MaxLeaseTime?.ToString() ?? currentServer.MaxLeaseTime, + Domain = Domain ?? currentServer.Domain, + DnsServers = DnsServers != null ? new List(DnsServers) : currentServer.DnsServers, + Gateway = Gateway ?? currentServer.Gateway + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + server.Enabled = "1"; + } + else if (Enabled.IsPresent) + { + server.Enabled = "1"; + } + else if (Disabled.IsPresent) + { + server.Enabled = "0"; + } + else + { + server.Enabled = currentServer.Enabled; + } + + // Update the server + var updateResult = ExecuteAsyncTask(() => dhcpService.UpdateServerAsync(Interface, server)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"DHCP server for interface {Interface} updated: {updateResult.Result}"); + + // Apply the changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"DHCP changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPStaticMappingCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPStaticMappingCmdlet.cs index 9abf4d8..77353e9 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPStaticMappingCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDHCPStaticMappingCmdlet.cs @@ -82,62 +82,72 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dhcpService = new DHCPService(ApiClient, Logger); + + // First, get the current mapping + var getResult = ExecuteAsyncTask(() => dhcpService.GetStaticMappingAsync(Interface, Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dhcpService = new DHCPService(ApiClient, Logger); - - // First, get the current mapping - var getTask = Task.Run(async () => await dhcpService.GetStaticMappingAsync(Interface, Uuid)); - var currentMapping = getTask.GetAwaiter().GetResult().Mapping; - - // Create the updated mapping - var mapping = new DHCPStaticMappingConfig - { - MacAddress = MacAddress ?? currentMapping.MacAddress, - IpAddress = IpAddress ?? currentMapping.IpAddress, - Hostname = Hostname ?? currentMapping.Hostname, - Description = Description ?? currentMapping.Description - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - mapping.Enabled = "1"; - } - else if (Enabled.IsPresent) - { - mapping.Enabled = "1"; - } - else if (Disabled.IsPresent) - { - mapping.Enabled = "0"; - } - else - { - mapping.Enabled = currentMapping.Enabled; - } - - // Update the mapping - var updateTask = Task.Run(async () => await dhcpService.UpdateStaticMappingAsync(Interface, Uuid, mapping)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"Static mapping {Uuid} updated: {updateResult.Result}"); - - // Apply the changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DHCP changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentMapping = getResult.Mapping; + + // Create the updated mapping + var mapping = new DHCPStaticMappingConfig { - HandleException(ex); + MacAddress = MacAddress ?? currentMapping.MacAddress, + IpAddress = IpAddress ?? currentMapping.IpAddress, + Hostname = Hostname ?? currentMapping.Hostname, + Description = Description ?? currentMapping.Description + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + mapping.Enabled = "1"; + } + else if (Enabled.IsPresent) + { + mapping.Enabled = "1"; + } + else if (Disabled.IsPresent) + { + mapping.Enabled = "0"; + } + else + { + mapping.Enabled = currentMapping.Enabled; + } + + // Update the mapping + var updateResult = ExecuteAsyncTask(() => dhcpService.UpdateStaticMappingAsync(Interface, Uuid, mapping)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"Static mapping {Uuid} updated: {updateResult.Result}"); + + // Apply the changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"DHCP changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingCmdlet.cs index e170b55..0c61863 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingCmdlet.cs @@ -58,69 +58,79 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dnsService = new DNSService(ApiClient, Logger); + + // Get current configuration + var getResult = ExecuteAsyncTask(() => dnsService.GetDNSForwardingAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dnsService = new DNSService(ApiClient, Logger); - - // Get current configuration - var getTask = Task.Run(async () => await dnsService.GetDNSForwardingAsync()); - var currentConfig = getTask.GetAwaiter().GetResult().Forward; - - // Create updated configuration - var config = new DNSForwardingConfig - { - Type = Type ?? currentConfig.Type - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - config.Enabled = "1"; - } - else if (Enabled.IsPresent) - { - config.Enabled = "1"; - } - else if (Disabled.IsPresent) - { - config.Enabled = "0"; - } - else - { - config.Enabled = currentConfig.Enabled; - } - - // Handle DNS servers - if (DnsServers != null && DnsServers.Length > 0) - { - config.DnsServers = new List(DnsServers); - } - else - { - config.DnsServers = currentConfig.DnsServers; - } - - // Update configuration - var updateTask = Task.Run(async () => await dnsService.UpdateDNSForwardingAsync(config)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS forwarding configuration updated: {updateResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentConfig = getResult.Forward; + + // Create updated configuration + var config = new DNSForwardingConfig { - HandleException(ex); + Type = Type ?? currentConfig.Type + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + config.Enabled = "1"; + } + else if (Enabled.IsPresent) + { + config.Enabled = "1"; + } + else if (Disabled.IsPresent) + { + config.Enabled = "0"; + } + else + { + config.Enabled = currentConfig.Enabled; + } + + // Handle DNS servers + if (DnsServers != null && DnsServers.Length > 0) + { + config.DnsServers = new List(DnsServers); + } + else + { + config.DnsServers = currentConfig.DnsServers; + } + + // Update configuration + var updateResult = ExecuteAsyncTask(() => dnsService.UpdateDNSForwardingAsync(config)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"DNS forwarding configuration updated: {updateResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"DNS changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingHostCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingHostCmdlet.cs index 29068e5..ca5a862 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingHostCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSForwardingHostCmdlet.cs @@ -69,61 +69,71 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dnsService = new DNSService(ApiClient, Logger); + + // Get current host + var getResult = ExecuteAsyncTask(() => dnsService.GetDNSForwardingHostAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dnsService = new DNSService(ApiClient, Logger); - - // Get current host - var getTask = Task.Run(async () => await dnsService.GetDNSForwardingHostAsync(Uuid)); - var currentHost = getTask.GetAwaiter().GetResult().Host; - - // Create updated host - var host = new DNSForwardingHostConfig - { - Domain = Domain ?? currentHost.Domain, - Server = Server ?? currentHost.Server, - Description = Description ?? currentHost.Description - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - host.Enabled = "1"; - } - else if (Enabled.IsPresent) - { - host.Enabled = "1"; - } - else if (Disabled.IsPresent) - { - host.Enabled = "0"; - } - else - { - host.Enabled = currentHost.Enabled; - } - - // Update host - var updateTask = Task.Run(async () => await dnsService.UpdateDNSForwardingHostAsync(Uuid, host)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS forwarding host {Uuid} updated: {updateResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentHost = getResult.Host; + + // Create updated host + var host = new DNSForwardingHostConfig { - HandleException(ex); + Domain = Domain ?? currentHost.Domain, + Server = Server ?? currentHost.Server, + Description = Description ?? currentHost.Description + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + host.Enabled = "1"; + } + else if (Enabled.IsPresent) + { + host.Enabled = "1"; + } + else if (Disabled.IsPresent) + { + host.Enabled = "0"; + } + else + { + host.Enabled = currentHost.Enabled; + } + + // Update host + var updateResult = ExecuteAsyncTask(() => dnsService.UpdateDNSForwardingHostAsync(Uuid, host)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"DNS forwarding host {Uuid} updated: {updateResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"DNS changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSServerCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSServerCmdlet.cs index 90c3a01..f154d06 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSServerCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseDNSServerCmdlet.cs @@ -82,48 +82,58 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var dnsService = new DNSService(ApiClient, Logger); + + // First, get the current DNS configuration + var getResult = ExecuteAsyncTask(() => dnsService.GetDNSConfigAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var dnsService = new DNSService(ApiClient, Logger); - - // First, get the current DNS configuration - var getTask = Task.Run(async () => await dnsService.GetDNSConfigAsync()); - var currentConfig = getTask.GetAwaiter().GetResult().Unbound; - - // Create the updated configuration - var dnsConfig = new DNSConfig - { - Enabled = MyInvocation.BoundParameters.ContainsKey(nameof(Enabled)) ? (Enabled.IsPresent ? "1" : "0") : currentConfig.Enabled, - Port = Port?.ToString() ?? currentConfig.Port, - Interfaces = Interfaces != null ? new List(Interfaces) : currentConfig.Interfaces, - Forwarding = MyInvocation.BoundParameters.ContainsKey(nameof(Forwarding)) ? (Forwarding.IsPresent ? "1" : "0") : currentConfig.Forwarding, - Forwarders = Forwarders != null ? new List(Forwarders) : currentConfig.Forwarders, - RegisterDhcp = MyInvocation.BoundParameters.ContainsKey(nameof(RegisterDhcp)) ? (RegisterDhcp.IsPresent ? "1" : "0") : currentConfig.RegisterDhcp, - RegisterDhcpDomain = RegisterDhcpDomain ?? currentConfig.RegisterDhcpDomain, - RegisterDhcpStatic = MyInvocation.BoundParameters.ContainsKey(nameof(RegisterDhcpStatic)) ? (RegisterDhcpStatic.IsPresent ? "1" : "0") : currentConfig.RegisterDhcpStatic, - ActiveInterfaces = currentConfig.ActiveInterfaces - }; - - // Update the DNS configuration - var updateTask = Task.Run(async () => await dnsService.UpdateDNSConfigAsync(dnsConfig)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS server configuration updated: {updateResult.Result}"); - - // Apply the changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"DNS changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentConfig = getResult.Unbound; + + // Create the updated configuration + var dnsConfig = new DNSConfig { - HandleException(ex); + Enabled = MyInvocation.BoundParameters.ContainsKey(nameof(Enabled)) ? (Enabled.IsPresent ? "1" : "0") : currentConfig.Enabled, + Port = Port?.ToString() ?? currentConfig.Port, + Interfaces = Interfaces != null ? new List(Interfaces) : currentConfig.Interfaces, + Forwarding = MyInvocation.BoundParameters.ContainsKey(nameof(Forwarding)) ? (Forwarding.IsPresent ? "1" : "0") : currentConfig.Forwarding, + Forwarders = Forwarders != null ? new List(Forwarders) : currentConfig.Forwarders, + RegisterDhcp = MyInvocation.BoundParameters.ContainsKey(nameof(RegisterDhcp)) ? (RegisterDhcp.IsPresent ? "1" : "0") : currentConfig.RegisterDhcp, + RegisterDhcpDomain = RegisterDhcpDomain ?? currentConfig.RegisterDhcpDomain, + RegisterDhcpStatic = MyInvocation.BoundParameters.ContainsKey(nameof(RegisterDhcpStatic)) ? (RegisterDhcpStatic.IsPresent ? "1" : "0") : currentConfig.RegisterDhcpStatic, + ActiveInterfaces = currentConfig.ActiveInterfaces + }; + + // Update the DNS configuration + var updateResult = ExecuteAsyncTask(() => dnsService.UpdateDNSConfigAsync(dnsConfig)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"DNS server configuration updated: {updateResult.Result}"); + + // Apply the changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"DNS changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseFirewallRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseFirewallRuleCmdlet.cs index 84ea326..2d86266 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseFirewallRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseFirewallRuleCmdlet.cs @@ -95,58 +95,63 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var firewallService = new FirewallService(ApiClient, Logger); + + // First, get the current rule + var getResult = ExecuteAsyncTask(() => firewallService.GetRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var firewallService = new FirewallService(ApiClient, Logger); - - // First, get the current rule - var getTask = Task.Run(async () => await firewallService.GetRuleAsync(Uuid)); - var currentRule = getTask.GetAwaiter().GetResult().Rule; - - // Create the updated rule - var rule = new FirewallRuleCreate - { - Description = Description ?? currentRule.Description, - Protocol = Protocol ?? currentRule.Protocol, - SourceNet = SourceNet ?? currentRule.SourceNet, - SourcePort = SourcePort ?? currentRule.SourcePort, - DestinationNet = DestinationNet ?? currentRule.DestinationNet, - DestinationPort = DestinationPort ?? currentRule.DestinationPort, - Action = Action ?? currentRule.Action, - Sequence = Sequence ?? currentRule.Sequence - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - rule.Enabled = "1"; - } - else if (Enabled.IsPresent) - { - rule.Enabled = "1"; - } - else if (Disabled.IsPresent) - { - rule.Enabled = "0"; - } - else - { - rule.Enabled = currentRule.Enabled; - } - - // Update the rule - var updateTask = Task.Run(async () => await firewallService.UpdateRuleAsync(Uuid, rule)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"Firewall rule {Uuid} updated: {updateResult.Result}"); + return; } - catch (Exception ex) + + var currentRule = getResult.Rule; + + // Create the updated rule + var rule = new FirewallRuleCreate { - HandleException(ex); + Description = Description ?? currentRule.Description, + Protocol = Protocol ?? currentRule.Protocol, + SourceNet = SourceNet ?? currentRule.SourceNet, + SourcePort = SourcePort ?? currentRule.SourcePort, + DestinationNet = DestinationNet ?? currentRule.DestinationNet, + DestinationPort = DestinationPort ?? currentRule.DestinationPort, + Action = Action ?? currentRule.Action, + Sequence = Sequence ?? currentRule.Sequence + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + rule.Enabled = "1"; } + else if (Enabled.IsPresent) + { + rule.Enabled = "1"; + } + else if (Disabled.IsPresent) + { + rule.Enabled = "0"; + } + else + { + rule.Enabled = currentRule.Enabled; + } + + // Update the rule + var updateResult = ExecuteAsyncTask(() => firewallService.UpdateRuleAsync(Uuid, rule)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"Firewall rule {Uuid} updated: {updateResult.Result}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseGatewayCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseGatewayCmdlet.cs index 0cf6c28..719d090 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseGatewayCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseGatewayCmdlet.cs @@ -131,122 +131,132 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var gatewayService = new GatewayService(ApiClient, Logger); + + // Get current gateway + var getResult = ExecuteAsyncTask(() => gatewayService.GetGatewayAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var gatewayService = new GatewayService(ApiClient, Logger); - - // Get current gateway - var getTask = Task.Run(async () => await gatewayService.GetGatewayAsync(Uuid)); - var currentGateway = getTask.GetAwaiter().GetResult().Gateway; - - // Create updated gateway - var gateway = new GatewayConfig - { - Name = Name ?? currentGateway.Name, - Interface = Interface ?? currentGateway.Interface, - IpAddress = IpAddress ?? currentGateway.IpAddress, - MonitorIp = MonitorIp ?? currentGateway.MonitorIp, - Description = Description ?? currentGateway.Description, - Weight = Weight?.ToString() ?? currentGateway.Weight, - IpProtocol = IpProtocol ?? currentGateway.IpProtocol - }; - - // Handle default/not default - if (Default.IsPresent && NotDefault.IsPresent) - { - WriteWarning("Both -Default and -NotDefault parameters were specified. Using -Default."); - gateway.IsDefault = "1"; - } - else if (Default.IsPresent) - { - gateway.IsDefault = "1"; - } - else if (NotDefault.IsPresent) - { - gateway.IsDefault = "0"; - } - else - { - gateway.IsDefault = currentGateway.IsDefault; - } - - // Handle enabled/disabled - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - gateway.Disabled = "0"; - } - else if (Enabled.IsPresent) - { - gateway.Disabled = "0"; - } - else if (Disabled.IsPresent) - { - gateway.Disabled = "1"; - } - else - { - gateway.Disabled = currentGateway.Disabled; - } - - // Handle monitoring - if (EnableMonitoring.IsPresent && DisableMonitoring.IsPresent) - { - WriteWarning("Both -EnableMonitoring and -DisableMonitoring parameters were specified. Using -EnableMonitoring."); - gateway.MonitorDisable = "0"; - } - else if (EnableMonitoring.IsPresent) - { - gateway.MonitorDisable = "0"; - } - else if (DisableMonitoring.IsPresent) - { - gateway.MonitorDisable = "1"; - } - else - { - gateway.MonitorDisable = currentGateway.MonitorDisable; - } - - // Handle force down - if (ForceDown.IsPresent && NoForceDown.IsPresent) - { - WriteWarning("Both -ForceDown and -NoForceDown parameters were specified. Using -ForceDown."); - gateway.ForceDown = "1"; - } - else if (ForceDown.IsPresent) - { - gateway.ForceDown = "1"; - } - else if (NoForceDown.IsPresent) - { - gateway.ForceDown = "0"; - } - else - { - gateway.ForceDown = currentGateway.ForceDown; - } - - // Update gateway - var updateTask = Task.Run(async () => await gatewayService.UpdateGatewayAsync(Uuid, gateway)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"Gateway {Uuid} updated: {updateResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await gatewayService.ApplyGatewayChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"Gateway changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentGateway = getResult.Gateway; + + // Create updated gateway + var gateway = new GatewayConfig { - HandleException(ex); + Name = Name ?? currentGateway.Name, + Interface = Interface ?? currentGateway.Interface, + IpAddress = IpAddress ?? currentGateway.IpAddress, + MonitorIp = MonitorIp ?? currentGateway.MonitorIp, + Description = Description ?? currentGateway.Description, + Weight = Weight?.ToString() ?? currentGateway.Weight, + IpProtocol = IpProtocol ?? currentGateway.IpProtocol + }; + + // Handle default/not default + if (Default.IsPresent && NotDefault.IsPresent) + { + WriteWarning("Both -Default and -NotDefault parameters were specified. Using -Default."); + gateway.IsDefault = "1"; + } + else if (Default.IsPresent) + { + gateway.IsDefault = "1"; + } + else if (NotDefault.IsPresent) + { + gateway.IsDefault = "0"; + } + else + { + gateway.IsDefault = currentGateway.IsDefault; + } + + // Handle enabled/disabled + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + gateway.Disabled = "0"; + } + else if (Enabled.IsPresent) + { + gateway.Disabled = "0"; + } + else if (Disabled.IsPresent) + { + gateway.Disabled = "1"; + } + else + { + gateway.Disabled = currentGateway.Disabled; + } + + // Handle monitoring + if (EnableMonitoring.IsPresent && DisableMonitoring.IsPresent) + { + WriteWarning("Both -EnableMonitoring and -DisableMonitoring parameters were specified. Using -EnableMonitoring."); + gateway.MonitorDisable = "0"; + } + else if (EnableMonitoring.IsPresent) + { + gateway.MonitorDisable = "0"; + } + else if (DisableMonitoring.IsPresent) + { + gateway.MonitorDisable = "1"; + } + else + { + gateway.MonitorDisable = currentGateway.MonitorDisable; + } + + // Handle force down + if (ForceDown.IsPresent && NoForceDown.IsPresent) + { + WriteWarning("Both -ForceDown and -NoForceDown parameters were specified. Using -ForceDown."); + gateway.ForceDown = "1"; + } + else if (ForceDown.IsPresent) + { + gateway.ForceDown = "1"; + } + else if (NoForceDown.IsPresent) + { + gateway.ForceDown = "0"; + } + else + { + gateway.ForceDown = currentGateway.ForceDown; + } + + // Update gateway + var updateResult = ExecuteAsyncTask(() => gatewayService.UpdateGatewayAsync(Uuid, gateway)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"Gateway {Uuid} updated: {updateResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => gatewayService.ApplyGatewayChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"Gateway changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseInterfaceCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseInterfaceCmdlet.cs index 140fb99..c2e9673 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseInterfaceCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseInterfaceCmdlet.cs @@ -87,44 +87,54 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var interfaceService = new InterfaceService(ApiClient, Logger); + + // First, get the current interface configuration + var getResult = ExecuteAsyncTask(() => interfaceService.GetInterfaceDetailAsync(Name)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var interfaceService = new InterfaceService(ApiClient, Logger); - - // First, get the current interface configuration - var getTask = Task.Run(async () => await interfaceService.GetInterfaceDetailAsync(Name)); - var currentInterface = getTask.GetAwaiter().GetResult().Interface; - - // Create the updated configuration - var interfaceConfig = new InterfaceConfig - { - Description = Description ?? currentInterface.Description, - IpAddress = IpAddress ?? currentInterface.IpAddress, - SubnetMask = SubnetMask ?? currentInterface.SubnetMask, - Gateway = Gateway ?? currentInterface.Gateway, - Enabled = Enabled.IsPresent ? "1" : "0" - }; - - // Update the interface - var updateTask = Task.Run(async () => await interfaceService.UpdateInterfaceAsync(Name, interfaceConfig)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"Interface {Name} updated: {updateResult.Result}"); - - // Apply the changes if requested - if (Apply.IsPresent) - { - var restartTask = Task.Run(async () => await interfaceService.RestartInterfaceAsync(Name)); - var restartResult = restartTask.GetAwaiter().GetResult(); - - WriteVerbose($"Interface {Name} restarted: {restartResult.Status}"); - } + return; } - catch (Exception ex) + + var currentInterface = getResult.Interface; + + // Create the updated configuration + var interfaceConfig = new InterfaceConfig { - HandleException(ex); + Description = Description ?? currentInterface.Description, + IpAddress = IpAddress ?? currentInterface.IpAddress, + SubnetMask = SubnetMask ?? currentInterface.SubnetMask, + Gateway = Gateway ?? currentInterface.Gateway, + Enabled = Enabled.IsPresent ? "1" : "0" + }; + + // Update the interface + var updateResult = ExecuteAsyncTask(() => interfaceService.UpdateInterfaceAsync(Name, interfaceConfig)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"Interface {Name} updated: {updateResult.Result}"); + + // Apply the changes if requested + if (Apply.IsPresent) + { + var restartResult = ExecuteAsyncTask(() => interfaceService.RestartInterfaceAsync(Name)); + + // Only continue if no exception occurred + if (ProcessingException != null || restartResult == null) + { + return; + } + + WriteVerbose($"Interface {Name} restarted: {restartResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSensePortForwardingRuleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSensePortForwardingRuleCmdlet.cs index de694db..7dae3af 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSensePortForwardingRuleCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSensePortForwardingRuleCmdlet.cs @@ -15,7 +15,7 @@ namespace PSOPNSenseAPI.Cmdlets /// [Cmdlet(VerbsCommon.Set, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)] [OutputType(typeof(PortForwardingRule))] - public class SetOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet + public class SetOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet { /// /// The UUID of the port forwarding rule to update. @@ -118,20 +118,23 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - var portForwardingService = new PortForwardingService(SessionState.ApiClient); + var portForwardingService = new PortForwardingService(ApiClient); // Get the existing rule - var existingRule = Task.Run(async () => await portForwardingService.GetPortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); + var existingRule = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRuleAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } if (existingRule == null) { - WriteError(new ErrorRecord( - new PSArgumentException($"Port forwarding rule with UUID '{Uuid}' not found."), - "PortForwardingRuleNotFound", - ErrorCategory.ObjectNotFound, - Uuid)); + ProcessingException = new PSArgumentException($"Port forwarding rule with UUID '{Uuid}' not found."); + WriteWarning($"Port forwarding rule with UUID '{Uuid}' not found."); return; } @@ -177,7 +180,13 @@ namespace PSOPNSenseAPI.Cmdlets if (Force || ShouldProcess($"OPNSense firewall", $"Update port forwarding rule with UUID '{Uuid}'")) { - var success = Task.Run(async () => await portForwardingService.UpdatePortForwardingRuleAsync(existingRule)).GetAwaiter().GetResult(); + var success = ExecuteAsyncTask(() => portForwardingService.UpdatePortForwardingRuleAsync(existingRule)); + + // Only continue if no exception occurred + if (ProcessingException != null) + { + return; + } if (success) { @@ -190,11 +199,8 @@ namespace PSOPNSenseAPI.Cmdlets } else { - WriteError(new ErrorRecord( - new PSInvalidOperationException($"Failed to update port forwarding rule with UUID '{Uuid}'."), - "PortForwardingRuleUpdateFailed", - ErrorCategory.InvalidOperation, - existingRule)); + ProcessingException = new PSInvalidOperationException($"Failed to update port forwarding rule with UUID '{Uuid}'."); + WriteWarning($"Failed to update port forwarding rule with UUID '{Uuid}'."); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseRouteCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseRouteCmdlet.cs index 0030ff6..cbb6c4e 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseRouteCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseRouteCmdlet.cs @@ -69,61 +69,71 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var routeService = new RouteService(ApiClient, Logger); + + // Get current route + var getResult = ExecuteAsyncTask(() => routeService.GetRouteAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var routeService = new RouteService(ApiClient, Logger); - - // Get current route - var getTask = Task.Run(async () => await routeService.GetRouteAsync(Uuid)); - var currentRoute = getTask.GetAwaiter().GetResult().Route; - - // Create updated route - var route = new RouteConfig - { - Network = Network ?? currentRoute.Network, - Gateway = Gateway ?? currentRoute.Gateway, - Description = Description ?? currentRoute.Description - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - route.Disabled = "0"; - } - else if (Enabled.IsPresent) - { - route.Disabled = "0"; - } - else if (Disabled.IsPresent) - { - route.Disabled = "1"; - } - else - { - route.Disabled = currentRoute.Disabled; - } - - // Update route - var updateTask = Task.Run(async () => await routeService.UpdateRouteAsync(Uuid, route)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"Route {Uuid} updated: {updateResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await routeService.ApplyRouteChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"Route changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentRoute = getResult.Route; + + // Create updated route + var route = new RouteConfig { - HandleException(ex); + Network = Network ?? currentRoute.Network, + Gateway = Gateway ?? currentRoute.Gateway, + Description = Description ?? currentRoute.Description + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + route.Disabled = "0"; + } + else if (Enabled.IsPresent) + { + route.Disabled = "0"; + } + else if (Disabled.IsPresent) + { + route.Disabled = "1"; + } + else + { + route.Disabled = currentRoute.Disabled; + } + + // Update route + var updateResult = ExecuteAsyncTask(() => routeService.UpdateRouteAsync(Uuid, route)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"Route {Uuid} updated: {updateResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => routeService.ApplyRouteChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"Route changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseSystemDNSCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseSystemDNSCmdlet.cs index 0d399f8..0547f05 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseSystemDNSCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseSystemDNSCmdlet.cs @@ -93,92 +93,102 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var systemDNSService = new SystemDNSService(ApiClient, Logger); + + // Get current configuration + var getResult = ExecuteAsyncTask(() => systemDNSService.GetSystemDNSAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var systemDNSService = new SystemDNSService(ApiClient, Logger); - - // Get current configuration - var getTask = Task.Run(async () => await systemDNSService.GetSystemDNSAsync()); - var currentConfig = getTask.GetAwaiter().GetResult().System; - - // Create updated configuration - var config = new SystemDNSConfig - { - Hostname = Hostname ?? currentConfig.Hostname, - Domain = Domain ?? currentConfig.Domain, - Timezone = Timezone ?? currentConfig.Timezone, - TimeServers = TimeServers ?? currentConfig.TimeServers, - Language = Language ?? currentConfig.Language - }; - - // Handle DNS servers - if (DnsServers != null && DnsServers.Length > 0) - { - config.DnsServers = new List(DnsServers); - } - else - { - config.DnsServers = currentConfig.DnsServers; - } - - // Handle DNS override - if (AllowDnsOverride.IsPresent && DisallowDnsOverride.IsPresent) - { - WriteWarning("Both -AllowDnsOverride and -DisallowDnsOverride parameters were specified. Using -AllowDnsOverride."); - config.DnsAllowOverride = "1"; - } - else if (AllowDnsOverride.IsPresent) - { - config.DnsAllowOverride = "1"; - } - else if (DisallowDnsOverride.IsPresent) - { - config.DnsAllowOverride = "0"; - } - else - { - config.DnsAllowOverride = currentConfig.DnsAllowOverride; - } - - // Handle DNS rebind protection - if (DisableDnsRebindProtection.IsPresent && EnableDnsRebindProtection.IsPresent) - { - WriteWarning("Both -DisableDnsRebindProtection and -EnableDnsRebindProtection parameters were specified. Using -DisableDnsRebindProtection."); - config.DnssecStripped = "1"; - } - else if (DisableDnsRebindProtection.IsPresent) - { - config.DnssecStripped = "1"; - } - else if (EnableDnsRebindProtection.IsPresent) - { - config.DnssecStripped = "0"; - } - else - { - config.DnssecStripped = currentConfig.DnssecStripped; - } - - // Update configuration - var updateTask = Task.Run(async () => await systemDNSService.UpdateSystemDNSAsync(config)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"System DNS configuration updated: {updateResult.Result}"); - - // Apply changes if requested - if (Apply.IsPresent) - { - var applyTask = Task.Run(async () => await systemDNSService.ApplySystemDNSChangesAsync()); - var applyResult = applyTask.GetAwaiter().GetResult(); - - WriteVerbose($"System DNS changes applied: {applyResult.Status}"); - } + return; } - catch (Exception ex) + + var currentConfig = getResult.System; + + // Create updated configuration + var config = new SystemDNSConfig { - HandleException(ex); + Hostname = Hostname ?? currentConfig.Hostname, + Domain = Domain ?? currentConfig.Domain, + Timezone = Timezone ?? currentConfig.Timezone, + TimeServers = TimeServers ?? currentConfig.TimeServers, + Language = Language ?? currentConfig.Language + }; + + // Handle DNS servers + if (DnsServers != null && DnsServers.Length > 0) + { + config.DnsServers = new List(DnsServers); + } + else + { + config.DnsServers = currentConfig.DnsServers; + } + + // Handle DNS override + if (AllowDnsOverride.IsPresent && DisallowDnsOverride.IsPresent) + { + WriteWarning("Both -AllowDnsOverride and -DisallowDnsOverride parameters were specified. Using -AllowDnsOverride."); + config.DnsAllowOverride = "1"; + } + else if (AllowDnsOverride.IsPresent) + { + config.DnsAllowOverride = "1"; + } + else if (DisallowDnsOverride.IsPresent) + { + config.DnsAllowOverride = "0"; + } + else + { + config.DnsAllowOverride = currentConfig.DnsAllowOverride; + } + + // Handle DNS rebind protection + if (DisableDnsRebindProtection.IsPresent && EnableDnsRebindProtection.IsPresent) + { + WriteWarning("Both -DisableDnsRebindProtection and -EnableDnsRebindProtection parameters were specified. Using -DisableDnsRebindProtection."); + config.DnssecStripped = "1"; + } + else if (DisableDnsRebindProtection.IsPresent) + { + config.DnssecStripped = "1"; + } + else if (EnableDnsRebindProtection.IsPresent) + { + config.DnssecStripped = "0"; + } + else + { + config.DnssecStripped = currentConfig.DnssecStripped; + } + + // Update configuration + var updateResult = ExecuteAsyncTask(() => systemDNSService.UpdateSystemDNSAsync(config)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"System DNS configuration updated: {updateResult.Result}"); + + // Apply changes if requested + if (Apply.IsPresent) + { + var applyResult = ExecuteAsyncTask(() => systemDNSService.ApplySystemDNSChangesAsync()); + + // Only continue if no exception occurred + if (ProcessingException != null || applyResult == null) + { + return; + } + + WriteVerbose($"System DNS changes applied: {applyResult.Status}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseUserCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseUserCmdlet.cs index ec85614..58d73b2 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseUserCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseUserCmdlet.cs @@ -76,56 +76,61 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var userService = new UserService(ApiClient, Logger); + + // First, get the current user + var getResult = ExecuteAsyncTask(() => userService.GetUserAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var userService = new UserService(ApiClient, Logger); - - // First, get the current user - var getTask = Task.Run(async () => await userService.GetUserAsync(Uuid)); - var currentUser = getTask.GetAwaiter().GetResult().User; - - // Create the updated user - var user = new UserConfig - { - Username = currentUser.Username, - Password = Password ?? "", - FullName = FullName ?? currentUser.FullName, - Email = Email ?? currentUser.Email, - Groups = Groups != null ? new List(Groups) : currentUser.Groups, - Authorizations = Authorizations != null ? new List(Authorizations) : currentUser.Authorizations - }; - - // Handle enabled/disabled state - if (Enabled.IsPresent && Disabled.IsPresent) - { - WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); - user.Disabled = "0"; - } - else if (Enabled.IsPresent) - { - user.Disabled = "0"; - } - else if (Disabled.IsPresent) - { - user.Disabled = "1"; - } - else - { - user.Disabled = currentUser.Disabled; - } - - // Update the user - var updateTask = Task.Run(async () => await userService.UpdateUserAsync(Uuid, user)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"User {Uuid} updated: {updateResult.Result}"); + return; } - catch (Exception ex) + + var currentUser = getResult.User; + + // Create the updated user + var user = new UserConfig { - HandleException(ex); + Username = currentUser.Username, + Password = Password ?? "", + FullName = FullName ?? currentUser.FullName, + Email = Email ?? currentUser.Email, + Groups = Groups != null ? new List(Groups) : currentUser.Groups, + Authorizations = Authorizations != null ? new List(Authorizations) : currentUser.Authorizations + }; + + // Handle enabled/disabled state + if (Enabled.IsPresent && Disabled.IsPresent) + { + WriteWarning("Both -Enabled and -Disabled parameters were specified. Using -Enabled."); + user.Disabled = "0"; } + else if (Enabled.IsPresent) + { + user.Disabled = "0"; + } + else if (Disabled.IsPresent) + { + user.Disabled = "1"; + } + else + { + user.Disabled = currentUser.Disabled; + } + + // Update the user + var updateResult = ExecuteAsyncTask(() => userService.UpdateUserAsync(Uuid, user)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; + } + + WriteVerbose($"User {Uuid} updated: {updateResult.Result}"); } } } diff --git a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseVLANCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseVLANCmdlet.cs index ae5ce36..bc7b1f0 100644 --- a/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseVLANCmdlet.cs +++ b/src/PSOPNSenseAPI/Cmdlets/SetOPNSenseVLANCmdlet.cs @@ -59,35 +59,40 @@ namespace PSOPNSenseAPI.Cmdlets /// /// Processes the cmdlet /// - protected override void ProcessRecord() + protected override void ProcessRecordInternal() { - try + var interfaceService = new InterfaceService(ApiClient, Logger); + + // First, get the current VLAN configuration + var getResult = ExecuteAsyncTask(() => interfaceService.GetVLANAsync(Uuid)); + + // Only continue if no exception occurred + if (ProcessingException != null || getResult == null) { - var interfaceService = new InterfaceService(ApiClient, Logger); - - // First, get the current VLAN configuration - var getTask = Task.Run(async () => await interfaceService.GetVLANAsync(Uuid)); - var currentVlan = getTask.GetAwaiter().GetResult().Vlan; - - // Create the updated configuration - var vlan = new VLANConfig - { - Interface = Interface ?? currentVlan.Interface, - Tag = Tag?.ToString() ?? currentVlan.Tag, - Priority = Priority?.ToString() ?? currentVlan.Priority, - Description = Description ?? currentVlan.Description - }; - - // Update the VLAN - var updateTask = Task.Run(async () => await interfaceService.UpdateVLANAsync(Uuid, vlan)); - var updateResult = updateTask.GetAwaiter().GetResult(); - - WriteVerbose($"VLAN {Uuid} updated: {updateResult.Result}"); + return; } - catch (Exception ex) + + var currentVlan = getResult.Vlan; + + // Create the updated configuration + var vlan = new VLANConfig { - HandleException(ex); + Interface = Interface ?? currentVlan.Interface, + Tag = Tag?.ToString() ?? currentVlan.Tag, + Priority = Priority?.ToString() ?? currentVlan.Priority, + Description = Description ?? currentVlan.Description + }; + + // Update the VLAN + var updateResult = ExecuteAsyncTask(() => interfaceService.UpdateVLANAsync(Uuid, vlan)); + + // Only continue if no exception occurred + if (ProcessingException != null || updateResult == null) + { + return; } + + WriteVerbose($"VLAN {Uuid} updated: {updateResult.Result}"); } } } diff --git a/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1 b/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1 index 6480f15..5bce804 100644 --- a/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1 +++ b/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1 @@ -3,7 +3,7 @@ RootModule = 'lib\PSOPNSenseAPI.dll' # Version number of this module. - ModuleVersion = '2025.04.15.1257' + ModuleVersion = '2025.04.15.1543' # Supported PSEditions CompatiblePSEditions = @('Desktop', 'Core')