From 4c3eb0d97368023fe71c0f5293fc6d0d0c9c19c8 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 2 Jun 2020 10:54:57 +0800 Subject: [PATCH 1/6] [Go][Experimental] Add discriminator support to anyOf (#6511) * add discriminator support in anyof * update samples --- .../go-experimental/model_anyof.mustache | 31 ++++++++++++++++++- .../go-petstore/model_gm_fruit.go | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/resources/go-experimental/model_anyof.mustache b/modules/openapi-generator/src/main/resources/go-experimental/model_anyof.mustache index 86cda3bc747b..dcf8c9f8df1b 100644 --- a/modules/openapi-generator/src/main/resources/go-experimental/model_anyof.mustache +++ b/modules/openapi-generator/src/main/resources/go-experimental/model_anyof.mustache @@ -15,6 +15,35 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error { } {{/isNullable}} + {{#discriminator}} + {{#mappedModels}} + {{#-first}} + // use discriminator value to speed up the lookup + var jsonDict map[string]interface{} + err := json.Unmarshal(data, &jsonDict) + if err != nil { + return fmt.Errorf("Failed to unmarshal JSON into map for the discrimintor lookup.") + } + + {{/-first}} + // check if the discriminator value is '{{{mappingName}}}' + if jsonDict["{{{propertyBaseName}}}"] == "{{{mappingName}}}" { + // try to unmarshal JSON data into {{{modelName}}} + err = json.Unmarshal(data, &dst.{{{modelName}}}); + if err == nil { + json{{{modelName}}}, _ := json.Marshal(dst.{{{modelName}}}) + if string(json{{{modelName}}}) == "{}" { // empty struct + dst.{{{modelName}}} = nil + } else { + return nil // data stored in dst.{{{modelName}}}, return on the first match + } + } else { + dst.{{{modelName}}} = nil + } + } + + {{/mappedModels}} + {{/discriminator}} {{#anyOf}} // try to unmarshal JSON data into {{{.}}} err = json.Unmarshal(data, &dst.{{{.}}}); @@ -44,4 +73,4 @@ func (src *{{classname}}) MarshalJSON() ([]byte, error) { return nil, nil // no data in anyOf schemas } -{{>nullable_model}} \ No newline at end of file +{{>nullable_model}} diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_gm_fruit.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_gm_fruit.go index 03baf438d135..6f2960cc3199 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_gm_fruit.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_gm_fruit.go @@ -101,3 +101,4 @@ func (v *NullableGmFruit) UnmarshalJSON(src []byte) error { return json.Unmarshal(src, &v.value) } + From 0fbbbe8a9505da9ef4c7a8a727e116082fb3942e Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 2 Jun 2020 10:55:56 +0800 Subject: [PATCH 2/6] add discriminator support to anyOf powershell client (#6512) --- .../resources/powershell/model_anyof.mustache | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/modules/openapi-generator/src/main/resources/powershell/model_anyof.mustache b/modules/openapi-generator/src/main/resources/powershell/model_anyof.mustache index f58773df0490..a3310c354b34 100644 --- a/modules/openapi-generator/src/main/resources/powershell/model_anyof.mustache +++ b/modules/openapi-generator/src/main/resources/powershell/model_anyof.mustache @@ -38,6 +38,35 @@ function ConvertFrom-{{{apiNamePrefix}}}JsonTo{{{classname}}} { } {{/isNullable}} + {{#discriminator}} + {{#mappedModels}} + {{#-first}} + $JsonData = ConvertFrom-Json -InputObject $Json + {{/-first}} + # check if the discriminator value is '{{{mappingName}}}' + if ($JsonData.PSobject.Properties["{{{propertyBaseName}}}"].value == "{{{mappingName}}}") { + # try to match {{{modelName}}} defined in the anyOf schemas + try { + $matchInstance = ConvertFrom-{{{apiNamePrefix}}}JsonTo{{{modelName}}} $Json + + foreach($property in $matchInstance.PsObject.Properties) { + if ($null -ne $property.Value) { + $matchType = "{{{modelName}}}" + return [PSCustomObject]@{ + "ActualType" = ${matchType} + "ActualInstance" = ${matchInstance} + "anyOfSchemas" = @({{#anyOf}}"{{{.}}}"{{^-last}}, {{/-last}}{{/anyOf}}) + } + } + } + } catch { + # fail to match the schema defined in anyOf with the discriminator lookup, proceed to the next one + Write-Debug "Failed to match '{{{modelName}}}' defined in anyOf ({{{apiNamePrefix}}}{{{classname}}}) using the discriminator lookup ({{{mappingName}}}). Proceeding with the typical anyOf type matching." + } + } + + {{/mappedModels}} + {{/discriminator}} {{#anyOf}} if ($match -ne 0) { # no match yet # try to match {{{.}}} defined in the anyOf schemas From c1cf63e81cb21fab20994c683c0fb627484fee56 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 2 Jun 2020 14:07:05 +0800 Subject: [PATCH 3/6] [PowerShell] Add useOneOfDiscriminatorLookup option (#6516) * add useOneOfDiscriminatorLookup option * update doc --- docs/generators/powershell.md | 1 + .../codegen/CodegenConstants.java | 2 + .../languages/PowerShellClientCodegen.java | 17 +- .../resources/powershell/model_oneof.mustache | 31 ++ .../src/PSPetstore/Client/PSConfiguration.ps1 | 137 ++++++ .../Private/PSHttpSignatureAuth.ps1 | 451 ++++++++++++++---- .../Private/PSRSAEncryptionProvider.cs | 286 ++++------- 7 files changed, 630 insertions(+), 295 deletions(-) diff --git a/docs/generators/powershell.md b/docs/generators/powershell.md index 2ce5aad86758..2b16a3196987 100644 --- a/docs/generators/powershell.md +++ b/docs/generators/powershell.md @@ -11,6 +11,7 @@ sidebar_label: powershell |packageName|Client package name (e.g. PSTwitter).| |PSOpenAPITools| |packageVersion|Package version (e.g. 0.1.2).| |0.1.2| |powershellGalleryUrl|URL to the module in PowerShell Gallery (e.g. https://www.powershellgallery.com/packages/PSTwitter/).| |null| +|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and onlye one match in oneOf's schemas) will be skipped.| |null| ## IMPORT MAPPING diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index fded4a057660..0fcb51998401 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -375,4 +375,6 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, " 2) Boolean values of the 'additionalProperties' keyword are ignored. It's as if additional properties are NOT allowed." + "Note: the root cause are issues #1369 and #1371, which must be resolved in the swagger-parser project."; + public static final String USE_ONEOF_DISCRIMINATOR_LOOKUP = "useOneOfDiscriminatorLookup"; + public static final String USE_ONEOF_DISCRIMINATOR_LOOKUP_DESC = "Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and onlye one match in oneOf's schemas) will be skipped."; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java index e81406fcbbff..bcdf58f57fcd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java @@ -53,6 +53,7 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo protected HashSet powershellVerbs; protected Map commonVerbs; // verbs not in the official ps verb list but can be mapped to one of the verbs protected HashSet methodNames; // store a list of method names to detect duplicates + protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup /** * Constructs an instance of `PowerShellClientCodegen`. @@ -498,7 +499,7 @@ public PowerShellClientCodegen() { cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_PROJECT_GUID, "GUID for PowerShell module (e.g. a27b908d-2a20-467f-bc32-af6f3a654ac5). A random GUID will be generated by default.")); cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, "Prefix that will be appended to all PS objects. Default: empty string. e.g. Pet => PSPet.")); cliOptions.add(new CliOption("commonVerbs", "PS common verb mappings. e.g. Delete=Remove:Patch=Update to map Delete with Remove and Patch with Update accordingly.")); - + cliOptions.add(new CliOption(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP_DESC)); } public CodegenType getTag() { @@ -535,6 +536,14 @@ public void setPowershellGalleryUrl(String powershellGalleryUrl) { this.powershellGalleryUrl = powershellGalleryUrl; } + public void setUseOneOfDiscriminatorLookup(boolean useOneOfDiscriminatorLookup) { + this.useOneOfDiscriminatorLookup = useOneOfDiscriminatorLookup; + } + + public boolean getUseOneOfDiscriminatorLookup() { + return this.useOneOfDiscriminatorLookup; + } + @Override public void processOpts() { super.processOpts(); @@ -550,6 +559,12 @@ public void processOpts() { additionalProperties.put("powershellGalleryUrl", powershellGalleryUrl); } + if (additionalProperties.containsKey(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP)) { + setUseOneOfDiscriminatorLookup(convertPropertyToBooleanAndWriteBack(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP)); + } else { + additionalProperties.put(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, useOneOfDiscriminatorLookup); + } + if (StringUtils.isNotBlank(powershellGalleryUrl)) { // get the last segment of the URL // e.g. https://www.powershellgallery.com/packages/PSTwitter => PSTwitter diff --git a/modules/openapi-generator/src/main/resources/powershell/model_oneof.mustache b/modules/openapi-generator/src/main/resources/powershell/model_oneof.mustache index 5ff351bc4a83..4bda9700eab8 100644 --- a/modules/openapi-generator/src/main/resources/powershell/model_oneof.mustache +++ b/modules/openapi-generator/src/main/resources/powershell/model_oneof.mustache @@ -38,6 +38,37 @@ function ConvertFrom-{{{apiNamePrefix}}}JsonTo{{{classname}}} { } {{/isNullable}} + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{#mappedModels}} + {{#-first}} + $JsonData = ConvertFrom-Json -InputObject $Json + {{/-first}} + # check if the discriminator value is '{{{mappingName}}}' + if ($JsonData.PSobject.Properties["{{{propertyBaseName}}}"].value == "{{{mappingName}}}") { + # try to match {{{modelName}}} defined in the oneOf schemas + try { + $matchInstance = ConvertFrom-{{{apiNamePrefix}}}JsonTo{{{modelName}}} $Json + + foreach($property in $matchInstance.PsObject.Properties) { + if ($null -ne $property.Value) { + $matchType = "{{{modelName}}}" + return [PSCustomObject]@{ + "ActualType" = ${matchType} + "ActualInstance" = ${matchInstance} + "oneOfSchemas" = @({{#oneOf}}"{{{.}}}"{{^-last}}, {{/-last}}{{/oneOf}}) + } + } + } + } catch { + # fail to match the schema defined in oneOf with the discriminator lookup, proceed to the next one + Write-Debug "Failed to match '{{{modelName}}}' defined in oneOf ({{{apiNamePrefix}}}{{{classname}}}) using the discriminator lookup ({{{mappingName}}}). Proceeding with the typical oneOf type matching." + } + } + + {{/mappedModels}} + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} {{#oneOf}} # try to match {{{.}}} defined in the oneOf schemas try { diff --git a/samples/client/petstore/powershell/src/PSPetstore/Client/PSConfiguration.ps1 b/samples/client/petstore/powershell/src/PSPetstore/Client/PSConfiguration.ps1 index ddb37a19c6e2..8e6910f19707 100644 --- a/samples/client/petstore/powershell/src/PSPetstore/Client/PSConfiguration.ps1 +++ b/samples/client/petstore/powershell/src/PSPetstore/Client/PSConfiguration.ps1 @@ -388,3 +388,140 @@ function Get-PSUrlFromHostSetting { } } + +<# +.SYNOPSIS +Sets the configuration for http signing. +.DESCRIPTION + +Sets the configuration for the HTTP signature security scheme. +The HTTP signature security scheme is used to sign HTTP requests with a key +which is in possession of the API client. +An 'Authorization' header is calculated by creating a hash of select headers, +and optionally the body of the HTTP request, then signing the hash value using +a key. The 'Authorization' header is added to outbound HTTP requests. + +Ref: https://openapi-generator.tech + +.PARAMETER KeyId +KeyId for HTTP signing + +.PARAMETER KeyFilePath +KeyFilePath for HTTP signing + +.PARAMETER KeyPassPhrase +KeyPassPhrase, if the HTTP signing key is protected + +.PARAMETER HttpSigningHeader +HttpSigningHeader list of HTTP headers used to calculate the signature. The two special signature headers '(request-target)' and '(created)' +SHOULD be included. + The '(created)' header expresses when the signature was created. + The '(request-target)' header is a concatenation of the lowercased :method, an + ASCII space, and the :path pseudo-headers. +If no headers are specified then '(created)' sets as default. + +.PARAMETER HashAlgorithm +HashAlgrithm to calculate the hash, Supported values are "sha256" and "sha512" + +.PARAMETER SigningAlgorithm +SigningAlgorithm specifies the signature algorithm, supported values are "RSASSA-PKCS1-v1_5" and "RSASSA-PSS" +RSA key : Supported values "RSASSA-PKCS1-v1_5" and "RSASSA-PSS", for ECDSA key this parameter is not applicable + +.PARAMETER SignatureValidityPeriod +SignatureValidityPeriod specifies the signature maximum validity time in seconds. It accepts integer value + +.OUTPUTS + +System.Collections.Hashtable +#> +function Set-PSConfigurationHttpSigning { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$KeyId, + [Parameter(Mandatory = $true)] + [string]$KeyFilePath, + [Parameter(Mandatory = $false)] + [securestring]$KeyPassPhrase, + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string[]] $HttpSigningHeader = @("(created)"), + [Parameter(Mandatory = $false)] + [ValidateSet("sha256", "sha512")] + [string] $HashAlgorithm = "sha256", + [Parameter(Mandatory = $false)] + [ValidateSet("RSASSA-PKCS1-v1_5", "RSASSA-PSS")] + [string]$SigningAlgorithm , + [Parameter(Mandatory = $false)] + [int]$SignatureValidityPeriod + ) + + Process { + $httpSignatureConfiguration = @{ } + + if (Test-Path -Path $KeyFilePath) { + $httpSignatureConfiguration["KeyId"] = $KeyId + $httpSignatureConfiguration["KeyFilePath"] = $KeyFilePath + } + else { + throw "Private key file path does not exist" + } + + $keyType = Get-PSKeyTypeFromFile -KeyFilePath $KeyFilePath + if ([String]::IsNullOrEmpty($SigningAlgorithm)) { + if ($keyType -eq "RSA") { + $SigningAlgorithm = "RSASSA-PKCS1-v1_5" + } + } + + if ($keyType -eq "RSA" -and + ($SigningAlgorithm -ne "RSASSA-PKCS1-v1_5" -and $SigningAlgorithm -ne "RSASSA-PSS" )) { + throw "Provided Key and SigningAlgorithm : $SigningAlgorithm is not compatible." + } + + if ($HttpSigningHeader -contains "(expires)" -and $SignatureValidityPeriod -le 0) { + throw "SignatureValidityPeriod must be greater than 0 seconds." + } + + if ($HttpSigningHeader -contains "(expires)") { + $httpSignatureConfiguration["SignatureValidityPeriod"] = $SignatureValidityPeriod + } + if ($null -ne $HttpSigningHeader -and $HttpSigningHeader.Length -gt 0) { + $httpSignatureConfiguration["HttpSigningHeader"] = $HttpSigningHeader + } + + if ($null -ne $HashAlgorithm ) { + $httpSignatureConfiguration["HashAlgorithm"] = $HashAlgorithm + } + + if ($null -ne $SigningAlgorithm) { + $httpSignatureConfiguration["SigningAlgorithm"] = $SigningAlgorithm + } + + if ($null -ne $KeyPassPhrase) { + $httpSignatureConfiguration["KeyPassPhrase"] = $KeyPassPhrase + } + + $Script:Configuration["HttpSigning"] = New-Object -TypeName PSCustomObject -Property $httpSignatureConfiguration + } +} + +<# +.SYNOPSIS + +Get the configuration object 'PSConfigurationHttpSigning'. + +.DESCRIPTION + +Get the configuration object 'PSConfigurationHttpSigning'. + +.OUTPUTS + +[PSCustomObject] +#> +function Get-PSConfigurationHttpSigning{ + + $httpSignatureConfiguration = $Script:Configuration["HttpSigning"] + return $httpSignatureConfiguration +} diff --git a/samples/client/petstore/powershell/src/PSPetstore/Private/PSHttpSignatureAuth.ps1 b/samples/client/petstore/powershell/src/PSPetstore/Private/PSHttpSignatureAuth.ps1 index 1eabb0a2f54f..d3fed6ead985 100644 --- a/samples/client/petstore/powershell/src/PSPetstore/Private/PSHttpSignatureAuth.ps1 +++ b/samples/client/petstore/powershell/src/PSPetstore/Private/PSHttpSignatureAuth.ps1 @@ -7,64 +7,11 @@ <# .SYNOPSIS -Get the API key Id and API key file path. - + Gets the headers for HTTP signature. .DESCRIPTION -Get the API key Id and API key file path. If no api prefix is provided then it use default api key prefix 'Signature' -.OUTPUTS -PSCustomObject : This contains APIKeyId, APIKeyFilePath, APIKeyPrefix -#> -function Get-PSAPIKeyInfo { - $ApiKeysList = $Script:Configuration['ApiKey'] - $ApiKeyPrefixList = $Script:Configuration['ApiKeyPrefix'] - $apiPrefix = "Signature" - - if ($null -eq $ApiKeysList -or $ApiKeysList.Count -eq 0) { - throw "Unable to reterieve the api key details" - } - - if ($null -eq $ApiKeyPrefixList -or $ApiKeyPrefixList.Count -eq 0) { - Write-Verbose "Unable to reterieve the api key prefix details,setting it to default ""Signature""" - } - - foreach ($item in $ApiKeysList.GetEnumerator()) { - if (![string]::IsNullOrEmpty($item.Name)) { - if (Test-Path -Path $item.Value) { - $apiKey = $item.Value - $apikeyId = $item.Name - break; - } - else { - throw "API key file path does not exist." - } - } - } - - if ($ApiKeyPrefixList.ContainsKey($apikeyId)) { - $apiPrefix = ApiKeyPrefixList[$apikeyId] - } - - if ($apikeyId -and $apiKey -and $apiPrefix) { - $result = New-Object -Type PSCustomObject -Property @{ - ApiKeyId = $apikeyId; - ApiKeyFilePath = $apiKey - ApiKeyPrefix = $apiPrefix - } - } - else { - return $null - } - return $result -} - -<# -.SYNOPSIS - Gets the headers for http signed auth. - -.DESCRIPTION - Gets the headers for the http signed auth. It use (targetpath), date, host and body digest to create authorization header. + Gets the headers for the http sigature. .PARAMETER Method - Http method + HTTP method .PARAMETER UriBuilder UriBuilder for url and query parameter .PARAMETER Body @@ -76,93 +23,393 @@ function Get-PSHttpSignedHeader { param( [string]$Method, [System.UriBuilder]$UriBuilder, - [string]$Body + [string]$Body, + [hashtable]$RequestHeader ) + $HEADER_REQUEST_TARGET = '(request-target)' + # The time when the HTTP signature was generated. + $HEADER_CREATED = '(created)' + # The time when the HTTP signature expires. The API server should reject HTTP requests + # that have expired. + $HEADER_EXPIRES = '(expires)' + # The 'Host' header. + $HEADER_HOST = 'Host' + # The 'Date' header. + $HEADER_DATE = 'Date' + # When the 'Digest' header is included in the HTTP signature, the client automatically + # computes the digest of the HTTP request body, per RFC 3230. + $HEADER_DIGEST = 'Digest' + # The 'Authorization' header is automatically generated by the client. It includes + # the list of signed headers and a base64-encoded signature. + $HEADER_AUTHORIZATION = 'Authorization' + #Hash table to store singed headers - $HttpSignedHeader = @{} + $HttpSignedRequestHeader = @{ } + $HttpSignatureHeader = @{ } $TargetHost = $UriBuilder.Host + $httpSigningConfiguration = Get-PSConfigurationHttpSigning + $Digest = $null + + #get the body digest + $bodyHash = Get-PSStringHash -String $Body -HashName $httpSigningConfiguration.HashAlgorithm + if ($httpSigningConfiguration.HashAlgorithm -eq "SHA256") { + $Digest = [String]::Format("SHA-256={0}", [Convert]::ToBase64String($bodyHash)) + } + elseif ($httpSigningConfiguration.HashAlgorithm -eq "SHA512") { + $Digest = [String]::Format("SHA-512={0}", [Convert]::ToBase64String($bodyHash)) + } + + $dateTime = Get-Date + #get the date in UTC + $currentDate = $dateTime.ToUniversalTime().ToString("r") + + foreach ($headerItem in $httpSigningConfiguration.HttpSigningHeader) { + + if ($headerItem -eq $HEADER_REQUEST_TARGET) { + $requestTargetPath = [string]::Format("{0} {1}{2}", $Method.ToLower(), $UriBuilder.Path, $UriBuilder.Query) + $HttpSignatureHeader.Add($HEADER_REQUEST_TARGET, $requestTargetPath) + } + elseif ($headerItem -eq $HEADER_CREATED) { + $created = Get-PSUnixTime -Date $dateTime -TotalTime TotalSeconds + $HttpSignatureHeader.Add($HEADER_CREATED, $created) + } + elseif ($headerItem -eq $HEADER_EXPIRES) { + $expire = $dateTime.AddSeconds($httpSigningConfiguration.SignatureValidityPeriod) + $expireEpocTime = Get-PSUnixTime -Date $expire -TotalTime TotalSeconds + $HttpSignatureHeader.Add($HEADER_EXPIRES, $expireEpocTime) + } + elseif ($headerItem -eq $HEADER_HOST) { + $HttpSignedRequestHeader[$HEADER_HOST] = $TargetHost + $HttpSignatureHeader.Add($HEADER_HOST.ToLower(), $TargetHost) + } + elseif ($headerItem -eq $HEADER_DATE) { + $HttpSignedRequestHeader[$HEADER_DATE] = $currentDate + $HttpSignatureHeader.Add($HEADER_DATE.ToLower(), $currentDate) + } + elseif ($headerItem -eq $HEADER_DIGEST) { + $HttpSignedRequestHeader[$HEADER_DIGEST] = $Digest + $HttpSignatureHeader.Add($HEADER_DIGEST.ToLower(), $Digest) + }elseif($RequestHeader.ContainsKey($headerItem)){ + $HttpSignatureHeader.Add($headerItem.ToLower(), $RequestHeader[$headerItem]) + }else{ + throw "Cannot sign HTTP request. Request does not contain the $headerItem header." + } + } - #Check for Authentication type - $apiKeyInfo = Get-PSAPIKeyInfo - if ($null -eq $apiKeyInfo) { - throw "Unable to reterieve the api key info " + # header's name separated by space + $headersKeysString = $HttpSignatureHeader.Keys -join " " + $headerValuesList = @() + foreach ($item in $HttpSignatureHeader.GetEnumerator()) { + $headerValuesList += [string]::Format("{0}: {1}", $item.Name, $item.Value) } + #Concatinate headers value separated by new line + $headerValuesString = $headerValuesList -join "`n" + + #Gets the hash of the headers value + $signatureHashString = Get-PSStringHash -String $headerValuesString -HashName $httpSigningConfiguration.HashAlgorithm - #get the body digest - $bodyHash = Get-PSStringHash -String $Body - $Digest = [String]::Format("SHA-256={0}", [Convert]::ToBase64String($bodyHash)) + #Gets the Key type to select the correct signing alogorithm + $KeyType = Get-PSKeyTypeFromFile -KeyFilePath $httpSigningConfiguration.KeyFilePath - #get the date in UTC - $dateTime = Get-Date - $currentDate = $dateTime.ToUniversalTime().ToString("r") + if ($keyType -eq "RSA") { + $headerSignatureStr = Get-PSRSASignature -PrivateKeyFilePath $httpSigningConfiguration.KeyFilePath ` + -DataToSign $signatureHashString ` + -HashAlgorithmName $httpSigningConfiguration.HashAlgorithm ` + -KeyPassPhrase $httpSigningConfiguration.KeyPassPhrase ` + -SigningAlgorithm $httpSigningConfiguration.SigningAlgorithm + } + elseif ($KeyType -eq "EC") { + $headerSignatureStr = Get-PSECDSASignature -ECKeyFilePath $httpSigningConfiguration.KeyFilePath ` + -DataToSign $signatureHashString ` + -HashAlgorithmName $httpSigningConfiguration.HashAlgorithm ` + -KeyPassPhrase $httpSigningConfiguration.KeyPassPhrase + } + #Depricated + <#$cryptographicScheme = Get-PSCryptographicScheme -SigningAlgorithm $httpSigningConfiguration.SigningAlgorithm ` + -HashAlgorithm $httpSigningConfiguration.HashAlgorithm + #> + $cryptographicScheme = "hs2019" + $authorizationHeaderValue = [string]::Format("Signature keyId=""{0}"",algorithm=""{1}""", + $httpSigningConfiguration.KeyId, $cryptographicScheme) - $requestTargetPath = [string]::Format("{0} {1}{2}",$Method.ToLower(),$UriBuilder.Path.ToLower(),$UriBuilder.Query) - $h_requestTarget = [string]::Format("(request-target): {0}",$requestTargetPath) - $h_cdate = [string]::Format("date: {0}",$currentDate) - $h_digest = [string]::Format("digest: {0}",$Digest) - $h_targetHost = [string]::Format("host: {0}",$TargetHost) + if ($HttpSignatureHeader.ContainsKey($HEADER_CREATED)) { + $authorizationHeaderValue += [string]::Format(",created={0}", $HttpSignatureHeader[$HEADER_CREATED]) + } - $stringToSign = [String]::Format("{0}`n{1}`n{2}`n{3}", - $h_requestTarget,$h_cdate, - $h_targetHost,$h_digest) + if ($HttpSignatureHeader.ContainsKey($HEADER_EXPIRES)) { + $authorizationHeaderValue += [string]::Format(",expires={0}", $HttpSignatureHeader[$HEADER_EXPIRES]) + } - $hashedString = Get-PSStringHash -String $stringToSign - $signedHeader = Get-PSRSASHA256SignedString -APIKeyFilePath $apiKeyInfo.ApiKeyFilePath -DataToSign $hashedString - $authorizationHeader = [string]::Format("{0} keyId=""{1}"",algorithm=""rsa-sha256"",headers=""(request-target) date host digest"",signature=""{2}""", - $apiKeyInfo.ApiKeyPrefix, $apiKeyInfo.ApiKeyId, $signedHeader) + $authorizationHeaderValue += [string]::Format(",headers=""{0}"",signature=""{1}""", + $headersKeysString , $headerSignatureStr) - $HttpSignedHeader["Date"] = $currentDate - $HttpSignedHeader["Host"] = $TargetHost - $HttpSignedHeader["Content-Type"] = "application/json" - $HttpSignedHeader["Digest"] = $Digest - $HttpSignedHeader["Authorization"] = $authorizationHeader - return $HttpSignedHeader + $HttpSignedRequestHeader[$HEADER_AUTHORIZATION] = $authorizationHeaderValue + return $HttpSignedRequestHeader } <# .SYNOPSIS - Gets the headers for http signed auth. + Gets the RSA signature .DESCRIPTION - Gets the headers for the http signed auth. It use (targetpath), date, host and body digest to create authorization header. -.PARAMETER APIKeyFilePath + Gets the RSA signature for the http signing +.PARAMETER PrivateKeyFilePath Specify the API key file path .PARAMETER DataToSign Specify the data to sign +.PARAMETER HashAlgorithmName + HashAlgorithm to calculate the hash +.PARAMETER KeyPassPhrase + KeyPassPhrase for the encrypted key .OUTPUTS - String + Base64String #> -function Get-PSRSASHA256SignedString { +function Get-PSRSASignature { Param( - [string]$APIKeyFilePath, - [byte[]]$DataToSign + [string]$PrivateKeyFilePath, + [byte[]]$DataToSign, + [string]$HashAlgorithmName, + [string]$SigningAlgorithm, + [securestring]$KeyPassPhrase ) try { - $rsa_provider_path = Join-Path -Path $PSScriptRoot -ChildPath "PSRSAEncryptionProvider.cs" - $rsa_provider_sourceCode = Get-Content -Path $rsa_provider_path -Raw - Add-Type -TypeDefinition $rsa_provider_sourceCode - $signed_string = [RSAEncryption.RSAEncryptionProvider]::GetRSASignb64encode($APIKeyFilePath, $DataToSign) - if ($null -eq $signed_string) { - throw "Unable to sign the header using the API key" + if ($hashAlgorithmName -eq "sha256") { + $hashAlgo = [System.Security.Cryptography.HashAlgorithmName]::SHA256 + } + elseif ($hashAlgorithmName -eq "sha512") { + $hashAlgo = [System.Security.Cryptography.HashAlgorithmName]::SHA512 + } + + if ($PSVersionTable.PSVersion.Major -ge 7) { + $ecKeyHeader = "-----BEGIN RSA PRIVATE KEY-----" + $ecKeyFooter = "-----END RSA PRIVATE KEY-----" + $keyStr = Get-Content -Path $PrivateKeyFilePath -Raw + $ecKeyBase64String = $keyStr.Replace($ecKeyHeader, "").Replace($ecKeyFooter, "").Trim() + $keyBytes = [System.Convert]::FromBase64String($ecKeyBase64String) + $rsa = [System.Security.Cryptography.RSACng]::new() + [int]$bytCount = 0 + $rsa.ImportRSAPrivateKey($keyBytes, [ref] $bytCount) + + if ($SigningAlgorithm -eq "RSASSA-PSS") { + $signedBytes = $rsa.SignHash($DataToSign, $hashAlgo, [System.Security.Cryptography.RSASignaturePadding]::Pss) + } + else { + $signedBytes = $rsa.SignHash($DataToSign, $hashAlgo, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) + } + } + else { + $rsa_provider_path = Join-Path -Path $PSScriptRoot -ChildPath "PSRSAEncryptionProvider.cs" + $rsa_provider_sourceCode = Get-Content -Path $rsa_provider_path -Raw + Add-Type -TypeDefinition $rsa_provider_sourceCode + + [System.Security.Cryptography.RSA]$rsa = [RSAEncryption.RSAEncryptionProvider]::GetRSAProviderFromPemFile($PrivateKeyFilePath, $KeyPassPhrase) + + if ($SigningAlgorithm -eq "RSASSA-PSS") { + throw "$SigningAlgorithm is not supported on $($PSVersionTable.PSVersion)" + } + else { + $signedBytes = $rsa.SignHash($DataToSign, $hashAlgo, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) + } + } - return $signed_string + + $signedString = [Convert]::ToBase64String($signedBytes) + return $signedString } catch { throw $_ } } + +<# +.SYNOPSIS + Gets the ECDSA signature + +.DESCRIPTION + Gets the ECDSA signature for the http signing +.PARAMETER PrivateKeyFilePath + Specify the API key file path +.PARAMETER DataToSign + Specify the data to sign +.PARAMETER HashAlgorithmName + HashAlgorithm to calculate the hash +.PARAMETER KeyPassPhrase + KeyPassPhrase for the encrypted key +.OUTPUTS + Base64String +#> +function Get-PSECDSASignature { + param( + [Parameter(Mandatory = $true)] + [string]$ECKeyFilePath, + [Parameter(Mandatory = $true)] + [byte[]]$DataToSign, + [Parameter(Mandatory = $false)] + [String]$HashAlgorithmName, + [Parameter(Mandatory = $false)] + [securestring]$KeyPassPhrase + ) + if (!(Test-Path -Path $ECKeyFilePath)) { + throw "key file path does not exist." + } + + if($PSVersionTable.PSVersion.Major -lt 7){ + throw "ECDSA key is not supported on $($PSVersionTable.PSVersion), Use PSVersion 7.0 and above" + } + + $ecKeyHeader = "-----BEGIN EC PRIVATE KEY-----" + $ecKeyFooter = "-----END EC PRIVATE KEY-----" + $keyStr = Get-Content -Path $ECKeyFilePath -Raw + $ecKeyBase64String = $keyStr.Replace($ecKeyHeader, "").Replace($ecKeyFooter, "").Trim() + $keyBytes = [System.Convert]::FromBase64String($ecKeyBase64String) + + #$cngKey = [System.Security.Cryptography.CngKey]::Import($keyBytes,[System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob) + #$ecdsa = [System.Security.Cryptography.ECDsaCng]::New($cngKey) + $ecdsa = [System.Security.Cryptography.ECDsaCng]::New() + [int]$bytCount =0 + if(![string]::IsNullOrEmpty($KeyPassPhrase)){ + $ecdsa.ImportEncryptedPkcs8PrivateKey($KeyPassPhrase,$keyBytes,[ref]$bytCount) + } + else{ + $ecdsa.ImportPkcs8PrivateKey($keyBytes,[ref]$bytCount) + } + + if ($HashAlgorithmName -eq "sha512") { + $ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha512 + } + else { + $ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha256 + } + + $signedBytes = $ecdsa.SignHash($DataToSign) + $signedString = [System.Convert]::ToBase64String($signedBytes) + return $signedString + +} + + <# .Synopsis Gets the hash of string. .Description Gets the hash of string +.Parameter String + Specifies the string to calculate the hash +.Parameter HashName + Specifies the hash name to calculate the hash, Accepted values are "SHA1", "SHA256" and "SHA512" + It is recommneded not to use "SHA1" to calculate the Hash .Outputs String #> -Function Get-PSStringHash([String] $String, $HashName = "SHA256") { - +Function Get-PSStringHash { + param( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [string]$String, + [Parameter(Mandatory = $true)] + [ValidateSet("SHA1", "SHA256", "SHA512")] + $HashName + ) $hashAlogrithm = [System.Security.Cryptography.HashAlgorithm]::Create($HashName) $hashAlogrithm.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String)) +} + +<# +.Synopsis + Gets the Unix time. +.Description + Gets the Unix time +.Parameter Date + Specifies the date to calculate the unix time +.Parameter ToTalTime + Specifies the total time , Accepted values are "TotalDays", "TotalHours", "TotalMinutes", "TotalSeconds" and "TotalMilliseconds" +.Outputs +Integer +#> +function Get-PSUnixTime { + param( + [Parameter(Mandatory = $true)] + [DateTime]$Date, + [Parameter(Mandatory = $false)] + [ValidateSet("TotalDays", "TotalHours", "TotalMinutes", "TotalSeconds", "TotalMilliseconds")] + [string]$TotalTime = "TotalSeconds" + ) + $date1 = Get-Date -Date "01/01/1970" + $timespan = New-TimeSpan -Start $date1 -End $Date + switch ($TotalTime) { + "TotalDays" { [int]$timespan.TotalDays } + "TotalHours" { [int]$timespan.TotalHours } + "TotalMinutes" { [int]$timespan.TotalMinutes } + "TotalSeconds" { [int]$timespan.TotalSeconds } + "TotalMilliseconds" { [int]$timespan.TotalMilliseconds } + } +} + +function Get-PSCryptographicScheme { + param( + [Parameter(Mandatory = $true)] + [string]$SigningAlgorithm, + [Parameter(Mandatory = $true)] + [string]$HashAlgorithm + ) + $rsaSigntureType = @("RSASSA-PKCS1-v1_5", "RSASSA-PSS") + $SigningAlgorithm = $null + if ($rsaSigntureType -contains $SigningAlgorithm) { + switch ($HashAlgorithm) { + "sha256" { $SigningAlgorithm = "rsa-sha256" } + "sha512" { $SigningAlgorithm = "rsa-sha512" } + } + } + return $SigningAlgorithm +} + + +<# +.Synopsis + Gets the key type from the pem file. +.Description + Gets the key type from the pem file. +.Parameter KeyFilePath + Specifies the key file path (pem file) +.Outputs +String +#> +function Get-PSKeyTypeFromFile { + param( + [Parameter(Mandatory = $true)] + [string]$KeyFilePath + ) + + if (-not(Test-Path -Path $KeyFilePath)) { + throw "Key file path does not exist." + } + $ecPrivateKeyHeader = "BEGIN EC PRIVATE KEY" + $ecPrivateKeyFooter = "END EC PRIVATE KEY" + $rsaPrivateKeyHeader = "BEGIN RSA PRIVATE KEY" + $rsaPrivateFooter = "END RSA PRIVATE KEY" + $pkcs8Header = "BEGIN PRIVATE KEY" + $pkcs8Footer = "END PRIVATE KEY" + $keyType = $null + $key = Get-Content -Path $KeyFilePath + + if ($key[0] -match $rsaPrivateKeyHeader -and $key[$key.Length - 1] -match $rsaPrivateFooter) { + $KeyType = "RSA" + + } + elseif ($key[0] -match $ecPrivateKeyHeader -and $key[$key.Length - 1] -match $ecPrivateKeyFooter) { + $keyType = "EC" + } + elseif ($key[0] -match $ecPrivateKeyHeader -and $key[$key.Length - 1] -match $ecPrivateKeyFooter) { + <#this type of key can hold many type different types of private key, but here due lack of pem header + Considering this as EC key + #> + #TODO :- update the key based on oid + $keyType = "EC" + } + else { + throw "Either the key is invalid or key is not supported" + } + return $keyType } \ No newline at end of file diff --git a/samples/client/petstore/powershell/src/PSPetstore/Private/PSRSAEncryptionProvider.cs b/samples/client/petstore/powershell/src/PSPetstore/Private/PSRSAEncryptionProvider.cs index a23490b366e4..7a671929fb2b 100644 --- a/samples/client/petstore/powershell/src/PSPetstore/Private/PSRSAEncryptionProvider.cs +++ b/samples/client/petstore/powershell/src/PSPetstore/Private/PSRSAEncryptionProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Net; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; @@ -10,15 +11,97 @@ namespace RSAEncryption { public class RSAEncryptionProvider { + public static RSACryptoServiceProvider GetRSAProviderFromPemFile(String pemfile,SecureString keyPassPharse = null) + { + const String pempubheader = "-----BEGIN PUBLIC KEY-----"; + const String pempubfooter = "-----END PUBLIC KEY-----"; + bool isPrivateKeyFile = true; + byte[] pemkey = null; + + if (!File.Exists(pemfile)) + { + throw new Exception("private key file does not exist."); + } + string pemstr = File.ReadAllText(pemfile).Trim(); + + if (pemstr.StartsWith(pempubheader) && pemstr.EndsWith(pempubfooter)) + { + isPrivateKeyFile = false; + } + + if (isPrivateKeyFile) + { + pemkey = ConvertPrivateKeyToBytes(pemstr,keyPassPharse); + if (pemkey == null) + { + return null; + } + return DecodeRSAPrivateKey(pemkey); + } + return null ; + } + + static byte[] ConvertPrivateKeyToBytes(String instr, SecureString keyPassPharse = null) + { + const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----"; + const String pemprivfooter = "-----END RSA PRIVATE KEY-----"; + String pemstr = instr.Trim(); + byte[] binkey; + + if (!pemstr.StartsWith(pemprivheader) || !pemstr.EndsWith(pemprivfooter)) + { + return null; + } + + StringBuilder sb = new StringBuilder(pemstr); + sb.Replace(pemprivheader, ""); + sb.Replace(pemprivfooter, ""); + String pvkstr = sb.ToString().Trim(); + + try + { // if there are no PEM encryption info lines, this is an UNencrypted PEM private key + binkey = Convert.FromBase64String(pvkstr); + return binkey; + } + catch (System.FormatException) + { + StringReader str = new StringReader(pvkstr); + + //-------- read PEM encryption info. lines and extract salt ----- + if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED")) + return null; + String saltline = str.ReadLine(); + if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,")) + return null; + String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim(); + byte[] salt = new byte[saltstr.Length / 2]; + for (int i = 0; i < salt.Length; i++) + salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16); + if (!(str.ReadLine() == "")) + return null; + + //------ remaining b64 data is encrypted RSA key ---- + String encryptedstr = str.ReadToEnd(); + + try + { //should have b64 encrypted RSA key now + binkey = Convert.FromBase64String(encryptedstr); + } + catch (System.FormatException) + { //data is not in base64 fromat + return null; + } + + byte[] deskey = GetEncryptedKey(salt, keyPassPharse, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes + if (deskey == null) + return null; + + //------ Decrypt the encrypted 3des-encrypted RSA private key ------ + byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV + return rsakey; + } + } - const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----"; - const String pemprivfooter = "-----END RSA PRIVATE KEY-----"; - const String pempubheader = "-----BEGIN PUBLIC KEY-----"; - const String pempubfooter = "-----END PUBLIC KEY-----"; - const String pemp8header = "-----BEGIN PRIVATE KEY-----"; - const String pemp8footer = "-----END PRIVATE KEY-----"; - const String pemp8encheader = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; - const String pemp8encfooter = "-----END ENCRYPTED PRIVATE KEY-----"; public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey) { byte[] MODULUS, E, D, P, Q, DP, DQ, IQ; @@ -46,7 +129,6 @@ public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey) if (bt != 0x00) return null; - //------ all private key components are Integer sequences ---- elems = GetIntegerSize(binr); MODULUS = binr.ReadBytes(elems); @@ -72,19 +154,6 @@ public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey) elems = GetIntegerSize(binr); IQ = binr.ReadBytes(elems); - /*Console.WriteLine("showing components .."); - if (true) - { - showBytes("\nModulus", MODULUS); - showBytes("\nExponent", E); - showBytes("\nD", D); - showBytes("\nP", P); - showBytes("\nQ", Q); - showBytes("\nDP", DP); - showBytes("\nDQ", DQ); - showBytes("\nIQ", IQ); - }*/ - // ------- create RSACryptoServiceProvider instance and initialize with public key ----- RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSAParameters RSAparams = new RSAParameters(); @@ -140,94 +209,17 @@ private static int GetIntegerSize(BinaryReader binr) return count; } - static byte[] DecodeOpenSSLPrivateKey(String instr) - { - const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----"; - const String pemprivfooter = "-----END RSA PRIVATE KEY-----"; - String pemstr = instr.Trim(); - byte[] binkey; - if (!pemstr.StartsWith(pemprivheader) || !pemstr.EndsWith(pemprivfooter)) - return null; - - StringBuilder sb = new StringBuilder(pemstr); - sb.Replace(pemprivheader, ""); //remove headers/footers, if present - sb.Replace(pemprivfooter, ""); - - String pvkstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace - - try - { // if there are no PEM encryption info lines, this is an UNencrypted PEM private key - binkey = Convert.FromBase64String(pvkstr); - return binkey; - } - catch (System.FormatException) - { //if can't b64 decode, it must be an encrypted private key - //Console.WriteLine("Not an unencrypted OpenSSL PEM private key"); - } - - StringReader str = new StringReader(pvkstr); - - //-------- read PEM encryption info. lines and extract salt ----- - if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED")) - return null; - String saltline = str.ReadLine(); - if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,")) - return null; - String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim(); - byte[] salt = new byte[saltstr.Length / 2]; - for (int i = 0; i < salt.Length; i++) - salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16); - if (!(str.ReadLine() == "")) - return null; - - //------ remaining b64 data is encrypted RSA key ---- - String encryptedstr = str.ReadToEnd(); - - try - { //should have b64 encrypted RSA key now - binkey = Convert.FromBase64String(encryptedstr); - } - catch (System.FormatException) - { // bad b64 data. - return null; - } - - //------ Get the 3DES 24 byte key using PDK used by OpenSSL ---- - - SecureString despswd = GetSecPswd("Enter password to derive 3DES key==>"); - //Console.Write("\nEnter password to derive 3DES key: "); - //String pswd = Console.ReadLine(); - byte[] deskey = GetOpenSSL3deskey(salt, despswd, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes - if (deskey == null) - return null; - //showBytes("3DES key", deskey) ; - - //------ Decrypt the encrypted 3des-encrypted RSA private key ------ - byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV - if (rsakey != null) - return rsakey; //we have a decrypted RSA private key - else - { - Console.WriteLine("Failed to decrypt RSA private key; probably wrong password."); - return null; - } - } - - static byte[] GetOpenSSL3deskey(byte[] salt, SecureString secpswd, int count, int miter) + static byte[] GetEncryptedKey(byte[] salt, SecureString secpswd, int count, int miter) { IntPtr unmanagedPswd = IntPtr.Zero; int HASHLENGTH = 16; //MD5 bytes byte[] keymaterial = new byte[HASHLENGTH * miter]; //to store contatenated Mi hashed results - byte[] psbytes = new byte[secpswd.Length]; unmanagedPswd = Marshal.SecureStringToGlobalAllocAnsi(secpswd); Marshal.Copy(unmanagedPswd, psbytes, 0, psbytes.Length); Marshal.ZeroFreeGlobalAllocAnsi(unmanagedPswd); - //UTF8Encoding utf8 = new UTF8Encoding(); - //byte[] psbytes = utf8.GetBytes(pswd); - // --- contatenate salt and pswd bytes into fixed data array --- byte[] data00 = new byte[psbytes.Length + salt.Length]; Array.Copy(psbytes, data00, psbytes.Length); //copy the pswd bytes @@ -248,15 +240,12 @@ static byte[] GetOpenSSL3deskey(byte[] salt, SecureString secpswd, int count, in Array.Copy(result, hashtarget, result.Length); Array.Copy(data00, 0, hashtarget, result.Length, data00.Length); result = hashtarget; - //Console.WriteLine("Updated new initial hash target:") ; - //showBytes(result) ; } for (int i = 0; i < count; i++) result = md5.ComputeHash(result); Array.Copy(result, 0, keymaterial, j * HASHLENGTH, result.Length); //contatenate to keymaterial } - //showBytes("Final key material", keymaterial); byte[] deskey = new byte[24]; Array.Copy(keymaterial, deskey, deskey.Length); @@ -265,46 +254,9 @@ static byte[] GetOpenSSL3deskey(byte[] salt, SecureString secpswd, int count, in Array.Clear(result, 0, result.Length); Array.Clear(hashtarget, 0, hashtarget.Length); Array.Clear(keymaterial, 0, keymaterial.Length); - return deskey; } - public static string GetRSASignb64encode(string private_key_path, byte[] digest) - { - RSACryptoServiceProvider cipher = new RSACryptoServiceProvider(); - cipher = GetRSAProviderFromPemFile(private_key_path); - RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(cipher); - RSAFormatter.SetHashAlgorithm("SHA256"); - byte[] signedHash = RSAFormatter.CreateSignature(digest); - return Convert.ToBase64String(signedHash); - } - - public static RSACryptoServiceProvider GetRSAProviderFromPemFile(String pemfile) - { - bool isPrivateKeyFile = true; - if (!File.Exists(pemfile)) - { - throw new Exception("pemfile does not exist."); - } - string pemstr = File.ReadAllText(pemfile).Trim(); - if (pemstr.StartsWith(pempubheader) && pemstr.EndsWith(pempubfooter)) - isPrivateKeyFile = false; - - byte[] pemkey = null; - if (isPrivateKeyFile) - pemkey = DecodeOpenSSLPrivateKey(pemstr); - - - if (pemkey == null) - return null; - - if (isPrivateKeyFile) - { - return DecodeRSAPrivateKey(pemkey); - } - return null; - } - static byte[] DecryptKey(byte[] cipherData, byte[] desKey, byte[] IV) { MemoryStream memst = new MemoryStream(); @@ -317,61 +269,11 @@ static byte[] DecryptKey(byte[] cipherData, byte[] desKey, byte[] IV) cs.Write(cipherData, 0, cipherData.Length); cs.Close(); } - catch (Exception exc) - { - Console.WriteLine(exc.Message); + catch (Exception){ return null; } byte[] decryptedData = memst.ToArray(); return decryptedData; } - - static SecureString GetSecPswd(String prompt) - { - SecureString password = new SecureString(); - - Console.ForegroundColor = ConsoleColor.Gray; - Console.ForegroundColor = ConsoleColor.Magenta; - - while (true) - { - ConsoleKeyInfo cki = Console.ReadKey(true); - if (cki.Key == ConsoleKey.Enter) - { - Console.ForegroundColor = ConsoleColor.Gray; - return password; - } - else if (cki.Key == ConsoleKey.Backspace) - { - // remove the last asterisk from the screen... - if (password.Length > 0) - { - Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop); - Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop); - password.RemoveAt(password.Length - 1); - } - } - else if (cki.Key == ConsoleKey.Escape) - { - Console.ForegroundColor = ConsoleColor.Gray; - return password; - } - else if (Char.IsLetterOrDigit(cki.KeyChar) || Char.IsSymbol(cki.KeyChar)) - { - if (password.Length < 20) - { - password.AppendChar(cki.KeyChar); - } - else - { - Console.Beep(); - } - } - else - { - Console.Beep(); - } - } - } } -} +} \ No newline at end of file From 66a3ec7cf07b273e4f9d1f78435ab426677659e4 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 2 Jun 2020 16:50:35 +0800 Subject: [PATCH 4/6] add oneof discrimistrator lookup to go experimental (#6517) --- docs/generators/go-experimental.md | 1 + .../GoClientExperimentalCodegen.java | 17 ++++++++++ .../go-experimental/model_oneof.mustache | 33 ++++++++++++++++++- .../go-petstore/model_fruit.go | 1 + .../go-petstore/model_fruit_req.go | 1 + .../go-petstore/model_mammal.go | 1 + 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/docs/generators/go-experimental.md b/docs/generators/go-experimental.md index d5298fd44f16..5866c95004ef 100644 --- a/docs/generators/go-experimental.md +++ b/docs/generators/go-experimental.md @@ -12,6 +12,7 @@ sidebar_label: go-experimental |packageVersion|Go package version.| |1.0.0| |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |structPrefix|whether to prefix struct with the class name. e.g. DeletePetOpts => PetApiDeletePetOpts| |false| +|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and onlye one match in oneOf's schemas) will be skipped.| |false| |withAWSV4Signature|whether to include AWS v4 signature support| |false| |withGoCodegenComment|whether to include Go codegen comment to disable Go Lint and collapse by default in GitHub PRs and diffs| |false| |withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java index a72d18959b18..ddb10684f2a0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoClientExperimentalCodegen.java @@ -35,6 +35,7 @@ public class GoClientExperimentalCodegen extends GoClientCodegen { private static final Logger LOGGER = LoggerFactory.getLogger(GoClientExperimentalCodegen.class); protected String goImportAlias = "openapiclient"; + protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup public GoClientExperimentalCodegen() { super(); @@ -44,6 +45,8 @@ public GoClientExperimentalCodegen() { usesOptionals = false; generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata).stability(Stability.EXPERIMENTAL).build(); + + cliOptions.add(new CliOption(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP_DESC).defaultValue("false")); } /** @@ -93,6 +96,20 @@ public void processOpts() { additionalProperties.put("goImportAlias", goImportAlias); } + if (additionalProperties.containsKey(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP)) { + setUseOneOfDiscriminatorLookup(convertPropertyToBooleanAndWriteBack(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP)); + } else { + additionalProperties.put(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, useOneOfDiscriminatorLookup); + } + + } + + public void setUseOneOfDiscriminatorLookup(boolean useOneOfDiscriminatorLookup) { + this.useOneOfDiscriminatorLookup = useOneOfDiscriminatorLookup; + } + + public boolean getUseOneOfDiscriminatorLookup() { + return this.useOneOfDiscriminatorLookup; } public void setGoImportAlias(String goImportAlias) { diff --git a/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache b/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache index 20cb13d541b1..bbd9aeecccee 100644 --- a/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache +++ b/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache @@ -24,6 +24,37 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error { } {{/isNullable}} + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{#mappedModels}} + {{#-first}} + // use discriminator value to speed up the lookup + var jsonDict map[string]interface{} + err := json.Unmarshal(data, &jsonDict) + if err != nil { + return fmt.Errorf("Failed to unmarshal JSON into map for the discrimintor lookup.") + } + + {{/-first}} + // check if the discriminator value is '{{{mappingName}}}' + if jsonDict["{{{propertyBaseName}}}"] == "{{{mappingName}}}" { + // try to unmarshal JSON data into {{{modelName}}} + err = json.Unmarshal(data, &dst.{{{modelName}}}); + if err == nil { + json{{{modelName}}}, _ := json.Marshal(dst.{{{modelName}}}) + if string(json{{{modelName}}}) == "{}" { // empty struct + dst.{{{modelName}}} = nil + } else { + return nil // data stored in dst.{{{modelName}}}, return on the first match + } + } else { + dst.{{{modelName}}} = nil + } + } + + {{/mappedModels}} + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} {{#oneOf}} // try to unmarshal data into {{{.}}} err = json.Unmarshal(data, &dst.{{{.}}}); @@ -76,4 +107,4 @@ func (obj *{{classname}}) GetActualInstance() (interface{}) { return nil } -{{>nullable_model}} \ No newline at end of file +{{>nullable_model}} diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go index ec7e137f352e..416ae81c7188 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go @@ -137,3 +137,4 @@ func (v *NullableFruit) UnmarshalJSON(src []byte) error { return json.Unmarshal(src, &v.value) } + diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go index b70da598b420..dce03284f0f0 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go @@ -137,3 +137,4 @@ func (v *NullableFruitReq) UnmarshalJSON(src []byte) error { return json.Unmarshal(src, &v.value) } + diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go index a3af711d6f39..e9731f1d550d 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go @@ -137,3 +137,4 @@ func (v *NullableMammal) UnmarshalJSON(src []byte) error { return json.Unmarshal(src, &v.value) } + From 8fc7ec84580693a686b7cf4c84f82cc8822d8b8e Mon Sep 17 00:00:00 2001 From: Justin Van Dort Date: Tue, 2 Jun 2020 06:46:30 -0400 Subject: [PATCH 5/6] Typescript-rxjs: print param name (#6368) * Prints out the parameter name in throwIfNullOrUndefined * Fixed misspelling Co-authored-by: Justin Van Dort Co-authored-by: Esteban Gehring --- .../resources/typescript-rxjs/apis.mustache | 2 +- .../resources/typescript-rxjs/runtime.mustache | 4 ++-- .../builds/default/apis/PetApi.ts | 16 ++++++++-------- .../builds/default/apis/StoreApi.ts | 6 +++--- .../builds/default/apis/UserApi.ts | 18 +++++++++--------- .../typescript-rxjs/builds/default/runtime.ts | 4 ++-- .../builds/es6-target/apis/PetApi.ts | 16 ++++++++-------- .../builds/es6-target/apis/StoreApi.ts | 6 +++--- .../builds/es6-target/apis/UserApi.ts | 18 +++++++++--------- .../builds/es6-target/runtime.ts | 4 ++-- .../builds/with-interfaces/apis/PetApi.ts | 16 ++++++++-------- .../builds/with-interfaces/apis/StoreApi.ts | 6 +++--- .../builds/with-interfaces/apis/UserApi.ts | 18 +++++++++--------- .../builds/with-interfaces/runtime.ts | 4 ++-- .../builds/with-npm-version/apis/PetApi.ts | 16 ++++++++-------- .../builds/with-npm-version/apis/StoreApi.ts | 6 +++--- .../builds/with-npm-version/apis/UserApi.ts | 18 +++++++++--------- .../builds/with-npm-version/runtime.ts | 4 ++-- 18 files changed, 91 insertions(+), 91 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/typescript-rxjs/apis.mustache b/modules/openapi-generator/src/main/resources/typescript-rxjs/apis.mustache index 6fc3928c4872..4aae18a02f0e 100644 --- a/modules/openapi-generator/src/main/resources/typescript-rxjs/apis.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-rxjs/apis.mustache @@ -41,7 +41,7 @@ export class {{classname}} extends BaseAPI { {{#hasParams}} {{#allParams}} {{#required}} - throwIfNullOrUndefined({{> paramNamePartial}}, '{{nickname}}'); + throwIfNullOrUndefined({{> paramNamePartial}}, '{{> paramNamePartial}}', '{{nickname}}'); {{/required}} {{/allParams}} diff --git a/modules/openapi-generator/src/main/resources/typescript-rxjs/runtime.mustache b/modules/openapi-generator/src/main/resources/typescript-rxjs/runtime.mustache index 97989df889a6..db845a859459 100644 --- a/modules/openapi-generator/src/main/resources/typescript-rxjs/runtime.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-rxjs/runtime.mustache @@ -178,9 +178,9 @@ export const throwIfRequired = (params: {[key: string]: any}, key: string, nickn } }; -export const throwIfNullOrUndefined = (value: any, nickname?: string) => { +export const throwIfNullOrUndefined = (value: any, paramName: string, nickname: string) => { if (value == null) { - throw new Error(`Parameter "${value}" was null or undefined when calling "${nickname}".`); + throw new Error(`Parameter "${paramName}" was null or undefined when calling "${nickname}".`); } }; diff --git a/samples/client/petstore/typescript-rxjs/builds/default/apis/PetApi.ts b/samples/client/petstore/typescript-rxjs/builds/default/apis/PetApi.ts index 3b3232c44dbb..021781fd7abb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/default/apis/PetApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/default/apis/PetApi.ts @@ -64,7 +64,7 @@ export class PetApi extends BaseAPI { * Add a new pet to the store */ addPet = ({ body }: AddPetRequest): Observable => { - throwIfNullOrUndefined(body, 'addPet'); + throwIfNullOrUndefined(body, 'body', 'addPet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -89,7 +89,7 @@ export class PetApi extends BaseAPI { * Deletes a pet */ deletePet = ({ petId, apiKey }: DeletePetRequest): Observable => { - throwIfNullOrUndefined(petId, 'deletePet'); + throwIfNullOrUndefined(petId, 'petId', 'deletePet'); const headers: HttpHeaders = { ...(apiKey != null ? { 'api_key': String(apiKey) } : undefined), @@ -114,7 +114,7 @@ export class PetApi extends BaseAPI { * Finds Pets by status */ findPetsByStatus = ({ status }: FindPetsByStatusRequest): Observable> => { - throwIfNullOrUndefined(status, 'findPetsByStatus'); + throwIfNullOrUndefined(status, 'status', 'findPetsByStatus'); const headers: HttpHeaders = { // oauth required @@ -143,7 +143,7 @@ export class PetApi extends BaseAPI { * Finds Pets by tags */ findPetsByTags = ({ tags }: FindPetsByTagsRequest): Observable> => { - throwIfNullOrUndefined(tags, 'findPetsByTags'); + throwIfNullOrUndefined(tags, 'tags', 'findPetsByTags'); const headers: HttpHeaders = { // oauth required @@ -172,7 +172,7 @@ export class PetApi extends BaseAPI { * Find pet by ID */ getPetById = ({ petId }: GetPetByIdRequest): Observable => { - throwIfNullOrUndefined(petId, 'getPetById'); + throwIfNullOrUndefined(petId, 'petId', 'getPetById'); const headers: HttpHeaders = { ...(this.configuration.apiKey && { 'api_key': this.configuration.apiKey('api_key') }), // api_key authentication @@ -189,7 +189,7 @@ export class PetApi extends BaseAPI { * Update an existing pet */ updatePet = ({ body }: UpdatePetRequest): Observable => { - throwIfNullOrUndefined(body, 'updatePet'); + throwIfNullOrUndefined(body, 'body', 'updatePet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -214,7 +214,7 @@ export class PetApi extends BaseAPI { * Updates a pet in the store with form data */ updatePetWithForm = ({ petId, name, status }: UpdatePetWithFormRequest): Observable => { - throwIfNullOrUndefined(petId, 'updatePetWithForm'); + throwIfNullOrUndefined(petId, 'petId', 'updatePetWithForm'); const headers: HttpHeaders = { // oauth required @@ -242,7 +242,7 @@ export class PetApi extends BaseAPI { * uploads an image */ uploadFile = ({ petId, additionalMetadata, file }: UploadFileRequest): Observable => { - throwIfNullOrUndefined(petId, 'uploadFile'); + throwIfNullOrUndefined(petId, 'petId', 'uploadFile'); const headers: HttpHeaders = { // oauth required diff --git a/samples/client/petstore/typescript-rxjs/builds/default/apis/StoreApi.ts b/samples/client/petstore/typescript-rxjs/builds/default/apis/StoreApi.ts index aac36206d606..8ce04d16aa04 100644 --- a/samples/client/petstore/typescript-rxjs/builds/default/apis/StoreApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/default/apis/StoreApi.ts @@ -39,7 +39,7 @@ export class StoreApi extends BaseAPI { * Delete purchase order by ID */ deleteOrder = ({ orderId }: DeleteOrderRequest): Observable => { - throwIfNullOrUndefined(orderId, 'deleteOrder'); + throwIfNullOrUndefined(orderId, 'orderId', 'deleteOrder'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -68,7 +68,7 @@ export class StoreApi extends BaseAPI { * Find purchase order by ID */ getOrderById = ({ orderId }: GetOrderByIdRequest): Observable => { - throwIfNullOrUndefined(orderId, 'getOrderById'); + throwIfNullOrUndefined(orderId, 'orderId', 'getOrderById'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -80,7 +80,7 @@ export class StoreApi extends BaseAPI { * Place an order for a pet */ placeOrder = ({ body }: PlaceOrderRequest): Observable => { - throwIfNullOrUndefined(body, 'placeOrder'); + throwIfNullOrUndefined(body, 'body', 'placeOrder'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/default/apis/UserApi.ts b/samples/client/petstore/typescript-rxjs/builds/default/apis/UserApi.ts index 1b3c07eea4f7..a223874786eb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/default/apis/UserApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/default/apis/UserApi.ts @@ -57,7 +57,7 @@ export class UserApi extends BaseAPI { * Create user */ createUser = ({ body }: CreateUserRequest): Observable => { - throwIfNullOrUndefined(body, 'createUser'); + throwIfNullOrUndefined(body, 'body', 'createUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -75,7 +75,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithArrayInput = ({ body }: CreateUsersWithArrayInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithArrayInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithArrayInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -93,7 +93,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithListInput = ({ body }: CreateUsersWithListInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithListInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithListInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -112,7 +112,7 @@ export class UserApi extends BaseAPI { * Delete user */ deleteUser = ({ username }: DeleteUserRequest): Observable => { - throwIfNullOrUndefined(username, 'deleteUser'); + throwIfNullOrUndefined(username, 'username', 'deleteUser'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -124,7 +124,7 @@ export class UserApi extends BaseAPI { * Get user by user name */ getUserByName = ({ username }: GetUserByNameRequest): Observable => { - throwIfNullOrUndefined(username, 'getUserByName'); + throwIfNullOrUndefined(username, 'username', 'getUserByName'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -136,8 +136,8 @@ export class UserApi extends BaseAPI { * Logs user into the system */ loginUser = ({ username, password }: LoginUserRequest): Observable => { - throwIfNullOrUndefined(username, 'loginUser'); - throwIfNullOrUndefined(password, 'loginUser'); + throwIfNullOrUndefined(username, 'username', 'loginUser'); + throwIfNullOrUndefined(password, 'password', 'loginUser'); const query: HttpQuery = { // required parameters are used directly since they are already checked by throwIfNullOrUndefined 'username': username, @@ -166,8 +166,8 @@ export class UserApi extends BaseAPI { * Updated user */ updateUser = ({ username, body }: UpdateUserRequest): Observable => { - throwIfNullOrUndefined(username, 'updateUser'); - throwIfNullOrUndefined(body, 'updateUser'); + throwIfNullOrUndefined(username, 'username', 'updateUser'); + throwIfNullOrUndefined(body, 'body', 'updateUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/default/runtime.ts b/samples/client/petstore/typescript-rxjs/builds/default/runtime.ts index ad383a116427..42ddef55ae1c 100644 --- a/samples/client/petstore/typescript-rxjs/builds/default/runtime.ts +++ b/samples/client/petstore/typescript-rxjs/builds/default/runtime.ts @@ -189,9 +189,9 @@ export const throwIfRequired = (params: {[key: string]: any}, key: string, nickn } }; -export const throwIfNullOrUndefined = (value: any, nickname?: string) => { +export const throwIfNullOrUndefined = (value: any, paramName: string, nickname: string) => { if (value == null) { - throw new Error(`Parameter "${value}" was null or undefined when calling "${nickname}".`); + throw new Error(`Parameter "${paramName}" was null or undefined when calling "${nickname}".`); } }; diff --git a/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/PetApi.ts b/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/PetApi.ts index 3b3232c44dbb..021781fd7abb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/PetApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/PetApi.ts @@ -64,7 +64,7 @@ export class PetApi extends BaseAPI { * Add a new pet to the store */ addPet = ({ body }: AddPetRequest): Observable => { - throwIfNullOrUndefined(body, 'addPet'); + throwIfNullOrUndefined(body, 'body', 'addPet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -89,7 +89,7 @@ export class PetApi extends BaseAPI { * Deletes a pet */ deletePet = ({ petId, apiKey }: DeletePetRequest): Observable => { - throwIfNullOrUndefined(petId, 'deletePet'); + throwIfNullOrUndefined(petId, 'petId', 'deletePet'); const headers: HttpHeaders = { ...(apiKey != null ? { 'api_key': String(apiKey) } : undefined), @@ -114,7 +114,7 @@ export class PetApi extends BaseAPI { * Finds Pets by status */ findPetsByStatus = ({ status }: FindPetsByStatusRequest): Observable> => { - throwIfNullOrUndefined(status, 'findPetsByStatus'); + throwIfNullOrUndefined(status, 'status', 'findPetsByStatus'); const headers: HttpHeaders = { // oauth required @@ -143,7 +143,7 @@ export class PetApi extends BaseAPI { * Finds Pets by tags */ findPetsByTags = ({ tags }: FindPetsByTagsRequest): Observable> => { - throwIfNullOrUndefined(tags, 'findPetsByTags'); + throwIfNullOrUndefined(tags, 'tags', 'findPetsByTags'); const headers: HttpHeaders = { // oauth required @@ -172,7 +172,7 @@ export class PetApi extends BaseAPI { * Find pet by ID */ getPetById = ({ petId }: GetPetByIdRequest): Observable => { - throwIfNullOrUndefined(petId, 'getPetById'); + throwIfNullOrUndefined(petId, 'petId', 'getPetById'); const headers: HttpHeaders = { ...(this.configuration.apiKey && { 'api_key': this.configuration.apiKey('api_key') }), // api_key authentication @@ -189,7 +189,7 @@ export class PetApi extends BaseAPI { * Update an existing pet */ updatePet = ({ body }: UpdatePetRequest): Observable => { - throwIfNullOrUndefined(body, 'updatePet'); + throwIfNullOrUndefined(body, 'body', 'updatePet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -214,7 +214,7 @@ export class PetApi extends BaseAPI { * Updates a pet in the store with form data */ updatePetWithForm = ({ petId, name, status }: UpdatePetWithFormRequest): Observable => { - throwIfNullOrUndefined(petId, 'updatePetWithForm'); + throwIfNullOrUndefined(petId, 'petId', 'updatePetWithForm'); const headers: HttpHeaders = { // oauth required @@ -242,7 +242,7 @@ export class PetApi extends BaseAPI { * uploads an image */ uploadFile = ({ petId, additionalMetadata, file }: UploadFileRequest): Observable => { - throwIfNullOrUndefined(petId, 'uploadFile'); + throwIfNullOrUndefined(petId, 'petId', 'uploadFile'); const headers: HttpHeaders = { // oauth required diff --git a/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/StoreApi.ts b/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/StoreApi.ts index aac36206d606..8ce04d16aa04 100644 --- a/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/StoreApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/StoreApi.ts @@ -39,7 +39,7 @@ export class StoreApi extends BaseAPI { * Delete purchase order by ID */ deleteOrder = ({ orderId }: DeleteOrderRequest): Observable => { - throwIfNullOrUndefined(orderId, 'deleteOrder'); + throwIfNullOrUndefined(orderId, 'orderId', 'deleteOrder'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -68,7 +68,7 @@ export class StoreApi extends BaseAPI { * Find purchase order by ID */ getOrderById = ({ orderId }: GetOrderByIdRequest): Observable => { - throwIfNullOrUndefined(orderId, 'getOrderById'); + throwIfNullOrUndefined(orderId, 'orderId', 'getOrderById'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -80,7 +80,7 @@ export class StoreApi extends BaseAPI { * Place an order for a pet */ placeOrder = ({ body }: PlaceOrderRequest): Observable => { - throwIfNullOrUndefined(body, 'placeOrder'); + throwIfNullOrUndefined(body, 'body', 'placeOrder'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/UserApi.ts b/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/UserApi.ts index 1b3c07eea4f7..a223874786eb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/UserApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/es6-target/apis/UserApi.ts @@ -57,7 +57,7 @@ export class UserApi extends BaseAPI { * Create user */ createUser = ({ body }: CreateUserRequest): Observable => { - throwIfNullOrUndefined(body, 'createUser'); + throwIfNullOrUndefined(body, 'body', 'createUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -75,7 +75,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithArrayInput = ({ body }: CreateUsersWithArrayInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithArrayInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithArrayInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -93,7 +93,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithListInput = ({ body }: CreateUsersWithListInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithListInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithListInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -112,7 +112,7 @@ export class UserApi extends BaseAPI { * Delete user */ deleteUser = ({ username }: DeleteUserRequest): Observable => { - throwIfNullOrUndefined(username, 'deleteUser'); + throwIfNullOrUndefined(username, 'username', 'deleteUser'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -124,7 +124,7 @@ export class UserApi extends BaseAPI { * Get user by user name */ getUserByName = ({ username }: GetUserByNameRequest): Observable => { - throwIfNullOrUndefined(username, 'getUserByName'); + throwIfNullOrUndefined(username, 'username', 'getUserByName'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -136,8 +136,8 @@ export class UserApi extends BaseAPI { * Logs user into the system */ loginUser = ({ username, password }: LoginUserRequest): Observable => { - throwIfNullOrUndefined(username, 'loginUser'); - throwIfNullOrUndefined(password, 'loginUser'); + throwIfNullOrUndefined(username, 'username', 'loginUser'); + throwIfNullOrUndefined(password, 'password', 'loginUser'); const query: HttpQuery = { // required parameters are used directly since they are already checked by throwIfNullOrUndefined 'username': username, @@ -166,8 +166,8 @@ export class UserApi extends BaseAPI { * Updated user */ updateUser = ({ username, body }: UpdateUserRequest): Observable => { - throwIfNullOrUndefined(username, 'updateUser'); - throwIfNullOrUndefined(body, 'updateUser'); + throwIfNullOrUndefined(username, 'username', 'updateUser'); + throwIfNullOrUndefined(body, 'body', 'updateUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/es6-target/runtime.ts b/samples/client/petstore/typescript-rxjs/builds/es6-target/runtime.ts index ad383a116427..42ddef55ae1c 100644 --- a/samples/client/petstore/typescript-rxjs/builds/es6-target/runtime.ts +++ b/samples/client/petstore/typescript-rxjs/builds/es6-target/runtime.ts @@ -189,9 +189,9 @@ export const throwIfRequired = (params: {[key: string]: any}, key: string, nickn } }; -export const throwIfNullOrUndefined = (value: any, nickname?: string) => { +export const throwIfNullOrUndefined = (value: any, paramName: string, nickname: string) => { if (value == null) { - throw new Error(`Parameter "${value}" was null or undefined when calling "${nickname}".`); + throw new Error(`Parameter "${paramName}" was null or undefined when calling "${nickname}".`); } }; diff --git a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/PetApi.ts b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/PetApi.ts index 3b3232c44dbb..021781fd7abb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/PetApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/PetApi.ts @@ -64,7 +64,7 @@ export class PetApi extends BaseAPI { * Add a new pet to the store */ addPet = ({ body }: AddPetRequest): Observable => { - throwIfNullOrUndefined(body, 'addPet'); + throwIfNullOrUndefined(body, 'body', 'addPet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -89,7 +89,7 @@ export class PetApi extends BaseAPI { * Deletes a pet */ deletePet = ({ petId, apiKey }: DeletePetRequest): Observable => { - throwIfNullOrUndefined(petId, 'deletePet'); + throwIfNullOrUndefined(petId, 'petId', 'deletePet'); const headers: HttpHeaders = { ...(apiKey != null ? { 'api_key': String(apiKey) } : undefined), @@ -114,7 +114,7 @@ export class PetApi extends BaseAPI { * Finds Pets by status */ findPetsByStatus = ({ status }: FindPetsByStatusRequest): Observable> => { - throwIfNullOrUndefined(status, 'findPetsByStatus'); + throwIfNullOrUndefined(status, 'status', 'findPetsByStatus'); const headers: HttpHeaders = { // oauth required @@ -143,7 +143,7 @@ export class PetApi extends BaseAPI { * Finds Pets by tags */ findPetsByTags = ({ tags }: FindPetsByTagsRequest): Observable> => { - throwIfNullOrUndefined(tags, 'findPetsByTags'); + throwIfNullOrUndefined(tags, 'tags', 'findPetsByTags'); const headers: HttpHeaders = { // oauth required @@ -172,7 +172,7 @@ export class PetApi extends BaseAPI { * Find pet by ID */ getPetById = ({ petId }: GetPetByIdRequest): Observable => { - throwIfNullOrUndefined(petId, 'getPetById'); + throwIfNullOrUndefined(petId, 'petId', 'getPetById'); const headers: HttpHeaders = { ...(this.configuration.apiKey && { 'api_key': this.configuration.apiKey('api_key') }), // api_key authentication @@ -189,7 +189,7 @@ export class PetApi extends BaseAPI { * Update an existing pet */ updatePet = ({ body }: UpdatePetRequest): Observable => { - throwIfNullOrUndefined(body, 'updatePet'); + throwIfNullOrUndefined(body, 'body', 'updatePet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -214,7 +214,7 @@ export class PetApi extends BaseAPI { * Updates a pet in the store with form data */ updatePetWithForm = ({ petId, name, status }: UpdatePetWithFormRequest): Observable => { - throwIfNullOrUndefined(petId, 'updatePetWithForm'); + throwIfNullOrUndefined(petId, 'petId', 'updatePetWithForm'); const headers: HttpHeaders = { // oauth required @@ -242,7 +242,7 @@ export class PetApi extends BaseAPI { * uploads an image */ uploadFile = ({ petId, additionalMetadata, file }: UploadFileRequest): Observable => { - throwIfNullOrUndefined(petId, 'uploadFile'); + throwIfNullOrUndefined(petId, 'petId', 'uploadFile'); const headers: HttpHeaders = { // oauth required diff --git a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/StoreApi.ts b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/StoreApi.ts index aac36206d606..8ce04d16aa04 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/StoreApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/StoreApi.ts @@ -39,7 +39,7 @@ export class StoreApi extends BaseAPI { * Delete purchase order by ID */ deleteOrder = ({ orderId }: DeleteOrderRequest): Observable => { - throwIfNullOrUndefined(orderId, 'deleteOrder'); + throwIfNullOrUndefined(orderId, 'orderId', 'deleteOrder'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -68,7 +68,7 @@ export class StoreApi extends BaseAPI { * Find purchase order by ID */ getOrderById = ({ orderId }: GetOrderByIdRequest): Observable => { - throwIfNullOrUndefined(orderId, 'getOrderById'); + throwIfNullOrUndefined(orderId, 'orderId', 'getOrderById'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -80,7 +80,7 @@ export class StoreApi extends BaseAPI { * Place an order for a pet */ placeOrder = ({ body }: PlaceOrderRequest): Observable => { - throwIfNullOrUndefined(body, 'placeOrder'); + throwIfNullOrUndefined(body, 'body', 'placeOrder'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/UserApi.ts b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/UserApi.ts index 1b3c07eea4f7..a223874786eb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/UserApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/apis/UserApi.ts @@ -57,7 +57,7 @@ export class UserApi extends BaseAPI { * Create user */ createUser = ({ body }: CreateUserRequest): Observable => { - throwIfNullOrUndefined(body, 'createUser'); + throwIfNullOrUndefined(body, 'body', 'createUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -75,7 +75,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithArrayInput = ({ body }: CreateUsersWithArrayInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithArrayInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithArrayInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -93,7 +93,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithListInput = ({ body }: CreateUsersWithListInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithListInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithListInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -112,7 +112,7 @@ export class UserApi extends BaseAPI { * Delete user */ deleteUser = ({ username }: DeleteUserRequest): Observable => { - throwIfNullOrUndefined(username, 'deleteUser'); + throwIfNullOrUndefined(username, 'username', 'deleteUser'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -124,7 +124,7 @@ export class UserApi extends BaseAPI { * Get user by user name */ getUserByName = ({ username }: GetUserByNameRequest): Observable => { - throwIfNullOrUndefined(username, 'getUserByName'); + throwIfNullOrUndefined(username, 'username', 'getUserByName'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -136,8 +136,8 @@ export class UserApi extends BaseAPI { * Logs user into the system */ loginUser = ({ username, password }: LoginUserRequest): Observable => { - throwIfNullOrUndefined(username, 'loginUser'); - throwIfNullOrUndefined(password, 'loginUser'); + throwIfNullOrUndefined(username, 'username', 'loginUser'); + throwIfNullOrUndefined(password, 'password', 'loginUser'); const query: HttpQuery = { // required parameters are used directly since they are already checked by throwIfNullOrUndefined 'username': username, @@ -166,8 +166,8 @@ export class UserApi extends BaseAPI { * Updated user */ updateUser = ({ username, body }: UpdateUserRequest): Observable => { - throwIfNullOrUndefined(username, 'updateUser'); - throwIfNullOrUndefined(body, 'updateUser'); + throwIfNullOrUndefined(username, 'username', 'updateUser'); + throwIfNullOrUndefined(body, 'body', 'updateUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/runtime.ts b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/runtime.ts index ad383a116427..42ddef55ae1c 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-interfaces/runtime.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-interfaces/runtime.ts @@ -189,9 +189,9 @@ export const throwIfRequired = (params: {[key: string]: any}, key: string, nickn } }; -export const throwIfNullOrUndefined = (value: any, nickname?: string) => { +export const throwIfNullOrUndefined = (value: any, paramName: string, nickname: string) => { if (value == null) { - throw new Error(`Parameter "${value}" was null or undefined when calling "${nickname}".`); + throw new Error(`Parameter "${paramName}" was null or undefined when calling "${nickname}".`); } }; diff --git a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/PetApi.ts b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/PetApi.ts index 3b3232c44dbb..021781fd7abb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/PetApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/PetApi.ts @@ -64,7 +64,7 @@ export class PetApi extends BaseAPI { * Add a new pet to the store */ addPet = ({ body }: AddPetRequest): Observable => { - throwIfNullOrUndefined(body, 'addPet'); + throwIfNullOrUndefined(body, 'body', 'addPet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -89,7 +89,7 @@ export class PetApi extends BaseAPI { * Deletes a pet */ deletePet = ({ petId, apiKey }: DeletePetRequest): Observable => { - throwIfNullOrUndefined(petId, 'deletePet'); + throwIfNullOrUndefined(petId, 'petId', 'deletePet'); const headers: HttpHeaders = { ...(apiKey != null ? { 'api_key': String(apiKey) } : undefined), @@ -114,7 +114,7 @@ export class PetApi extends BaseAPI { * Finds Pets by status */ findPetsByStatus = ({ status }: FindPetsByStatusRequest): Observable> => { - throwIfNullOrUndefined(status, 'findPetsByStatus'); + throwIfNullOrUndefined(status, 'status', 'findPetsByStatus'); const headers: HttpHeaders = { // oauth required @@ -143,7 +143,7 @@ export class PetApi extends BaseAPI { * Finds Pets by tags */ findPetsByTags = ({ tags }: FindPetsByTagsRequest): Observable> => { - throwIfNullOrUndefined(tags, 'findPetsByTags'); + throwIfNullOrUndefined(tags, 'tags', 'findPetsByTags'); const headers: HttpHeaders = { // oauth required @@ -172,7 +172,7 @@ export class PetApi extends BaseAPI { * Find pet by ID */ getPetById = ({ petId }: GetPetByIdRequest): Observable => { - throwIfNullOrUndefined(petId, 'getPetById'); + throwIfNullOrUndefined(petId, 'petId', 'getPetById'); const headers: HttpHeaders = { ...(this.configuration.apiKey && { 'api_key': this.configuration.apiKey('api_key') }), // api_key authentication @@ -189,7 +189,7 @@ export class PetApi extends BaseAPI { * Update an existing pet */ updatePet = ({ body }: UpdatePetRequest): Observable => { - throwIfNullOrUndefined(body, 'updatePet'); + throwIfNullOrUndefined(body, 'body', 'updatePet'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -214,7 +214,7 @@ export class PetApi extends BaseAPI { * Updates a pet in the store with form data */ updatePetWithForm = ({ petId, name, status }: UpdatePetWithFormRequest): Observable => { - throwIfNullOrUndefined(petId, 'updatePetWithForm'); + throwIfNullOrUndefined(petId, 'petId', 'updatePetWithForm'); const headers: HttpHeaders = { // oauth required @@ -242,7 +242,7 @@ export class PetApi extends BaseAPI { * uploads an image */ uploadFile = ({ petId, additionalMetadata, file }: UploadFileRequest): Observable => { - throwIfNullOrUndefined(petId, 'uploadFile'); + throwIfNullOrUndefined(petId, 'petId', 'uploadFile'); const headers: HttpHeaders = { // oauth required diff --git a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/StoreApi.ts b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/StoreApi.ts index aac36206d606..8ce04d16aa04 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/StoreApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/StoreApi.ts @@ -39,7 +39,7 @@ export class StoreApi extends BaseAPI { * Delete purchase order by ID */ deleteOrder = ({ orderId }: DeleteOrderRequest): Observable => { - throwIfNullOrUndefined(orderId, 'deleteOrder'); + throwIfNullOrUndefined(orderId, 'orderId', 'deleteOrder'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -68,7 +68,7 @@ export class StoreApi extends BaseAPI { * Find purchase order by ID */ getOrderById = ({ orderId }: GetOrderByIdRequest): Observable => { - throwIfNullOrUndefined(orderId, 'getOrderById'); + throwIfNullOrUndefined(orderId, 'orderId', 'getOrderById'); return this.request({ path: '/store/order/{orderId}'.replace('{orderId}', encodeURI(orderId)), @@ -80,7 +80,7 @@ export class StoreApi extends BaseAPI { * Place an order for a pet */ placeOrder = ({ body }: PlaceOrderRequest): Observable => { - throwIfNullOrUndefined(body, 'placeOrder'); + throwIfNullOrUndefined(body, 'body', 'placeOrder'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/UserApi.ts b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/UserApi.ts index 1b3c07eea4f7..a223874786eb 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/UserApi.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/apis/UserApi.ts @@ -57,7 +57,7 @@ export class UserApi extends BaseAPI { * Create user */ createUser = ({ body }: CreateUserRequest): Observable => { - throwIfNullOrUndefined(body, 'createUser'); + throwIfNullOrUndefined(body, 'body', 'createUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -75,7 +75,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithArrayInput = ({ body }: CreateUsersWithArrayInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithArrayInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithArrayInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -93,7 +93,7 @@ export class UserApi extends BaseAPI { * Creates list of users with given input array */ createUsersWithListInput = ({ body }: CreateUsersWithListInputRequest): Observable => { - throwIfNullOrUndefined(body, 'createUsersWithListInput'); + throwIfNullOrUndefined(body, 'body', 'createUsersWithListInput'); const headers: HttpHeaders = { 'Content-Type': 'application/json', @@ -112,7 +112,7 @@ export class UserApi extends BaseAPI { * Delete user */ deleteUser = ({ username }: DeleteUserRequest): Observable => { - throwIfNullOrUndefined(username, 'deleteUser'); + throwIfNullOrUndefined(username, 'username', 'deleteUser'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -124,7 +124,7 @@ export class UserApi extends BaseAPI { * Get user by user name */ getUserByName = ({ username }: GetUserByNameRequest): Observable => { - throwIfNullOrUndefined(username, 'getUserByName'); + throwIfNullOrUndefined(username, 'username', 'getUserByName'); return this.request({ path: '/user/{username}'.replace('{username}', encodeURI(username)), @@ -136,8 +136,8 @@ export class UserApi extends BaseAPI { * Logs user into the system */ loginUser = ({ username, password }: LoginUserRequest): Observable => { - throwIfNullOrUndefined(username, 'loginUser'); - throwIfNullOrUndefined(password, 'loginUser'); + throwIfNullOrUndefined(username, 'username', 'loginUser'); + throwIfNullOrUndefined(password, 'password', 'loginUser'); const query: HttpQuery = { // required parameters are used directly since they are already checked by throwIfNullOrUndefined 'username': username, @@ -166,8 +166,8 @@ export class UserApi extends BaseAPI { * Updated user */ updateUser = ({ username, body }: UpdateUserRequest): Observable => { - throwIfNullOrUndefined(username, 'updateUser'); - throwIfNullOrUndefined(body, 'updateUser'); + throwIfNullOrUndefined(username, 'username', 'updateUser'); + throwIfNullOrUndefined(body, 'body', 'updateUser'); const headers: HttpHeaders = { 'Content-Type': 'application/json', diff --git a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/runtime.ts b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/runtime.ts index ad383a116427..42ddef55ae1c 100644 --- a/samples/client/petstore/typescript-rxjs/builds/with-npm-version/runtime.ts +++ b/samples/client/petstore/typescript-rxjs/builds/with-npm-version/runtime.ts @@ -189,9 +189,9 @@ export const throwIfRequired = (params: {[key: string]: any}, key: string, nickn } }; -export const throwIfNullOrUndefined = (value: any, nickname?: string) => { +export const throwIfNullOrUndefined = (value: any, paramName: string, nickname: string) => { if (value == null) { - throw new Error(`Parameter "${value}" was null or undefined when calling "${nickname}".`); + throw new Error(`Parameter "${paramName}" was null or undefined when calling "${nickname}".`); } }; From 4d68953dedb80bb8cb432cbd77ca20d421ca697b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 3 Jun 2020 01:11:41 +0800 Subject: [PATCH 6/6] [Go][Experimental] Fix discriminator lookup (#6521) * bug fix, better code format * update oas3 sample --- .../go-experimental/model_oneof.mustache | 60 +++++++++---------- .../go-petstore/model_fruit.go | 4 +- .../go-petstore/model_fruit_req.go | 4 +- .../go-petstore/model_mammal.go | 4 +- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache b/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache index bbd9aeecccee..c86af51efb9c 100644 --- a/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache +++ b/modules/openapi-generator/src/main/resources/go-experimental/model_oneof.mustache @@ -24,40 +24,40 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error { } {{/isNullable}} - {{#useOneOfDiscriminatorLookup}} - {{#discriminator}} - {{#mappedModels}} - {{#-first}} - // use discriminator value to speed up the lookup - var jsonDict map[string]interface{} - err := json.Unmarshal(data, &jsonDict) - if err != nil { - return fmt.Errorf("Failed to unmarshal JSON into map for the discrimintor lookup.") - } + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{#mappedModels}} + {{#-first}} + // use discriminator value to speed up the lookup + var jsonDict map[string]interface{} + err = json.Unmarshal(data, &jsonDict) + if err != nil { + return fmt.Errorf("Failed to unmarshal JSON into map for the discrimintor lookup.") + } - {{/-first}} - // check if the discriminator value is '{{{mappingName}}}' - if jsonDict["{{{propertyBaseName}}}"] == "{{{mappingName}}}" { - // try to unmarshal JSON data into {{{modelName}}} - err = json.Unmarshal(data, &dst.{{{modelName}}}); - if err == nil { - json{{{modelName}}}, _ := json.Marshal(dst.{{{modelName}}}) - if string(json{{{modelName}}}) == "{}" { // empty struct - dst.{{{modelName}}} = nil - } else { - return nil // data stored in dst.{{{modelName}}}, return on the first match - } - } else { - dst.{{{modelName}}} = nil - } - } + {{/-first}} + // check if the discriminator value is '{{{mappingName}}}' + if jsonDict["{{{propertyBaseName}}}"] == "{{{mappingName}}}" { + // try to unmarshal JSON data into {{{modelName}}} + err = json.Unmarshal(data, &dst.{{{modelName}}}) + if err == nil { + json{{{modelName}}}, _ := json.Marshal(dst.{{{modelName}}}) + if string(json{{{modelName}}}) == "{}" { // empty struct + dst.{{{modelName}}} = nil + } else { + return nil // data stored in dst.{{{modelName}}}, return on the first match + } + } else { + dst.{{{modelName}}} = nil + } + } - {{/mappedModels}} - {{/discriminator}} - {{/useOneOfDiscriminatorLookup}} + {{/mappedModels}} + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} {{#oneOf}} // try to unmarshal data into {{{.}}} - err = json.Unmarshal(data, &dst.{{{.}}}); + err = json.Unmarshal(data, &dst.{{{.}}}) if err == nil { json{{{.}}}, _ := json.Marshal(dst.{{{.}}}) if string(json{{{.}}}) == "{}" { // empty struct diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go index 416ae81c7188..d9c7a0b3b41f 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit.go @@ -36,7 +36,7 @@ func (dst *Fruit) UnmarshalJSON(data []byte) error { var err error match := 0 // try to unmarshal data into Apple - err = json.Unmarshal(data, &dst.Apple); + err = json.Unmarshal(data, &dst.Apple) if err == nil { jsonApple, _ := json.Marshal(dst.Apple) if string(jsonApple) == "{}" { // empty struct @@ -49,7 +49,7 @@ func (dst *Fruit) UnmarshalJSON(data []byte) error { } // try to unmarshal data into Banana - err = json.Unmarshal(data, &dst.Banana); + err = json.Unmarshal(data, &dst.Banana) if err == nil { jsonBanana, _ := json.Marshal(dst.Banana) if string(jsonBanana) == "{}" { // empty struct diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go index dce03284f0f0..d20957648c65 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_fruit_req.go @@ -36,7 +36,7 @@ func (dst *FruitReq) UnmarshalJSON(data []byte) error { var err error match := 0 // try to unmarshal data into AppleReq - err = json.Unmarshal(data, &dst.AppleReq); + err = json.Unmarshal(data, &dst.AppleReq) if err == nil { jsonAppleReq, _ := json.Marshal(dst.AppleReq) if string(jsonAppleReq) == "{}" { // empty struct @@ -49,7 +49,7 @@ func (dst *FruitReq) UnmarshalJSON(data []byte) error { } // try to unmarshal data into BananaReq - err = json.Unmarshal(data, &dst.BananaReq); + err = json.Unmarshal(data, &dst.BananaReq) if err == nil { jsonBananaReq, _ := json.Marshal(dst.BananaReq) if string(jsonBananaReq) == "{}" { // empty struct diff --git a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go index e9731f1d550d..49d5dfdfe2a4 100644 --- a/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go +++ b/samples/openapi3/client/petstore/go-experimental/go-petstore/model_mammal.go @@ -36,7 +36,7 @@ func (dst *Mammal) UnmarshalJSON(data []byte) error { var err error match := 0 // try to unmarshal data into Whale - err = json.Unmarshal(data, &dst.Whale); + err = json.Unmarshal(data, &dst.Whale) if err == nil { jsonWhale, _ := json.Marshal(dst.Whale) if string(jsonWhale) == "{}" { // empty struct @@ -49,7 +49,7 @@ func (dst *Mammal) UnmarshalJSON(data []byte) error { } // try to unmarshal data into Zebra - err = json.Unmarshal(data, &dst.Zebra); + err = json.Unmarshal(data, &dst.Zebra) if err == nil { jsonZebra, _ := json.Marshal(dst.Zebra) if string(jsonZebra) == "{}" { // empty struct