From 1eed05ff9dc3dcc024d3c0e06f6db2904e847213 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 11 Jul 2024 07:43:47 -0700 Subject: [PATCH 1/4] 5.1 compatibility issues FIxes: - Poweshell 5.1 dislike `-is [ordered] ` has to be changed to `-is [System.Collections.Specialized.OrderedDictionary]` :( - Some Version of PoweShell 5.1 doesn't understand [ValidateSet( 3.1 , 3.0 )] [decimal] changed to [ValidateSet( '3.1' , '3.0' )] [string] --- src/Private/OpenApi.ps1 | 2 +- src/Private/Secrets.ps1 | 2 +- src/Public/OAComponents.ps1 | 4 ++-- src/Public/OpenApi.ps1 | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Private/OpenApi.ps1 b/src/Private/OpenApi.ps1 index 3d0d6b105..e396e7cee 100644 --- a/src/Private/OpenApi.ps1 +++ b/src/Private/OpenApi.ps1 @@ -1933,7 +1933,7 @@ function New-PodeOResponseInternal { $_headers = $null if ($null -ne $Params.Headers) { if ($Params.Headers -is [System.Object[]] -or $Params.Headers -is [string] -or $Params.Headers -is [string[]]) { - if ($Params.Headers -is [System.Object[]] -and $Params.Headers.Count -gt 0 -and ($Params.Headers[0] -is [hashtable] -or $Params.Headers[0] -is [ordered])) { + if ($Params.Headers -is [System.Object[]] -and $Params.Headers.Count -gt 0 -and ($Params.Headers[0] -is [hashtable] -or $Params.Headers[0] -is [System.Collections.Specialized.OrderedDictionary])) { $_headers = ConvertTo-PodeOAHeaderProperty -Headers $Params.Headers } else { diff --git a/src/Private/Secrets.ps1 b/src/Private/Secrets.ps1 index 14811bd8c..75c579908 100644 --- a/src/Private/Secrets.ps1 +++ b/src/Private/Secrets.ps1 @@ -525,7 +525,7 @@ function Protect-PodeSecretValueType { $Value = [string]::Empty } - if ($Value -is [ordered]) { + if ($Value -is [System.Collections.Specialized.OrderedDictionary]) { $Value = [hashtable]$Value } diff --git a/src/Public/OAComponents.ps1 b/src/Public/OAComponents.ps1 index fe7fff934..b0ccca20c 100644 --- a/src/Public/OAComponents.ps1 +++ b/src/Public/OAComponents.ps1 @@ -785,8 +785,8 @@ Test-PodeOAVersion -Version 3.1 -DefinitionTag 'default' function Test-PodeOAVersion { param ( [Parameter(Mandatory = $true)] - [ValidateSet( 3.1 , 3.0 )] - [decimal] + [ValidateSet( '3.1' , '3.0' )] + [string] $Version, [Parameter(Mandatory = $true)] diff --git a/src/Public/OpenApi.ps1 b/src/Public/OpenApi.ps1 index b995dcb18..df3249aaa 100644 --- a/src/Public/OpenApi.ps1 +++ b/src/Public/OpenApi.ps1 @@ -589,7 +589,7 @@ function Add-PodeOAResponse { [Alias('HeaderSchemas')] [AllowEmptyString()] [ValidateNotNullOrEmpty()] - [ValidateScript({ $_ -is [string] -or $_ -is [string[]] -or $_ -is [hashtable] -or $_ -is [ordered] })] + [ValidateScript({ $_ -is [string] -or $_ -is [string[]] -or $_ -is [hashtable] -or $_ -is [System.Collections.Specialized.OrderedDictionary]})] $Headers, [Parameter(Mandatory = $false, ParameterSetName = 'Schema')] From 4115d629e4e761038e056f1bb07d1c3c15f27269 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 11 Jul 2024 08:49:40 -0700 Subject: [PATCH 2/4] Fixes AdditionalProperties now properly renders any properties assigned Remove an issue with examples in `New-PodeOARequestBody` Add `Example` and `Examples` to `ConverTo-PodeOAParameter` when the property `Style` is present Block `Set-PodeOARouteInfo` to change the Definition Tags of a Route if already set Fix the romoval of the OpenAPI metadata in `Remove-PodeRoute` when the same route is configured to multiple endpoint --- src/Locales/ar/Pode.psd1 | 1 + src/Locales/de/Pode.psd1 | 1 + src/Locales/en-us/Pode.psd1 | 1 + src/Locales/en/Pode.psd1 | 1 + src/Locales/es/Pode.psd1 | 4 ++-- src/Locales/fr/Pode.psd1 | 1 + src/Locales/it/Pode.psd1 | 1 + src/Locales/ja/Pode.psd1 | 4 ++-- src/Locales/ko/Pode.psd1 | 1 + src/Locales/pl/Pode.psd1 | 4 ++-- src/Locales/pt/Pode.psd1 | 1 + src/Locales/zh/Pode.psd1 | 4 ++-- src/Private/OpenApi.ps1 | 8 +++++++- src/Public/OpenApi.ps1 | 24 +++++++++++++++++------- src/Public/Routes.ps1 | 30 ++++++++++++++++++------------ 15 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/Locales/ar/Pode.psd1 b/src/Locales/ar/Pode.psd1 index 274731000..64e424d55 100644 --- a/src/Locales/ar/Pode.psd1 +++ b/src/Locales/ar/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'وحدة Active Directory متاحة فقط على نظام Windows.' requestLoggingAlreadyEnabledExceptionMessage = 'تم تمكين تسجيل الطلبات بالفعل.' invalidAccessControlMaxAgeDurationExceptionMessage = 'مدة Access-Control-Max-Age غير صالحة المقدمة: {0}. يجب أن تكون أكبر من 0.' + DefinitionTagChangeNotAllowedExceptionMessage = 'لا يمكن تغيير علامة التعريف لمسار.' } diff --git a/src/Locales/de/Pode.psd1 b/src/Locales/de/Pode.psd1 index 6ae1aaa24..5f34aad7a 100644 --- a/src/Locales/de/Pode.psd1 +++ b/src/Locales/de/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'Active Directory-Modul nur unter Windows verfügbar.' requestLoggingAlreadyEnabledExceptionMessage = 'Die Anforderungsprotokollierung wurde bereits aktiviert.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Ungültige Access-Control-Max-Age-Dauer angegeben: {0}. Sollte größer als 0 sein.' + DefinitionTagChangeNotAllowedExceptionMessage = 'Definitionstag für eine Route kann nicht geändert werden.' } diff --git a/src/Locales/en-us/Pode.psd1 b/src/Locales/en-us/Pode.psd1 index b3cde218b..f899da6ca 100644 --- a/src/Locales/en-us/Pode.psd1 +++ b/src/Locales/en-us/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'Active Directory module only available on Windows OS.' requestLoggingAlreadyEnabledExceptionMessage = 'Request Logging has already been enabled.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Invalid Access-Control-Max-Age duration supplied: {0}. Should be greater than 0.' + DefinitionTagChangeNotAllowedExceptionMessage = 'Definition Tag for a Route cannot be changed.' } diff --git a/src/Locales/en/Pode.psd1 b/src/Locales/en/Pode.psd1 index 04eff1509..ff909da4e 100644 --- a/src/Locales/en/Pode.psd1 +++ b/src/Locales/en/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'Active Directory module only available on Windows OS.' requestLoggingAlreadyEnabledExceptionMessage = 'Request Logging has already been enabled.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Invalid Access-Control-Max-Age duration supplied: {0}. Should be greater than 0.' + DefinitionTagChangeNotAllowedExceptionMessage = 'Definition Tag for a Route cannot be changed.' } diff --git a/src/Locales/es/Pode.psd1 b/src/Locales/es/Pode.psd1 index 4610ed29c..4369ae52f 100644 --- a/src/Locales/es/Pode.psd1 +++ b/src/Locales/es/Pode.psd1 @@ -283,5 +283,5 @@ adModuleWindowsOnlyExceptionMessage = 'El módulo de Active Directory solo está disponible en Windows.' requestLoggingAlreadyEnabledExceptionMessage = 'El registro de solicitudes ya está habilitado.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Duración inválida para Access-Control-Max-Age proporcionada: {0}. Debe ser mayor que 0.' -} - + DefinitionTagChangeNotAllowedExceptionMessage = 'La etiqueta de definición para una Route no se puede cambiar.' +} \ No newline at end of file diff --git a/src/Locales/fr/Pode.psd1 b/src/Locales/fr/Pode.psd1 index c92181571..3c9beb577 100644 --- a/src/Locales/fr/Pode.psd1 +++ b/src/Locales/fr/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'Le module Active Directory est uniquement disponible sur Windows.' requestLoggingAlreadyEnabledExceptionMessage = 'La journalisation des requêtes est déjà activée.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Durée Access-Control-Max-Age invalide fournie : {0}. Doit être supérieure à 0.' + DefinitionTagChangeNotAllowedExceptionMessage = 'Le tag de définition pour une Route ne peut pas être modifié.' } diff --git a/src/Locales/it/Pode.psd1 b/src/Locales/it/Pode.psd1 index 239b1a9e9..2885e96d2 100644 --- a/src/Locales/it/Pode.psd1 +++ b/src/Locales/it/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'Il modulo Active Directory è disponibile solo su Windows OS.' requestLoggingAlreadyEnabledExceptionMessage = 'La registrazione delle richieste è già abilitata.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Durata non valida fornita per Access-Control-Max-Age: {0}. Deve essere maggiore di 0.' + DefinitionTagChangeNotAllowedExceptionMessage = 'Il tag di definizione per una Route non può essere cambiato.' } diff --git a/src/Locales/ja/Pode.psd1 b/src/Locales/ja/Pode.psd1 index 66543eb99..eb7f423e6 100644 --- a/src/Locales/ja/Pode.psd1 +++ b/src/Locales/ja/Pode.psd1 @@ -283,5 +283,5 @@ adModuleWindowsOnlyExceptionMessage = 'Active DirectoryモジュールはWindowsでのみ利用可能です。' requestLoggingAlreadyEnabledExceptionMessage = 'リクエストロギングは既に有効になっています。' invalidAccessControlMaxAgeDurationExceptionMessage = '無効な Access-Control-Max-Age 期間が提供されました:{0}。0 より大きくする必要があります。' -} - + DefinitionTagChangeNotAllowedExceptionMessage = 'Routeの定義タグは変更できません。' +} \ No newline at end of file diff --git a/src/Locales/ko/Pode.psd1 b/src/Locales/ko/Pode.psd1 index 82f96b665..7f425b373 100644 --- a/src/Locales/ko/Pode.psd1 +++ b/src/Locales/ko/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'Active Directory 모듈은 Windows에서만 사용할 수 있습니다.' requestLoggingAlreadyEnabledExceptionMessage = '요청 로깅이 이미 활성화되었습니다.' invalidAccessControlMaxAgeDurationExceptionMessage = '잘못된 Access-Control-Max-Age 기간이 제공되었습니다: {0}. 0보다 커야 합니다.' + DefinitionTagChangeNotAllowedExceptionMessage = 'Route에 대한 정의 태그는 변경할 수 없습니다.' } diff --git a/src/Locales/pl/Pode.psd1 b/src/Locales/pl/Pode.psd1 index 17cbabd57..a3809754e 100644 --- a/src/Locales/pl/Pode.psd1 +++ b/src/Locales/pl/Pode.psd1 @@ -283,5 +283,5 @@ adModuleWindowsOnlyExceptionMessage = 'Moduł Active Directory jest dostępny tylko w systemie Windows.' requestLoggingAlreadyEnabledExceptionMessage = 'Rejestrowanie żądań jest już włączone.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Podano nieprawidłowy czas trwania Access-Control-Max-Age: {0}. Powinien być większy niż 0.' -} - + DefinitionTagChangeNotAllowedExceptionMessage = 'Tag definicji dla Route nie może zostać zmieniony.' +} \ No newline at end of file diff --git a/src/Locales/pt/Pode.psd1 b/src/Locales/pt/Pode.psd1 index a3df34515..a8cace84a 100644 --- a/src/Locales/pt/Pode.psd1 +++ b/src/Locales/pt/Pode.psd1 @@ -283,5 +283,6 @@ adModuleWindowsOnlyExceptionMessage = 'O módulo Active Directory está disponível apenas no Windows.' requestLoggingAlreadyEnabledExceptionMessage = 'O registro de solicitações já está habilitado.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Duração inválida fornecida para Access-Control-Max-Age: {0}. Deve ser maior que 0.' + DefinitionTagChangeNotAllowedExceptionMessage = 'A Tag de definição para uma Route não pode ser alterada.' } diff --git a/src/Locales/zh/Pode.psd1 b/src/Locales/zh/Pode.psd1 index 6bc71fb10..04b6e8e87 100644 --- a/src/Locales/zh/Pode.psd1 +++ b/src/Locales/zh/Pode.psd1 @@ -283,5 +283,5 @@ adModuleWindowsOnlyExceptionMessage = '仅支持 Windows 的 Active Directory 模块。' requestLoggingAlreadyEnabledExceptionMessage = '请求日志记录已启用。' invalidAccessControlMaxAgeDurationExceptionMessage = '提供的 Access-Control-Max-Age 时长无效:{0}。应大于 0。' -} - + DefinitionTagChangeNotAllowedExceptionMessage = 'Route的定义标签无法更改。' +} \ No newline at end of file diff --git a/src/Private/OpenApi.ps1 b/src/Private/OpenApi.ps1 index e396e7cee..11c2938ac 100644 --- a/src/Private/OpenApi.ps1 +++ b/src/Private/OpenApi.ps1 @@ -622,7 +622,13 @@ function ConvertTo-PodeOASchemaProperty { } #Fix an issue when additionalProperties has an assigned value of $false if ($Property.ContainsKey('additionalProperties')) { - $schema['additionalProperties'] = $Property.additionalProperties + if ($Property.additionalProperties) { + $schema['additionalProperties'] = $Property.additionalProperties | ConvertTo-PodeOASchemaProperty -DefinitionTag $DefinitionTag + } + else { + #the value is $false + $schema['additionalProperties'] = $false + } } if ($Property.discriminator) { diff --git a/src/Public/OpenApi.ps1 b/src/Public/OpenApi.ps1 index df3249aaa..3542c8329 100644 --- a/src/Public/OpenApi.ps1 +++ b/src/Public/OpenApi.ps1 @@ -589,7 +589,7 @@ function Add-PodeOAResponse { [Alias('HeaderSchemas')] [AllowEmptyString()] [ValidateNotNullOrEmpty()] - [ValidateScript({ $_ -is [string] -or $_ -is [string[]] -or $_ -is [hashtable] -or $_ -is [System.Collections.Specialized.OrderedDictionary]})] + [ValidateScript({ $_ -is [string] -or $_ -is [string[]] -or $_ -is [hashtable] -or $_ -is [System.Collections.Specialized.OrderedDictionary] })] $Headers, [Parameter(Mandatory = $false, ParameterSetName = 'Schema')] @@ -882,10 +882,6 @@ function New-PodeOARequestBody { $DefinitionTag = Test-PodeOADefinitionTag -Tag $DefinitionTag - if ($Example -and $Examples) { - # Parameters 'Examples' and 'Example' are mutually exclusive - throw ($PodeLocale.parametersMutuallyExclusiveExceptionMessage -f 'Example', 'Examples') - } $result = @{} foreach ($tag in $DefinitionTag) { switch ($PSCmdlet.ParameterSetName.ToLowerInvariant()) { @@ -1302,6 +1298,12 @@ function ConvertTo-PodeOAParameter { $prop['allowReserved'] = $AllowReserved.IsPresent } + if ($Example ) { + $prop.example = $Example + } + elseif ($Examples) { + $prop.examples = $Examples + } } } elseif ($PSCmdlet.ParameterSetName -ieq 'Reference') { @@ -1559,8 +1561,16 @@ function Set-PodeOARouteInfo { $DefinitionTag = Test-PodeOADefinitionTag -Tag $DefinitionTag foreach ($r in @($Route)) { - - $r.OpenApi.DefinitionTag = $DefinitionTag + if ((Compare-Object -ReferenceObject $r.OpenApi.DefinitionTag -DifferenceObject $DefinitionTag).Count -ne 0) { + if ($r.OpenApi.IsDefTagConfigured ) { + # Definition Tag for a Route cannot be changed. + throw ($PodeLocale.DefinitionTagChangeNotAllowedExceptionMessage) + } + else { + $r.OpenApi.DefinitionTag = $DefinitionTag + $r.OpenApi.IsDefTagConfigured = $true + } + } if ($Summary) { $r.OpenApi.Summary = $Summary diff --git a/src/Public/Routes.ps1 b/src/Public/Routes.ps1 index 073e3ddef..ffed8e91f 100644 --- a/src/Public/Routes.ps1 +++ b/src/Public/Routes.ps1 @@ -431,14 +431,15 @@ function Add-PodeRoute { Method = $_method Path = $Path OpenApi = @{ - Path = $OpenApiPath - Responses = $DefaultResponse - Parameters = $null - RequestBody = $null - CallBacks = @{} - Authentication = @() - Servers = @() - DefinitionTag = $DefinitionTag + Path = $OpenApiPath + Responses = $DefaultResponse + Parameters = $null + RequestBody = $null + CallBacks = @{} + Authentication = @() + Servers = @() + DefinitionTag = $DefinitionTag + IsDefTagConfigured = ($null -ne $OADefinitionTag) #Definition Tag has been configured (Not default) } IsStatic = $false Metrics = @{ @@ -1692,11 +1693,16 @@ function Remove-PodeRoute { return } + # select the candidate route for deletion + $route = @($PodeContext.Server.Routes[$Method][$Path] | Where-Object { + $_.Endpoint.Name -ine $EndpointName + }) + # remove the operationId from the openapi operationId list - if ($PodeContext.Server.Routes[$Method][$Path].OpenAPI) { - foreach ( $tag in $PodeContext.Server.Routes[$Method][$Path].OpenAPI.DefinitionTag) { - if ($tag -and ($PodeContext.Server.OpenAPI.Definitions[$tag].hiddenComponents.operationId -ccontains $PodeContext.Server.Routes[$Method][$Path].OpenAPI.OperationId)) { - $PodeContext.Server.OpenAPI.Definitions[$tag].hiddenComponents.operationId = $PodeContext.Server.OpenAPI.Definitions[$tag].hiddenComponents.operationId | Where-Object { $_ -ne $PodeContext.Server.Routes[$Method][$Path].OpenAPI.OperationId } + if ($route.OpenAPI) { + foreach ( $tag in $route.OpenAPI.DefinitionTag) { + if ($tag -and ($PodeContext.Server.OpenAPI.Definitions[$tag].hiddenComponents.operationId -ccontains $route.OpenAPI.OperationId)) { + $PodeContext.Server.OpenAPI.Definitions[$tag].hiddenComponents.operationId = $PodeContext.Server.OpenAPI.Definitions[$tag].hiddenComponents.operationId | Where-Object { $_ -ne $route.OpenAPI.OperationId } } } } From 24a19eb549ead57ab749969c2e8b165c8af3c682 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Thu, 11 Jul 2024 09:24:16 -0700 Subject: [PATCH 3/4] test fix --- tests/unit/OpenApi.Tests.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/unit/OpenApi.Tests.ps1 b/tests/unit/OpenApi.Tests.ps1 index dbc3671b2..43f221922 100644 --- a/tests/unit/OpenApi.Tests.ps1 +++ b/tests/unit/OpenApi.Tests.ps1 @@ -2193,9 +2193,11 @@ Describe 'OpenApi' { '200' = @{ description = 'OK' } 'default' = @{ description = 'Internal server error' } } - Parameters = $null - RequestBody = $null - Authentication = @() + Parameters = $null + RequestBody = $null + Authentication = @() + DefinitionTag = @('Default') + IsDefTagConfigured = $false } } From abf41cbf3f3852d73b31dfff5a201c2c09c142fa Mon Sep 17 00:00:00 2001 From: mdaneri Date: Sat, 20 Jul 2024 07:30:07 -0700 Subject: [PATCH 4/4] fix Dutch locales --- src/Locales/en/Pode.psd1 | 2 +- src/Locales/nl/Pode.psd1 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Locales/en/Pode.psd1 b/src/Locales/en/Pode.psd1 index ee3097cf6..03d71e7cf 100644 --- a/src/Locales/en/Pode.psd1 +++ b/src/Locales/en/Pode.psd1 @@ -284,7 +284,7 @@ requestLoggingAlreadyEnabledExceptionMessage = 'Request Logging has already been enabled.' invalidAccessControlMaxAgeDurationExceptionMessage = 'Invalid Access-Control-Max-Age duration supplied: {0}. Should be greater than 0.' openApiDefinitionAlreadyExistsExceptionMessage = 'OpenAPI definition named {0} already exists.' - renamePodeOADefinitionTagExceptionMessage = "Rename-PodeOADefinitionTag cannot be used inside a Select-PodeOADefinition 'ScriptBlock'." + renamePodeOADefinitionTagExceptionMessage = "Rename-PodeOADefinitionTag cannot be used inside a Select-PodeOADefinition 'ScriptBlock'." DefinitionTagChangeNotAllowedExceptionMessage = 'Definition Tag for a Route cannot be changed.' } diff --git a/src/Locales/nl/Pode.psd1 b/src/Locales/nl/Pode.psd1 index 724b7de7f..8ae79d12d 100644 --- a/src/Locales/nl/Pode.psd1 +++ b/src/Locales/nl/Pode.psd1 @@ -285,5 +285,6 @@ invalidAccessControlMaxAgeDurationExceptionMessage = 'Ongeldige Access-Control-Max-Age duur opgegeven: {0}. Moet groter zijn dan 0.' openApiDefinitionAlreadyExistsExceptionMessage = 'OpenAPI-definitie met de naam {0} bestaat al.' renamePodeOADefinitionTagExceptionMessage = "Rename-PodeOADefinitionTag kan niet worden gebruikt binnen een Select-PodeOADefinition 'ScriptBlock'." + DefinitionTagChangeNotAllowedExceptionMessage = 'Definitietag voor een route kan niet worden gewijzigd.' }