Modules/businessdev.ALbuild.Core/Public/Test-ALbuildLicense.ps1
|
function Test-ALbuildLicense { <# .SYNOPSIS Verifies an ALbuild commercial license against the licensing service. .DESCRIPTION Free-tier functionality performs no license check. Licensed features call this to verify a tenant's license via the 365 business development licensing service. The result is cached per tenant for the session. Network/service failures do NOT throw - they return an object with IsValid = $false and a Reason - so that license enforcement is an explicit decision of the caller (see Assert-ALbuildLicensed), never an accidental side effect. .PARAMETER TenantId The Azure DevOps organization / collection id. Defaults to $env:System_CollectionId. .PARAMETER TenantName The Azure DevOps organization / collection URI. Defaults to $env:System_CollectionUri. .PARAMETER Refresh Bypass the per-tenant session cache and re-query the service. .EXAMPLE Test-ALbuildLicense -TenantId $env:System_CollectionId .OUTPUTS PSCustomObject with IsValid, Status, IsTrial, ExpiresOn, TenantId, TenantName, Reason. #> [CmdletBinding()] param( [string] $TenantId = $env:System_CollectionId, [string] $TenantName = $env:System_CollectionUri, [switch] $Refresh ) if ([string]::IsNullOrWhiteSpace($TenantId)) { return [PSCustomObject]@{ IsValid = $false; Status = 'NoTenant'; IsTrial = $false; ExpiresOn = $null TenantId = $TenantId; TenantName = $TenantName Reason = 'No tenant id available (set -TenantId or run inside Azure DevOps).' } } $normalizedName = if ($TenantName) { $TenantName -replace '^https?://', '' -replace '/+$', '' } else { '' } if (-not $script:ALbuildLicenseCache) { $script:ALbuildLicenseCache = @{} } if (-not $Refresh -and $script:ALbuildLicenseCache.ContainsKey($TenantId)) { return $script:ALbuildLicenseCache[$TenantId] } $baseUrl = (Get-ALbuildConfig -Name 'LicensingBaseUrl').TrimEnd('/') $appId = Get-ALbuildConfig -Name 'LicenseAppId' $url = "$baseUrl/v1/apps/$appId/features/$appId/tenant/$TenantId/verifyLicense" try { $response = Invoke-RestMethod -Uri $url -Method Get -TimeoutSec 30 -ErrorAction Stop $license = $response.license $status = [string]$response.status $isOk = $status -and ($status.ToLowerInvariant() -eq 'ok') $isTrial = $isOk -and ($null -ne $license) -and [string]::IsNullOrEmpty([string]$license.licenseKey) $expires = $null if ($isOk -and $license -and $license.PSObject.Properties.Name -contains 'trialPeriodEndingDate' -and $license.trialPeriodEndingDate) { [datetime] $parsed = [datetime]::MinValue if ([datetime]::TryParse([string]$license.trialPeriodEndingDate, [ref] $parsed)) { $expires = $parsed } } $result = [PSCustomObject]@{ IsValid = [bool]$isOk Status = if ($status) { $status } else { 'Unknown' } IsTrial = [bool]$isTrial ExpiresOn = $expires TenantId = $TenantId TenantName = $normalizedName Reason = if ($isOk) { '' } else { "Licensing service returned status '$status'." } } } catch { $result = [PSCustomObject]@{ IsValid = $false; Status = 'Error'; IsTrial = $false; ExpiresOn = $null TenantId = $TenantId; TenantName = $normalizedName Reason = "Could not reach the licensing service: $($_.Exception.Message)" } } $script:ALbuildLicenseCache[$TenantId] = $result return $result } |